From 55a38739d48fdb1cff63c9084ca0df5aaaffc7d1 Mon Sep 17 00:00:00 2001 From: "github-action[bot]" Date: Tue, 2 Jul 2024 20:34:19 +0200 Subject: [PATCH] Update On Tue Jul 2 20:34:19 CEST 2024 --- .github/update.log | 1 + clash-nyanpasu/backend/Cargo.lock | 4 +- clash-nyanpasu/frontend/nyanpasu/package.json | 8 +- clash-nyanpasu/manifest/version.json | 4 +- clash-nyanpasu/package.json | 4 +- clash-nyanpasu/pnpm-lock.yaml | 256 +- .../.github/build-for-linux/build.sh | 2 +- .../.github/build-for-linux/entrypoint.sh | 2 - clash-verge-rev/.github/workflows/alpha.yml | 18 +- clash-verge-rev/.github/workflows/release.yml | 18 +- clash-verge-rev/UPDATELOG.md | 35 + clash-verge-rev/package.json | 24 +- clash-verge-rev/pnpm-lock.yaml | 383 +- clash-verge-rev/src-tauri/Cargo.lock | 37 +- clash-verge-rev/src-tauri/Cargo.toml | 6 +- .../src-tauri/src/config/prfitem.rs | 4 +- clash-verge-rev/src-tauri/src/enhance/mod.rs | 43 +- clash-verge-rev/src-tauri/src/utils/tmpl.rs | 7 + clash-verge-rev/src-tauri/tauri.conf.json | 2 +- .../src/components/base/base-search-box.tsx | 15 +- .../base/base-styled-text-field.tsx | 2 +- .../src/components/profile/editor-viewer.tsx | 303 +- .../src/components/profile/profile-item.tsx | 107 +- .../src/components/profile/profile-more.tsx | 19 +- .../src/components/profile/rule-item.tsx | 10 +- .../profile/rules-editor-viewer.tsx | 664 +- .../src/components/proxy/proxy-head.tsx | 3 +- .../setting/mods/clash-port-viewer.tsx | 10 +- .../components/setting/mods/config-viewer.tsx | 5 +- .../setting/mods/controller-viewer.tsx | 4 +- .../components/setting/mods/misc-viewer.tsx | 4 +- .../setting/mods/sysproxy-viewer.tsx | 16 +- .../components/setting/mods/theme-viewer.tsx | 7 +- .../components/setting/mods/tun-viewer.tsx | 6 +- .../components/setting/mods/web-ui-item.tsx | 2 +- .../src/components/setting/setting-clash.tsx | 2 +- clash-verge-rev/src/locales/en.json | 61 +- clash-verge-rev/src/locales/fa.json | 52 + clash-verge-rev/src/locales/ru.json | 58 +- clash-verge-rev/src/locales/zh.json | 46 +- clash-verge-rev/src/pages/profiles.tsx | 7 +- echo/.github/workflows/cd.yaml | 3 +- echo/internal/glue/interface.go | 2 +- echo/internal/relay/conf/cfg.go | 4 + echo/internal/relay/health_check.go | 4 +- echo/internal/transporter/base.go | 5 +- echo/internal/transporter/interface.go | 2 +- echo/internal/web/handlers.go | 13 +- echo/internal/web/server.go | 1 + echo/internal/web/templates/index.html | 7 + echo/internal/web/templates/rule_list.html | 86 + echo/internal/web/types.go | 6 +- geoip/lib/instance.go | 2 +- .../base-files/files/lib/upgrade/common.sh | 18 + .../base-files/files/lib/upgrade/nand.sh | 502 +- .../base-files/files/lib/upgrade/stage2 | 3 +- lede/package/kernel/mt76/Makefile | 4 + lede/package/lean/autocore/files/x86/autocore | 2 - lede/package/system/fstools/Makefile | 11 +- ...port-extroot-for-non-MTD-rootfs_data.patch | 129 - lede/package/utils/fitblk/Makefile | 2 +- ....h-removed-REPEAT_BYTE-from-kernel.h.patch | 161 + ...per_-_bits-and-lower_-_bits-to-wordp.patch | 107 + ...nand-Support-write-protection-settin.patch | 36 + ...T_DEV-for-partitions-marked-as-rootf.patch | 2 +- ...mtd-spi-nor-add-generic-flash-driver.patch | 117 + ...licon-Labs-EM3581-device-compatible.patch} | 10 +- ...licon-Labs-SI3210-device-compatible.patch} | 10 +- ....3-mtd-ubi-wire-up-parent-MTD-device.patch | 33 + ...-mtd-ubi-block-wire-up-device-parent.patch | 49 + ...mtd_otp_nvmem_add-to-handle-EPROBE_.patch} | 0 ...-aquantia-move-to-separate-directory.patch | 2306 +++++++ ...antia-move-MMD_VEND-define-to-header.patch | 183 + ...y-aquantia-add-firmware-load-support.patch | 504 ++ ...edicated-C45-API-to-MDIO-bus-drivers.patch | 326 + ...-Introduce-PSGMII-PHY-interface-mode.patch | 105 + ...eplace-of_gpio.h-with-what-indeed-is.patch | 32 + ...upport-qca8081-genphy_c45_pma_read_a.patch | 70 + ...3x-merge-qca8081-slave-seed-function.patch | 73 + ...nable-qca8081-slave-seed-conditional.patch | 76 + ...-at803x-support-qca8081-1G-chip-type.patch | 48 + ...emove-qca8081-1G-fast-retrain-and-sl.patch | 98 + ...dd-qca8081-fifo-reset-on-the-link-ch.patch | 55 + ...ove-disable-WOL-to-specific-at8031-p.patch | 69 + ...aname-hw_stats-functions-to-qca83xx-.patch | 129 + ...ove-qca83xx-specific-check-in-dedica.patch | 155 + ...ove-specific-DT-option-for-at8031-to.patch | 94 + ...ove-specific-at8031-probe-mode-check.patch | 78 + ...ove-specific-at8031-config_init-to-d.patch | 86 + ...ove-specific-at8031-WOL-bits-to-dedi.patch | 92 + ...ove-specific-at8031-config_intr-to-d.patch | 78 + ...ake-at8031-related-DT-functions-name.patch | 78 + ...ove-at8031-functions-in-dedicated-se.patch | 297 + ...ove-at8035-specific-DT-parse-to-dedi.patch | 114 + ...rop-specific-PHY-ID-check-from-cable.patch | 219 + ...ove-specific-qca808x-config_aneg-to-.patch | 116 + ...ake-read-specific-status-function-mo.patch | 97 + ...at803x-remove-extra-space-after-cast.patch | 27 + ...x-replace-msleep-1-with-usleep_range.patch | 38 + ...etter-align-function-varibles-to-ope.patch | 152 + ...generalize-cdt-fault-length-function.patch | 62 + ...efactor-qca808x-cable-test-get-statu.patch | 118 + ...dd-support-for-cdt-cross-short-test-.patch | 182 + ...at803x-make-read_status-more-generic.patch | 62 + ...y-at803x-add-LED-support-for-qca808x.patch | 408 ++ ...03x-PHY-driver-to-dedicated-director.patch | 5598 +++++++++++++++++ ...ate-and-move-functions-to-shared-lib.patch | 243 + ...eatch-qca83xx-PHY-driver-from-at803x.patch | 638 ++ ...e-additional-functions-to-shared-lib.patch | 1014 +++ ...etach-qca808x-PHY-driver-from-at803x.patch | 1936 ++++++ ...s-add-driver-for-MediaTek-SGMII-PCS.patch} | 0 ...r-type-u8-in-phy_package_shared-stru.patch | 28 + ...HY-package-API-to-support-multiple-g.patch | 341 + ...ure-__phy_write-read_mmd-to-helper-a.patch | 116 + ...pport-for-PHY-package-MMD-read-write.patch | 196 + ....2-net-fman-memac-Add-serdes-support.patch | 103 + ...2-net-fman-memac-Use-lynx-pcs-driver.patch | 384 ++ ...-03-v6.2-net-dpaa-Convert-to-phylink.patch | 2451 ++++++++ ...ide-phylink_validate_mask_caps-helpe.patch | 93 + ...valid-state-argument-to-phylink_vali.patch | 39 + ...dd-phylink_get_link_timer_ns-helper.patch} | 6 +- ...cit-phylink_generic_validate-referen.patch | 250 + ..._bus_find_fwnode-take-a-const-fwnode.patch | 48 + ...-t-print-an_enabled-in-pcs_get_state.patch | 31 + ...e-Autoneg-bit-rather-than-an_enabled.patch | 32 + ...ort-validated-pause-and-autoneg-in-f.patch | 64 + ...2-v6.4-net-phylink-remove-an_enabled.patch | 177 + ...et-phylink-constify-fwnode-arguments.patch | 88 + ...-fwnode_get_phy_node-fwnode-argument.patch | 38 + ...ylink-fix-ksettings_set-ethtool-call.patch | 44 + ...-support-for-setting-signalling-rate.patch | 149 + ...hy-add-helpers-for-comparing-phy-IDs.patch | 147 + ...ire-supported_interfaces-to-be-fille.patch | 71 + ...ve-duplicated-linkmode-pause-resolut.patch | 64 + ...function-to-resolve-clause-73-negoti.patch | 76 + ...ide-phylink_pcs_config-and-phylink_p.patch | 100 + ...ually-fix-ksettings_set-ethtool-call.patch | 55 + ...net-phylink-add-PCS-negotiation-mode.patch | 324 + ...ert-phylink_mii_c22_pcs_config-to-ne.patch | 45 + ...-neg_mode-into-phylink_mii_c22_pcs_c.patch | 187 + ...xi-update-PCS-driver-to-use-neg_mode.patch | 101 + ...e-Autoneg-bit-rather-than-an_enabled.patch | 55 + ...s-fix-incorrect-number-of-interfaces.patch | 30 + ...808x-fix-logic-error-in-LED-brightne.patch | 36 + ...808x-default-to-LED-active-High-if-n.patch | 41 + ...ort-for-scanning-PHY-in-PHY-packages.patch | 211 + ...-add-devm-of_phy_package_join-helper.patch | 185 + ...move-more-function-to-shared-library.patch | 583 ++ ...whether-link-has-changed-in-c37_read.patch | 100 + ...m-add-support-for-QCA807x-PHY-Family.patch | 668 ++ ...e-common-qca808x-LED-define-to-share.patch | 179 + ...eneralize-some-qca808x-LED-functions.patch | 172 + ...07x-add-support-for-configurable-LED.patch | 326 + ...move-interface-mode-check-to-.config.patch | 51 + ...03x-fix-kernel-panic-with-at8031_pro.patch | 45 + ...-add-support-for-clock-frequency-pro.patch | 205 + ...-drop-wrong-endianness-conversion-fo.patch | 92 + ..._eth_soc-enable-flow-offloading-supp.patch | 2 +- ..._eth_soc-remove-cpu_relax-in-mtk_pen.patch | 4 +- ..._eth_soc-introduce-mtk_hw_reset-util.patch | 4 +- ..._eth_soc-introduce-mtk_hw_warm_reset.patch | 8 +- ..._eth_soc-align-reset-procedure-to-ve.patch | 10 +- ..._eth_soc-add-dma-checks-to-mtk_hw_re.patch | 8 +- ..._wed-add-reset-reset_complete-callba.patch | 4 +- ..._eth_soc-increase-tx-ring-side-for-Q.patch | 14 +- ..._eth_soc-avoid-port_mg-assignment-on.patch | 4 +- ..._eth_soc-implement-multi-queue-suppo.patch | 58 +- ..._eth_soc-fix-VLAN-rx-hardware-accele.patch | 10 +- ..._eth_soc-disable-hardware-DSA-untagg.patch | 4 +- ..._eth_soc-enable-special-tag-when-any.patch | 6 +- ..._eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch | 4 +- ...t-mtk_eth_soc-add-support-for-MT7981.patch | 4 +- ..._eth_soc-set-MDIO-bus-clock-frequenc.patch | 4 +- ..._eth_soc-switch-to-external-PCS-driv.patch | 10 +- ..._eth_soc-ppe-add-support-for-flow-ac.patch | 10 +- ..._eth_soc-drop-generic-vlan-rx-offloa.patch | 14 +- ...net-phy-bcm54612e-add-suspend-resume.patch | 27 + ..._ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch | 10 +- ..._eth_soc-remove-incorrect-PLL-config.patch | 4 +- ..._eth_soc-remove-mac_pcs_get_state-an.patch | 6 +- ..._eth_soc-add-version-in-mtk_soc_data.patch | 56 +- ..._eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch | 30 +- ..._eth_soc-add-NETSYS_V3-version-suppo.patch | 22 +- ..._eth_soc-add-basic-support-for-MT798.patch | 10 +- ..._eth_soc-enable-page_pool-support-fo.patch | 2 +- ..._eth_soc-enable-nft-hw-flowtable_off.patch | 2 +- ..._eth_soc-support-per-flow-accounting.patch | 2 +- ...tk_eth_soc-add-reset-bits-for-MT7988.patch | 8 +- ..._eth_soc-add-support-for-in-SoC-SRAM.patch | 24 +- ..._eth_soc-support-36-bit-DMA-addressi.patch | 16 +- ...k_eth_soc-fix-uninitialized-variable.patch | 44 + ..._eth_soc-fix-pse_port-configuration-.patch | 33 + ...eth_soc-add-code-for-offloading-flo.patch} | 10 +- ...atek-mtk_ppe-prefer-newly-added-l2-.patch} | 2 +- ...eth_soc-improve-keeping-track-of-of.patch} | 18 +- ...atek-fix-ppe-flow-accounting-for-L2.patch} | 24 +- ..._wed-add-some-more-info-in-wed_txinf.patch | 45 + ..._wed-minor-change-in-wed_-tx-rx-info.patch | 47 + ..._eth_soc-rely-on-mtk_pse_port-defini.patch | 29 + ..._wed-check-update_wo_rx_stats-in-mtk.patch | 26 + ..._wed-do-not-assume-offload-callbacks.patch | 68 + ..._wed-introduce-versioning-utility-ro.patch | 232 + ..._wed-do-not-configure-rx-offload-if-.patch | 234 + ..._wed-rename-mtk_rxbm_desc-in-mtk_wed.patch | 52 + ..._wed-introduce-mtk_wed_buf-structure.patch | 87 + ..._wed-move-mem_region-array-out-of-mt.patch | 88 + ...-mtk_wed-make-memory-region-optional.patch | 71 + ...k_wed-add-mtk_wed_soc_data-structure.patch | 217 + ..._wed-introduce-WED-support-for-MT798.patch | 1280 ++++ ..._wed-refactor-mtk_wed_check_wfdma_rx.patch | 95 + ..._wed-introduce-partial-AMSDU-offload.patch | 465 ++ ..._wed-introduce-hw_rro-support-for-MT.patch | 483 ++ ..._wed-debugfs-move-wed_v2-specific-re.patch | 78 + ..._wed-debugfs-add-WED-3.0-debugfs-ent.patch | 432 ++ ...et-mtk_wed-add-wed-3.0-reset-support.patch | 587 ++ ...antia-add-AQR111-and-AQR111B0-PHY-ID.patch | 102 + ...9-net-phy-aquantia-add-AQR113-PHY-ID.patch | 60 + ...9-net-phy-aquantia-add-AQR813-PHY-ID.patch | 59 + ...et-dsa-introduce-dsa_phylink_to_port.patch | 99 + ...A-switch-drivers-to-provide-their-ow.patch | 117 + ...t-introduce-napi_is_scheduled-helper.patch | 96 + ...et-stmmac-improve-TX-timer-arm-logic.patch | 77 + ...c-move-TX-timer-arm-after-DMA-enable.patch | 96 + ...ac-increase-TX-coalesce-timer-to-5ms.patch | 38 + ...d-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch | 63 + ...a8k-convert-to-regmap-read-write-API.patch | 261 + ...-enable-use_single_write-for-qca8xxx.patch | 78 + ...ke-learning-configurable-and-keep-of.patch | 146 + ...mit-user-ports-access-to-the-first-C.patch | 53 + ...ve-qca8xxx-hol-fixup-to-separate-fun.patch | 111 + ...e-dsa_for_each-macro-instead-of-for-.patch | 158 + ...x-regmap-bulk-read-write-methods-on-.patch | 61 + ...a-mt7530-remove-redundant-assignment.patch | 32 + ...-dsa-mt7530-use-external-PCS-driver.patch} | 71 +- ...ke-some-noise-if-register-read-fail.patch} | 4 +- ...-mt7530-refactor-SGMII-PCS-creation.patch} | 8 +- ...t7530-use-unlocked-regmap-accessors.patch} | 10 +- ...e-regmap-to-access-switch-register-.patch} | 14 +- ...ve-SGMII-PCS-creation-to-mt7530_pro.patch} | 10 +- ...-dsa-mt7530-introduce-mutex-helpers.patch} | 4 +- ...ve-p5_intf_modes-function-to-mt7530.patch} | 4 +- ...troduce-mt7530_probe_common-helper-.patch} | 10 +- ...troduce-mt7530_remove_common-helper.patch} | 8 +- ...7530-introduce-separate-MDIO-driver.patch} | 30 +- ...ip-locking-if-MDIO-bus-isn-t-presen.patch} | 4 +- ...troduce-driver-for-MT7988-built-in-.patch} | 12 +- ...dsa-mt7530-fix-support-for-MT7531BE.patch} | 6 +- ...30-update-PCS-driver-to-use-neg_mode.patch | 35 + ...onvert-to-platform-remove-callback-r.patch | 58 + ...3x-remove-mt753x_phylink_pcs_link_up.patch | 51 + ...eplace-deprecated-strncpy-with-ethto.patch | 40 + ...upport-OF-based-registration-of-swit.patch | 116 + ...-fix-10M-100M-speed-on-MT7988-switch.patch | 34 + ...lways-trap-frames-to-active-CPU-port.patch | 125 + ...se-p5_interface_select-as-data-type-.patch | 45 + ...tore-port-5-SGMII-capability-of-MT75.patch | 227 + ...mprove-comments-regarding-switch-por.patch | 133 + ...mprove-code-path-for-setting-up-port.patch | 95 + ...o-not-set-priv-p5_interface-on-mt753.patch | 42 + ...o-not-run-mt7530_setup_port5-if-port.patch | 62 + ...mpty-default-case-on-mt7530_setup_po.patch | 58 + ...7530-move-XTAL-check-to-mt7530_setup.patch | 53 + ...mt7530-simplify-mt7530_pad_clk_setup.patch | 146 + ...all-port-6-setup-from-mt7530_mac_con.patch | 97 + ...30-remove-pad_setup-function-pointer.patch | 148 + ...-correct-port-capabilities-of-MT7988.patch | 36 + ...o-not-clear-config-supported_interfa.patch | 38 + ...emove-.mac_port_config-for-MT7988-an.patch | 81 + ...et-interrupt-register-only-for-MT753.patch | 31 + ...o-not-use-SW_PHY_RST-to-reset-MT7531.patch | 41 + ...et-rid-of-useless-error-returns-on-p.patch | 217 + ...get-rid-of-priv-info-cpu_port_config.patch | 305 + ...-mt7530-get-rid-of-mt753x_mac_config.patch | 48 + ...ut-initialising-PCS-devices-code-bac.patch | 57 + ...ort-link-settings-ops-and-force-link.patch | 68 + ...-dsa-mt7530-simplify-link-operations.patch | 83 + ...0-provide-own-phylink-MAC-operations.patch | 135 + ...ix-port-mirroring-for-MT7988-SoC-swi.patch | 49 + ...dio-read-PHY-address-of-switch-from-.patch | 238 + ...-dsa-mt7530-simplify-core-operations.patch | 186 + ...isable-EEE-abilities-on-failure-on-M.patch | 88 + ...et-dsa-mt7530-refactor-MT7530_PMCR_P.patch | 200 + ...ename-p5_intf_sel-and-use-only-for-M.patch | 185 + ...ename-mt753x_bpdu_port_fw-enum-to-mt.patch | 169 + ...efactor-MT7530_MFC-and-MT7531_CFC-ad.patch | 201 + ...efactor-MT7530_HWTRAP-and-MT7530_MHW.patch | 257 + ...ove-MT753X_MTRAP-operations-for-MT75.patch | 117 + ...eturn-mt7530_setup_mdio-mt7531_setup.patch | 39 + ...efine-MAC-speed-capabilities-per-swi.patch | 75 + ...530-get-rid-of-function-sanity-check.patch | 33 + ...dsa-mt7530-refactor-MT7530_PMEEECR_P.patch | 71 + ...et-rid-of-mac_port_validate-member-o.patch | 46 + ...se-priv-ds-num_ports-instead-of-MT75.patch | 57 + ...o-not-pass-port-variable-to-mt7531_r.patch | 37 + ...xplain-exposing-MDIO-bus-of-MT7531AE.patch | 33 + ...0-do-not-set-MT7530_P5_DIS-when-PHY-.patch | 45 + ...etect-PHY-muxing-when-PHY-is-defined.patch | 45 + ...or-Motorcomm-yt8521-gigabit-ethernet.patch | 2 +- ...net-phy-add-Motorcomm-YT8531S-phy-id.patch | 2 +- ...or-Motorcomm-yt8531-gigabit-ethernet.patch | 2 +- ...k-add-pcs_enable-pcs_disable-methods.patch | 41 +- ...t-pcs-lynxi-implement-pcs_disable-op.patch | 2 +- ...ive-renaming-when-an-interface-is-up.patch | 136 + ...ix-risk-of-NULL-pointer-deallocation.patch | 30 + ...ansmit-URBs-without-trailing-padding.patch | 35 + ...03-usbnet-ipheth-add-CDC-NCM-support.patch | 326 + ...et-ipheth-update-Kconfig-description.patch | 36 + ...6xxx-fix-marvell-6350-switch-probing.patch | 89 + ...11h-Add-the-Airoha-EN8811H-PHY-drive.patch | 1140 ++++ ...phy-air_en8811h-fix-some-error-codes.patch | 47 + ...a8k-move-qca8k_port_to_phy-to-header.patch | 4 +- ...net-dsa-qca8k-add-LEDs-basic-support.patch | 6 +- ...5-net-phy-Add-a-binding-for-PHY-LEDs.patch | 12 +- ...ce-Call-into-the-PHY-driver-to-set-L.patch | 8 +- ...ce-Call-into-the-PHY-driver-to-set-L.patch | 6 +- ...d-support-for-additional-modes-for-n.patch | 64 + ...x-pass-directly-chip-structure-to-mv.patch | 64 + ...x-use-mv88e6xxx_phy_is_internal-in-m.patch | 31 + ...x-add-field-to-specify-internal-phys.patch | 69 + ...x-fix-88E6393X-family-internal-phys-.patch | 52 + ...x-pass-mv88e6xxx_chip-structure-to-p.patch | 110 + ...xx-enable-support-for-88E6361-switch.patch | 153 + ...ount-to-list.h-as-list_count_nodes-f.patch | 75 + ...Convert-to-devm_platform_ioremap_res.patch | 36 + ...-Use-devm_platform_get_and_ioremap_r.patch | 30 + ...p-Convert-to-devm_platform_ioremap_r.patch | 34 + ...fuse-Convert-to-devm_platform_iorema.patch | 36 + ...fuse-Use-devm_platform_get_and_iorem.patch | 31 + ...m-Use-devm_platform_get_and_ioremap_.patch | 30 + ....6-0007-nvmem-qfprom-do-some-cleanup.patch | 59 + ...se-devm_platform_get_and_ioremap_res.patch | 29 + ...nvmem-add-new-NXP-QorIQ-eFuse-driver.patch | 133 + ...-nvmem-Kconfig-Fix-typo-drive-driver.patch | 37 + ...m-Add-Qualcomm-secure-QFPROM-support.patch | 152 + ...-Replace-zero-length-array-with-DECL.patch | 30 + ...e-all-cells-before-adding-the-nvmem-.patch | 40 + ...n-NULL-when-no-nvmem-layout-is-found.patch | 35 + ...-Do-not-open-code-existing-functions.patch | 29 + ...tify-when-a-new-layout-is-registered.patch | 44 + ...ia-Use-sysfs_emit-instead-of-sprintf.patch | 29 + ...a-Make-set_brightness-more-efficient.patch | 207 + ...a-Support-HW-controlled-mode-via-pri.patch | 202 + ...a-Add-support-for-enabling-disabling.patch | 244 + ...a-Fix-brightness-setting-and-trigger.patch | 167 + ...mem-qfprom-Mark-core-clk-as-optional.patch | 37 + ...it-config-option-to-read-old-syntax-.patch | 330 + ...0003-nvmem-Use-device_get_match_data.patch | 77 + ...4-Revert-nvmem-add-new-config-option.patch | 77 + ...ect-fixed-layouts-to-grab-a-layout-d.patch | 45 + ..._nvram-store-a-copy-of-NVRAM-content.patch | 261 + ...-Add-FUNCTION-defines-for-per-band-W.patch | 34 + ...-Add-LED_FUNCTION_WAN_ONLINE-for-Int.patch | 35 + ...-device-Export-of_device_make_bus_id.patch | 140 + ...mem_layout_get_container-in-another-.patch | 95 + ...Create-a-header-for-internal-sharing.patch | 91 + ...03-nvmem-Simplify-the-add_cells-hook.patch | 79 + ...vmem-Move-and-rename-fixup_cell_info.patch | 169 + ...rk-layouts-to-become-regular-devices.patch | 763 +++ ...vmem-core-Expose-cells-through-sysfs.patch | 240 + ...support-for-STM32MP25-BSEC-to-contro.patch | 65 + ...factor-.add_cells-callback-arguments.patch | 94 + ...mem-drop-nvmem_layout_get_match_data.patch | 72 + ...nvmem-core-add-nvmem_dev_size-helper.patch | 53 + ...-use-nvmem_add_one_cell-nvmem-subsys.patch | 126 + ...-u-boot-env-use-nvmem-device-helpers.patch | 81 + ...vmem-u-boot-env-improve-coding-style.patch | 62 + ...fix-circular-LEDS_CLASS-dependencies.patch | 2 +- ...net-phy-Fix-reading-LED-reg-property.patch | 4 +- ...emove-LEDs-to-ensure-correct-orderin.patch | 8 +- ...ce-Call-into-the-PHY-driver-to-set-L.patch | 6 +- ...tc-rtc7301-Support-byte-addressed-IO.patch | 93 + ...t-phy-amd-Support-the-Altima-AMI101L.patch | 82 + ...ors-from-DT-bindings-to-led_co.patch.patch | 29 + ...igger-netdev-Extend-speeds-up-to-10G.patch | 111 + ...-support-for-PHY-LEDs-polarity-modes.patch | 98 + ...dev-fix-RTNL-handling-to-prevent-pot.patch | 170 + ....4-net-phy-hide-the-PHYLIB_LEDS-knob.patch | 43 + ...dev-Fix-kernel-panic-on-interface-re.patch | 55 + ...ix-order-of-pek-rise-and-fall-events.patch | 80 + ...x-Switch-to-the-sys-off-handler-API.patch} | 0 ...fd-axp20x-Fix-axp288-writable-ranges.patch | 28 + ...xp20x-Add-support-for-AXP15060-PMIC.patch} | 16 +- ...axp20x-Add-support-for-AXP313a-PMIC.patch} | 18 +- ...20x-Add-support-for-AXP313a-variant.patch} | 0 ...gulator-axp20x-Add-AXP15060-support.patch} | 0 ...5-mfd-axp20x-Add-support-for-AXP192.patch} | 14 +- ...v6.8-net-phy-add-possible-interfaces.patch | 60 + ...6.8-net-phylink-use-for_each_set_bit.patch | 46 + ...k-split-out-per-interface-validation.patch | 76 + ...k-pass-PHY-into-phylink_validate_one.patch | 47 + ...-pass-PHY-into-phylink_validate_mask.patch | 58 + ...t-out-PHY-validation-from-phylink_br.patch | 95 + ...the-PHY-s-possible_interfaces-if-pop.patch | 130 + ...808x-add-helper-for-checking-for-1G-.patch | 50 + ...-qca808x-fill-in-possible_interfaces.patch | 44 + lede/target/linux/generic/config-6.1 | 20 +- lede/target/linux/generic/config-6.6 | 667 +- .../files/drivers/mtd/mtdsplit/Kconfig | 13 +- .../files/drivers/mtd/mtdsplit/Makefile | 2 + .../drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c | 16 +- .../files/drivers/mtd/mtdsplit/mtdsplit_fit.c | 20 +- .../drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c | 170 + .../drivers/mtd/mtdsplit/mtdsplit_seil.c | 191 + .../generic/files/drivers/mtd/nand/mtk_bmt.h | 8 +- .../files/drivers/mtd/nand/mtk_bmt_v2.c | 55 +- .../drivers/mtd/parsers/routerbootpart.c | 2 +- .../generic/files/drivers/net/phy/ar8216.c | 21 +- .../generic/files/drivers/net/phy/ar8216.h | 26 +- .../generic/files/drivers/net/phy/ar8327.c | 2 +- .../files/drivers/net/phy/b53/b53_common.c | 24 +- .../files/drivers/net/phy/b53/b53_mdio.c | 38 +- .../files/drivers/net/phy/b53/b53_mmap.c | 4 +- .../files/drivers/net/phy/b53/b53_priv.h | 8 +- .../files/drivers/net/phy/b53/b53_spi.c | 4 +- .../files/drivers/net/phy/b53/b53_srab.c | 4 +- .../generic/files/drivers/net/phy/psb6970.c | 17 +- .../files/drivers/net/phy/rtl8366_smi.c | 39 +- .../files/drivers/net/phy/rtl8366_smi.h | 5 +- .../generic/files/drivers/net/phy/rtl8367.c | 7 +- .../generic/files/drivers/net/phy/rtl8367b.c | 11 +- .../generic/files/drivers/net/phy/swconfig.c | 3 + .../files/drivers/net/phy/swconfig_leds.c | 9 +- .../files/drivers/platform/mikrotik/Kconfig | 7 +- .../files/drivers/platform/mikrotik/Makefile | 1 + .../drivers/platform/mikrotik/rb_hardconfig.c | 37 +- .../drivers/platform/mikrotik/rb_hardconfig.h | 32 + .../drivers/platform/mikrotik/rb_nvmem.c | 230 + .../drivers/platform/mikrotik/rb_softconfig.c | 35 +- .../drivers/platform/mikrotik/routerboot.c | 47 +- .../drivers/platform/mikrotik/routerboot.h | 8 +- ...-abort-configuration-on-unset-symbol.patch | 41 + .../generic/hack-6.1/205-kconfig-exit.patch | 20 - .../hack-6.1/212-tools_portability.patch | 285 +- .../linux/generic/hack-6.1/251-kconfig.patch | 53 - ...rans-call-add-disks-after-mtd-device.patch | 2 +- ...upport-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch | 2 +- .../700-swconfig_switch_drivers.patch | 4 +- ...-dsa-mv88e6xxx-disable-ATU-violation.patch | 2 +- .../hack-6.1/720-net-phy-add-aqr-phys.patch | 120 - .../721-net-add-packet-mangeling.patch | 14 +- ...hy-aquantia-enable-AQR112-and-AQR412.patch | 20 +- ...aquantia-fix-system-side-protocol-mi.patch | 8 +- ...y-aquantia-Add-AQR113-driver-support.patch | 43 - ...ntia-add-PHY_IDs-for-AQR112-variants.patch | 20 +- ...mtk-lynxi-workaround-2500BaseX-no-an.patch | 24 +- .../765-mxl-gpy-control-LED-reg-from-DT.patch | 10 +- .../781-usb-net-rndis-support-asr.patch | 13 + .../790-SFP-GE-T-ignore-TX_FAULT.patch | 2 +- .../800-GPIO-add-named-gpio-exports.patch | 38 +- .../hack-6.1/901-debloat_sock_diag.patch | 10 + .../generic/hack-6.1/902-debloat_proc.patch | 11 + ...m350.patch => 931-usb-net-for-fm350.patch} | 0 ...t-send-arp-replies-if-src-and-target.patch | 37 + .../pending-6.1/307-mips_highmem_offset.patch | 19 - ...el-fix-detect_memory_region-function.patch | 74 + ...er-NVMEM-devices-for-partitions-with.patch | 48 + ...support-for-minor-aligned-partitions.patch | 6 +- ...30-mtd-add-myloader-partition-parser.patch | 2 +- ...dings-mtd-add-basic-bindings-for-UBI.patch | 121 + ...ubi-volume-allow-UBI-volumes-to-prov.patch | 48 + ...e-notifier-to-create-ubiblock-from-p.patch | 225 + ...0-04-mtd-ubi-attach-from-device-tree.patch | 264 + ...e-pre-removal-notification-for-UBI-v.patch | 226 + ...6-mtd-ubi-populate-ubi-volume-fwnode.patch | 65 + ...provide-NVMEM-layer-over-UBI-volumes.patch | 246 + ...k-add-basic-bindings-for-block-devic.patch | 120 + ...-09-block-partitions-populate-fwnode.patch | 77 + ...ck-add-new-genhd-flag-GENHD_FL_NVMEM.patch | 29 + ...50-11-block-implement-NVMEM-provider.patch | 235 + ...-mmc-mmc-card-add-block-device-nodes.patch | 74 + ...0-13-mmc-core-set-card-fwnode_handle.patch | 23 + ...mmc-block-set-fwnode-of-disk-devices.patch | 39 + .../450-15-mmc-block-set-GENHD_FL_NVMEM.patch | 22 + .../479-mtd-spi-nor-add-xtx-xt25f128b.patch | 2 +- ...mtd-device-named-ubi-or-data-on-boot.patch | 17 +- ...to-create-ubiblock-device-for-rootfs.patch | 76 +- ...ROOT_DEV-to-ubiblock-rootfs-if-unset.patch | 4 +- .../494-mtd-ubi-add-EOF-marker-support.patch | 2 +- ...add-uImage.FIT-subimage-block-driver.patch | 7 +- .../530-jffs2_make_lzma_available.patch | 2 +- ...les-ignore-EOPNOTSUPP-on-flowtable-d.patch | 29 + ...net-mtk_eth_soc-enable-threaded-NAPI.patch | 2 +- ...detach-callback-to-struct-phy_driver.patch | 4 +- ...-qca8k-implement-lag_fdb_add-del-ops.patch | 86 + ...a8k-enable-flooding-to-both-CPU-port.patch | 37 + ...k-add-support-for-port_change_master.patch | 158 + ...enable-assisted-learning-on-CPU-port.patch | 57 + ...pq8074-add-clock-frequency-to-MDIO-n.patch | 25 + ...support-switching-between-SGMII-and-.patch | 16 + ...e-all-MACs-are-powered-down-before-r.patch | 28 - ...sable-SGMII-in-band-AN-for-2-5G-PHYs.patch | 1 + ...-phy-realtek-introduce-rtl822x_probe.patch | 24 +- ...tek-detect-early-version-of-RTL8221B.patch | 14 +- ...0211_ptr-even-with-no-CFG82111-suppo.patch | 2 +- ..._eth_soc-fix-remaining-throughput-re.patch | 4 +- ..._eth_soc-ppe-fix-L2-offloading-with-.patch | 2 +- ..._eth_soc-add-paths-and-SerDes-modes-.patch | 1294 +--- ..._eth_soc-set-coherent-mask-to-get-PP.patch | 46 + ...y-mediatek-xfi-tphy-add-new-bindings.patch | 136 + ...hy-add-driver-for-MediaTek-XFI-T-PHY.patch | 498 ++ ...lynxi-add-platform-driver-for-MT7988.patch | 371 ++ ...pcs-add-bindings-for-MediaTek-USXGMI.patch | 81 + ...-add-driver-for-MediaTek-USXGMII-PCS.patch | 547 ++ ...et-phy-motorcomm-Add-missing-include.patch | 22 + ...ealtek-support-interrupt-of-RTL8221B.patch | 16 +- ...11h-reset-netdev-rules-when-LED-is-s.patch | 45 + ...ional-threading-for-backlog-processi.patch | 22 +- ...equest-assisted-learning-on-CPU-port.patch | 2 +- ...gister-OF-node-for-internal-MDIO-bus.patch | 43 - ...env-align-endianness-of-crc32-values.patch | 6 +- ...-support-mac-base-fixed-layout-cells.patch | 124 + ...-nxp-imx7d-pico-add-cpu-supply-nodes.patch | 43 + ...-add-LED_FUNCTION_MOBILE-for-mobile-.patch | 37 + ...-add-LED_FUNCTION_SPEED_-for-link-sp.patch | 37 + ...mtd-device-named-ubi-or-data-on-boot.patch | 10 +- ...ediatek-Allow-gaps-in-MAC-allocation.patch | 33 + .../base-files/lib/upgrade/platform.sh | 14 +- lede/target/linux/mediatek/image/filogic.mk | 16 +- .../041-block-fit-partition-parser.patch | 17 +- ..._wed-rename-mtk_wed_get_memory_regio.patch | 23 +- ..._wed-move-cpuboot-in-a-dedicated-dts.patch | 54 +- ...tk_wed-move-ilm-a-dedicated-dts-node.patch | 87 +- lede/target/linux/x86/Makefile | 2 +- nekobox-android/.github/workflows/ci.yml | 74 - .../buildScript/lib/core/get_source.sh | 25 +- .../buildScript/lib/core/get_source_env.sh | 10 +- nekobox-android/libcore/box.go | 23 +- nekobox-android/libcore/dns_box.go | 6 +- nekobox-android/libcore/go.mod | 60 +- nekobox-android/libcore/go.sum | 123 +- nekobox-android/libcore/nb4a.go | 7 +- nekobox-android/libcore/platform_box.go | 6 +- ...2ray-cmake.yml => build-nekoray-cmake.yml} | 6 +- nekoray/CMakeLists.txt | 4 + nekoray/db/ConfigBuilder.cpp | 8 +- nekoray/go/cmd/nekobox_core/core_box.go | 16 +- nekoray/go/cmd/nekobox_core/go.mod | 97 +- nekoray/go/cmd/nekobox_core/go.sum | 213 +- nekoray/go/cmd/nekobox_core/grpc_box.go | 14 +- nekoray/go/cmd/nekobox_core/main.go | 7 +- nekoray/go/grpc_server/fulltest.go | 2 +- nekoray/libs/get_source.sh | 24 +- nekoray/libs/get_source_env.sh | 10 +- nekoray/main/NekoGui_DataStore.hpp | 4 +- nekoray/nekoray_version.txt | 2 +- nekoray/ui/dialog_manage_routes.ui | 7 +- nekoray/ui/mainwindow_grpc.cpp | 4 +- openwrt-packages/luci-app-store/API.md | 2 +- openwrt-packages/luci-app-store/Makefile | 2 +- .../luasrc/controller/store.lua | 86 +- .../luci-app-store/root/bin/is-opkg | 3 + .../root/usr/libexec/istore/docker | 114 + openwrt-packages/luci-app-store/swagger.yaml | 164 +- shadowsocks-rust/Cargo.lock | 16 +- .../internet/httpupgrade/httpupgrade_test.go | 2 + .../internet/splithttp/splithttp_test.go | 1 + .../transport/internet/websocket/ws_test.go | 1 + yass/.github/workflows/compiler.yml | 21 +- yass/src/net/content_server.hpp | 1 - yass/src/net/doh_request.cpp | 1 - yass/src/net/dot_request.cpp | 1 - yass/src/net/ssl_server_socket.cpp | 1 - yass/src/net/ssl_socket.cpp | 1 - yass/src/net/stream.hpp | 1 - yass/src/ss_test.cpp | 19 +- .../include/asio/detail/impl/win_mutex.ipp | 6 +- .../asio/detail/impl/win_static_mutex.ipp | 9 +- .../asio/include/asio/detail/win_mutex.hpp | 24 +- .../include/asio/detail/win_static_mutex.hpp | 29 +- yass/third_party/gperftools/cmake/config.h.in | 5 - .../gperftools/src/windows/config.h | 265 - .../nghttp2/cmake/PickyWarningsC.cmake | 12 +- .../nghttp2/cmake/PickyWarningsCXX.cmake | 6 +- youtube-dl/test/test_utils.py | 46 + youtube-dl/youtube_dl/YoutubeDL.py | 17 + youtube-dl/youtube_dl/__init__.py | 4 + youtube-dl/youtube_dl/options.py | 4 + youtube-dl/youtube_dl/utils.py | 173 +- yt-dlp/.github/workflows/build.yml | 4 + yt-dlp/CONTRIBUTING.md | 12 +- yt-dlp/CONTRIBUTORS | 13 + yt-dlp/Changelog.md | 81 + yt-dlp/Collaborators.md | 7 + yt-dlp/README.md | 85 +- yt-dlp/devscripts/changelog_override.json | 11 + yt-dlp/devscripts/cli_to_api.py | 2 + yt-dlp/pyproject.toml | 2 +- yt-dlp/supportedsites.md | 19 +- yt-dlp/test/test_jsinterp.py | 1 + yt-dlp/test/test_utils.py | 31 + yt-dlp/test/test_youtube_signature.py | 4 + yt-dlp/yt_dlp/YoutubeDL.py | 26 +- yt-dlp/yt_dlp/__init__.py | 8 + yt-dlp/yt_dlp/cookies.py | 6 +- yt-dlp/yt_dlp/downloader/external.py | 2 +- yt-dlp/yt_dlp/extractor/arcpublishing.py | 3 +- yt-dlp/yt_dlp/extractor/arkena.py | 4 +- yt-dlp/yt_dlp/extractor/bandcamp.py | 2 +- yt-dlp/yt_dlp/extractor/bilibili.py | 364 +- yt-dlp/yt_dlp/extractor/brightcove.py | 8 +- yt-dlp/yt_dlp/extractor/cbsnews.py | 1 - yt-dlp/yt_dlp/extractor/dailymail.py | 3 +- yt-dlp/yt_dlp/extractor/eitb.py | 12 +- yt-dlp/yt_dlp/extractor/eporner.py | 3 - yt-dlp/yt_dlp/extractor/go.py | 3 +- yt-dlp/yt_dlp/extractor/hbo.py | 3 +- yt-dlp/yt_dlp/extractor/hketv.py | 3 - yt-dlp/yt_dlp/extractor/instagram.py | 2 +- yt-dlp/yt_dlp/extractor/iwara.py | 1 - yt-dlp/yt_dlp/extractor/nbc.py | 5 +- yt-dlp/yt_dlp/extractor/nhl.py | 3 +- yt-dlp/yt_dlp/extractor/patreon.py | 3 +- yt-dlp/yt_dlp/extractor/peloton.py | 6 +- yt-dlp/yt_dlp/extractor/performgroup.py | 7 +- yt-dlp/yt_dlp/extractor/pr0gramm.py | 2 +- yt-dlp/yt_dlp/extractor/prosiebensat1.py | 5 +- yt-dlp/yt_dlp/extractor/tubetugraz.py | 10 +- yt-dlp/yt_dlp/extractor/twitter.py | 3 +- yt-dlp/yt_dlp/extractor/viewlift.py | 3 +- yt-dlp/yt_dlp/extractor/vimeo.py | 34 +- yt-dlp/yt_dlp/extractor/weibo.py | 1 + yt-dlp/yt_dlp/extractor/wsj.py | 3 +- yt-dlp/yt_dlp/extractor/yahoo.py | 8 +- yt-dlp/yt_dlp/extractor/yandexdisk.py | 6 +- yt-dlp/yt_dlp/extractor/youtube.py | 2 +- yt-dlp/yt_dlp/networking/_websockets.py | 2 +- yt-dlp/yt_dlp/options.py | 8 +- yt-dlp/yt_dlp/postprocessor/ffmpeg.py | 3 +- yt-dlp/yt_dlp/utils/_utils.py | 114 +- yt-dlp/yt_dlp/version.py | 6 +- 630 files changed, 55392 insertions(+), 5173 deletions(-) create mode 100644 echo/internal/web/templates/rule_list.html delete mode 100644 lede/package/system/fstools/patches/0001-fstools-support-extroot-for-non-MTD-rootfs_data.patch create mode 100644 lede/target/linux/generic/backport-6.1/301-v6.9-kernel.h-removed-REPEAT_BYTE-from-kernel.h.patch create mode 100644 lede/target/linux/generic/backport-6.1/302-v6.9-kernel.h-Move-upper_-_bits-and-lower_-_bits-to-wordp.patch create mode 100644 lede/target/linux/generic/backport-6.1/400-v6.9-mtd-rawnand-brcmnand-Support-write-protection-settin.patch create mode 100644 lede/target/linux/generic/backport-6.1/410-v6.2-mtd-spi-nor-add-generic-flash-driver.patch rename lede/target/linux/generic/{pending-6.1/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch => backport-6.1/412-v6.3-01-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch} (74%) rename lede/target/linux/generic/{pending-6.1/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch => backport-6.1/412-v6.3-02-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch} (74%) create mode 100644 lede/target/linux/generic/backport-6.1/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch create mode 100644 lede/target/linux/generic/backport-6.1/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch rename lede/target/linux/generic/backport-6.1/{424-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch => 426-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch} (100%) create mode 100644 lede/target/linux/generic/backport-6.1/702-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch create mode 100644 lede/target/linux/generic/backport-6.1/702-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch create mode 100644 lede/target/linux/generic/backport-6.1/702-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch create mode 100644 lede/target/linux/generic/backport-6.1/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch create mode 100644 lede/target/linux/generic/backport-6.1/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch create mode 100644 lede/target/linux/generic/backport-6.1/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch create mode 100644 lede/target/linux/generic/backport-6.1/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch create mode 100644 lede/target/linux/generic/backport-6.1/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch create mode 100644 lede/target/linux/generic/backport-6.1/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch create mode 100644 lede/target/linux/generic/backport-6.1/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch create mode 100644 lede/target/linux/generic/backport-6.1/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch create mode 100644 lede/target/linux/generic/backport-6.1/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch create mode 100644 lede/target/linux/generic/backport-6.1/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch create mode 100644 lede/target/linux/generic/backport-6.1/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch create mode 100644 lede/target/linux/generic/backport-6.1/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch create mode 100644 lede/target/linux/generic/backport-6.1/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch create mode 100644 lede/target/linux/generic/backport-6.1/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch create mode 100644 lede/target/linux/generic/backport-6.1/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch create mode 100644 lede/target/linux/generic/backport-6.1/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch create mode 100644 lede/target/linux/generic/backport-6.1/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch create mode 100644 lede/target/linux/generic/backport-6.1/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch create mode 100644 lede/target/linux/generic/backport-6.1/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch create mode 100644 lede/target/linux/generic/backport-6.1/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch create mode 100644 lede/target/linux/generic/backport-6.1/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch create mode 100644 lede/target/linux/generic/backport-6.1/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch create mode 100644 lede/target/linux/generic/backport-6.1/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch create mode 100644 lede/target/linux/generic/backport-6.1/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch create mode 100644 lede/target/linux/generic/backport-6.1/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch create mode 100644 lede/target/linux/generic/backport-6.1/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch create mode 100644 lede/target/linux/generic/backport-6.1/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch create mode 100644 lede/target/linux/generic/backport-6.1/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch create mode 100644 lede/target/linux/generic/backport-6.1/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch create mode 100644 lede/target/linux/generic/backport-6.1/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch create mode 100644 lede/target/linux/generic/backport-6.1/712-v6.9-net-phy-at803x-add-LED-support-for-qca808x.patch create mode 100644 lede/target/linux/generic/backport-6.1/713-v6.9-01-net-phy-move-at803x-PHY-driver-to-dedicated-director.patch create mode 100644 lede/target/linux/generic/backport-6.1/713-v6.9-02-net-phy-qcom-create-and-move-functions-to-shared-lib.patch create mode 100644 lede/target/linux/generic/backport-6.1/713-v6.9-03-net-phy-qcom-deatch-qca83xx-PHY-driver-from-at803x.patch create mode 100644 lede/target/linux/generic/backport-6.1/713-v6.9-04-net-phy-qcom-move-additional-functions-to-shared-lib.patch create mode 100644 lede/target/linux/generic/backport-6.1/713-v6.9-05-net-phy-qcom-detach-qca808x-PHY-driver-from-at803x.patch rename lede/target/linux/generic/backport-6.1/{723-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch => 714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch} (100%) create mode 100644 lede/target/linux/generic/backport-6.1/714-v6.8-01-net-phy-make-addr-type-u8-in-phy_package_shared-stru.patch create mode 100644 lede/target/linux/generic/backport-6.1/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch create mode 100644 lede/target/linux/generic/backport-6.1/714-v6.8-03-net-phy-restructure-__phy_write-read_mmd-to-helper-a.patch create mode 100644 lede/target/linux/generic/backport-6.1/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-01-v6.2-net-fman-memac-Add-serdes-support.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-03-v6.2-net-dpaa-Convert-to-phylink.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch rename lede/target/linux/generic/backport-6.1/{700-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch => 715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch} (87%) create mode 100644 lede/target/linux/generic/backport-6.1/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-12-v6.4-net-phylink-remove-an_enabled.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-v6.9-01-net-phy-qcom-qca808x-fix-logic-error-in-LED-brightne.patch create mode 100644 lede/target/linux/generic/backport-6.1/715-v6.9-02-net-phy-qcom-qca808x-default-to-LED-active-High-if-n.patch create mode 100644 lede/target/linux/generic/backport-6.1/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch create mode 100644 lede/target/linux/generic/backport-6.1/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch create mode 100644 lede/target/linux/generic/backport-6.1/716-v6.9-04-net-phy-qcom-move-more-function-to-shared-library.patch create mode 100644 lede/target/linux/generic/backport-6.1/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch create mode 100644 lede/target/linux/generic/backport-6.1/716-v6.9-07-net-phy-qcom-add-support-for-QCA807x-PHY-Family.patch create mode 100644 lede/target/linux/generic/backport-6.1/716-v6.9-08-net-phy-qcom-move-common-qca808x-LED-define-to-share.patch create mode 100644 lede/target/linux/generic/backport-6.1/716-v6.9-09-net-phy-qcom-generalize-some-qca808x-LED-functions.patch create mode 100644 lede/target/linux/generic/backport-6.1/716-v6.9-10-net-phy-qca807x-add-support-for-configurable-LED.patch create mode 100644 lede/target/linux/generic/backport-6.1/717-v6.9-net-phy-qca807x-move-interface-mode-check-to-.config.patch create mode 100644 lede/target/linux/generic/backport-6.1/718-v6.9-net-phy-qcom-at803x-fix-kernel-panic-with-at8031_pro.patch create mode 100644 lede/target/linux/generic/backport-6.1/720-v6.9-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch create mode 100644 lede/target/linux/generic/backport-6.1/721-v6.7-net-phy-aquantia-drop-wrong-endianness-conversion-fo.patch create mode 100644 lede/target/linux/generic/backport-6.1/734-v6.8-net-phy-bcm54612e-add-suspend-resume.patch create mode 100644 lede/target/linux/generic/backport-6.1/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch create mode 100644 lede/target/linux/generic/backport-6.1/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch rename lede/target/linux/generic/{pending-6.1/736-01-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch => backport-6.1/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch} (96%) rename lede/target/linux/generic/{pending-6.1/736-02-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch => backport-6.1/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch} (94%) rename lede/target/linux/generic/{pending-6.1/736-03-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch => backport-6.1/751-03-v6.4-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch} (94%) rename lede/target/linux/generic/{pending-6.1/736-04-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch => backport-6.1/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch} (93%) create mode 100644 lede/target/linux/generic/backport-6.1/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-03-v6.6-net-ethernet-mtk_eth_soc-rely-on-mtk_pse_port-defini.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-04-v6.6-net-ethernet-mtk_wed-check-update_wo_rx_stats-in-mtk.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-05-v6.7-net-ethernet-mtk_wed-do-not-assume-offload-callbacks.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-06-v6.7-net-ethernet-mtk_wed-introduce-versioning-utility-ro.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-07-v6.7-net-ethernet-mtk_wed-do-not-configure-rx-offload-if-.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-09-v6.7-net-ethernet-mtk_wed-introduce-mtk_wed_buf-structure.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-10-v6.7-net-ethernet-mtk_wed-move-mem_region-array-out-of-mt.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-11-v6.7-net-ethernet-mtk_wed-make-memory-region-optional.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-13-v6.7-net-ethernet-mtk_wed-add-mtk_wed_soc_data-structure.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-14-v6.7-net-ethernet-mtk_wed-introduce-WED-support-for-MT798.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-15-v6.7-net-ethernet-mtk_wed-refactor-mtk_wed_check_wfdma_rx.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-16-v6.7-net-ethernet-mtk_wed-introduce-partial-AMSDU-offload.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-17-v6.7-net-ethernet-mtk_wed-introduce-hw_rro-support-for-MT.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-18-v6.7-net-ethernet-mtk_wed-debugfs-move-wed_v2-specific-re.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-19-v6.7-net-ethernet-mtk_wed-debugfs-add-WED-3.0-debugfs-ent.patch create mode 100644 lede/target/linux/generic/backport-6.1/752-20-v6.7-net-ethernet-mtk_wed-add-wed-3.0-reset-support.patch create mode 100644 lede/target/linux/generic/backport-6.1/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch create mode 100644 lede/target/linux/generic/backport-6.1/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch create mode 100644 lede/target/linux/generic/backport-6.1/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch create mode 100644 lede/target/linux/generic/backport-6.1/765-v6.10-net-dsa-introduce-dsa_phylink_to_port.patch create mode 100644 lede/target/linux/generic/backport-6.1/766-v6.10-net-dsa-allow-DSA-switch-drivers-to-provide-their-ow.patch create mode 100644 lede/target/linux/generic/backport-6.1/770-net-introduce-napi_is_scheduled-helper.patch create mode 100644 lede/target/linux/generic/backport-6.1/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch create mode 100644 lede/target/linux/generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch create mode 100644 lede/target/linux/generic/backport-6.1/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch create mode 100644 lede/target/linux/generic/backport-6.1/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch create mode 100644 lede/target/linux/generic/backport-6.1/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch create mode 100644 lede/target/linux/generic/backport-6.1/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch create mode 100644 lede/target/linux/generic/backport-6.1/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch create mode 100644 lede/target/linux/generic/backport-6.1/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch create mode 100644 lede/target/linux/generic/backport-6.1/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch create mode 100644 lede/target/linux/generic/backport-6.1/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch create mode 100644 lede/target/linux/generic/backport-6.1/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-01-v6.2-net-dsa-mt7530-remove-redundant-assignment.patch rename lede/target/linux/generic/backport-6.1/{788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch => 790-02-v6.4-net-dsa-mt7530-use-external-PCS-driver.patch} (84%) rename lede/target/linux/generic/backport-6.1/{790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch => 790-03-v6.4-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch} (88%) rename lede/target/linux/generic/backport-6.1/{790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch => 790-04-v6.4-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch} (92%) rename lede/target/linux/generic/backport-6.1/{790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch => 790-05-v6.4-net-dsa-mt7530-use-unlocked-regmap-accessors.patch} (86%) rename lede/target/linux/generic/backport-6.1/{790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch => 790-06-v6.4-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch} (92%) rename lede/target/linux/generic/backport-6.1/{790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch => 790-07-v6.4-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch} (79%) rename lede/target/linux/generic/backport-6.1/{790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch => 790-08-v6.4-net-dsa-mt7530-introduce-mutex-helpers.patch} (98%) rename lede/target/linux/generic/backport-6.1/{790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch => 790-09-v6.4-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch} (94%) rename lede/target/linux/generic/backport-6.1/{790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch => 790-10-v6.4-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch} (93%) rename lede/target/linux/generic/backport-6.1/{790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch => 790-11-v6.4-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch} (83%) rename lede/target/linux/generic/backport-6.1/{790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch => 790-12-v6.4-net-dsa-mt7530-introduce-separate-MDIO-driver.patch} (95%) rename lede/target/linux/generic/backport-6.1/{790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch => 790-13-v6.4-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch} (91%) rename lede/target/linux/generic/backport-6.1/{790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch => 790-14-v6.4-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch} (97%) rename lede/target/linux/generic/backport-6.1/{790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch => 790-15-v6.4-net-dsa-mt7530-fix-support-for-MT7531BE.patch} (95%) create mode 100644 lede/target/linux/generic/backport-6.1/790-17-v6.5-net-dsa-mt7530-update-PCS-driver-to-use-neg_mode.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-18-v6.7-net-dsa-mt7530-Convert-to-platform-remove-callback-r.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-19-v6.7-net-dsa-mt753x-remove-mt753x_phylink_pcs_link_up.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-20-v6.7-net-dsa-mt7530-replace-deprecated-strncpy-with-ethto.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-21-v6.9-net-dsa-mt7530-support-OF-based-registration-of-swit.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-22-v6.8-net-dsa-mt7530-fix-10M-100M-speed-on-MT7988-switch.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-23-v6.9-net-dsa-mt7530-always-trap-frames-to-active-CPU-port.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-24-v6.9-net-dsa-mt7530-use-p5_interface_select-as-data-type-.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-25-v6.9-net-dsa-mt7530-store-port-5-SGMII-capability-of-MT75.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-26-v6.9-net-dsa-mt7530-improve-comments-regarding-switch-por.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-27-v6.9-net-dsa-mt7530-improve-code-path-for-setting-up-port.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-28-v6.9-net-dsa-mt7530-do-not-set-priv-p5_interface-on-mt753.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-29-v6.9-net-dsa-mt7530-do-not-run-mt7530_setup_port5-if-port.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-30-v6.9-net-dsa-mt7530-empty-default-case-on-mt7530_setup_po.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-31-v6.9-net-dsa-mt7530-move-XTAL-check-to-mt7530_setup.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-32-v6.9-net-dsa-mt7530-simplify-mt7530_pad_clk_setup.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-33-v6.9-net-dsa-mt7530-call-port-6-setup-from-mt7530_mac_con.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-34-v6.9-net-dsa-mt7530-remove-pad_setup-function-pointer.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-35-v6.9-net-dsa-mt7530-correct-port-capabilities-of-MT7988.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-36-v6.9-net-dsa-mt7530-do-not-clear-config-supported_interfa.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-37-v6.9-net-dsa-mt7530-remove-.mac_port_config-for-MT7988-an.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-38-v6.9-net-dsa-mt7530-set-interrupt-register-only-for-MT753.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-39-v6.9-net-dsa-mt7530-do-not-use-SW_PHY_RST-to-reset-MT7531.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-40-v6.9-net-dsa-mt7530-get-rid-of-useless-error-returns-on-p.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-41-v6.9-net-dsa-mt7530-get-rid-of-priv-info-cpu_port_config.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-42-v6.9-net-dsa-mt7530-get-rid-of-mt753x_mac_config.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-43-v6.9-net-dsa-mt7530-put-initialising-PCS-devices-code-bac.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-44-v6.9-net-dsa-mt7530-sort-link-settings-ops-and-force-link.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-45-v6.9-net-dsa-mt7530-simplify-link-operations.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-49-v6.10-net-dsa-mt7530-provide-own-phylink-MAC-operations.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-51-v6.10-net-dsa-mt7530-fix-port-mirroring-for-MT7988-SoC-swi.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-52-v6.10-net-dsa-mt7530-mdio-read-PHY-address-of-switch-from-.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-53-v6.10-net-dsa-mt7530-simplify-core-operations.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-54-v6.10-net-dsa-mt7530-disable-EEE-abilities-on-failure-on-M.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-55-v6.10-net-dsa-mt7530-refactor-MT7530_PMCR_P.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-56-v6.10-net-dsa-mt7530-rename-p5_intf_sel-and-use-only-for-M.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-57-v6.10-net-dsa-mt7530-rename-mt753x_bpdu_port_fw-enum-to-mt.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-58-v6.10-net-dsa-mt7530-refactor-MT7530_MFC-and-MT7531_CFC-ad.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-59-v6.10-net-dsa-mt7530-refactor-MT7530_HWTRAP-and-MT7530_MHW.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-60-v6.10-net-dsa-mt7530-move-MT753X_MTRAP-operations-for-MT75.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-61-v6.10-net-dsa-mt7530-return-mt7530_setup_mdio-mt7531_setup.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-62-v6.10-net-dsa-mt7530-define-MAC-speed-capabilities-per-swi.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-63-v6.10-net-dsa-mt7530-get-rid-of-function-sanity-check.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-64-v6.10-net-dsa-mt7530-refactor-MT7530_PMEEECR_P.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-65-v6.10-net-dsa-mt7530-get-rid-of-mac_port_validate-member-o.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-66-v6.10-net-dsa-mt7530-use-priv-ds-num_ports-instead-of-MT75.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-67-v6.10-net-dsa-mt7530-do-not-pass-port-variable-to-mt7531_r.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-68-v6.10-net-dsa-mt7530-explain-exposing-MDIO-bus-of-MT7531AE.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-69-v6.10-net-dsa-mt7530-do-not-set-MT7530_P5_DIS-when-PHY-.patch create mode 100644 lede/target/linux/generic/backport-6.1/790-70-v6.10-796-net-dsa-mt7530-detect-PHY-muxing-when-PHY-is-defined.patch create mode 100644 lede/target/linux/generic/backport-6.1/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch create mode 100644 lede/target/linux/generic/backport-6.1/796-v6.5-01-usbnet-ipheth-fix-risk-of-NULL-pointer-deallocation.patch create mode 100644 lede/target/linux/generic/backport-6.1/796-v6.5-02-usbnet-ipheth-transmit-URBs-without-trailing-padding.patch create mode 100644 lede/target/linux/generic/backport-6.1/796-v6.5-03-usbnet-ipheth-add-CDC-NCM-support.patch create mode 100644 lede/target/linux/generic/backport-6.1/796-v6.5-04-usbnet-ipheth-update-Kconfig-description.patch create mode 100644 lede/target/linux/generic/backport-6.1/797-6.7-net-dsa-mv88e6xxx-fix-marvell-6350-switch-probing.patch create mode 100644 lede/target/linux/generic/backport-6.1/798-v6.10-net-phy-air_en8811h-Add-the-Airoha-EN8811H-PHY-drive.patch create mode 100644 lede/target/linux/generic/backport-6.1/799-v6.10-net-phy-air_en8811h-fix-some-error-codes.patch create mode 100644 lede/target/linux/generic/backport-6.1/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch create mode 100644 lede/target/linux/generic/backport-6.1/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch create mode 100644 lede/target/linux/generic/backport-6.1/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch create mode 100644 lede/target/linux/generic/backport-6.1/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch create mode 100644 lede/target/linux/generic/backport-6.1/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch create mode 100644 lede/target/linux/generic/backport-6.1/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch create mode 100644 lede/target/linux/generic/backport-6.1/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch create mode 100644 lede/target/linux/generic/backport-6.1/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch create mode 100644 lede/target/linux/generic/backport-6.1/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch create mode 100644 lede/target/linux/generic/backport-6.1/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch create mode 100644 lede/target/linux/generic/backport-6.1/815-v6.7-2-leds-turris-omnia-Make-set_brightness-more-efficient.patch create mode 100644 lede/target/linux/generic/backport-6.1/815-v6.7-3-leds-turris-omnia-Support-HW-controlled-mode-via-pri.patch create mode 100644 lede/target/linux/generic/backport-6.1/815-v6.7-4-leds-turris-omnia-Add-support-for-enabling-disabling.patch create mode 100644 lede/target/linux/generic/backport-6.1/815-v6.7-5-leds-turris-omnia-Fix-brightness-setting-and-trigger.patch create mode 100644 lede/target/linux/generic/backport-6.1/816-v6.7-0001-nvmem-qfprom-Mark-core-clk-as-optional.patch create mode 100644 lede/target/linux/generic/backport-6.1/816-v6.7-0002-nvmem-add-explicit-config-option-to-read-old-syntax-.patch create mode 100644 lede/target/linux/generic/backport-6.1/816-v6.7-0003-nvmem-Use-device_get_match_data.patch create mode 100644 lede/target/linux/generic/backport-6.1/816-v6.7-0004-Revert-nvmem-add-new-config-option.patch create mode 100644 lede/target/linux/generic/backport-6.1/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch create mode 100644 lede/target/linux/generic/backport-6.1/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch create mode 100644 lede/target/linux/generic/backport-6.1/817-v6.9-0001-dt-bindings-leds-Add-FUNCTION-defines-for-per-band-W.patch create mode 100644 lede/target/linux/generic/backport-6.1/817-v6.9-0002-dt-bindings-leds-Add-LED_FUNCTION_WAN_ONLINE-for-Int.patch create mode 100644 lede/target/linux/generic/backport-6.1/818-v6.8-of-device-Export-of_device_make_bus_id.patch create mode 100644 lede/target/linux/generic/backport-6.1/819-v6.8-0001-nvmem-Move-of_nvmem_layout_get_container-in-another-.patch create mode 100644 lede/target/linux/generic/backport-6.1/819-v6.8-0002-nvmem-Create-a-header-for-internal-sharing.patch create mode 100644 lede/target/linux/generic/backport-6.1/819-v6.8-0003-nvmem-Simplify-the-add_cells-hook.patch create mode 100644 lede/target/linux/generic/backport-6.1/819-v6.8-0004-nvmem-Move-and-rename-fixup_cell_info.patch create mode 100644 lede/target/linux/generic/backport-6.1/819-v6.8-0005-nvmem-core-Rework-layouts-to-become-regular-devices.patch create mode 100644 lede/target/linux/generic/backport-6.1/819-v6.8-0006-nvmem-core-Expose-cells-through-sysfs.patch create mode 100644 lede/target/linux/generic/backport-6.1/819-v6.8-0007-nvmem-stm32-add-support-for-STM32MP25-BSEC-to-contro.patch create mode 100644 lede/target/linux/generic/backport-6.1/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch create mode 100644 lede/target/linux/generic/backport-6.1/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch create mode 100644 lede/target/linux/generic/backport-6.1/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch create mode 100644 lede/target/linux/generic/backport-6.1/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch create mode 100644 lede/target/linux/generic/backport-6.1/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch create mode 100644 lede/target/linux/generic/backport-6.1/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch create mode 100644 lede/target/linux/generic/backport-6.1/831-v6.7-rtc-rtc7301-Support-byte-addressed-IO.patch create mode 100644 lede/target/linux/generic/backport-6.1/832-v6.7-net-phy-amd-Support-the-Altima-AMI101L.patch create mode 100644 lede/target/linux/generic/backport-6.1/833-v6.8-leds-core-Add-more-colors-from-DT-bindings-to-led_co.patch.patch create mode 100644 lede/target/linux/generic/backport-6.1/834-v6.8-leds-trigger-netdev-Extend-speeds-up-to-10G.patch create mode 100644 lede/target/linux/generic/backport-6.1/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch create mode 100644 lede/target/linux/generic/backport-6.1/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch create mode 100644 lede/target/linux/generic/backport-6.1/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch create mode 100644 lede/target/linux/generic/backport-6.1/838-v6.9-leds-trigger-netdev-Fix-kernel-panic-on-interface-re.patch create mode 100644 lede/target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Fix-order-of-pek-rise-and-fall-events.patch rename lede/target/linux/generic/backport-6.1/{880-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch => 881-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch} (100%) create mode 100644 lede/target/linux/generic/backport-6.1/882-v6.3-mfd-axp20x-Fix-axp288-writable-ranges.patch rename lede/target/linux/generic/backport-6.1/{881-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch => 883-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch} (95%) rename lede/target/linux/generic/backport-6.1/{882-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch => 884-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch} (93%) rename lede/target/linux/generic/backport-6.1/{883-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch => 885-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch} (100%) rename lede/target/linux/generic/backport-6.1/{884-v6.5-regulator-axp20x-Add-AXP15060-support.patch => 886-v6.5-regulator-axp20x-Add-AXP15060-support.patch} (100%) rename lede/target/linux/generic/backport-6.1/{885-v6.5-mfd-axp20x-Add-support-for-AXP192.patch => 887-v6.5-mfd-axp20x-Add-support-for-AXP192.patch} (96%) create mode 100644 lede/target/linux/generic/backport-6.1/895-01-v6.8-net-phy-add-possible-interfaces.patch create mode 100644 lede/target/linux/generic/backport-6.1/895-02-v6.8-net-phylink-use-for_each_set_bit.patch create mode 100644 lede/target/linux/generic/backport-6.1/895-03-v6.8-net-phylink-split-out-per-interface-validation.patch create mode 100644 lede/target/linux/generic/backport-6.1/895-04-v6.8-net-phylink-pass-PHY-into-phylink_validate_one.patch create mode 100644 lede/target/linux/generic/backport-6.1/895-05-v6.8-net-phylink-pass-PHY-into-phylink_validate_mask.patch create mode 100644 lede/target/linux/generic/backport-6.1/895-06-v6.8-net-phylink-split-out-PHY-validation-from-phylink_br.patch create mode 100644 lede/target/linux/generic/backport-6.1/895-07-v6.8-net-phylink-use-the-PHY-s-possible_interfaces-if-pop.patch create mode 100644 lede/target/linux/generic/backport-6.1/897-01-v6.9-net-phy-qcom-qca808x-add-helper-for-checking-for-1G-.patch create mode 100644 lede/target/linux/generic/backport-6.1/897-02-v6.9-net-phy-qcom-qca808x-fill-in-possible_interfaces.patch create mode 100644 lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c create mode 100644 lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seil.c create mode 100644 lede/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.h create mode 100644 lede/target/linux/generic/files/drivers/platform/mikrotik/rb_nvmem.c create mode 100644 lede/target/linux/generic/hack-6.1/205-kconfig-abort-configuration-on-unset-symbol.patch delete mode 100644 lede/target/linux/generic/hack-6.1/205-kconfig-exit.patch delete mode 100644 lede/target/linux/generic/hack-6.1/720-net-phy-add-aqr-phys.patch delete mode 100644 lede/target/linux/generic/hack-6.1/724-net-phy-aquantia-Add-AQR113-driver-support.patch rename lede/target/linux/generic/hack-6.1/{930-usb-net-for-fm350.patch => 931-usb-net-for-fm350.patch} (100%) create mode 100644 lede/target/linux/generic/pending-6.1/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch delete mode 100644 lede/target/linux/generic/pending-6.1/307-mips_highmem_offset.patch create mode 100644 lede/target/linux/generic/pending-6.1/350-mips-kernel-fix-detect_memory_region-function.patch create mode 100644 lede/target/linux/generic/pending-6.1/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-01-dt-bindings-mtd-add-basic-bindings-for-UBI.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-02-dt-bindings-mtd-ubi-volume-allow-UBI-volumes-to-prov.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-04-mtd-ubi-attach-from-device-tree.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-05-mtd-ubi-introduce-pre-removal-notification-for-UBI-v.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-06-mtd-ubi-populate-ubi-volume-fwnode.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-07-mtd-ubi-provide-NVMEM-layer-over-UBI-volumes.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-08-dt-bindings-block-add-basic-bindings-for-block-devic.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-09-block-partitions-populate-fwnode.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-10-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-11-block-implement-NVMEM-provider.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-12-dt-bindings-mmc-mmc-card-add-block-device-nodes.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-13-mmc-core-set-card-fwnode_handle.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-14-mmc-block-set-fwnode-of-disk-devices.patch create mode 100644 lede/target/linux/generic/pending-6.1/450-15-mmc-block-set-GENHD_FL_NVMEM.patch create mode 100644 lede/target/linux/generic/pending-6.1/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch create mode 100644 lede/target/linux/generic/pending-6.1/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch create mode 100644 lede/target/linux/generic/pending-6.1/711-02-net-dsa-qca8k-enable-flooding-to-both-CPU-port.patch create mode 100644 lede/target/linux/generic/pending-6.1/711-03-net-dsa-qca8k-add-support-for-port_change_master.patch create mode 100644 lede/target/linux/generic/pending-6.1/712-net-dsa-qca8k-enable-assisted-learning-on-CPU-port.patch create mode 100644 lede/target/linux/generic/pending-6.1/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch delete mode 100644 lede/target/linux/generic/pending-6.1/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch create mode 100644 lede/target/linux/generic/pending-6.1/738-net-ethernet-mtk_eth_soc-set-coherent-mask-to-get-PP.patch create mode 100644 lede/target/linux/generic/pending-6.1/739-01-dt-bindings-phy-mediatek-xfi-tphy-add-new-bindings.patch create mode 100644 lede/target/linux/generic/pending-6.1/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch create mode 100644 lede/target/linux/generic/pending-6.1/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch create mode 100644 lede/target/linux/generic/pending-6.1/739-04-dt-bindings-net-pcs-add-bindings-for-MediaTek-USXGMI.patch create mode 100644 lede/target/linux/generic/pending-6.1/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch create mode 100644 lede/target/linux/generic/pending-6.1/740-net-phy-motorcomm-Add-missing-include.patch create mode 100644 lede/target/linux/generic/pending-6.1/742-net-phy-air_en8811h-reset-netdev-rules-when-LED-is-s.patch delete mode 100644 lede/target/linux/generic/pending-6.1/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch create mode 100644 lede/target/linux/generic/pending-6.1/804-nvmem-core-support-mac-base-fixed-layout-cells.patch create mode 100644 lede/target/linux/generic/pending-6.1/870-ARM-dts-nxp-imx7d-pico-add-cpu-supply-nodes.patch create mode 100644 lede/target/linux/generic/pending-6.1/880-01-dt-bindings-leds-add-LED_FUNCTION_MOBILE-for-mobile-.patch create mode 100644 lede/target/linux/generic/pending-6.1/880-02-dt-bindings-leds-add-LED_FUNCTION_SPEED_-for-link-sp.patch create mode 100644 lede/target/linux/generic/pending-6.6/734-net-ethernet-mediatek-Allow-gaps-in-MAC-allocation.patch delete mode 100644 nekobox-android/.github/workflows/ci.yml rename nekoray/.github/workflows/{build-qv2ray-cmake.yml => build-nekoray-cmake.yml} (98%) create mode 100755 openwrt-packages/luci-app-store/root/usr/libexec/istore/docker delete mode 100644 yass/third_party/gperftools/src/windows/config.h mode change 100644 => 100755 yt-dlp/devscripts/cli_to_api.py diff --git a/.github/update.log b/.github/update.log index 9ffd083f42..c6c27a7fcd 100644 --- a/.github/update.log +++ b/.github/update.log @@ -690,3 +690,4 @@ Update On Fri Jun 28 20:30:26 CEST 2024 Update On Sat Jun 29 20:29:36 CEST 2024 Update On Sun Jun 30 20:30:33 CEST 2024 Update On Mon Jul 1 20:30:34 CEST 2024 +Update On Tue Jul 2 20:34:08 CEST 2024 diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index 9e67132eae..975296c5bb 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -5178,9 +5178,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.119" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8eddb61f0697cc3989c5d64b452f5488e2b8a60fd7d5076a3045076ffef8cb0" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "indexmap 2.2.6", "itoa 1.0.11", diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 0c414b4f7f..c8364e1960 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -35,8 +35,8 @@ "react": "18.3.1", "react-dom": "18.3.1", "react-error-boundary": "4.0.13", - "react-fast-marquee": "1.6.4", - "react-hook-form": "7.52.0", + "react-fast-marquee": "1.6.5", + "react-hook-form": "7.52.1", "react-hook-form-mui": "7.0.0", "react-i18next": "14.1.2", "react-markdown": "9.0.1", @@ -53,8 +53,8 @@ "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@types/react-transition-group": "4.4.10", - "@typescript-eslint/eslint-plugin": "7.14.1", - "@typescript-eslint/parser": "7.14.1", + "@typescript-eslint/eslint-plugin": "7.15.0", + "@typescript-eslint/parser": "7.15.0", "@vitejs/plugin-react": "4.3.1", "@vitejs/plugin-react-swc": "3.7.0", "clsx": "2.1.1", diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index 1d4f0f89ec..a58b243162 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "latest": { - "mihomo": "v1.18.5", + "mihomo": "v1.18.6", "mihomo_alpha": "alpha-0e22876", "clash_rs": "v0.1.18", "clash_premium": "2023-09-05-gdcc8d87" @@ -36,5 +36,5 @@ "darwin-x64": "clash-darwin-amd64-n{}.gz" } }, - "updated_at": "2024-06-28T22:20:05.617Z" + "updated_at": "2024-07-01T22:20:09.970Z" } diff --git a/clash-nyanpasu/package.json b/clash-nyanpasu/package.json index 7ee461e859..c4b7821014 100644 --- a/clash-nyanpasu/package.json +++ b/clash-nyanpasu/package.json @@ -107,11 +107,11 @@ "stylelint-scss": "6.3.2", "tailwindcss": "3.4.4", "tsx": "4.16.0", - "typescript": "5.5.2" + "typescript": "5.5.3" }, "packageManager": "pnpm@9.4.0", "engines": { - "node": "22.3.0" + "node": "22.4.0" }, "pnpm": { "overrides": { diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index cdc149864b..95425123eb 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -24,7 +24,7 @@ importers: devDependencies: '@commitlint/cli': specifier: 19.3.0 - version: 19.3.0(@types/node@20.14.9)(typescript@5.5.2) + version: 19.3.0(@types/node@20.14.9)(typescript@5.5.3) '@commitlint/config-conventional': specifier: 19.2.2 version: 19.2.2 @@ -111,25 +111,25 @@ importers: version: 5.3.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) stylelint: specifier: 16.6.1 - version: 16.6.1(typescript@5.5.2) + version: 16.6.1(typescript@5.5.3) stylelint-config-html: specifier: 1.1.0 - version: 1.1.0(postcss-html@1.7.0)(stylelint@16.6.1(typescript@5.5.2)) + version: 1.1.0(postcss-html@1.7.0)(stylelint@16.6.1(typescript@5.5.3)) stylelint-config-recess-order: specifier: 5.0.1 - version: 5.0.1(stylelint@16.6.1(typescript@5.5.2)) + version: 5.0.1(stylelint@16.6.1(typescript@5.5.3)) stylelint-config-standard: specifier: 36.0.1 - version: 36.0.1(stylelint@16.6.1(typescript@5.5.2)) + version: 36.0.1(stylelint@16.6.1(typescript@5.5.3)) stylelint-declaration-block-no-ignored-properties: specifier: 2.8.0 - version: 2.8.0(stylelint@16.6.1(typescript@5.5.2)) + version: 2.8.0(stylelint@16.6.1(typescript@5.5.3)) stylelint-order: specifier: 6.0.4 - version: 6.0.4(stylelint@16.6.1(typescript@5.5.2)) + version: 6.0.4(stylelint@16.6.1(typescript@5.5.3)) stylelint-scss: specifier: 6.3.2 - version: 6.3.2(stylelint@16.6.1(typescript@5.5.2)) + version: 6.3.2(stylelint@16.6.1(typescript@5.5.3)) tailwindcss: specifier: 3.4.4 version: 3.4.4 @@ -137,8 +137,8 @@ importers: specifier: 4.16.0 version: 4.16.0 typescript: - specifier: 5.5.2 - version: 5.5.2 + specifier: 5.5.3 + version: 5.5.3 frontend/interface: dependencies: @@ -243,14 +243,14 @@ importers: specifier: 4.0.13 version: 4.0.13(react@19.0.0-rc-fb9a90fa48-20240614) react-fast-marquee: - specifier: 1.6.4 - version: 1.6.4(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614) + specifier: 1.6.5 + version: 1.6.5(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614) react-hook-form: - specifier: 7.52.0 - version: 7.52.0(react@19.0.0-rc-fb9a90fa48-20240614) + specifier: 7.52.1 + version: 7.52.1(react@19.0.0-rc-fb9a90fa48-20240614) react-hook-form-mui: specifier: 7.0.0 - version: 7.0.0(zwihrdjnuz7uekpqkqd7rvdhli) + version: 7.0.0(hnsbxdphojlfk7ty6r3hqlevge) react-i18next: specifier: 14.1.2 version: 14.1.2(i18next@23.11.5)(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614) @@ -292,11 +292,11 @@ importers: specifier: 4.4.10 version: 4.4.10 '@typescript-eslint/eslint-plugin': - specifier: 7.14.1 - version: 7.14.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2) + specifier: 7.15.0 + version: 7.15.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) '@typescript-eslint/parser': - specifier: 7.14.1 - version: 7.14.1(eslint@8.57.0)(typescript@5.5.2) + specifier: 7.15.0 + version: 7.15.0(eslint@8.57.0)(typescript@5.5.3) '@vitejs/plugin-react': specifier: 4.3.1 version: 4.3.1(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) @@ -329,10 +329,10 @@ importers: version: 1.3.22(postcss@8.4.39)(prettier@3.3.2)(sass@1.77.6)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) vite-plugin-svgr: specifier: 4.2.0 - version: 4.2.0(rollup@4.17.2)(typescript@5.5.2)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) + version: 4.2.0(rollup@4.17.2)(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) vite-tsconfig-paths: specifier: 4.3.2 - version: 4.3.2(typescript@5.5.2)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) + version: 4.3.2(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) frontend/ui: dependencies: @@ -381,7 +381,7 @@ importers: version: 1.77.6 typescript-plugin-css-modules: specifier: 5.1.0 - version: 5.1.0(typescript@5.5.2) + version: 5.1.0(typescript@5.5.3) scripts: dependencies: @@ -2103,8 +2103,8 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@7.14.1': - resolution: {integrity: sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==} + '@typescript-eslint/eslint-plugin@7.15.0': + resolution: {integrity: sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: '@typescript-eslint/parser': ^7.0.0 @@ -2114,8 +2114,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@7.14.1': - resolution: {integrity: sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==} + '@typescript-eslint/parser@7.15.0': + resolution: {integrity: sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -2124,12 +2124,12 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@7.14.1': - resolution: {integrity: sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==} + '@typescript-eslint/scope-manager@7.15.0': + resolution: {integrity: sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/type-utils@7.14.1': - resolution: {integrity: sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==} + '@typescript-eslint/type-utils@7.15.0': + resolution: {integrity: sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -2138,12 +2138,12 @@ packages: typescript: optional: true - '@typescript-eslint/types@7.14.1': - resolution: {integrity: sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==} + '@typescript-eslint/types@7.15.0': + resolution: {integrity: sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/typescript-estree@7.14.1': - resolution: {integrity: sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==} + '@typescript-eslint/typescript-estree@7.15.0': + resolution: {integrity: sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' @@ -2151,14 +2151,14 @@ packages: typescript: optional: true - '@typescript-eslint/utils@7.14.1': - resolution: {integrity: sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ==} + '@typescript-eslint/utils@7.15.0': + resolution: {integrity: sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 - '@typescript-eslint/visitor-keys@7.14.1': - resolution: {integrity: sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==} + '@typescript-eslint/visitor-keys@7.15.0': + resolution: {integrity: sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==} engines: {node: ^18.18.0 || >=20.0.0} '@ungap/structured-clone@1.2.0': @@ -4872,8 +4872,8 @@ packages: react-fast-compare@3.2.2: resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} - react-fast-marquee@1.6.4: - resolution: {integrity: sha512-LAgvhRmHdqaUQ8R5jCUwzEGFUIjnCCt3T3W8X7j7wF6DWe0SATlpP0JX1V0pp2qX3DYUezmn1Iz5AtRFdL2EWQ==} + react-fast-marquee@1.6.5: + resolution: {integrity: sha512-swDnPqrT2XISAih0o74zQVE2wQJFMvkx+9VZXYYNSLb/CUcAzU9pNj637Ar2+hyRw6b4tP6xh4GQZip2ZCpQpg==} peerDependencies: react: npm:react@rc react-dom: npm:react-dom@rc @@ -4893,8 +4893,8 @@ packages: '@mui/x-date-pickers': optional: true - react-hook-form@7.52.0: - resolution: {integrity: sha512-mJX506Xc6mirzLsmXUJyqlAI3Kj9Ph2RhplYhUVffeOQSnubK2uVqBFOBJmvKikvbFV91pxVXmDiR+QMF19x6A==} + react-hook-form@7.52.1: + resolution: {integrity: sha512-uNKIhaoICJ5KQALYZ4TOaOLElyM+xipord+Ha3crEFhTntdLvWZqVY49Wqd/0GiVCA/f9NjemLeiNPjG7Hpurg==} engines: {node: '>=12.22.0'} peerDependencies: react: npm:react@rc @@ -5557,8 +5557,8 @@ packages: peerDependencies: typescript: '>=4.0.0' - typescript@5.5.2: - resolution: {integrity: sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==} + typescript@5.5.3: + resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==} engines: {node: '>=14.17'} hasBin: true @@ -6048,11 +6048,11 @@ snapshots: '@babel/helper-validator-identifier': 7.24.5 to-fast-properties: 2.0.0 - '@commitlint/cli@19.3.0(@types/node@20.14.9)(typescript@5.5.2)': + '@commitlint/cli@19.3.0(@types/node@20.14.9)(typescript@5.5.3)': dependencies: '@commitlint/format': 19.3.0 '@commitlint/lint': 19.2.2 - '@commitlint/load': 19.2.0(@types/node@20.14.9)(typescript@5.5.2) + '@commitlint/load': 19.2.0(@types/node@20.14.9)(typescript@5.5.3) '@commitlint/read': 19.2.1 '@commitlint/types': 19.0.3 execa: 8.0.1 @@ -6099,15 +6099,15 @@ snapshots: '@commitlint/rules': 19.0.3 '@commitlint/types': 19.0.3 - '@commitlint/load@19.2.0(@types/node@20.14.9)(typescript@5.5.2)': + '@commitlint/load@19.2.0(@types/node@20.14.9)(typescript@5.5.3)': dependencies: '@commitlint/config-validator': 19.0.3 '@commitlint/execute-rule': 19.0.0 '@commitlint/resolve-extends': 19.1.0 '@commitlint/types': 19.0.3 chalk: 5.3.0 - cosmiconfig: 9.0.0(typescript@5.5.2) - cosmiconfig-typescript-loader: 5.0.0(@types/node@20.14.9)(cosmiconfig@9.0.0(typescript@5.5.2))(typescript@5.5.2) + cosmiconfig: 9.0.0(typescript@5.5.3) + cosmiconfig-typescript-loader: 5.0.0(@types/node@20.14.9)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -7087,12 +7087,12 @@ snapshots: '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.24.5) '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.24.5) - '@svgr/core@8.1.0(typescript@5.5.2)': + '@svgr/core@8.1.0(typescript@5.5.3)': dependencies: '@babel/core': 7.24.5 '@svgr/babel-preset': 8.1.0(@babel/core@7.24.5) camelcase: 6.3.0 - cosmiconfig: 8.3.6(typescript@5.5.2) + cosmiconfig: 8.3.6(typescript@5.5.3) snake-case: 3.0.4 transitivePeerDependencies: - supports-color @@ -7103,11 +7103,11 @@ snapshots: '@babel/types': 7.24.5 entities: 4.5.0 - '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.5.2))': + '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.5.3))': dependencies: '@babel/core': 7.24.5 '@svgr/babel-preset': 8.1.0(@babel/core@7.24.5) - '@svgr/core': 8.1.0(typescript@5.5.2) + '@svgr/core': 8.1.0(typescript@5.5.3) '@svgr/hast-util-to-babel-ast': 8.0.0 svg-parser: 2.0.4 transitivePeerDependencies: @@ -7463,85 +7463,85 @@ snapshots: '@types/node': 20.14.9 optional: true - '@typescript-eslint/eslint-plugin@7.14.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2)': + '@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)': dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.14.1(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/scope-manager': 7.14.1 - '@typescript-eslint/type-utils': 7.14.1(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/utils': 7.14.1(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/visitor-keys': 7.14.1 + '@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/type-utils': 7.15.0(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/utils': 7.15.0(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.15.0 eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.5.2) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.2)': + '@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: - '@typescript-eslint/scope-manager': 7.14.1 - '@typescript-eslint/types': 7.14.1 - '@typescript-eslint/typescript-estree': 7.14.1(typescript@5.5.2) - '@typescript-eslint/visitor-keys': 7.14.1 + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.15.0 debug: 4.3.4 eslint: 8.57.0 optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@7.14.1': + '@typescript-eslint/scope-manager@7.15.0': dependencies: - '@typescript-eslint/types': 7.14.1 - '@typescript-eslint/visitor-keys': 7.14.1 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/visitor-keys': 7.15.0 - '@typescript-eslint/type-utils@7.14.1(eslint@8.57.0)(typescript@5.5.2)': + '@typescript-eslint/type-utils@7.15.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: - '@typescript-eslint/typescript-estree': 7.14.1(typescript@5.5.2) - '@typescript-eslint/utils': 7.14.1(eslint@8.57.0)(typescript@5.5.2) + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3) + '@typescript-eslint/utils': 7.15.0(eslint@8.57.0)(typescript@5.5.3) debug: 4.3.4 eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.5.2) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@7.14.1': {} + '@typescript-eslint/types@7.15.0': {} - '@typescript-eslint/typescript-estree@7.14.1(typescript@5.5.2)': + '@typescript-eslint/typescript-estree@7.15.0(typescript@5.5.3)': dependencies: - '@typescript-eslint/types': 7.14.1 - '@typescript-eslint/visitor-keys': 7.14.1 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/visitor-keys': 7.15.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.4 semver: 7.6.1 - ts-api-utils: 1.3.0(typescript@5.5.2) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@7.14.1(eslint@8.57.0)(typescript@5.5.2)': + '@typescript-eslint/utils@7.15.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@typescript-eslint/scope-manager': 7.14.1 - '@typescript-eslint/types': 7.14.1 - '@typescript-eslint/typescript-estree': 7.14.1(typescript@5.5.2) + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3) eslint: 8.57.0 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/visitor-keys@7.14.1': + '@typescript-eslint/visitor-keys@7.15.0': dependencies: - '@typescript-eslint/types': 7.14.1 + '@typescript-eslint/types': 7.15.0 eslint-visitor-keys: 3.4.3 '@ungap/structured-clone@1.2.0': {} @@ -8048,12 +8048,12 @@ snapshots: dependencies: is-what: 3.14.1 - cosmiconfig-typescript-loader@5.0.0(@types/node@20.14.9)(cosmiconfig@9.0.0(typescript@5.5.2))(typescript@5.5.2): + cosmiconfig-typescript-loader@5.0.0(@types/node@20.14.9)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3): dependencies: '@types/node': 20.14.9 - cosmiconfig: 9.0.0(typescript@5.5.2) + cosmiconfig: 9.0.0(typescript@5.5.3) jiti: 1.21.0 - typescript: 5.5.2 + typescript: 5.5.3 cosmiconfig@7.1.0: dependencies: @@ -8063,23 +8063,23 @@ snapshots: path-type: 4.0.0 yaml: 1.10.2 - cosmiconfig@8.3.6(typescript@5.5.2): + cosmiconfig@8.3.6(typescript@5.5.3): dependencies: import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 - cosmiconfig@9.0.0(typescript@5.5.2): + cosmiconfig@9.0.0(typescript@5.5.3): dependencies: env-paths: 2.2.1 import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 create-error-class@3.0.2: dependencies: @@ -10601,20 +10601,20 @@ snapshots: react-fast-compare@3.2.2: {} - react-fast-marquee@1.6.4(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614): + react-fast-marquee@1.6.5(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614): dependencies: react: 19.0.0-rc-fb9a90fa48-20240614 react-dom: 19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614) - react-hook-form-mui@7.0.0(zwihrdjnuz7uekpqkqd7rvdhli): + react-hook-form-mui@7.0.0(hnsbxdphojlfk7ty6r3hqlevge): dependencies: '@mui/material': 5.15.21(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) react: 19.0.0-rc-fb9a90fa48-20240614 - react-hook-form: 7.52.0(react@19.0.0-rc-fb9a90fa48-20240614) + react-hook-form: 7.52.1(react@19.0.0-rc-fb9a90fa48-20240614) optionalDependencies: '@mui/icons-material': 5.15.21(@mui/material@5.15.21(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) - react-hook-form@7.52.0(react@19.0.0-rc-fb9a90fa48-20240614): + react-hook-form@7.52.1(react@19.0.0-rc-fb9a90fa48-20240614): dependencies: react: 19.0.0-rc-fb9a90fa48-20240614 @@ -11071,45 +11071,45 @@ snapshots: dependencies: inline-style-parser: 0.2.3 - stylelint-config-html@1.1.0(postcss-html@1.7.0)(stylelint@16.6.1(typescript@5.5.2)): + stylelint-config-html@1.1.0(postcss-html@1.7.0)(stylelint@16.6.1(typescript@5.5.3)): dependencies: postcss-html: 1.7.0 - stylelint: 16.6.1(typescript@5.5.2) + stylelint: 16.6.1(typescript@5.5.3) - stylelint-config-recess-order@5.0.1(stylelint@16.6.1(typescript@5.5.2)): + stylelint-config-recess-order@5.0.1(stylelint@16.6.1(typescript@5.5.3)): dependencies: - stylelint: 16.6.1(typescript@5.5.2) - stylelint-order: 6.0.4(stylelint@16.6.1(typescript@5.5.2)) + stylelint: 16.6.1(typescript@5.5.3) + stylelint-order: 6.0.4(stylelint@16.6.1(typescript@5.5.3)) - stylelint-config-recommended@14.0.1(stylelint@16.6.1(typescript@5.5.2)): + stylelint-config-recommended@14.0.1(stylelint@16.6.1(typescript@5.5.3)): dependencies: - stylelint: 16.6.1(typescript@5.5.2) + stylelint: 16.6.1(typescript@5.5.3) - stylelint-config-standard@36.0.1(stylelint@16.6.1(typescript@5.5.2)): + stylelint-config-standard@36.0.1(stylelint@16.6.1(typescript@5.5.3)): dependencies: - stylelint: 16.6.1(typescript@5.5.2) - stylelint-config-recommended: 14.0.1(stylelint@16.6.1(typescript@5.5.2)) + stylelint: 16.6.1(typescript@5.5.3) + stylelint-config-recommended: 14.0.1(stylelint@16.6.1(typescript@5.5.3)) - stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.6.1(typescript@5.5.2)): + stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.6.1(typescript@5.5.3)): dependencies: - stylelint: 16.6.1(typescript@5.5.2) + stylelint: 16.6.1(typescript@5.5.3) - stylelint-order@6.0.4(stylelint@16.6.1(typescript@5.5.2)): + stylelint-order@6.0.4(stylelint@16.6.1(typescript@5.5.3)): dependencies: postcss: 8.4.39 postcss-sorting: 8.0.2(postcss@8.4.39) - stylelint: 16.6.1(typescript@5.5.2) + stylelint: 16.6.1(typescript@5.5.3) - stylelint-scss@6.3.2(stylelint@16.6.1(typescript@5.5.2)): + stylelint-scss@6.3.2(stylelint@16.6.1(typescript@5.5.3)): dependencies: known-css-properties: 0.31.0 postcss-media-query-parser: 0.2.3 postcss-resolve-nested-selector: 0.1.1 postcss-selector-parser: 6.1.0 postcss-value-parser: 4.2.0 - stylelint: 16.6.1(typescript@5.5.2) + stylelint: 16.6.1(typescript@5.5.3) - stylelint@16.6.1(typescript@5.5.2): + stylelint@16.6.1(typescript@5.5.3): dependencies: '@csstools/css-parser-algorithms': 2.6.3(@csstools/css-tokenizer@2.3.1) '@csstools/css-tokenizer': 2.3.1 @@ -11118,7 +11118,7 @@ snapshots: '@dual-bundle/import-meta-resolve': 4.1.0 balanced-match: 2.0.0 colord: 2.9.3 - cosmiconfig: 9.0.0(typescript@5.5.2) + cosmiconfig: 9.0.0(typescript@5.5.3) css-functions-list: 3.2.2 css-tree: 2.3.1 debug: 4.3.4 @@ -11332,17 +11332,17 @@ snapshots: trough@2.2.0: {} - ts-api-utils@1.3.0(typescript@5.5.2): + ts-api-utils@1.3.0(typescript@5.5.3): dependencies: - typescript: 5.5.2 + typescript: 5.5.3 ts-custom-error@3.3.1: {} ts-interface-checker@0.1.13: {} - tsconfck@3.0.3(typescript@5.5.2): + tsconfck@3.0.3(typescript@5.5.3): optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 tsconfig-paths@3.15.0: dependencies: @@ -11423,7 +11423,7 @@ snapshots: dependencies: csstype: 3.1.3 - typescript-plugin-css-modules@5.1.0(typescript@5.5.2): + typescript-plugin-css-modules@5.1.0(typescript@5.5.3): dependencies: '@types/postcss-modules-local-by-default': 4.0.2 '@types/postcss-modules-scope': 3.0.4 @@ -11441,12 +11441,12 @@ snapshots: source-map-js: 1.2.0 stylus: 0.62.0 tsconfig-paths: 4.2.0 - typescript: 5.5.2 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - ts-node - typescript@5.5.2: {} + typescript@5.5.3: {} ufo@1.5.3: {} @@ -11591,22 +11591,22 @@ snapshots: sass: 1.77.6 vite: 5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) - vite-plugin-svgr@4.2.0(rollup@4.17.2)(typescript@5.5.2)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): + vite-plugin-svgr@4.2.0(rollup@4.17.2)(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): dependencies: '@rollup/pluginutils': 5.1.0(rollup@4.17.2) - '@svgr/core': 8.1.0(typescript@5.5.2) - '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.5.2)) + '@svgr/core': 8.1.0(typescript@5.5.3) + '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.5.3)) vite: 5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) transitivePeerDependencies: - rollup - supports-color - typescript - vite-tsconfig-paths@4.3.2(typescript@5.5.2)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): + vite-tsconfig-paths@4.3.2(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): dependencies: debug: 4.3.4 globrex: 0.1.2 - tsconfck: 3.0.3(typescript@5.5.2) + tsconfck: 3.0.3(typescript@5.5.3) optionalDependencies: vite: 5.3.2(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) transitivePeerDependencies: diff --git a/clash-verge-rev/.github/build-for-linux/build.sh b/clash-verge-rev/.github/build-for-linux/build.sh index 7c2411b800..fbc18cc18a 100644 --- a/clash-verge-rev/.github/build-for-linux/build.sh +++ b/clash-verge-rev/.github/build-for-linux/build.sh @@ -2,4 +2,4 @@ pnpm install pnpm check $INPUT_TARGET sed -i "s/#openssl/openssl={version=\"0.10\",features=[\"vendored\"]}/g" src-tauri/Cargo.toml -cargo tauri build --target $INPUT_TARGET +pnpm build --target $INPUT_TARGET diff --git a/clash-verge-rev/.github/build-for-linux/entrypoint.sh b/clash-verge-rev/.github/build-for-linux/entrypoint.sh index c23f6217c2..c07360347e 100644 --- a/clash-verge-rev/.github/build-for-linux/entrypoint.sh +++ b/clash-verge-rev/.github/build-for-linux/entrypoint.sh @@ -5,8 +5,6 @@ tar -Jxvf ./node-v20.10.0-linux-x64.tar.xz export PATH=$(pwd)/node-v20.10.0-linux-x64/bin:$PATH npm install pnpm -g -cargo install --git https://github.com/tauri-apps/tauri --branch 1.x tauri-cli - rustup target add "$INPUT_TARGET" if [ "$INPUT_TARGET" = "x86_64-unknown-linux-gnu" ]; then diff --git a/clash-verge-rev/.github/workflows/alpha.yml b/clash-verge-rev/.github/workflows/alpha.yml index 8cc9050ddd..07c3b13161 100644 --- a/clash-verge-rev/.github/workflows/alpha.yml +++ b/clash-verge-rev/.github/workflows/alpha.yml @@ -49,13 +49,6 @@ jobs: cache-all-crates: true cache-on-failure: true - - name: Install Tauri CLI - uses: baptiste0928/cargo-install@v3 - with: - crate: tauri-cli - git: https://github.com/tauri-apps/tauri - branch: 1.x # `branch` and `commit` are also supported - - name: Install Node uses: actions/setup-node@v4 with: @@ -90,7 +83,7 @@ jobs: releaseBody: "More new features are now supported." releaseDraft: false prerelease: true - tauriScript: cargo tauri + tauriScript: pnpm args: --target ${{ matrix.target }} - name: Portable Bundle @@ -174,13 +167,6 @@ jobs: cache-all-crates: true cache-on-failure: true - - name: Install Tauri CLI - uses: baptiste0928/cargo-install@v3 - with: - crate: tauri-cli - git: https://github.com/tauri-apps/tauri - branch: 1.x # `branch` and `commit` are also supported - - name: Install Node uses: actions/setup-node@v4 with: @@ -212,7 +198,7 @@ jobs: TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} with: - tauriScript: cargo tauri + tauriScript: pnpm args: --target ${{ matrix.target }} - name: Rename diff --git a/clash-verge-rev/.github/workflows/release.yml b/clash-verge-rev/.github/workflows/release.yml index 619b17b359..cf5a6fc165 100644 --- a/clash-verge-rev/.github/workflows/release.yml +++ b/clash-verge-rev/.github/workflows/release.yml @@ -41,13 +41,6 @@ jobs: workspaces: src-tauri cache-all-crates: true - - name: Install Tauri CLI - uses: baptiste0928/cargo-install@v3 - with: - crate: tauri-cli - git: https://github.com/tauri-apps/tauri - branch: 1.x # `branch` and `commit` are also supported - - name: Install Node uses: actions/setup-node@v4 with: @@ -80,7 +73,7 @@ jobs: tagName: v__VERSION__ releaseName: "Clash Verge Rev v__VERSION__" releaseBody: "More new features are now supported." - tauriScript: cargo tauri + tauriScript: pnpm args: --target ${{ matrix.target }} - name: Portable Bundle @@ -160,13 +153,6 @@ jobs: with: workspaces: src-tauri - - name: Install Tauri CLI - uses: baptiste0928/cargo-install@v3 - with: - crate: tauri-cli - git: https://github.com/tauri-apps/tauri - branch: 1.x # `branch` and `commit` are also supported - - name: Install Node uses: actions/setup-node@v4 with: @@ -198,7 +184,7 @@ jobs: TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} with: - tauriScript: cargo tauri + tauriScript: pnpm args: --target ${{ matrix.target }} - name: Rename diff --git a/clash-verge-rev/UPDATELOG.md b/clash-verge-rev/UPDATELOG.md index 057b015067..8f818f661c 100644 --- a/clash-verge-rev/UPDATELOG.md +++ b/clash-verge-rev/UPDATELOG.md @@ -1,3 +1,38 @@ +## v1.7.0 + +### Break Changes + +- 此版本重构了 Merge/Script,更新前请先备份好自定义 Merge 和 Script(更新并不会删除配置文件,但是旧版 Merge 和 Script 在更新后无法从前端访问,备份以防万一) +- Merge 改名为 `扩展配置`,分为 `全局扩展配置` 和 `订阅扩展配置`,全局扩展配置对所有订阅生效,订阅扩展配置只对关联的订阅生效 +- Script 改名为 `扩展脚本`,同样分为 `全局扩展脚本` 和 `订阅扩展脚本` +- 执行优先级为: 全局扩展配置 -> 全局扩展脚本 -> 订阅扩展配置 ->订阅扩展脚本 +- MacOS 用户更新后请重新安装服务模式 + +### Features + +- 移除内核授权,改为服务模式实现 +- 自动填充本地订阅名称 +- 添加重大更新处理逻辑 +- 订阅单独指定扩展配置/脚本(需要重新导入订阅) +- 添加可视化规则编辑器(需要重新导入订阅) +- 编辑器新增工具栏按钮(格式化、最大化/最小化) +- WEBUI 使用最新版 metacubex,并解决无法自动登陆问问题 +- 禁用部分 Webview2 快捷键 +- 热键配置新增连接符 + 号 +- 新增部分悬浮提示按钮,用于解释说明 +- 当日志等级为`Debug`时(更改需重启软件生效),支持点击内存主动内存回收(绿色文字) +- 设置页面右上角新增 TG 频道链接 + +### Bugs Fixes + +- 修复代理绕过格式检查 +- 通过进程名称关闭进程 +- 退出软件时恢复 DNS 设置 +- 修复创建本地订阅时更新间隔无法保存 +- 连接页面列宽无法调整 + +--- + ## v1.6.6 ### Features diff --git a/clash-verge-rev/package.json b/clash-verge-rev/package.json index 05a39539c7..042bf26bba 100644 --- a/clash-verge-rev/package.json +++ b/clash-verge-rev/package.json @@ -1,6 +1,6 @@ { "name": "clash-verge", - "version": "1.6.6", + "version": "1.7.0", "license": "GPL-3.0-only", "scripts": { "dev": "tauri dev", @@ -24,11 +24,11 @@ "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", "@juggle/resize-observer": "^3.4.0", - "@mui/icons-material": "^5.15.20", + "@mui/icons-material": "^5.15.21", "@mui/lab": "5.0.0-alpha.149", - "@mui/material": "^5.15.20", - "@mui/x-data-grid": "^7.7.0", - "@tauri-apps/api": "^1.5.6", + "@mui/material": "^5.15.21", + "@mui/x-data-grid": "^7.8.0", + "@tauri-apps/api": "^1.6.0", "@types/json-schema": "^7.0.15", "ahooks": "^3.8.0", "axios": "^1.7.2", @@ -37,18 +37,18 @@ "i18next": "^23.11.5", "js-yaml": "^4.1.0", "lodash-es": "^4.17.21", - "meta-json-schema": "1.18.5-alpha6", + "meta-json-schema": "1.18.6", "monaco-editor": "^0.49.0", "monaco-yaml": "^5.2.0", "nanoid": "^5.0.7", "react": "^18.3.1", "react-dom": "^18.3.1", "react-error-boundary": "^3.1.4", - "react-hook-form": "^7.52.0", + "react-hook-form": "^7.52.1", "react-i18next": "^13.5.0", "react-markdown": "^9.0.1", "react-monaco-editor": "^0.55.0", - "react-router-dom": "^6.23.1", + "react-router-dom": "^6.24.0", "react-transition-group": "^4.4.5", "react-virtuoso": "^4.7.11", "sockette": "^2.0.6", @@ -58,7 +58,7 @@ }, "devDependencies": { "@actions/github": "^5.1.1", - "@tauri-apps/cli": "^1.5.14", + "@tauri-apps/cli": "^1.6.0", "@types/fs-extra": "^9.0.13", "@types/js-cookie": "^3.0.6", "@types/js-yaml": "^4.0.9", @@ -76,10 +76,10 @@ "node-fetch": "^3.3.2", "prettier": "^2.8.8", "pretty-quick": "^3.3.1", - "sass": "^1.77.5", + "sass": "^1.77.6", "terser": "^5.31.1", - "typescript": "^5.4.5", - "vite": "^5.3.1", + "typescript": "^5.5.3", + "vite": "^5.3.2", "vite-plugin-monaco-editor": "^1.1.0", "vite-plugin-svgr": "^4.2.0" }, diff --git a/clash-verge-rev/pnpm-lock.yaml b/clash-verge-rev/pnpm-lock.yaml index 1ff6d870e6..4953e61cc7 100644 --- a/clash-verge-rev/pnpm-lock.yaml +++ b/clash-verge-rev/pnpm-lock.yaml @@ -26,20 +26,20 @@ importers: specifier: ^3.4.0 version: 3.4.0 "@mui/icons-material": - specifier: ^5.15.20 - version: 5.15.20(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + specifier: ^5.15.21 + version: 5.15.21(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) "@mui/lab": specifier: 5.0.0-alpha.149 - version: 5.0.0-alpha.149(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 5.0.0-alpha.149(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) "@mui/material": - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^5.15.21 + version: 5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) "@mui/x-data-grid": - specifier: ^7.7.0 - version: 7.7.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^7.8.0 + version: 7.8.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) "@tauri-apps/api": - specifier: ^1.5.6 - version: 1.5.6 + specifier: ^1.6.0 + version: 1.6.0 "@types/json-schema": specifier: ^7.0.15 version: 7.0.15 @@ -65,8 +65,8 @@ importers: specifier: ^4.17.21 version: 4.17.21 meta-json-schema: - specifier: 1.18.5-alpha6 - version: 1.18.5-alpha6 + specifier: 1.18.6 + version: 1.18.6 monaco-editor: specifier: ^0.49.0 version: 0.49.0 @@ -86,8 +86,8 @@ importers: specifier: ^3.1.4 version: 3.1.4(react@18.3.1) react-hook-form: - specifier: ^7.52.0 - version: 7.52.0(react@18.3.1) + specifier: ^7.52.1 + version: 7.52.1(react@18.3.1) react-i18next: specifier: ^13.5.0 version: 13.5.0(i18next@23.11.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -98,8 +98,8 @@ importers: specifier: ^0.55.0 version: 0.55.0(@types/react@18.3.3)(monaco-editor@0.49.0)(react@18.3.1) react-router-dom: - specifier: ^6.23.1 - version: 6.23.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^6.24.0 + version: 6.24.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-transition-group: specifier: ^4.4.5 version: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -123,8 +123,8 @@ importers: specifier: ^5.1.1 version: 5.1.1 "@tauri-apps/cli": - specifier: ^1.5.14 - version: 1.5.14 + specifier: ^1.6.0 + version: 1.6.0 "@types/fs-extra": specifier: ^9.0.13 version: 9.0.13 @@ -148,10 +148,10 @@ importers: version: 4.4.10 "@vitejs/plugin-legacy": specifier: ^5.4.1 - version: 5.4.1(terser@5.31.1)(vite@5.3.1(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.1)) + version: 5.4.1(terser@5.31.1)(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1)) "@vitejs/plugin-react": specifier: ^4.3.1 - version: 4.3.1(vite@5.3.1(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.1)) + version: 4.3.1(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1)) adm-zip: specifier: ^0.5.14 version: 0.5.14 @@ -177,23 +177,23 @@ importers: specifier: ^3.3.1 version: 3.3.1(prettier@2.8.8) sass: - specifier: ^1.77.5 - version: 1.77.5 + specifier: ^1.77.6 + version: 1.77.6 terser: specifier: ^5.31.1 version: 5.31.1 typescript: - specifier: ^5.4.5 - version: 5.4.5 + specifier: ^5.5.3 + version: 5.5.3 vite: - specifier: ^5.3.1 - version: 5.3.1(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.1) + specifier: ^5.3.2 + version: 5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) vite-plugin-monaco-editor: specifier: ^1.1.0 version: 1.1.0(monaco-editor@0.49.0) vite-plugin-svgr: specifier: ^4.2.0 - version: 4.2.0(rollup@4.18.0)(typescript@5.4.5)(vite@5.3.1(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.1)) + version: 4.2.0(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1)) packages: "@actions/github@5.1.1": @@ -1474,31 +1474,31 @@ packages: } engines: { node: ">=14" } - "@floating-ui/core@1.6.2": + "@floating-ui/core@1.6.4": resolution: { - integrity: sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==, + integrity: sha512-a4IowK4QkXl4SCWTGUR0INAfEOX3wtsYw3rKK5InQEHMGObkR8Xk44qYQD9P4r6HHw0iIfK6GUKECmY8sTkqRA==, } - "@floating-ui/dom@1.6.5": + "@floating-ui/dom@1.6.7": resolution: { - integrity: sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==, + integrity: sha512-wmVfPG5o2xnKDU4jx/m4w5qva9FWHcnZ8BvzEe90D/RpwsJaTAVYPEPdQ8sbr/N8zZTAHlZUTQdqg8ZUbzHmng==, } - "@floating-ui/react-dom@2.1.0": + "@floating-ui/react-dom@2.1.1": resolution: { - integrity: sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==, + integrity: sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==, } peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" - "@floating-ui/utils@0.2.2": + "@floating-ui/utils@0.2.4": resolution: { - integrity: sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==, + integrity: sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==, } "@jridgewell/gen-mapping@0.3.5": @@ -1574,16 +1574,16 @@ packages: "@types/react": optional: true - "@mui/core-downloads-tracker@5.15.20": + "@mui/core-downloads-tracker@5.15.21": resolution: { - integrity: sha512-DoL2ppgldL16utL8nNyj/P12f8mCNdx/Hb/AJnX9rLY4b52hCMIx1kH83pbXQ6uMy6n54M3StmEbvSGoj2OFuA==, + integrity: sha512-dp9lXBaJZzJYeJfQY3Ow4Rb49QaCEdkl2KKYscdQHQm6bMJ+l4XPY3Cd9PCeeJTsHPIDJ60lzXbeRgs6sx/rpw==, } - "@mui/icons-material@5.15.20": + "@mui/icons-material@5.15.21": resolution: { - integrity: sha512-oGcKmCuHaYbAAoLN67WKSXtHmEgyWcJToT1uRtmPyxMj9N5uqwc/mRtEnst4Wj/eGr+zYH2FiZQ79v9k7kSk1Q==, + integrity: sha512-yqkq1MbdkmX5ZHyvZTBuAaA6RkvoqkoAgwBSx9Oh0L0jAfj9T/Ih/NhMNjkl8PWVSonjfDUkKroBnjRyo/1M9Q==, } engines: { node: ">=12.0.0" } peerDependencies: @@ -1615,10 +1615,10 @@ packages: "@types/react": optional: true - "@mui/material@5.15.20": + "@mui/material@5.15.21": resolution: { - integrity: sha512-tVq3l4qoXx/NxUgIx/x3lZiPn/5xDbdTE8VrLczNpfblLYZzlrbxA7kb9mI8NoBF6+w9WE9IrxWnKK5KlPI2bg==, + integrity: sha512-nTyCcgduKwHqiuQ/B03EQUa+utSMzn2sQp0QAibsnYe4tvc3zkMbO0amKpl48vhABIY3IvT6w9615BFIgMt0YA==, } engines: { node: ">=12.0.0" } peerDependencies: @@ -1707,10 +1707,10 @@ packages: "@types/react": optional: true - "@mui/x-data-grid@7.7.0": + "@mui/x-data-grid@7.8.0": resolution: { - integrity: sha512-s3Oii9EKcYPnL7M4g5evNley/J0slLL6xWRi0VwYqTHPGntBAMntUktMZ63bD/xko99f5ZcFoRBYTc55+mJ+AQ==, + integrity: sha512-X3t6EVSZ28vVKY9NfqKcClchw2o/KmHsywybp1tNFevIJiwjZSp7NDJ091GyTqMgyDt1Dy5z2hGxoTDUYYfeGg==, } engines: { node: ">=14.0.0" } peerDependencies: @@ -1803,10 +1803,10 @@ packages: integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==, } - "@remix-run/router@1.16.1": + "@remix-run/router@1.17.0": resolution: { - integrity: sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==, + integrity: sha512-2D6XaHEVvkCn682XBnipbJjgZUU7xjLtA4dGJRBVUKpEaDYOZMENZoZjAOSb7qirxt5RupjzZxz4fK2FO+EFPw==, } engines: { node: ">=14.0.0" } @@ -2054,107 +2054,107 @@ packages: peerDependencies: "@svgr/core": "*" - "@tauri-apps/api@1.5.6": + "@tauri-apps/api@1.6.0": resolution: { - integrity: sha512-LH5ToovAHnDVe5Qa9f/+jW28I6DeMhos8bNDtBOmmnaDpPmJmYLyHdeDblAWWWYc7KKRDg9/66vMuKyq0WIeFA==, + integrity: sha512-rqI++FWClU5I2UBp4HXFvl+sBWkdigBkxnpJDQUWttNyG7IZP4FwQGhTNL5EOw0vI8i6eSAJ5frLqO7n7jbJdg==, } engines: { node: ">= 14.6.0", npm: ">= 6.6.0", yarn: ">= 1.19.1" } - "@tauri-apps/cli-darwin-arm64@1.5.14": + "@tauri-apps/cli-darwin-arm64@1.6.0": resolution: { - integrity: sha512-lxoSOp3KKSqzHJa7iT32dukPGMlfsTuja1xXSgwR8o/fqzpYJY7FY/3ZxesP8HR66FcK+vtqa//HNqeOQ0mHkA==, + integrity: sha512-SNRwUD9nqGxY47mbY1CGTt/jqyQOU7Ps7Mx/mpgahL0FVUDiCEY/5L9QfEPPhEgccgcelEVn7i6aQHIkHyUtCA==, } engines: { node: ">= 10" } cpu: [arm64] os: [darwin] - "@tauri-apps/cli-darwin-x64@1.5.14": + "@tauri-apps/cli-darwin-x64@1.6.0": resolution: { - integrity: sha512-EXSwN1n5spfG8FoXuyc90ACtmDJXzaZ1gxyENaq9xEpQoo7j/Q1vb6qXxmr6azKr8zmqY4h08ZFbv3exh93xJg==, + integrity: sha512-g2/uDR/eeH2arvuawA4WwaEOqv/7jDO/ZLNI3JlBjP5Pk8GGb3Kdy0ro1xQzF94mtk2mOnOXa4dMgAet4sUJ1A==, } engines: { node: ">= 10" } cpu: [x64] os: [darwin] - "@tauri-apps/cli-linux-arm-gnueabihf@1.5.14": + "@tauri-apps/cli-linux-arm-gnueabihf@1.6.0": resolution: { - integrity: sha512-Yb8BH/KYR7Tl+de40sZPfrqbhcU3Jlu+UPIrnXt05sjn48xqIps74Xjz8zzVp0TuHxUp8FmIGtCVhQgsbrsvvg==, + integrity: sha512-EVwf4oRkQyG8BpSrk0gqO7oA0sDM2MdNDtJpMfleYFEgCxLIOGZKNqaOW3M7U+0Y4qikmG3TtRK+ngc8Ymtrjg==, } engines: { node: ">= 10" } cpu: [arm] os: [linux] - "@tauri-apps/cli-linux-arm64-gnu@1.5.14": + "@tauri-apps/cli-linux-arm64-gnu@1.6.0": resolution: { - integrity: sha512-QrKHP4gRaHiup478rPBZ+BmNd88yze9jMmheoNy9mN1K/aECRmTHO+tWhsxv5moFHZzRhO0QDWxxvTtiaPXaGg==, + integrity: sha512-YdpY17cAySrhK9dX4BUVEmhAxE2o+6skIEFg8iN/xrDwRxhaNPI9I80YXPatUTX54Kx55T5++25VJG9+3iw83A==, } engines: { node: ">= 10" } cpu: [arm64] os: [linux] - "@tauri-apps/cli-linux-arm64-musl@1.5.14": + "@tauri-apps/cli-linux-arm64-musl@1.6.0": resolution: { - integrity: sha512-Hb1C1VMxmUcyGjW/K/INKF87zzzgLEVRmWZZnQd7M1P4uue4xPyIwUELSdX12Z2jREPgmLW4AXPD0m6wsNu7iw==, + integrity: sha512-4U628tuf2U8pMr4tIBJhEkrFwt+46dwhXrDlpdyWSZtnop5RJAVKHODm0KbWns4xGKfTW1F3r6sSv+2ZxLcISA==, } engines: { node: ">= 10" } cpu: [arm64] os: [linux] - "@tauri-apps/cli-linux-x64-gnu@1.5.14": + "@tauri-apps/cli-linux-x64-gnu@1.6.0": resolution: { - integrity: sha512-kD9v/UwPDuhIgq2TJj/s2/7rqk+vmExVV6xHPKI8vVbIvlNAOZqmx3fpxjej1241vhJ/piGd/m6q6YMWGsL0oQ==, + integrity: sha512-AKRzp76fVUaJyXj5KRJT9bJyhwZyUnRQU0RqIRqOtZCT5yr6qGP8rjtQ7YhCIzWrseBlOllc3Qvbgw3Yl0VQcA==, } engines: { node: ">= 10" } cpu: [x64] os: [linux] - "@tauri-apps/cli-linux-x64-musl@1.5.14": + "@tauri-apps/cli-linux-x64-musl@1.6.0": resolution: { - integrity: sha512-204Drgg9Zx0+THKndqASz4+iPCwqA3gQVF9C0CDIArNXrjPyJjVvW8VP5CHiZYaTNWxlz/ltyxluM6UFWbXNFw==, + integrity: sha512-0edIdq6aMBTaRMIXddHfyAFL361JqulLLd2Wi2aoOie7DkQ2MYh6gv3hA7NB9gqFwNIGE+xtJ4BkXIP2tSGPlg==, } engines: { node: ">= 10" } cpu: [x64] os: [linux] - "@tauri-apps/cli-win32-arm64-msvc@1.5.14": + "@tauri-apps/cli-win32-arm64-msvc@1.6.0": resolution: { - integrity: sha512-sqPSni2MnWNCm+8YZnLdWCclxfSHaYqKuPFSz8q7Tn1G1m/cA9gyPoC1G0esHftY7bu/ZM5lB4kM3I4U0KlLiA==, + integrity: sha512-QwWpWk4ubcwJ1rljsRAmINgB2AwkyzZhpYbalA+MmzyYMREcdXWGkyixWbRZgqc6fEWEBmq5UG73qz5eBJiIKg==, } engines: { node: ">= 10" } cpu: [arm64] os: [win32] - "@tauri-apps/cli-win32-ia32-msvc@1.5.14": + "@tauri-apps/cli-win32-ia32-msvc@1.6.0": resolution: { - integrity: sha512-8xN8W0zTs8oFsQmvYLxHFeqhzVI7oTaPK1xQMc5gbpFP45jN41c21aCXfjnvzT+h90EfCHUF9EWj2HTEJSb7Iw==, + integrity: sha512-Vtw0yxO9+aEFuhuxQ57ALG43tjECopRimRuKGbtZYDCriB/ty5TrT3QWMdy0dxBkpDTu3Rqsz30sbDzw6tlP3Q==, } engines: { node: ">= 10" } cpu: [ia32] os: [win32] - "@tauri-apps/cli-win32-x64-msvc@1.5.14": + "@tauri-apps/cli-win32-x64-msvc@1.6.0": resolution: { - integrity: sha512-U0slee5tNM2PYECBpPHavLSwkT3szGMZ+qhcikQQbDan84bQdLn/kHWjyXOgLJs4KSve4+KxcrN+AVqj0VyHnw==, + integrity: sha512-h54FHOvGi7+LIfRchzgZYSCHB1HDlP599vWXQQJ/XnwJY+6Rwr2E5bOe/EhqoG8rbGkfK0xX3KPAvXPbUlmggg==, } engines: { node: ">= 10" } cpu: [x64] os: [win32] - "@tauri-apps/cli@1.5.14": + "@tauri-apps/cli@1.6.0": resolution: { - integrity: sha512-JOSMKymlg116UdEXSj69eg5p1OtZnQkUE0qIGbtNDO1sk3X/KgBN6+oHBW0BzPStp/W0AjBgrMWCqjHPwEpOug==, + integrity: sha512-DBBpBl6GhTzm8ImMbKkfaZ4fDTykWrC7Q5OXP4XqD91recmDEn2LExuvuiiS3HYe7uP8Eb5B9NPHhqJb+Zo7qQ==, } engines: { node: ">= 10" } hasBin: true @@ -2237,10 +2237,10 @@ packages: integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==, } - "@types/lodash@4.17.5": + "@types/lodash@4.17.6": resolution: { - integrity: sha512-MBIOHVZqVqgfro1euRDWX7OO0fBVUUMrN6Pwm8LQsz8cWhEpihlvR70ENj3f40j58TNxZaWv2ndSkInykNBBJw==, + integrity: sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA==, } "@types/mdast@4.0.4": @@ -2255,10 +2255,10 @@ packages: integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==, } - "@types/node@20.14.2": + "@types/node@20.14.9": resolution: { - integrity: sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==, + integrity: sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==, } "@types/parse-json@4.0.2": @@ -2486,10 +2486,10 @@ packages: } engines: { node: ">=10" } - caniuse-lite@1.0.30001636: + caniuse-lite@1.0.30001639: resolution: { - integrity: sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==, + integrity: sha512-eFHflNTBIlFwP2AIKaYuBQN/apnUoKNhBdza8ZnW/h2di4LCZ4xFqYlxUxo+LQ76KFI1PGcC1QDxMbxTZpSCAg==, } ccount@2.0.1: @@ -2720,10 +2720,10 @@ packages: integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==, } - electron-to-chromium@1.4.803: + electron-to-chromium@1.4.816: resolution: { - integrity: sha512-61H9mLzGOCLLVsnLiRzCbc63uldP0AniRYPV3hbGVtONA1pI7qSGILdbofR7A8TMbOypDocEAjH/e+9k1QIe3g==, + integrity: sha512-EKH5X5oqC6hLmiS7/vYtZHZFTNdhsYG5NVPRN6Yn0kQHNBlT59+xSM8HBy66P5fxWpKgZbPqb+diC64ng295Jw==, } end-of-stream@1.4.4: @@ -3061,11 +3061,12 @@ packages: } engines: { node: ">=8" } - is-core-module@2.13.1: + is-core-module@2.14.0: resolution: { - integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==, + integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==, } + engines: { node: ">= 0.4" } is-decimal@2.0.1: resolution: @@ -3175,10 +3176,10 @@ packages: engines: { node: ">=6" } hasBin: true - jsonc-parser@3.2.1: + jsonc-parser@3.3.1: resolution: { - integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==, + integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==, } jsonfile@6.1.0: @@ -3310,10 +3311,10 @@ packages: integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==, } - meta-json-schema@1.18.5-alpha6: + meta-json-schema@1.18.6: resolution: { - integrity: sha512-Qh1NOgM8HMKLdx59NUy+Um+r2xOJptD7ge/0rnwxGS+MuEFeBCmNF1lUjW3e1Iktngd8TCopji8KdmGPCla+cw==, + integrity: sha512-HMDu+1lcVsgEsa4kPlyo2ZNgOEbaQJhOzU4ll4qJahwx5TIw8NkcbXgxnKEW6NieqL4AOWWtoNgw3EKeuHg4+A==, } micromark-core-commonmark@2.0.1: @@ -3504,10 +3505,10 @@ packages: integrity: sha512-d58sP5yNhjs8uG1ESXs0hFnuX2YfdMhiGeWhdgTUZyG9aaWgyI4dDwrK1khf1mPF2u9Sljv42sfYqPFZnqYMYg==, } - monaco-marker-data-provider@1.2.2: + monaco-marker-data-provider@1.2.3: resolution: { - integrity: sha512-vLsgwsIm4fcqQAi54SsfLYuvWuIOgPV3kmkvtXVh7SGCO2cWvkXhLm4PAHpDyaK3w8AwWAxM/sP/vKXvZJi7Pw==, + integrity: sha512-BOiQs9UNEwVrF1rwYI32HUP8D7JTuHlJRlykx83e4+jfh1ceBWIBfB5ENDVSFUz651d95kxjKj36vV2JO3zr9w==, } monaco-types@0.1.0: @@ -3727,10 +3728,10 @@ packages: } engines: { node: ">=10" } - postcss@8.4.38: + postcss@8.4.39: resolution: { - integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==, + integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==, } engines: { node: ^10 || ^12 || >=14 } @@ -3799,10 +3800,10 @@ packages: integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==, } - react-hook-form@7.52.0: + react-hook-form@7.52.1: resolution: { - integrity: sha512-mJX506Xc6mirzLsmXUJyqlAI3Kj9Ph2RhplYhUVffeOQSnubK2uVqBFOBJmvKikvbFV91pxVXmDiR+QMF19x6A==, + integrity: sha512-uNKIhaoICJ5KQALYZ4TOaOLElyM+xipord+Ha3crEFhTntdLvWZqVY49Wqd/0GiVCA/f9NjemLeiNPjG7Hpurg==, } engines: { node: ">=12.22.0" } peerDependencies: @@ -3862,20 +3863,20 @@ packages: } engines: { node: ">=0.10.0" } - react-router-dom@6.23.1: + react-router-dom@6.24.0: resolution: { - integrity: sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==, + integrity: sha512-960sKuau6/yEwS8e+NVEidYQb1hNjAYM327gjEyXlc6r3Skf2vtwuJ2l7lssdegD2YjoKG5l8MsVyeTDlVeY8g==, } engines: { node: ">=14.0.0" } peerDependencies: react: ">=16.8" react-dom: ">=16.8" - react-router@6.23.1: + react-router@6.24.0: resolution: { - integrity: sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==, + integrity: sha512-sQrgJ5bXk7vbcC4BxQxeNa5UmboFm35we1AFK0VvQaz9g0LzxEIuLOhHIoZ8rnu9BO21ishGeL9no1WB76W/eg==, } engines: { node: ">=14.0.0" } peerDependencies: @@ -3999,10 +4000,10 @@ packages: engines: { node: ">=18.0.0", npm: ">=8.0.0" } hasBin: true - sass@1.77.5: + sass@1.77.6: resolution: { - integrity: sha512-oDfX1mukIlxacPdQqNb6mV2tVCrnE+P3nVYioy72V5tlk56CPNcO4TCuFcaCRKKfJ1M3lH95CleRS+dVKL2qMg==, + integrity: sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==, } engines: { node: ">=14.0.0" } hasBin: true @@ -4223,10 +4224,10 @@ packages: integrity: sha512-9zOLBtvgzEesEgpkJPrrh+uGTzSdNcYA+gk1jv3+14ytTsuxnunBko98OgbCCgUfcMzraEi4h+3zPrZaPoEsQg==, } - typescript@5.4.5: + typescript@5.5.3: resolution: { - integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==, + integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==, } engines: { node: ">=14.17" } hasBin: true @@ -4272,10 +4273,10 @@ packages: } engines: { node: ">=4" } - unified@11.0.4: + unified@11.0.5: resolution: { - integrity: sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==, + integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==, } unist-util-is@6.0.0: @@ -4372,10 +4373,10 @@ packages: peerDependencies: vite: ^2.6.0 || 3 || 4 || 5 - vite@5.3.1: + vite@5.3.2: resolution: { - integrity: sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==, + integrity: sha512-6lA7OBHBlXUxiJxbO5aAY2fsHHzDr1q7DvXYnyZycRs2Dz+dXBWuhpWHvmljTRTpQC2uvGmUFFkSHF2vGo90MA==, } engines: { node: ^18.0.0 || >=20.0.0 } hasBin: true @@ -5484,22 +5485,22 @@ snapshots: "@fastify/busboy@2.1.1": {} - "@floating-ui/core@1.6.2": + "@floating-ui/core@1.6.4": dependencies: - "@floating-ui/utils": 0.2.2 + "@floating-ui/utils": 0.2.4 - "@floating-ui/dom@1.6.5": + "@floating-ui/dom@1.6.7": dependencies: - "@floating-ui/core": 1.6.2 - "@floating-ui/utils": 0.2.2 + "@floating-ui/core": 1.6.4 + "@floating-ui/utils": 0.2.4 - "@floating-ui/react-dom@2.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": + "@floating-ui/react-dom@2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": dependencies: - "@floating-ui/dom": 1.6.5 + "@floating-ui/dom": 1.6.7 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - "@floating-ui/utils@0.2.2": {} + "@floating-ui/utils@0.2.4": {} "@jridgewell/gen-mapping@0.3.5": dependencies: @@ -5528,7 +5529,7 @@ snapshots: "@mui/base@5.0.0-beta.20(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 - "@floating-ui/react-dom": 2.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + "@floating-ui/react-dom": 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) "@mui/types": 7.2.14(@types/react@18.3.3) "@mui/utils": 5.15.20(@types/react@18.3.3)(react@18.3.1) "@popperjs/core": 2.11.8 @@ -5542,7 +5543,7 @@ snapshots: "@mui/base@5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 - "@floating-ui/react-dom": 2.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + "@floating-ui/react-dom": 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) "@mui/types": 7.2.14(@types/react@18.3.3) "@mui/utils": 5.15.20(@types/react@18.3.3)(react@18.3.1) "@popperjs/core": 2.11.8 @@ -5553,25 +5554,25 @@ snapshots: optionalDependencies: "@types/react": 18.3.3 - "@mui/core-downloads-tracker@5.15.20": {} + "@mui/core-downloads-tracker@5.15.21": {} - "@mui/icons-material@5.15.20(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react@18.3.1)": + "@mui/icons-material@5.15.21(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 - "@mui/material": 5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + "@mui/material": 5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 optionalDependencies: "@types/react": 18.3.3 - "@mui/lab@5.0.0-alpha.149(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": + "@mui/lab@5.0.0-alpha.149(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 "@mui/base": 5.0.0-beta.20(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - "@mui/material": 5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + "@mui/material": 5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) "@mui/system": 5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) "@mui/types": 7.2.14(@types/react@18.3.3) "@mui/utils": 5.15.20(@types/react@18.3.3)(react@18.3.1) - "@mui/x-tree-view": 6.0.0-alpha.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/base@5.0.0-beta.20(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/system@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + "@mui/x-tree-view": 6.0.0-alpha.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/base@5.0.0-beta.20(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/system@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) clsx: 2.1.1 prop-types: 15.8.1 react: 18.3.1 @@ -5581,11 +5582,11 @@ snapshots: "@emotion/styled": 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) "@types/react": 18.3.3 - "@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": + "@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 "@mui/base": 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - "@mui/core-downloads-tracker": 5.15.20 + "@mui/core-downloads-tracker": 5.15.21 "@mui/system": 5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) "@mui/types": 7.2.14(@types/react@18.3.3) "@mui/utils": 5.15.20(@types/react@18.3.3)(react@18.3.1) @@ -5652,10 +5653,10 @@ snapshots: optionalDependencies: "@types/react": 18.3.3 - "@mui/x-data-grid@7.7.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": + "@mui/x-data-grid@7.8.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 - "@mui/material": 5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + "@mui/material": 5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) "@mui/system": 5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) "@mui/utils": 5.15.20(@types/react@18.3.3)(react@18.3.1) clsx: 2.1.1 @@ -5668,13 +5669,13 @@ snapshots: - "@emotion/styled" - "@types/react" - "@mui/x-tree-view@6.0.0-alpha.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/base@5.0.0-beta.20(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/system@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": + "@mui/x-tree-view@6.0.0-alpha.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/base@5.0.0-beta.20(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/system@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 "@emotion/react": 11.11.4(@types/react@18.3.3)(react@18.3.1) "@emotion/styled": 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) "@mui/base": 5.0.0-beta.20(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - "@mui/material": 5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + "@mui/material": 5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) "@mui/system": 5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) "@mui/utils": 5.15.20(@types/react@18.3.3)(react@18.3.1) "@types/react-transition-group": 4.4.10 @@ -5752,7 +5753,7 @@ snapshots: "@popperjs/core@2.11.8": {} - "@remix-run/router@1.16.1": {} + "@remix-run/router@1.17.0": {} "@rollup/pluginutils@5.1.0(rollup@4.18.0)": dependencies: @@ -5854,12 +5855,12 @@ snapshots: "@svgr/babel-plugin-transform-react-native-svg": 8.1.0(@babel/core@7.24.7) "@svgr/babel-plugin-transform-svg-component": 8.0.0(@babel/core@7.24.7) - "@svgr/core@8.1.0(typescript@5.4.5)": + "@svgr/core@8.1.0(typescript@5.5.3)": dependencies: "@babel/core": 7.24.7 "@svgr/babel-preset": 8.1.0(@babel/core@7.24.7) camelcase: 6.3.0 - cosmiconfig: 8.3.6(typescript@5.4.5) + cosmiconfig: 8.3.6(typescript@5.5.3) snake-case: 3.0.4 transitivePeerDependencies: - supports-color @@ -5870,60 +5871,60 @@ snapshots: "@babel/types": 7.24.7 entities: 4.5.0 - "@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.4.5))": + "@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.5.3))": dependencies: "@babel/core": 7.24.7 "@svgr/babel-preset": 8.1.0(@babel/core@7.24.7) - "@svgr/core": 8.1.0(typescript@5.4.5) + "@svgr/core": 8.1.0(typescript@5.5.3) "@svgr/hast-util-to-babel-ast": 8.0.0 svg-parser: 2.0.4 transitivePeerDependencies: - supports-color - "@tauri-apps/api@1.5.6": {} + "@tauri-apps/api@1.6.0": {} - "@tauri-apps/cli-darwin-arm64@1.5.14": + "@tauri-apps/cli-darwin-arm64@1.6.0": optional: true - "@tauri-apps/cli-darwin-x64@1.5.14": + "@tauri-apps/cli-darwin-x64@1.6.0": optional: true - "@tauri-apps/cli-linux-arm-gnueabihf@1.5.14": + "@tauri-apps/cli-linux-arm-gnueabihf@1.6.0": optional: true - "@tauri-apps/cli-linux-arm64-gnu@1.5.14": + "@tauri-apps/cli-linux-arm64-gnu@1.6.0": optional: true - "@tauri-apps/cli-linux-arm64-musl@1.5.14": + "@tauri-apps/cli-linux-arm64-musl@1.6.0": optional: true - "@tauri-apps/cli-linux-x64-gnu@1.5.14": + "@tauri-apps/cli-linux-x64-gnu@1.6.0": optional: true - "@tauri-apps/cli-linux-x64-musl@1.5.14": + "@tauri-apps/cli-linux-x64-musl@1.6.0": optional: true - "@tauri-apps/cli-win32-arm64-msvc@1.5.14": + "@tauri-apps/cli-win32-arm64-msvc@1.6.0": optional: true - "@tauri-apps/cli-win32-ia32-msvc@1.5.14": + "@tauri-apps/cli-win32-ia32-msvc@1.6.0": optional: true - "@tauri-apps/cli-win32-x64-msvc@1.5.14": + "@tauri-apps/cli-win32-x64-msvc@1.6.0": optional: true - "@tauri-apps/cli@1.5.14": + "@tauri-apps/cli@1.6.0": optionalDependencies: - "@tauri-apps/cli-darwin-arm64": 1.5.14 - "@tauri-apps/cli-darwin-x64": 1.5.14 - "@tauri-apps/cli-linux-arm-gnueabihf": 1.5.14 - "@tauri-apps/cli-linux-arm64-gnu": 1.5.14 - "@tauri-apps/cli-linux-arm64-musl": 1.5.14 - "@tauri-apps/cli-linux-x64-gnu": 1.5.14 - "@tauri-apps/cli-linux-x64-musl": 1.5.14 - "@tauri-apps/cli-win32-arm64-msvc": 1.5.14 - "@tauri-apps/cli-win32-ia32-msvc": 1.5.14 - "@tauri-apps/cli-win32-x64-msvc": 1.5.14 + "@tauri-apps/cli-darwin-arm64": 1.6.0 + "@tauri-apps/cli-darwin-x64": 1.6.0 + "@tauri-apps/cli-linux-arm-gnueabihf": 1.6.0 + "@tauri-apps/cli-linux-arm64-gnu": 1.6.0 + "@tauri-apps/cli-linux-arm64-musl": 1.6.0 + "@tauri-apps/cli-linux-x64-gnu": 1.6.0 + "@tauri-apps/cli-linux-x64-musl": 1.6.0 + "@tauri-apps/cli-win32-arm64-msvc": 1.6.0 + "@tauri-apps/cli-win32-ia32-msvc": 1.6.0 + "@tauri-apps/cli-win32-x64-msvc": 1.6.0 "@types/babel__core@7.20.5": dependencies: @@ -5958,7 +5959,7 @@ snapshots: "@types/fs-extra@9.0.13": dependencies: - "@types/node": 20.14.2 + "@types/node": 20.14.9 "@types/hast@3.0.4": dependencies: @@ -5972,9 +5973,9 @@ snapshots: "@types/lodash-es@4.17.12": dependencies: - "@types/lodash": 4.17.5 + "@types/lodash": 4.17.6 - "@types/lodash@4.17.5": {} + "@types/lodash@4.17.6": {} "@types/mdast@4.0.4": dependencies: @@ -5982,7 +5983,7 @@ snapshots: "@types/ms@0.7.34": {} - "@types/node@20.14.2": + "@types/node@20.14.9": dependencies: undici-types: 5.26.5 @@ -6009,7 +6010,7 @@ snapshots: "@ungap/structured-clone@1.2.0": {} - "@vitejs/plugin-legacy@5.4.1(terser@5.31.1)(vite@5.3.1(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.1))": + "@vitejs/plugin-legacy@5.4.1(terser@5.31.1)(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1))": dependencies: "@babel/core": 7.24.7 "@babel/preset-env": 7.24.7(@babel/core@7.24.7) @@ -6020,18 +6021,18 @@ snapshots: regenerator-runtime: 0.14.1 systemjs: 6.15.1 terser: 5.31.1 - vite: 5.3.1(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.1) + vite: 5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) transitivePeerDependencies: - supports-color - "@vitejs/plugin-react@4.3.1(vite@5.3.1(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.1))": + "@vitejs/plugin-react@4.3.1(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1))": dependencies: "@babel/core": 7.24.7 "@babel/plugin-transform-react-jsx-self": 7.24.7(@babel/core@7.24.7) "@babel/plugin-transform-react-jsx-source": 7.24.7(@babel/core@7.24.7) "@types/babel__core": 7.20.5 react-refresh: 0.14.2 - vite: 5.3.1(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.1) + vite: 5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) transitivePeerDependencies: - supports-color @@ -6126,8 +6127,8 @@ snapshots: browserslist@4.23.1: dependencies: - caniuse-lite: 1.0.30001636 - electron-to-chromium: 1.4.803 + caniuse-lite: 1.0.30001639 + electron-to-chromium: 1.4.816 node-releases: 2.0.14 update-browserslist-db: 1.0.16(browserslist@4.23.1) @@ -6137,7 +6138,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001636: {} + caniuse-lite@1.0.30001639: {} ccount@2.0.1: {} @@ -6205,14 +6206,14 @@ snapshots: path-type: 4.0.0 yaml: 1.10.2 - cosmiconfig@8.3.6(typescript@5.4.5): + cosmiconfig@8.3.6(typescript@5.5.3): dependencies: import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 cross-env@7.0.3: dependencies: @@ -6258,7 +6259,7 @@ snapshots: no-case: 3.0.4 tslib: 2.6.3 - electron-to-chromium@1.4.803: {} + electron-to-chromium@1.4.816: {} end-of-stream@1.4.4: dependencies: @@ -6467,7 +6468,7 @@ snapshots: dependencies: binary-extensions: 2.3.0 - is-core-module@2.13.1: + is-core-module@2.14.0: dependencies: hasown: 2.0.2 @@ -6507,7 +6508,7 @@ snapshots: json5@2.2.3: {} - jsonc-parser@3.2.1: {} + jsonc-parser@3.3.1: {} jsonfile@6.1.0: dependencies: @@ -6638,7 +6639,7 @@ snapshots: merge-stream@2.0.0: {} - meta-json-schema@1.18.5-alpha6: {} + meta-json-schema@1.18.6: {} micromark-core-commonmark@2.0.1: dependencies: @@ -6802,7 +6803,7 @@ snapshots: vscode-languageserver-protocol: 3.17.5 vscode-uri: 3.0.8 - monaco-marker-data-provider@1.2.2: + monaco-marker-data-provider@1.2.3: dependencies: monaco-types: 0.1.0 @@ -6815,10 +6816,10 @@ snapshots: monaco-yaml@5.2.0(monaco-editor@0.49.0): dependencies: "@types/json-schema": 7.0.15 - jsonc-parser: 3.2.1 + jsonc-parser: 3.3.1 monaco-editor: 0.49.0 monaco-languageserver-types: 0.3.4 - monaco-marker-data-provider: 1.2.2 + monaco-marker-data-provider: 1.2.3 monaco-types: 0.1.0 monaco-worker-manager: 2.0.1(monaco-editor@0.49.0) path-browserify: 1.0.1 @@ -6919,7 +6920,7 @@ snapshots: picomatch@3.0.1: {} - postcss@8.4.38: + postcss@8.4.39: dependencies: nanoid: 3.3.7 picocolors: 1.0.1 @@ -6966,7 +6967,7 @@ snapshots: react-fast-compare@3.2.2: {} - react-hook-form@7.52.0(react@18.3.1): + react-hook-form@7.52.1(react@18.3.1): dependencies: react: 18.3.1 @@ -6994,7 +6995,7 @@ snapshots: react: 18.3.1 remark-parse: 11.0.0 remark-rehype: 11.1.0 - unified: 11.0.4 + unified: 11.0.5 unist-util-visit: 5.0.0 vfile: 6.0.1 transitivePeerDependencies: @@ -7009,16 +7010,16 @@ snapshots: react-refresh@0.14.2: {} - react-router-dom@6.23.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + react-router-dom@6.24.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - "@remix-run/router": 1.16.1 + "@remix-run/router": 1.17.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-router: 6.23.1(react@18.3.1) + react-router: 6.24.0(react@18.3.1) - react-router@6.23.1(react@18.3.1): + react-router@6.24.0(react@18.3.1): dependencies: - "@remix-run/router": 1.16.1 + "@remix-run/router": 1.17.0 react: 18.3.1 react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): @@ -7073,7 +7074,7 @@ snapshots: "@types/mdast": 4.0.4 mdast-util-from-markdown: 2.0.1 micromark-util-types: 2.0.0 - unified: 11.0.4 + unified: 11.0.5 transitivePeerDependencies: - supports-color @@ -7082,7 +7083,7 @@ snapshots: "@types/hast": 3.0.4 "@types/mdast": 4.0.4 mdast-util-to-hast: 13.2.0 - unified: 11.0.4 + unified: 11.0.5 vfile: 6.0.1 reselect@4.1.8: {} @@ -7093,7 +7094,7 @@ snapshots: resolve@1.22.8: dependencies: - is-core-module: 2.13.1 + is-core-module: 2.14.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -7119,7 +7120,7 @@ snapshots: "@rollup/rollup-win32-x64-msvc": 4.18.0 fsevents: 2.3.3 - sass@1.77.5: + sass@1.77.6: dependencies: chokidar: 3.6.0 immutable: 4.3.6 @@ -7226,7 +7227,7 @@ snapshots: types-pac@1.0.2: {} - typescript@5.4.5: {} + typescript@5.5.3: {} undici-types@5.26.5: {} @@ -7245,7 +7246,7 @@ snapshots: unicode-property-aliases-ecmascript@2.1.0: {} - unified@11.0.4: + unified@11.0.5: dependencies: "@types/unist": 3.0.2 bail: 2.0.2 @@ -7312,26 +7313,26 @@ snapshots: dependencies: monaco-editor: 0.49.0 - vite-plugin-svgr@4.2.0(rollup@4.18.0)(typescript@5.4.5)(vite@5.3.1(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.1)): + vite-plugin-svgr@4.2.0(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1)): dependencies: "@rollup/pluginutils": 5.1.0(rollup@4.18.0) - "@svgr/core": 8.1.0(typescript@5.4.5) - "@svgr/plugin-jsx": 8.1.0(@svgr/core@8.1.0(typescript@5.4.5)) - vite: 5.3.1(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.1) + "@svgr/core": 8.1.0(typescript@5.5.3) + "@svgr/plugin-jsx": 8.1.0(@svgr/core@8.1.0(typescript@5.5.3)) + vite: 5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) transitivePeerDependencies: - rollup - supports-color - typescript - vite@5.3.1(@types/node@20.14.2)(sass@1.77.5)(terser@5.31.1): + vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1): dependencies: esbuild: 0.21.5 - postcss: 8.4.38 + postcss: 8.4.39 rollup: 4.18.0 optionalDependencies: - "@types/node": 20.14.2 + "@types/node": 20.14.9 fsevents: 2.3.3 - sass: 1.77.5 + sass: 1.77.6 terser: 5.31.1 void-elements@3.1.0: {} diff --git a/clash-verge-rev/src-tauri/Cargo.lock b/clash-verge-rev/src-tauri/Cargo.lock index 24f9943841..ef122ce7ff 100644 --- a/clash-verge-rev/src-tauri/Cargo.lock +++ b/clash-verge-rev/src-tauri/Cargo.lock @@ -784,7 +784,7 @@ dependencies = [ [[package]] name = "clash-verge" -version = "1.6.6" +version = "1.7.0" dependencies = [ "anyhow", "auto-launch", @@ -5442,8 +5442,9 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tauri" -version = "1.6.7" -source = "git+https://github.com/tauri-apps/tauri?branch=1.x#c2d3afa4fbc0e6d118fe002a1b2ba97b4072438a" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e3b2c32de5bf5bed15a376064286643862b84e4e091d093f7bcdf1fda4b9758" dependencies = [ "anyhow", "base64 0.21.7", @@ -5505,8 +5506,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "1.5.2" -source = "git+https://github.com/tauri-apps/tauri?branch=1.x#c2d3afa4fbc0e6d118fe002a1b2ba97b4072438a" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c6ec7a5c3296330c7818478948b422967ce4649094696c985f61d50076d29c" dependencies = [ "anyhow", "cargo_toml", @@ -5523,8 +5525,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "1.4.3" -source = "git+https://github.com/tauri-apps/tauri?branch=1.x#c2d3afa4fbc0e6d118fe002a1b2ba97b4072438a" +version = "1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1aed706708ff1200ec12de9cfbf2582b5d8ec05f6a7293911091effbd22036b" dependencies = [ "base64 0.21.7", "brotli", @@ -5548,8 +5551,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "1.4.4" -source = "git+https://github.com/tauri-apps/tauri?branch=1.x#c2d3afa4fbc0e6d118fe002a1b2ba97b4072438a" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b88f831d2973ae4f81a706a0004e67dac87f2e4439973bbe98efbd73825d8ede" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -5561,8 +5565,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "0.14.3" -source = "git+https://github.com/tauri-apps/tauri?branch=1.x#c2d3afa4fbc0e6d118fe002a1b2ba97b4072438a" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3068ed62b63dedc705558f4248c7ecbd5561f0f8050949859ea0db2326f26012" dependencies = [ "gtk", "http 0.2.12", @@ -5581,8 +5586,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "0.14.8" -source = "git+https://github.com/tauri-apps/tauri?branch=1.x#c2d3afa4fbc0e6d118fe002a1b2ba97b4072438a" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c3db170233096aa30330feadcd895bf9317be97e624458560a20e814db7955" dependencies = [ "arboard", "cocoa 0.24.1", @@ -5601,8 +5607,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "1.5.4" -source = "git+https://github.com/tauri-apps/tauri?branch=1.x#c2d3afa4fbc0e6d118fe002a1b2ba97b4072438a" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2826db448309d382dac14d520f0c0a40839b87b57b977e59cf5f296b3ace6a93" dependencies = [ "brotli", "ctor", diff --git a/clash-verge-rev/src-tauri/Cargo.toml b/clash-verge-rev/src-tauri/Cargo.toml index 2f00f8d6e0..677df46b84 100644 --- a/clash-verge-rev/src-tauri/Cargo.toml +++ b/clash-verge-rev/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clash-verge" -version = "1.6.6" +version = "1.7.0" description = "clash verge" authors = ["zzzgydi", "wonfen", "MystiPanda"] license = "GPL-3.0-only" @@ -10,7 +10,7 @@ edition = "2021" build = "build.rs" [build-dependencies] -tauri-build = { git="https://github.com/tauri-apps/tauri",branch = "1.x", features = [] } +tauri-build = { version="1", features = [] } [dependencies] warp = "0.3" @@ -37,7 +37,7 @@ tokio = { version = "1", features = ["full"] } serde = { version = "1.0", features = ["derive"] } reqwest = { version = "0.12", features = ["json", "rustls-tls"] } sysproxy = { git="https://github.com/zzzgydi/sysproxy-rs", branch = "main" } -tauri = { git="https://github.com/tauri-apps/tauri",branch = "1.x", features = [ "fs-read-file", "fs-exists", "path-all", "protocol-asset", "dialog-open", "notification-all", "icon-png", "icon-ico", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all", "devtools"] } +tauri = { version="1", features = [ "fs-read-file", "fs-exists", "path-all", "protocol-asset", "dialog-open", "notification-all", "icon-png", "icon-ico", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all", "devtools"] } [target.'cfg(windows)'.dependencies] runas = "=1.2.0" deelevate = "0.2.0" diff --git a/clash-verge-rev/src-tauri/src/config/prfitem.rs b/clash-verge-rev/src-tauri/src/config/prfitem.rs index b5cfcf84b3..49c6455e52 100644 --- a/clash-verge-rev/src-tauri/src/config/prfitem.rs +++ b/clash-verge-rev/src-tauri/src/config/prfitem.rs @@ -428,8 +428,10 @@ impl PrfItem { /// create the enhanced item by using `merge` rule pub fn from_merge(uid: Option) -> Result { let mut id = help::get_uid("m"); + let mut template = tmpl::ITEM_MERGE_EMPTY.into(); if let Some(uid) = uid { id = uid; + template = tmpl::ITEM_MERGE.into(); } let file = format!("{id}.yaml"); @@ -445,7 +447,7 @@ impl PrfItem { option: None, home: None, updated: Some(chrono::Local::now().timestamp() as usize), - file_data: Some(tmpl::ITEM_MERGE.into()), + file_data: Some(template), }) } diff --git a/clash-verge-rev/src-tauri/src/enhance/mod.rs b/clash-verge-rev/src-tauri/src/enhance/mod.rs index 0ea77f5d2e..9d0f89c378 100644 --- a/clash-verge-rev/src-tauri/src/enhance/mod.rs +++ b/clash-verge-rev/src-tauri/src/enhance/mod.rs @@ -138,8 +138,28 @@ pub async fn enhance() -> (Mapping, Vec, HashMap) { let mut result_map = HashMap::new(); // 保存脚本日志 let mut exists_keys = use_keys(&config); // 保存出现过的keys - // 处理用户的profile + // 全局Merge和Script + if let ChainType::Merge(merge) = global_merge.data { + exists_keys.extend(use_keys(&merge)); + config = use_merge(merge, config.to_owned()); + } + if let ChainType::Script(script) = global_script.data { + let mut logs = vec![]; + + match use_script(script, config.to_owned()) { + Ok((res_config, res_logs)) => { + exists_keys.extend(use_keys(&res_config)); + config = res_config; + logs.extend(res_logs); + } + Err(err) => logs.push(("exception".into(), err.to_string())), + } + + result_map.insert(global_script.uid, logs); + } + + // 订阅关联的Merge、Script、Rules、Proxies、Groups if let ChainType::Rules(rules) = rules_item.data { config = use_seq(rules, config.to_owned(), "rules"); } @@ -172,27 +192,6 @@ pub async fn enhance() -> (Mapping, Vec, HashMap) { result_map.insert(script_item.uid, logs); } - // 全局Merge和Script - if let ChainType::Merge(merge) = global_merge.data { - exists_keys.extend(use_keys(&merge)); - config = use_merge(merge, config.to_owned()); - } - - if let ChainType::Script(script) = global_script.data { - let mut logs = vec![]; - - match use_script(script, config.to_owned()) { - Ok((res_config, res_logs)) => { - exists_keys.extend(use_keys(&res_config)); - config = res_config; - logs.extend(res_logs); - } - Err(err) => logs.push(("exception".into(), err.to_string())), - } - - result_map.insert(global_script.uid, logs); - } - // 合并默认的config for (key, value) in clash_config.into_iter() { if key.as_str() == Some("tun") { diff --git a/clash-verge-rev/src-tauri/src/utils/tmpl.rs b/clash-verge-rev/src-tauri/src/utils/tmpl.rs index be83ca51f5..15aa926d7b 100644 --- a/clash-verge-rev/src-tauri/src/utils/tmpl.rs +++ b/clash-verge-rev/src-tauri/src/utils/tmpl.rs @@ -15,6 +15,13 @@ pub const ITEM_MERGE: &str = "# Profile Enhancement Merge Template for Clash Ver profile: store-selected: true + +dns: + use-system-hosts: false +"; + +pub const ITEM_MERGE_EMPTY: &str = "# Profile Enhancement Merge Template for Clash Verge + "; /// enhanced profile diff --git a/clash-verge-rev/src-tauri/tauri.conf.json b/clash-verge-rev/src-tauri/tauri.conf.json index 7db1115ffc..7d294ea9f0 100644 --- a/clash-verge-rev/src-tauri/tauri.conf.json +++ b/clash-verge-rev/src-tauri/tauri.conf.json @@ -2,7 +2,7 @@ "$schema": "../node_modules/@tauri-apps/cli/schema.json", "package": { "productName": "Clash Verge", - "version": "1.6.6" + "version": "1.7.0" }, "build": { "distDir": "../dist", diff --git a/clash-verge-rev/src/components/base/base-search-box.tsx b/clash-verge-rev/src/components/base/base-search-box.tsx index 3a1545867a..f3f8d53eac 100644 --- a/clash-verge-rev/src/components/base/base-search-box.tsx +++ b/clash-verge-rev/src/components/base/base-search-box.tsx @@ -9,6 +9,9 @@ import useRegularExpressionIcon from "@/assets/image/component/use_regular_expre type SearchProps = { placeholder?: string; + matchCase?: boolean; + matchWholeWord?: boolean; + useRegularExpression?: boolean; onSearch: ( match: (content: string) => boolean, state: { @@ -23,9 +26,13 @@ type SearchProps = { export const BaseSearchBox = styled((props: SearchProps) => { const { t } = useTranslation(); const inputRef = useRef(null); - const [matchCase, setMatchCase] = useState(true); - const [matchWholeWord, setMatchWholeWord] = useState(false); - const [useRegularExpression, setUseRegularExpression] = useState(false); + const [matchCase, setMatchCase] = useState(props.matchCase ?? true); + const [matchWholeWord, setMatchWholeWord] = useState( + props.matchWholeWord ?? false + ); + const [useRegularExpression, setUseRegularExpression] = useState( + props.useRegularExpression ?? false + ); const [errorMessage, setErrorMessage] = useState(""); const iconStyle = { @@ -89,11 +96,11 @@ export const BaseSearchBox = styled((props: SearchProps) => { return ( { return ( void; - onChange?: (prev?: string, curr?: string) => void; +type Language = "yaml" | "javascript" | "css"; +type Schema = LanguageSchemaMap[T]; +interface LanguageSchemaMap { + yaml: "clash" | "merge"; + javascript: never; + css: never; } -// yaml worker -configureMonacoYaml(monaco, { - validate: true, - enableSchemaRequest: true, - schemas: [ - { - uri: "http://example.com/meta-json-schema.json", - fileMatch: ["**/*.clash.yaml"], - //@ts-ignore - schema: metaSchema as JSONSchema7, - }, - { - uri: "http://example.com/clash-verge-merge-json-schema.json", - fileMatch: ["**/*.merge.yaml"], - //@ts-ignore - schema: mergeSchema as JSONSchema7, - }, - ], -}); -// PAC definition -monaco.languages.typescript.javascriptDefaults.addExtraLib(pac, "pac.d.ts"); -monaco.languages.registerCompletionItemProvider("javascript", { - provideCompletionItems: (model, position) => ({ - suggestions: [ +interface Props { + open: boolean; + title?: string | ReactNode; + initialData: Promise; + readOnly?: boolean; + language: T; + schema?: Schema; + onChange?: (prev?: string, curr?: string) => void; + onSave?: (prev?: string, curr?: string) => void; + onClose: () => void; +} + +let initialized = false; +const monacoInitialization = () => { + if (initialized) return; + + // configure yaml worker + configureMonacoYaml(monaco, { + validate: true, + enableSchemaRequest: true, + schemas: [ { - label: "%mixed-port%", - kind: monaco.languages.CompletionItemKind.Text, - insertText: "%mixed-port%", - range: { - startLineNumber: position.lineNumber, - endLineNumber: position.lineNumber, - startColumn: model.getWordUntilPosition(position).startColumn - 1, - endColumn: model.getWordUntilPosition(position).endColumn - 1, - }, + uri: "http://example.com/meta-json-schema.json", + fileMatch: ["**/*.clash.yaml"], + // @ts-ignore + schema: metaSchema as JSONSchema7, + }, + { + uri: "http://example.com/clash-verge-merge-json-schema.json", + fileMatch: ["**/*.merge.yaml"], + // @ts-ignore + schema: mergeSchema as JSONSchema7, }, ], - }), -}); + }); + // configure PAC definition + monaco.languages.typescript.javascriptDefaults.addExtraLib(pac, "pac.d.ts"); -export const EditorViewer = (props: Props) => { - const { - title, - mode, - property, - open, - readOnly, - language, - schema, - onClose, - onChange, - } = props; + initialized = true; +}; + +export const EditorViewer = (props: Props) => { const { t } = useTranslation(); - const editorRef = useRef(); - const instanceRef = useRef(null); const themeMode = useThemeMode(); - const prevData = useRef(); + const [isMaximized, setIsMaximized] = useState(false); - useEffect(() => { - if (!open) return; + const { + open = false, + title = t("Edit File"), + initialData = Promise.resolve(""), + readOnly = false, + language = "yaml", + schema, + onChange, + onSave, + onClose, + } = props; - let fetchContent; - switch (mode) { - case "profile": // profile文件 - fetchContent = readProfileFile(property); - break; - case "text": // 文本内容 - fetchContent = Promise.resolve(property); - break; - } - fetchContent.then((data) => { - const dom = editorRef.current; + const editorRef = useRef(); + const prevData = useRef(""); + const currData = useRef(""); - if (!dom) return; + const editorWillMount = () => { + monacoInitialization(); // initialize monaco + }; - if (instanceRef.current) instanceRef.current.dispose(); + const editorDidMount = async ( + editor: monaco.editor.IStandaloneCodeEditor + ) => { + editorRef.current = editor; + // retrieve initial data + await initialData.then((data) => { + prevData.current = data; + currData.current = data; + + // create and set model const uri = monaco.Uri.parse(`${nanoid()}.${schema}.${language}`); const model = monaco.editor.createModel(data, language, uri); - instanceRef.current = editor.create(editorRef.current, { - model: model, - language: language, - tabSize: ["yaml", "javascript", "css"].includes(language) ? 2 : 4, // 根据语言类型设置缩进大小 - theme: themeMode === "light" ? "vs" : "vs-dark", - minimap: { enabled: dom.clientWidth >= 1000 }, // 超过一定宽度显示minimap滚动条 - mouseWheelZoom: true, // 按住Ctrl滚轮调节缩放比例 - readOnly: readOnly, // 只读模式 - readOnlyMessage: { value: t("ReadOnlyMessage") }, // 只读模式尝试编辑时的提示信息 - renderValidationDecorations: "on", // 只读模式下显示校验信息 - quickSuggestions: { - strings: true, // 字符串类型的建议 - comments: true, // 注释类型的建议 - other: true, // 其他类型的建议 - }, - padding: { - top: 33, // 顶部padding防止遮挡snippets - }, - fontFamily: `Fira Code, JetBrains Mono, Roboto Mono, "Source Code Pro", Consolas, Menlo, Monaco, monospace, "Courier New", "Apple Color Emoji"${ - getSystem() === "windows" ? ", twemoji mozilla" : "" - }`, - fontLigatures: true, // 连字符 - smoothScrolling: true, // 平滑滚动 - }); - - prevData.current = data; + editorRef.current?.setModel(model); }); + }; - return () => { - if (instanceRef.current) { - instanceRef.current.dispose(); - instanceRef.current = null; - } - }; - }, [open]); - - const onSave = useLockFn(async () => { - const currData = instanceRef.current?.getValue(); - - if (currData == null) return; - + const handleChange = useLockFn(async (value: string | undefined) => { try { - if (mode === "profile") { - await saveProfileFile(property, currData); - } - onChange?.(prevData.current, currData); + currData.current = value; + onChange?.(prevData.current, currData.current); + } catch (err: any) { + Notice.error(err.message || err.toString()); + } + }); + + const handleSave = useLockFn(async () => { + try { + !readOnly && onSave?.(prevData.current, currData.current); onClose(); } catch (err: any) { Notice.error(err.message || err.toString()); } }); + const handleClose = useLockFn(async () => { + try { + onClose(); + } catch (err: any) { + Notice.error(err.message || err.toString()); + } + }); + + useEffect(() => { + const unlistenResized = appWindow.onResized(() => { + appWindow.isMaximized().then((maximized) => { + setIsMaximized(() => maximized); + }); + }); + + return () => { + unlistenResized.then((fn) => fn()); + editorRef.current?.dispose(); + editorRef.current = undefined; + }; + }, []); + return ( - {title ?? t("Edit File")} + {title} -
+ = 1500, // 超过一定宽度显示minimap滚动条 + }, + mouseWheelZoom: true, // 按住Ctrl滚轮调节缩放比例 + readOnly: readOnly, // 只读模式 + readOnlyMessage: { value: t("ReadOnlyMessage") }, // 只读模式尝试编辑时的提示信息 + renderValidationDecorations: "on", // 只读模式下显示校验信息 + quickSuggestions: { + strings: true, // 字符串类型的建议 + comments: true, // 注释类型的建议 + other: true, // 其他类型的建议 + }, + padding: { + top: 33, // 顶部padding防止遮挡snippets + }, + fontFamily: `Fira Code, JetBrains Mono, Roboto Mono, "Source Code Pro", Consolas, Menlo, Monaco, monospace, "Courier New", "Apple Color Emoji"${ + getSystem() === "windows" ? ", twemoji mozilla" : "" + }`, + fontLigatures: true, // 连字符 + smoothScrolling: true, // 平滑滚动 + }} + editorWillMount={editorWillMount} + editorDidMount={editorDidMount} + onChange={handleChange} + /> + + + + editorRef.current + ?.getAction("editor.action.formatDocument") + ?.run() + } + > + + + + appWindow.toggleMaximize().then(() => editorRef.current?.layout()) + } + > + {isMaximized ? : } + + - {!readOnly && ( - )} diff --git a/clash-verge-rev/src/components/profile/profile-item.tsx b/clash-verge-rev/src/components/profile/profile-item.tsx index 7feaab2e86..0ecaed6fef 100644 --- a/clash-verge-rev/src/components/profile/profile-item.tsx +++ b/clash-verge-rev/src/components/profile/profile-item.tsx @@ -17,7 +17,12 @@ import { } from "@mui/material"; import { RefreshRounded, DragIndicator } from "@mui/icons-material"; import { useLoadingCache, useSetLoadingCache } from "@/services/states"; -import { updateProfile, viewProfile } from "@/services/cmds"; +import { + viewProfile, + readProfileFile, + updateProfile, + saveProfileFile, +} from "@/services/cmds"; import { Notice } from "@/components/base"; import { RulesEditorViewer } from "@/components/profile/rules-editor-viewer"; import { EditorViewer } from "@/components/profile/editor-viewer"; @@ -37,20 +42,13 @@ interface Props { itemData: IProfileItem; onSelect: (force: boolean) => void; onEdit: () => void; - onChange?: (prev?: string, curr?: string) => void; + onSave?: (prev?: string, curr?: string) => void; onDelete: () => void; } export const ProfileItem = (props: Props) => { - const { - selected, - activating, - itemData, - onSelect, - onEdit, - onChange, - onDelete, - } = props; + const { selected, activating, itemData, onSelect, onEdit, onSave, onDelete } = + props; const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: props.id }); @@ -215,16 +213,16 @@ export const ProfileItem = (props: Props) => { handler: onEditRules, disabled: option?.rules === null, }, - { - label: "Edit Proxies", - handler: onEditProxies, - disabled: option?.proxies === null, - }, - { - label: "Edit Groups", - handler: onEditGroups, - disabled: option?.groups === null, - }, + // { + // label: "Edit Proxies", + // handler: onEditProxies, + // disabled: option?.proxies === null, + // }, + // { + // label: "Edit Groups", + // handler: onEditGroups, + // disabled: option?.groups === null, + // }, { label: "Extend Config", handler: onEditMerge, @@ -256,16 +254,16 @@ export const ProfileItem = (props: Props) => { handler: onEditRules, disabled: option?.rules === null, }, - { - label: "Edit Proxies", - handler: onEditProxies, - disabled: option?.proxies === null, - }, - { - label: "Edit Groups", - handler: onEditGroups, - disabled: option?.groups === null, - }, + // { + // label: "Edit Proxies", + // handler: onEditProxies, + // disabled: option?.proxies === null, + // }, + // { + // label: "Edit Groups", + // handler: onEditGroups, + // disabled: option?.groups === null, + // }, { label: "Extend Config", handler: onEditMerge, @@ -474,55 +472,62 @@ export const ProfileItem = (props: Props) => { { + await saveProfileFile(uid, curr ?? ""); + onSave && onSave(prev, curr); + }} onClose={() => setFileOpen(false)} /> setRulesOpen(false)} /> { + await saveProfileFile(option?.proxies ?? "", curr ?? ""); + onSave && onSave(prev, curr); + }} onClose={() => setProxiesOpen(false)} /> { + await saveProfileFile(option?.proxies ?? "", curr ?? ""); + onSave && onSave(prev, curr); + }} onClose={() => setGroupsOpen(false)} /> { + await saveProfileFile(option?.merge ?? "", curr ?? ""); + onSave && onSave(prev, curr); + }} onClose={() => setMergeOpen(false)} /> { + await saveProfileFile(option?.script ?? "", curr ?? ""); + onSave && onSave(prev, curr); + }} onClose={() => setScriptOpen(false)} /> void; + onSave?: (prev?: string, curr?: string) => void; } // profile enhanced item export const ProfileMore = (props: Props) => { - const { id, logInfo = [], onChange } = props; + const { id, logInfo = [], onSave } = props; - const { t, i18n } = useTranslation(); + const { t } = useTranslation(); const [anchorEl, setAnchorEl] = useState(null); const [position, setPosition] = useState({ left: 0, top: 0 }); const [fileOpen, setFileOpen] = useState(false); @@ -169,12 +169,15 @@ export const ProfileMore = (props: Props) => { { + await saveProfileFile(id, curr ?? ""); + onSave && onSave(prev, curr); + }} onClose={() => setFileOpen(false)} /> diff --git a/clash-verge-rev/src/components/profile/rule-item.tsx b/clash-verge-rev/src/components/profile/rule-item.tsx index 2b30f42cad..7093a3e8fb 100644 --- a/clash-verge-rev/src/components/profile/rule-item.tsx +++ b/clash-verge-rev/src/components/profile/rule-item.tsx @@ -46,10 +46,14 @@ export const RuleItem = (props: Props) => { primary={ <> {rule.length === 3 ? rule[1] : "-"} diff --git a/clash-verge-rev/src/components/profile/rules-editor-viewer.tsx b/clash-verge-rev/src/components/profile/rules-editor-viewer.tsx index aab7dc27bf..6cf0f23316 100644 --- a/clash-verge-rev/src/components/profile/rules-editor-viewer.tsx +++ b/clash-verge-rev/src/components/profile/rules-editor-viewer.tsx @@ -17,6 +17,7 @@ import { } from "@dnd-kit/sortable"; import { Autocomplete, + Box, Button, Dialog, DialogActions, @@ -33,6 +34,8 @@ import { readProfileFile, saveProfileFile } from "@/services/cmds"; import { Notice, Switch } from "@/components/base"; import getSystem from "@/utils/get-system"; import { RuleItem } from "@/components/profile/rule-item"; +import { BaseSearchBox } from "../base/base-search-box"; +import { Virtuoso } from "react-virtuoso"; interface Props { profileUid: string; @@ -40,103 +43,201 @@ interface Props { property: string; open: boolean; onClose: () => void; - onChange?: (prev?: string, curr?: string) => void; + onSave?: (prev?: string, curr?: string) => void; } -const RuleTypeList = [ - "DOMAIN", - "DOMAIN-SUFFIX", - "DOMAIN-KEYWORD", - "DOMAIN-REGEX", - "GEOSITE", - "IP-CIDR", - "IP-SUFFIX", - "IP-ASN", - "GEOIP", - "SRC-GEOIP", - "SRC-IP-ASN", - "SRC-IP-CIDR", - "SRC-IP-SUFFIX", - "DST-PORT", - "SRC-PORT", - "IN-PORT", - "IN-TYPE", - "IN-USER", - "IN-NAME", - "PROCESS-PATH", - "PROCESS-PATH-REGEX", - "PROCESS-NAME", - "PROCESS-NAME-REGEX", - "UID", - "NETWORK", - "DSCP", - "RULE-SET", - "SUB-RULE", - "AND", - "OR", - "NOT", - "MATCH", -] as const; - -const NoResolveList = [ - "GEOIP", - "IP-ASN", - "IP-CIDR", - "IP-CIDR6", - "IP-SUFFIX", - "RULE-SET", -]; -const ExampleMap = { - DOMAIN: "example.com", - "DOMAIN-SUFFIX": "example.com", - "DOMAIN-KEYWORD": "example", - "DOMAIN-REGEX": "example.*", - GEOSITE: "youtube", - "IP-CIDR": "127.0.0.0/8", - "IP-SUFFIX": "8.8.8.8/24", - "IP-ASN": "13335", - GEOIP: "CN", - "SRC-GEOIP": "cn", - "SRC-IP-ASN": "9808", - "SRC-IP-CIDR": "192.168.1.201/32", - "SRC-IP-SUFFIX": "192.168.1.201/8", - "DST-PORT": "80", - "SRC-PORT": "7777", - "IN-PORT": "7890", - "IN-TYPE": "SOCKS/HTTP", - "IN-USER": "mihomo", - "IN-NAME": "ss", - "PROCESS-PATH": - getSystem() === "windows" - ? "C:Program FilesGoogleChromeApplicationchrome.exe" - : "/usr/bin/wget", - "PROCESS-PATH-REGEX": - getSystem() === "windows" ? "(?i).*Application\\chrome.*" : ".*bin/wget", - "PROCESS-NAME": getSystem() === "windows" ? "chrome.exe" : "curl", - "PROCESS-NAME-REGEX": ".*telegram.*", - UID: "1001", - NETWORK: "udp", - DSCP: "4", - "RULE-SET": "providername", - "SUB-RULE": "", - AND: "((DOMAIN,baidu.com),(NETWORK,UDP))", - OR: "((NETWORK,UDP),(DOMAIN,baidu.com))", - NOT: "((DOMAIN,baidu.com))", - MATCH: "", +const portValidator = (value: string): boolean => { + return new RegExp( + "^(?:[1-9]\\d{0,3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])$" + ).test(value); +}; +const ipv4CIDRValidator = (value: string): boolean => { + return new RegExp( + "^(?:(?:[1-9]?[0-9]|1[0-9][0-9]|2(?:[0-4][0-9]|5[0-5]))\\.){3}(?:[1-9]?[0-9]|1[0-9][0-9]|2(?:[0-4][0-9]|5[0-5]))(?:\\/(?:[12]?[0-9]|3[0-2]))$" + ).test(value); +}; +const ipv6CIDRValidator = (value: string): boolean => { + return new RegExp( + "^([0-9a-fA-F]{1,4}(?::[0-9a-fA-F]{1,4}){7}|::|:(?::[0-9a-fA-F]{1,4}){1,6}|[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,5}|(?:[0-9a-fA-F]{1,4}:){2}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){3}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){4}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){5}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,6}:)\\/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9])$" + ).test(value); }; -const BuiltinProxyPolicyList = ["DIRECT", "REJECT", "REJECT-DROP", "PASS"]; +const rules: { + name: string; + required?: boolean; + example?: string; + noResolve?: boolean; + validator?: (value: string) => boolean; +}[] = [ + { + name: "DOMAIN", + example: "example.com", + }, + { + name: "DOMAIN-SUFFIX", + example: "example.com", + }, + { + name: "DOMAIN-KEYWORD", + example: "example", + }, + { + name: "DOMAIN-REGEX", + example: "example.*", + }, + { + name: "GEOSITE", + example: "youtube", + }, + { + name: "GEOIP", + example: "CN", + noResolve: true, + }, + { + name: "SRC-GEOIP", + example: "CN", + }, + { + name: "IP-ASN", + example: "13335", + noResolve: true, + validator: (value) => (+value ? true : false), + }, + { + name: "SRC-IP-ASN", + example: "9808", + validator: (value) => (+value ? true : false), + }, + { + name: "IP-CIDR", + example: "127.0.0.0/8", + noResolve: true, + validator: (value) => ipv4CIDRValidator(value) || ipv6CIDRValidator(value), + }, + { + name: "IP-CIDR6", + example: "2620:0:2d0:200::7/32", + noResolve: true, + validator: (value) => ipv4CIDRValidator(value) || ipv6CIDRValidator(value), + }, + { + name: "SRC-IP-CIDR", + example: "192.168.1.201/32", + validator: (value) => ipv4CIDRValidator(value) || ipv6CIDRValidator(value), + }, + { + name: "IP-SUFFIX", + example: "8.8.8.8/24", + noResolve: true, + validator: (value) => ipv4CIDRValidator(value) || ipv6CIDRValidator(value), + }, + { + name: "SRC-IP-SUFFIX", + example: "192.168.1.201/8", + validator: (value) => ipv4CIDRValidator(value) || ipv6CIDRValidator(value), + }, + { + name: "SRC-PORT", + example: "7777", + validator: (value) => portValidator(value), + }, + { + name: "DST-PORT", + example: "80", + validator: (value) => portValidator(value), + }, + { + name: "IN-PORT", + example: "7890", + validator: (value) => portValidator(value), + }, + { + name: "DSCP", + example: "4", + }, + { + name: "PROCESS-NAME", + example: getSystem() === "windows" ? "chrome.exe" : "curl", + }, + { + name: "PROCESS-PATH", + example: + getSystem() === "windows" + ? "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" + : "/usr/bin/wget", + }, + { + name: "PROCESS-NAME-REGEX", + example: ".*telegram.*", + }, + { + name: "PROCESS-PATH-REGEX", + example: + getSystem() === "windows" ? "(?i).*Application\\chrome.*" : ".*bin/wget", + }, + { + name: "NETWORK", + example: "udp", + validator: (value) => ["tcp", "udp"].includes(value), + }, + { + name: "UID", + example: "1001", + validator: (value) => (+value ? true : false), + }, + { + name: "IN-TYPE", + example: "SOCKS/HTTP", + }, + { + name: "IN-USER", + example: "mihomo", + }, + { + name: "IN-NAME", + example: "ss", + }, + { + name: "SUB-RULE", + example: "(NETWORK,tcp)", + }, + { + name: "RULE-SET", + example: "providername", + noResolve: true, + }, + { + name: "AND", + example: "((DOMAIN,baidu.com),(NETWORK,UDP))", + }, + { + name: "OR", + example: "((NETWORK,UDP),(DOMAIN,baidu.com))", + }, + { + name: "NOT", + example: "((DOMAIN,baidu.com))", + }, + { + name: "MATCH", + required: false, + }, +]; + +const builtinProxyPolicies = ["DIRECT", "REJECT", "REJECT-DROP", "PASS"]; export const RulesEditorViewer = (props: Props) => { - const { title, profileUid, property, open, onClose, onChange } = props; + const { title, profileUid, property, open, onClose, onSave } = props; const { t } = useTranslation(); const [prevData, setPrevData] = useState(""); - const [ruleType, setRuleType] = - useState<(typeof RuleTypeList)[number]>("DOMAIN"); + const [match, setMatch] = useState(() => (_: string) => true); + + const [ruleType, setRuleType] = useState<(typeof rules)[number]>(rules[0]); const [ruleContent, setRuleContent] = useState(""); const [noResolve, setNoResolve] = useState(false); - const [proxyPolicy, setProxyPolicy] = useState("DIRECT"); + const [proxyPolicy, setProxyPolicy] = useState(builtinProxyPolicies[0]); const [proxyPolicyList, setProxyPolicyList] = useState([]); const [ruleList, setRuleList] = useState([]); const [ruleSetList, setRuleSetList] = useState([]); @@ -195,7 +296,7 @@ export const RulesEditorViewer = (props: Props) => { let ruleSetObj = yaml.load(data) as { "rule-providers": [] }; let subRuleObj = yaml.load(data) as { "sub-rules": [] }; setProxyPolicyList( - BuiltinProxyPolicyList.concat( + builtinProxyPolicies.concat( groupsObj["proxy-groups"] ? groupsObj["proxy-groups"].map((item: any) => item.name) : [] @@ -217,7 +318,20 @@ export const RulesEditorViewer = (props: Props) => { fetchProfile(); }, [open]); - const onSave = useLockFn(async () => { + const validateRule = () => { + if ((ruleType.required ?? true) && !ruleContent) { + throw new Error(t("Rule Condition Required")); + } + if (ruleType.validator && !ruleType.validator(ruleContent)) { + throw new Error(t("Invalid Rule")); + } + + return `${ruleType.name}${ + ruleContent ? "," + ruleContent : "" + },${proxyPolicy}${ruleType.noResolve && noResolve ? ",no-resolve" : ""}`; + }; + + const handleSave = useLockFn(async () => { try { let currData = yaml.dump({ prepend: prependSeq, @@ -225,7 +339,7 @@ export const RulesEditorViewer = (props: Props) => { delete: deleteSeq, }); await saveProfileFile(property, currData); - onChange?.(prevData, currData); + onSave?.(prevData, currData); onClose(); } catch (err: any) { Notice.error(err.message || err.toString()); @@ -237,106 +351,106 @@ export const RulesEditorViewer = (props: Props) => { {title ?? t("Edit Rules")} -
- - - + + + } + options={rules} + value={ruleType} + getOptionLabel={(option) => option.name} + renderOption={(props, option) => ( +
  • + {option.name} +
  • + )} + onChange={(_, value) => value && setRuleType(value)} + /> +
    + + + + {ruleType.name === "RULE-SET" && ( { - if (v) setRuleType(v); - }} renderInput={(params) => } + options={ruleSetList} + value={ruleContent} + onChange={(_, value) => value && setRuleContent(value)} /> - - - - {ruleType === "RULE-SET" && ( - { - if (v) setRuleContent(v); - }} - renderInput={(params) => } - /> - )} - {ruleType === "SUB-RULE" && ( - { - if (v) setRuleContent(v); - }} - renderInput={(params) => } - /> - )} - {ruleType !== "RULE-SET" && ruleType !== "SUB-RULE" && ( - { - setRuleContent(e.target.value); - }} - /> - )} - - - - { - if (v) setProxyPolicy(v); - }} - renderInput={(params) => } - /> - - {NoResolveList.includes(ruleType) && ( - - - { - setNoResolve(!noResolve); - }} - /> - )} -
    + {ruleType.name === "SUB-RULE" && ( + } + options={subRuleList} + value={ruleContent} + onChange={(_, value) => value && setRuleContent(value)} + /> + )} + {ruleType.name !== "RULE-SET" && ruleType.name !== "SUB-RULE" && ( + setRuleContent(e.target.value)} + /> + )} + + + + } + options={proxyPolicyList} + value={proxyPolicy} + renderOption={(props, option) => ( +
  • + {option} +
  • + )} + onChange={(_, value) => value && setProxyPolicy(value)} + /> +
    + {ruleType.noResolve && ( + + + setNoResolve(!noResolve)} + /> + + )} @@ -344,107 +458,119 @@ export const RulesEditorViewer = (props: Props) => { fullWidth variant="contained" onClick={() => { - let raw = `${ruleType}${ - ruleType === "MATCH" ? "" : "," + ruleContent - },${proxyPolicy}${ - NoResolveList.includes(ruleType) && noResolve - ? ",no-resolve" - : "" - }`; - if (appendSeq.includes(raw)) return; - setAppendSeq([...appendSeq, raw]); + try { + let raw = validateRule(); + if (appendSeq.includes(raw)) return; + setAppendSeq([...appendSeq, raw]); + } catch (err: any) { + Notice.error(err.message || err.toString()); + } }} > - {t("Add Append Rule")} + {t("Append Rule")} -
    -
    + + - {prependSeq.length > 0 && ( - - - { - return x; - })} - > - {prependSeq.map((item, index) => { - return ( - { - setPrependSeq(prependSeq.filter((v) => v !== item)); - }} - /> - ); - })} - - - - )} - - - {ruleList.map((item, index) => { - return ( - { - if (deleteSeq.includes(item)) { - setDeleteSeq(deleteSeq.filter((v) => v !== item)); - } else { - setDeleteSeq([...deleteSeq, item]); + setMatch(() => match)} + /> + 0 ? 1 : 0) + + (appendSeq.length > 0 ? 1 : 0) + } + increaseViewportBy={256} + itemContent={(index) => { + let shift = prependSeq.length > 0 ? 1 : 0; + if (prependSeq.length > 0 && index === 0) { + return ( + + { + return x; + })} + > + {prependSeq.map((item, index) => { + return ( + { + setPrependSeq( + prependSeq.filter((v) => v !== item) + ); + }} + /> + ); + })} + + + ); + } else if (index < ruleList.length + shift) { + let newIndex = index - shift; + return ( + - ); - })} - - - {appendSeq.length > 0 && ( - - { - return x; - })} - > - - {appendSeq.map((item, index) => { - return ( - { - setAppendSeq(appendSeq.filter((v) => v !== item)); - }} - /> - ); - })} - - - - )} -
    + ruleRaw={ruleList[newIndex]} + onDelete={() => { + if (deleteSeq.includes(ruleList[newIndex])) { + setDeleteSeq( + deleteSeq.filter((v) => v !== ruleList[newIndex]) + ); + } else { + setDeleteSeq((prev) => [...prev, ruleList[newIndex]]); + } + }} + /> + ); + } else { + return ( + + { + return x; + })} + > + {appendSeq.map((item, index) => { + return ( + { + setAppendSeq(appendSeq.filter((v) => v !== item)); + }} + /> + ); + })} + + + ); + } + }} + /> +
    @@ -452,7 +578,7 @@ export const RulesEditorViewer = (props: Props) => { {t("Cancel")} - diff --git a/clash-verge-rev/src/components/proxy/proxy-head.tsx b/clash-verge-rev/src/components/proxy/proxy-head.tsx index e05d4816ba..fca57d3224 100644 --- a/clash-verge-rev/src/components/proxy/proxy-head.tsx +++ b/clash-verge-rev/src/components/proxy/proxy-head.tsx @@ -132,6 +132,7 @@ export const ProxyHead = (props: Props) => { {textState === "filter" && ( { {textState === "url" && ( ((props, ref) => { @@ -146,8 +146,8 @@ export const ClashPortViewer = forwardRef((props, ref) => { @@ -169,8 +169,8 @@ export const ClashPortViewer = forwardRef((props, ref) => { @@ -193,8 +193,8 @@ export const ClashPortViewer = forwardRef((props, ref) => { @@ -218,8 +218,8 @@ export const ClashPortViewer = forwardRef((props, ref) => { diff --git a/clash-verge-rev/src/components/setting/mods/config-viewer.tsx b/clash-verge-rev/src/components/setting/mods/config-viewer.tsx index 3f04356d4e..76d8c48a57 100644 --- a/clash-verge-rev/src/components/setting/mods/config-viewer.tsx +++ b/clash-verge-rev/src/components/setting/mods/config-viewer.tsx @@ -22,15 +22,14 @@ export const ConfigViewer = forwardRef((_, ref) => { return ( {t("Runtime Config")} } - mode="text" - property={runtimeConfig} - open={open} + initialData={Promise.resolve(runtimeConfig)} readOnly language="yaml" schema="clash" diff --git a/clash-verge-rev/src/components/setting/mods/controller-viewer.tsx b/clash-verge-rev/src/components/setting/mods/controller-viewer.tsx index 3af15e0555..80611edf6f 100644 --- a/clash-verge-rev/src/components/setting/mods/controller-viewer.tsx +++ b/clash-verge-rev/src/components/setting/mods/controller-viewer.tsx @@ -48,8 +48,8 @@ export const ControllerViewer = forwardRef((props, ref) => { ((props, ref) => { ((props, ref) => { /> ((props, ref) => { ((props, ref) => { ((props, ref) => { <> ((props, ref) => { ((props, ref) => { {t("Edit")} PAC { + onSave={(_prev, curr) => { let pac = DEFAULT_PAC; if (curr && curr.trim().length > 0) { pac = curr; } setValue((v) => ({ ...v, pac_content: pac })); }} - onClose={() => { - setEditorOpen(false); - }} + onClose={() => setEditorOpen(false)} /> diff --git a/clash-verge-rev/src/components/setting/mods/theme-viewer.tsx b/clash-verge-rev/src/components/setting/mods/theme-viewer.tsx index fc74b25192..8d52d7fb59 100644 --- a/clash-verge-rev/src/components/setting/mods/theme-viewer.tsx +++ b/clash-verge-rev/src/components/setting/mods/theme-viewer.tsx @@ -124,12 +124,11 @@ export const ThemeViewer = forwardRef((props, ref) => { {t("Edit")} CSS { + onSave={(_prev, curr) => { theme.css_injection = curr; handleChange("css_injection"); }} diff --git a/clash-verge-rev/src/components/setting/mods/tun-viewer.tsx b/clash-verge-rev/src/components/setting/mods/tun-viewer.tsx index 7e437b4a41..46d26f83d2 100644 --- a/clash-verge-rev/src/components/setting/mods/tun-viewer.tsx +++ b/clash-verge-rev/src/components/setting/mods/tun-viewer.tsx @@ -144,8 +144,8 @@ export const TunViewer = forwardRef((props, ref) => { ((props, ref) => { ((props, ref) => { { <> setEditValue(e.target.value)} placeholder={t("Support %host, %port, %secret")} - autoComplete="off" /> { } > { const { t } = useTranslation(); @@ -378,7 +377,7 @@ const ProfilePage = () => { itemData={item} onSelect={(f) => onSelect(item.uid, f)} onEdit={() => viewerRef.current?.edit(item)} - onChange={async (prev, curr) => { + onSave={async (prev, curr) => { if (prev !== curr && profiles.current === item.uid) { await onEnhance(); } @@ -401,7 +400,7 @@ const ProfilePage = () => { { + onSave={async (prev, curr) => { if (prev !== curr) { await onEnhance(); } @@ -412,7 +411,7 @@ const ProfilePage = () => { { + onSave={async (prev, curr) => { if (prev !== curr) { await onEnhance(); } diff --git a/echo/.github/workflows/cd.yaml b/echo/.github/workflows/cd.yaml index a2723fedc6..12a7734c7d 100644 --- a/echo/.github/workflows/cd.yaml +++ b/echo/.github/workflows/cd.yaml @@ -26,7 +26,8 @@ jobs: steps: - id: set-matrix run: | - echo '::set-output name=matrix::{"platform":["amd64","arm64"]}' + echo '{"platform": ["amd64", "arm64"]}' > matrix.json + echo "matrix=$(cat matrix.json)" >> $GITHUB_OUTPUT build-bin: runs-on: ubuntu-latest diff --git a/echo/internal/glue/interface.go b/echo/internal/glue/interface.go index 0b2a193f22..011cdfbfef 100644 --- a/echo/internal/glue/interface.go +++ b/echo/internal/glue/interface.go @@ -10,5 +10,5 @@ type Reloader interface { type HealthChecker interface { // get relay by ID and check the connection health - HealthCheck(ctx context.Context, RelayID string) error + HealthCheck(ctx context.Context, RelayID string) (int64, error) } diff --git a/echo/internal/relay/conf/cfg.go b/echo/internal/relay/conf/cfg.go index 14e66a0dc9..c1633452ea 100644 --- a/echo/internal/relay/conf/cfg.go +++ b/echo/internal/relay/conf/cfg.go @@ -55,6 +55,10 @@ func (r *Config) GetWSRemoteAddr(baseAddr string) (string, error) { return addr, nil } +func (r *Config) GetTCPRemotes() string { + return fmt.Sprintf("%v", r.TCPRemotes) +} + func (r *Config) Validate() error { if r.Adjust() != nil { return errors.New("adjust config failed") diff --git a/echo/internal/relay/health_check.go b/echo/internal/relay/health_check.go index c410ed9467..c3070fa189 100644 --- a/echo/internal/relay/health_check.go +++ b/echo/internal/relay/health_check.go @@ -9,10 +9,10 @@ import ( var _ glue.HealthChecker = (*Server)(nil) -func (r *Server) HealthCheck(ctx context.Context, relayID string) error { +func (r *Server) HealthCheck(ctx context.Context, relayID string) (int64, error) { rs, ok := r.relayM.Load(relayID) if !ok { - return fmt.Errorf("label for relay: %s not found,can not health check", relayID) + return 0, fmt.Errorf("label for relay: %s not found,can not health check", relayID) } inner, _ := rs.(*Relay) return inner.relayServer.HealthCheck(ctx) diff --git a/echo/internal/transporter/base.go b/echo/internal/transporter/base.go index 5428333827..8bbbe7bae8 100644 --- a/echo/internal/transporter/base.go +++ b/echo/internal/transporter/base.go @@ -101,6 +101,7 @@ func (b *baseTransporter) RelayTCPConn(c net.Conn, handshakeF TCPHandShakeF) err return relayConn.Transport(remote.Label) } -func (b *baseTransporter) HealthCheck(ctx context.Context) error { - return b.relayer.HealthCheck(ctx, b.GetRemote().Clone()) +func (b *baseTransporter) HealthCheck(ctx context.Context) (int64, error) { + remote := b.GetRemote().Clone() + return remote.HandShakeDuration.Milliseconds(), b.relayer.HealthCheck(ctx, remote) } diff --git a/echo/internal/transporter/interface.go b/echo/internal/transporter/interface.go index b81a959b47..dd1da9d4b7 100644 --- a/echo/internal/transporter/interface.go +++ b/echo/internal/transporter/interface.go @@ -40,7 +40,7 @@ func newRelayClient(cfg *conf.Config) (RelayClient, error) { type RelayServer interface { ListenAndServe() error Close() error - HealthCheck(ctx context.Context) error + HealthCheck(ctx context.Context) (int64, error) // latency in ms } func NewRelayServer(cfg *conf.Config, cmgr cmgr.Cmgr) (RelayServer, error) { diff --git a/echo/internal/web/handlers.go b/echo/internal/web/handlers.go index 450206f309..dc29ab62f9 100644 --- a/echo/internal/web/handlers.go +++ b/echo/internal/web/handlers.go @@ -103,11 +103,12 @@ func (s *Server) HandleHealthCheck(c echo.Context) error { if relayLabel == "" { return echo.NewHTTPError(http.StatusBadRequest, "relay_label is required") } - if err := s.HealthCheck(c.Request().Context(), relayLabel); err != nil { - res := CommonResp{Message: err.Error()} + latency, err := s.HealthCheck(c.Request().Context(), relayLabel) + if err != nil { + res := HealthCheckResp{Message: err.Error(), ErrorCode: -1} return c.JSON(http.StatusBadRequest, res) } - return c.JSON(http.StatusOK, CommonResp{Message: "connect success"}) + return c.JSON(http.StatusOK, HealthCheckResp{Message: "connect success", Latency: latency}) } func (s *Server) CurrentConfig(c echo.Context) error { @@ -158,3 +159,9 @@ func (s *Server) ListConnections(c echo.Context) error { "AllCount": s.connMgr.CountConnection("active") + s.connMgr.CountConnection("closed"), }) } + +func (s *Server) ListRules(c echo.Context) error { + return c.Render(http.StatusOK, "rule_list.html", map[string]interface{}{ + "Configs": s.cfg.RelayConfigs, + }) +} diff --git a/echo/internal/web/server.go b/echo/internal/web/server.go index 3e64fc2a3f..300f2cb8a2 100644 --- a/echo/internal/web/server.go +++ b/echo/internal/web/server.go @@ -102,6 +102,7 @@ func NewServer( e.GET("/", s.index) e.GET("/connections/", s.ListConnections) + e.GET("/rules/", s.ListRules) e.GET("/clash_proxy_provider/", s.HandleClashProxyProvider) // api group diff --git a/echo/internal/web/templates/index.html b/echo/internal/web/templates/index.html index ac294b7310..1c1293f43e 100644 --- a/echo/internal/web/templates/index.html +++ b/echo/internal/web/templates/index.html @@ -70,6 +70,13 @@ >Connections +
  • + Rule List +
  • + + + + + + + + + Rules + + +
    +
    +

    Rules

    + + + + + + + + + + + + + {{range .Configs}} + + + + + + + + + {{end}} + +
    LabelListenListen TypeTransport TypeRemoteActions
    {{.Label}}{{.Listen}}{{.ListenType}}{{.TransportType}}{{.GetTCPRemotes}} + +
    +
    +
    + + + + diff --git a/echo/internal/web/types.go b/echo/internal/web/types.go index 7bf91dd98d..0b2caba0f0 100644 --- a/echo/internal/web/types.go +++ b/echo/internal/web/types.go @@ -1,5 +1,7 @@ package web -type CommonResp struct { - Message string `json:"msg"` +type HealthCheckResp struct { + ErrorCode int `json:"error_code"` // code = 0 means success + Message string `json:"msg"` + Latency int64 `json:"latency"` } diff --git a/geoip/lib/instance.go b/geoip/lib/instance.go index e7bcbf416d..06f6f6e849 100644 --- a/geoip/lib/instance.go +++ b/geoip/lib/instance.go @@ -25,7 +25,7 @@ func (i *Instance) Init(configFile string) error { var content []byte var err error configFile = strings.TrimSpace(configFile) - if strings.HasPrefix(configFile, "http://") || strings.HasPrefix(configFile, "https://") { + if strings.HasPrefix(strings.ToLower(configFile), "http://") || strings.HasPrefix(strings.ToLower(configFile), "https://") { content, err = getRemoteURLContent(configFile) } else { content, err = os.ReadFile(configFile) diff --git a/lede/package/base-files/files/lib/upgrade/common.sh b/lede/package/base-files/files/lib/upgrade/common.sh index af1182cb16..ef8d01e168 100644 --- a/lede/package/base-files/files/lib/upgrade/common.sh +++ b/lede/package/base-files/files/lib/upgrade/common.sh @@ -165,6 +165,23 @@ part_magic_fat() { [ "$magic" = "FAT" ] || [ "$magic_fat32" = "FAT32" ] } +fitblk_get_bootdev() { + [ -e /sys/firmware/devicetree/base/chosen/rootdisk ] || return + + local rootdisk="$(cat /sys/firmware/devicetree/base/chosen/rootdisk)" + local handle bootdev + for handle in /sys/class/block/*/of_node/phandle /sys/class/block/*/device/of_node/phandle; do + [ ! -e "$handle" ] && continue + if [ "$rootdisk" = "$(cat $handle)" ]; then + bootdev="${handle%/of_node/phandle}" + bootdev="${bootdev%/device}" + bootdev="${bootdev#/sys/class/block/}" + echo "$bootdev" + break + fi + done +} + export_bootdevice() { local cmdline uuid blockdev uevent line class local MAJOR MINOR DEVNAME DEVTYPE @@ -196,6 +213,7 @@ export_bootdevice() { done ;; /dev/*) + [ "$rootpart" = "/dev/fit0" ] && rootpart="$(fitblk_get_bootdev)" uevent="/sys/class/block/${rootpart##*/}/../uevent" ;; 0x[a-f0-9][a-f0-9][a-f0-9] | 0x[a-f0-9][a-f0-9][a-f0-9][a-f0-9] | \ diff --git a/lede/package/base-files/files/lib/upgrade/nand.sh b/lede/package/base-files/files/lib/upgrade/nand.sh index faeb3d6fc1..0a6fd8432d 100644 --- a/lede/package/base-files/files/lib/upgrade/nand.sh +++ b/lede/package/base-files/files/lib/upgrade/nand.sh @@ -7,6 +7,8 @@ CI_KERNPART="${CI_KERNPART:-kernel}" # 'ubi' partition on NAND contains UBI +# There are also CI_KERN_UBIPART and CI_ROOT_UBIPART if kernel +# and rootfs are on separated UBIs. CI_UBIPART="${CI_UBIPART:-ubi}" # 'rootfs' UBI volume on NAND contains the rootfs @@ -26,7 +28,7 @@ ubi_mknod() { nand_find_volume() { local ubidevdir ubivoldir - ubidevdir="/sys/devices/virtual/ubi/$1" + ubidevdir="/sys/class/ubi/" [ ! -d "$ubidevdir" ] && return 1 for ubivoldir in $ubidevdir/${1}_*; do [ ! -d "$ubivoldir" ] && continue @@ -39,13 +41,12 @@ nand_find_volume() { } nand_find_ubi() { - local ubidevdir ubidev mtdnum + local ubidevdir ubidev mtdnum cmtdnum mtdnum="$( find_mtd_index $1 )" [ ! "$mtdnum" ] && return 1 - for ubidevdir in /sys/devices/virtual/ubi/ubi*; do - [ ! -d "$ubidevdir" ] && continue + for ubidevdir in /sys/class/ubi/ubi*; do + [ ! -e "$ubidevdir/mtd_num" ] && continue cmtdnum="$( cat $ubidevdir/mtd_num )" - [ ! "$mtdnum" ] && continue if [ "$mtdnum" = "$cmtdnum" ]; then ubidev=$( basename $ubidevdir ) ubi_mknod "$ubidevdir" @@ -56,128 +57,175 @@ nand_find_ubi() { } nand_get_magic_long() { - dd if="$1" skip=$2 bs=4 count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' + (${3}cat "$1" | dd bs=4 "skip=${2:-0}" count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null } get_magic_long_tar() { - ( tar xf $1 $2 -O | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null + (tar xO${3}f "$1" "$2" | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null } -identify_magic() { - local magic=$1 - case "$magic" in - "55424923") - echo "ubi" - ;; - "31181006") - echo "ubifs" - ;; - "68737173") - echo "squashfs" - ;; - "d00dfeed") - echo "fit" - ;; - "4349"*) - echo "combined" - ;; - *) - echo "unknown $magic" - ;; - esac -} - - identify() { - identify_magic $(nand_get_magic_long "$1" "${2:-0}") + identify_magic_long $(nand_get_magic_long "$@") } identify_tar() { - identify_magic $(get_magic_long_tar "$1" "$2") + identify_magic_long $(get_magic_long_tar "$@") +} + +identify_if_gzip() { + if [ "$(identify "$1")" = gzip ]; then echo -n z; fi } nand_restore_config() { - sync - local ubidev=$( nand_find_ubi $CI_UBIPART ) + local ubidev=$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" ) local ubivol="$( nand_find_volume $ubidev rootfs_data )" - [ ! "$ubivol" ] && - ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )" + if [ ! "$ubivol" ]; then + ubivol="$( nand_find_volume $ubidev "$CI_ROOTPART" )" + if [ ! "$ubivol" ]; then + echo "cannot find ubifs data volume" + return 1 + fi + fi mkdir /tmp/new_root if ! mount -t ubifs /dev/$ubivol /tmp/new_root; then - echo "mounting ubifs $ubivol failed" + echo "cannot mount ubifs volume $ubivol" rmdir /tmp/new_root return 1 fi - mv "$1" "/tmp/new_root/$BACKUP_FILE" - umount /tmp/new_root - sync + if mv "$1" "/tmp/new_root/$BACKUP_FILE"; then + if umount /tmp/new_root; then + echo "configuration saved" + rmdir /tmp/new_root + return 0 + fi + else + umount /tmp/new_root + fi + echo "could not save configuration to ubifs volume $ubivol" rmdir /tmp/new_root + return 1 +} + +nand_remove_ubiblock() { + local ubivol="$1" + + local ubiblk="ubiblock${ubivol:3}" + if [ -e "/dev/$ubiblk" ]; then + umount "/dev/$ubiblk" 2>/dev/null && echo "unmounted /dev/$ubiblk" || : + if ! ubiblock -r "/dev/$ubivol"; then + echo "cannot remove $ubiblk" + return 1 + fi + fi +} + +nand_attach_ubi() { + local ubipart="$1" + local has_env="${2:-0}" + + local mtdnum="$( find_mtd_index "$ubipart" )" + if [ ! "$mtdnum" ]; then + >&2 echo "cannot find ubi mtd partition $ubipart" + return 1 + fi + + local ubidev="$( nand_find_ubi "$ubipart" )" + if [ ! "$ubidev" ]; then + >&2 ubiattach -m "$mtdnum" + ubidev="$( nand_find_ubi "$ubipart" )" + + if [ ! "$ubidev" ]; then + >&2 ubiformat /dev/mtd$mtdnum -y + >&2 ubiattach -m "$mtdnum" + ubidev="$( nand_find_ubi "$ubipart" )" + + if [ ! "$ubidev" ]; then + >&2 echo "cannot attach ubi mtd partition $ubipart" + return 1 + fi + + if [ "$has_env" -gt 0 ]; then + >&2 ubimkvol /dev/$ubidev -n 0 -N ubootenv -s 1MiB + >&2 ubimkvol /dev/$ubidev -n 1 -N ubootenv2 -s 1MiB + fi + fi + fi + + echo "$ubidev" + return 0 +} + +nand_detach_ubi() { + local ubipart="$1" + + local mtdnum="$( find_mtd_index "$ubipart" )" + if [ ! "$mtdnum" ]; then + echo "cannot find ubi mtd partition $ubipart" + return 1 + fi + + local ubidev="$( nand_find_ubi "$ubipart" )" + if [ "$ubidev" ]; then + for ubivol in $(find /dev -name "${ubidev}_*" -maxdepth 1 | sort); do + ubivol="${ubivol:5}" + nand_remove_ubiblock "$ubivol" || : + umount "/dev/$ubivol" && echo "unmounted /dev/$ubivol" || : + done + if ! ubidetach -m "$mtdnum"; then + echo "cannot detach ubi mtd partition $ubipart" + return 1 + fi + fi } nand_upgrade_prepare_ubi() { local rootfs_length="$1" local rootfs_type="$2" - local rootfs_data_max="$(fw_printenv -n rootfs_data_max 2>/dev/null)" + local rootfs_data_max="$(fw_printenv -n rootfs_data_max 2> /dev/null)" [ -n "$rootfs_data_max" ] && rootfs_data_max=$((rootfs_data_max)) local kernel_length="$3" local has_env="${4:-0}" + local kern_ubidev + local root_ubidev [ -n "$rootfs_length" -o -n "$kernel_length" ] || return 1 - local mtdnum="$( find_mtd_index "$CI_UBIPART" )" - if [ ! "$mtdnum" ]; then - echo "cannot find ubi mtd partition $CI_UBIPART" - return 1 + if [ -n "$CI_KERN_UBIPART" -a -n "$CI_ROOT_UBIPART" ]; then + kern_ubidev="$( nand_attach_ubi "$CI_KERN_UBIPART" "$has_env" )" + [ -n "$kern_ubidev" ] || return 1 + root_ubidev="$( nand_attach_ubi "$CI_ROOT_UBIPART" )" + [ -n "$root_ubidev" ] || return 1 + else + kern_ubidev="$( nand_attach_ubi "$CI_UBIPART" "$has_env" )" + [ -n "$kern_ubidev" ] || return 1 + root_ubidev="$kern_ubidev" fi - local ubidev="$( nand_find_ubi "$CI_UBIPART" )" - if [ ! "$ubidev" ]; then - ubiattach -m "$mtdnum" - sync - ubidev="$( nand_find_ubi "$CI_UBIPART" )" - fi + local kern_ubivol="$( nand_find_volume $kern_ubidev "$CI_KERNPART" )" + local root_ubivol="$( nand_find_volume $root_ubidev "$CI_ROOTPART" )" + local data_ubivol="$( nand_find_volume $root_ubidev rootfs_data )" + [ "$root_ubivol" = "$kern_ubivol" ] && root_ubivol= - if [ ! "$ubidev" ]; then - ubiformat /dev/mtd$mtdnum -y - ubiattach -m "$mtdnum" - sync - ubidev="$( nand_find_ubi "$CI_UBIPART" )" - [ "$has_env" -gt 0 ] && { - ubimkvol /dev/$ubidev -n 0 -N ubootenv -s 1MiB - ubimkvol /dev/$ubidev -n 1 -N ubootenv2 -s 1MiB - } - fi - - local kern_ubivol="$( nand_find_volume $ubidev $CI_KERNPART )" - local root_ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )" - local data_ubivol="$( nand_find_volume $ubidev rootfs_data )" - - local ubiblk ubiblkvol - for ubiblk in /dev/ubiblock*_? ; do - [ -e "$ubiblk" ] || continue - echo "removing ubiblock${ubiblk:13}" - ubiblkvol=ubi${ubiblk:13} - if ! ubiblock -r /dev/$ubiblkvol; then - echo "cannot remove $ubiblk" - return 1 - fi - done + # remove ubiblocks + [ "$kern_ubivol" ] && { nand_remove_ubiblock $kern_ubivol || return 1; } + [ "$root_ubivol" ] && { nand_remove_ubiblock $root_ubivol || return 1; } + [ "$data_ubivol" ] && { nand_remove_ubiblock $data_ubivol || return 1; } # kill volumes - [ "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_KERNPART || true - [ "$root_ubivol" -a "$root_ubivol" != "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_ROOTPART || true - [ "$data_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs_data || true + [ "$kern_ubivol" ] && ubirmvol /dev/$kern_ubidev -N "$CI_KERNPART" || : + [ "$root_ubivol" ] && ubirmvol /dev/$root_ubidev -N "$CI_ROOTPART" || : + [ "$data_ubivol" ] && ubirmvol /dev/$root_ubidev -N rootfs_data || : - # update kernel + # create kernel vol if [ -n "$kernel_length" ]; then - if ! ubimkvol /dev/$ubidev -N $CI_KERNPART -s $kernel_length; then + if ! ubimkvol /dev/$kern_ubidev -N "$CI_KERNPART" -s $kernel_length; then echo "cannot create kernel volume" return 1; fi fi - # update rootfs + # create rootfs vol if [ -n "$rootfs_length" ]; then local rootfs_size_param if [ "$rootfs_type" = "ubifs" ]; then @@ -185,157 +233,224 @@ nand_upgrade_prepare_ubi() { else rootfs_size_param="-s $rootfs_length" fi - if ! ubimkvol /dev/$ubidev -N $CI_ROOTPART $rootfs_size_param; then + if ! ubimkvol /dev/$root_ubidev -N "$CI_ROOTPART" $rootfs_size_param; then echo "cannot create rootfs volume" return 1; fi fi - # create rootfs_data for non-ubifs rootfs + # create rootfs_data vol for non-ubifs rootfs if [ "$rootfs_type" != "ubifs" ]; then - local availeb=$(cat /sys/devices/virtual/ubi/$ubidev/avail_eraseblocks) - local ebsize=$(cat /sys/devices/virtual/ubi/$ubidev/eraseblock_size) - local avail_size=$((availeb * ebsize)) local rootfs_data_size_param="-m" - if [ -n "$rootfs_data_max" ] && - [ "$rootfs_data_max" != "0" ] && - [ "$rootfs_data_max" -le "$avail_size" ]; then + if [ -n "$rootfs_data_max" ]; then rootfs_data_size_param="-s $rootfs_data_max" fi - if ! ubimkvol /dev/$ubidev -N rootfs_data $rootfs_data_size_param; then - echo "cannot initialize rootfs_data volume" - return 1 + if ! ubimkvol /dev/$root_ubidev -N rootfs_data $rootfs_data_size_param; then + if ! ubimkvol /dev/$root_ubidev -N rootfs_data -m; then + echo "cannot initialize rootfs_data volume" + return 1 + fi fi fi - sync + return 0 } -nand_do_upgrade_success() { - local conf_tar="/tmp/sysupgrade.tgz" - - sync - [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" - echo "sysupgrade successful" - umount -a - reboot -f -} - -# Flash the UBI image to MTD partition +# Write the UBI image to MTD ubi partition nand_upgrade_ubinized() { local ubi_file="$1" - local mtdnum="$(find_mtd_index "$CI_UBIPART")" + local gz="$2" - [ ! "$mtdnum" ] && { - CI_UBIPART="rootfs" - mtdnum="$(find_mtd_index "$CI_UBIPART")" - } + local ubi_length=$( (${gz}cat "$ubi_file" | wc -c) 2> /dev/null) - if [ ! "$mtdnum" ]; then - echo "cannot find mtd device $CI_UBIPART" - umount -a - reboot -f - fi + nand_detach_ubi "$CI_UBIPART" || return 1 - local mtddev="/dev/mtd${mtdnum}" - ubidetach -p "${mtddev}" || true - sync - ubiformat "${mtddev}" -y -f "${ubi_file}" - ubiattach -p "${mtddev}" - nand_do_upgrade_success + local mtdnum="$( find_mtd_index "$CI_UBIPART" )" + ${gz}cat "$ubi_file" | ubiformat "/dev/mtd$mtdnum" -S "$ubi_length" -y -f - && ubiattach -m "$mtdnum" } -# Write the UBIFS image to UBI volume +# Write the UBIFS image to UBI rootfs volume nand_upgrade_ubifs() { - local rootfs_length=$( (cat $1 | wc -c) 2> /dev/null) + local ubifs_file="$1" + local gz="$2" - nand_upgrade_prepare_ubi "$rootfs_length" "ubifs" "" "" + local ubifs_length=$( (${gz}cat "$ubifs_file" | wc -c) 2> /dev/null) + + nand_upgrade_prepare_ubi "$ubifs_length" "ubifs" "" "" || return 1 local ubidev="$( nand_find_ubi "$CI_UBIPART" )" - local root_ubivol="$(nand_find_volume $ubidev $CI_ROOTPART)" - ubiupdatevol /dev/$root_ubivol -s $rootfs_length $1 - - nand_do_upgrade_success + local root_ubivol="$(nand_find_volume $ubidev "$CI_ROOTPART")" + ${gz}cat "$ubifs_file" | ubiupdatevol /dev/$root_ubivol -s "$ubifs_length" - } +# Write the FIT image to UBI kernel volume nand_upgrade_fit() { local fit_file="$1" - local fit_length="$(wc -c < "$fit_file")" + local gz="$2" - nand_upgrade_prepare_ubi "" "" "$fit_length" "1" + local fit_length=$( (${gz}cat "$fit_file" | wc -c) 2> /dev/null) + + nand_upgrade_prepare_ubi "" "" "$fit_length" "1" || return 1 local fit_ubidev="$(nand_find_ubi "$CI_UBIPART")" local fit_ubivol="$(nand_find_volume $fit_ubidev "$CI_KERNPART")" - ubiupdatevol /dev/$fit_ubivol -s $fit_length $fit_file - - nand_do_upgrade_success + ${gz}cat "$fit_file" | ubiupdatevol /dev/$fit_ubivol -s "$fit_length" - } +# Write images in the TAR file to MTD partitions and/or UBI volumes as required nand_upgrade_tar() { local tar_file="$1" - local kernel_mtd="$(find_mtd_index $CI_KERNPART)" + local gz="$2" + local jffs2_markers="${CI_JFFS2_CLEAN_MARKERS:-0}" - local board_dir=$(tar tf "$tar_file" | grep -m 1 '^sysupgrade-.*/$') - board_dir=${board_dir%/} + # WARNING: This fails if tar contains more than one 'sysupgrade-*' directory. + local board_dir="$(tar t${gz}f "$tar_file" | grep -m 1 '^sysupgrade-.*/$')" + board_dir="${board_dir%/}" - kernel_length=$( (tar xf "$tar_file" ${board_dir}/kernel -O | wc -c) 2> /dev/null) - local has_rootfs=0 - local rootfs_length + local kernel_mtd kernel_length + if [ "$CI_KERNPART" != "none" ]; then + kernel_mtd="$(find_mtd_index "$CI_KERNPART")" + kernel_length=$( (tar xO${gz}f "$tar_file" "$board_dir/kernel" | wc -c) 2> /dev/null) + [ "$kernel_length" = 0 ] && kernel_length= + fi + local rootfs_length=$( (tar xO${gz}f "$tar_file" "$board_dir/root" | wc -c) 2> /dev/null) + [ "$rootfs_length" = 0 ] && rootfs_length= local rootfs_type + [ "$rootfs_length" ] && rootfs_type="$(identify_tar "$tar_file" "$board_dir/root" "$gz")" - tar tf "$tar_file" ${board_dir}/root 1>/dev/null 2>/dev/null && has_rootfs=1 - [ "$has_rootfs" = "1" ] && { - rootfs_length=$( (tar xf "$tar_file" ${board_dir}/root -O | wc -c) 2> /dev/null) - rootfs_type="$(identify_tar "$tar_file" ${board_dir}/root)" - } + local ubi_kernel_length + if [ "$kernel_length" ]; then + if [ "$kernel_mtd" ]; then + # On some devices, the raw kernel and ubi partitions overlap. + # These devices brick if the kernel partition is erased. + # Hence only invalidate kernel for now. + dd if=/dev/zero bs=4096 count=1 2> /dev/null | \ + mtd write - "$CI_KERNPART" + else + ubi_kernel_length="$kernel_length" + fi + fi - local has_kernel=1 local has_env=0 + nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "$ubi_kernel_length" "$has_env" || return 1 - [ "$kernel_length" != 0 -a -n "$kernel_mtd" ] && { - tar xf "$tar_file" ${board_dir}/kernel -O | mtd write - $CI_KERNPART - } - [ "$kernel_length" = 0 -o ! -z "$kernel_mtd" ] && has_kernel= + if [ "$rootfs_length" ]; then + local ubidev="$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" )" + local root_ubivol="$( nand_find_volume $ubidev "$CI_ROOTPART" )" + tar xO${gz}f "$tar_file" "$board_dir/root" | \ + ubiupdatevol /dev/$root_ubivol -s "$rootfs_length" - + fi + if [ "$kernel_length" ]; then + if [ "$kernel_mtd" ]; then + if [ "$jffs2_markers" = 1 ]; then + flash_erase -j "/dev/mtd${kernel_mtd}" 0 0 + tar xO${gz}f "$tar_file" "$board_dir/kernel" | \ + nandwrite "/dev/mtd${kernel_mtd}" - + else + tar xO${gz}f "$tar_file" "$board_dir/kernel" | \ + mtd write - "$CI_KERNPART" + fi + else + local ubidev="$( nand_find_ubi "${CI_KERN_UBIPART:-$CI_UBIPART}" )" + local kern_ubivol="$( nand_find_volume $ubidev "$CI_KERNPART" )" + tar xO${gz}f "$tar_file" "$board_dir/kernel" | \ + ubiupdatevol /dev/$kern_ubivol -s "$kernel_length" - + fi + fi - nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "${has_kernel:+$kernel_length}" "$has_env" + return 0 +} - local ubidev="$( nand_find_ubi "$CI_UBIPART" )" - [ "$has_kernel" = "1" ] && { - local kern_ubivol="$( nand_find_volume $ubidev $CI_KERNPART )" - tar xf "$tar_file" ${board_dir}/kernel -O | \ - ubiupdatevol /dev/$kern_ubivol -s $kernel_length - - } +nand_verify_if_gzip_file() { + local file="$1" + local gz="$2" - [ "$has_rootfs" = "1" ] && { - local root_ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )" - tar xf "$tar_file" ${board_dir}/root -O | \ - ubiupdatevol /dev/$root_ubivol -s $rootfs_length - - } - nand_do_upgrade_success + if [ "$gz" = z ]; then + echo "verifying compressed sysupgrade file integrity" + if ! gzip -t "$file"; then + echo "corrupted compressed sysupgrade file" + return 1 + fi + fi +} + +nand_verify_tar_file() { + local file="$1" + local gz="$2" + + echo "verifying sysupgrade tar file integrity" + if ! tar xO${gz}f "$file" > /dev/null; then + echo "corrupted sysupgrade tar file" + return 1 + fi +} + +nand_do_flash_file() { + local file="$1" + + local gz="$(identify_if_gzip "$file")" + local file_type="$(identify "$file" "" "$gz")" + + [ ! "$(find_mtd_index "$CI_UBIPART")" ] && CI_UBIPART=rootfs + + case "$file_type" in + "fit") + nand_verify_if_gzip_file "$file" "$gz" || return 1 + nand_upgrade_fit "$file" "$gz" + ;; + "ubi") + nand_verify_if_gzip_file "$file" "$gz" || return 1 + nand_upgrade_ubinized "$file" "$gz" + ;; + "ubifs") + nand_verify_if_gzip_file "$file" "$gz" || return 1 + nand_upgrade_ubifs "$file" "$gz" + ;; + *) + nand_verify_tar_file "$file" "$gz" || return 1 + nand_upgrade_tar "$file" "$gz" + ;; + esac +} + +nand_do_restore_config() { + local conf_tar="/tmp/sysupgrade.tgz" + [ ! -f "$conf_tar" ] || nand_restore_config "$conf_tar" } # Recognize type of passed file and start the upgrade process nand_do_upgrade() { - local file_type=$(identify $1) + local file="$1" - [ ! "$(find_mtd_index "$CI_UBIPART")" ] && CI_UBIPART="rootfs" - - case "$file_type" in - "fit") nand_upgrade_fit $1;; - "ubi") nand_upgrade_ubinized $1;; - "ubifs") nand_upgrade_ubifs $1;; - *) nand_upgrade_tar $1;; - esac + sync + nand_do_flash_file "$file" && nand_do_upgrade_success + nand_do_upgrade_failed } -# Check if passed file is a valid one for NAND sysupgrade. Currently it accepts -# 3 types of files: -# 1) UBI - should contain an ubinized image, header is checked for the proper -# MAGIC -# 2) UBIFS - should contain UBIFS partition that will replace "rootfs" volume, -# header is checked for the proper MAGIC -# 3) TAR - archive has to include "sysupgrade-BOARD" directory with a non-empty -# "CONTROL" file (at this point its content isn't verified) +nand_do_upgrade_success() { + if nand_do_restore_config && sync; then + echo "sysupgrade successful" + umount -a + reboot -f + fi + nand_do_upgrade_failed +} + +nand_do_upgrade_failed() { + sync + echo "sysupgrade failed" + # Should we reboot or bring up some failsafe mode instead? + umount -a + reboot -f +} + +# Check if passed file is a valid one for NAND sysupgrade. +# Currently it accepts 4 types of files: +# 1) UBI: a ubinized image containing required UBI volumes. +# 2) UBIFS: a UBIFS rootfs volume image. +# 3) FIT: a FIT image containing kernel and rootfs. +# 4) TAR: an archive that includes directory "sysupgrade-${BOARD_NAME}" containing +# a non-empty "CONTROL" file and required partition and/or volume images. # # You usually want to call this function in platform_check_image. # @@ -343,14 +458,25 @@ nand_do_upgrade() { # $(2): file to be checked nand_do_platform_check() { local board_name="$1" - local tar_file="$2" - local control_length=$( (tar xf $tar_file sysupgrade-$board_name/CONTROL -O | wc -c) 2> /dev/null) - local file_type="$(identify $2)" + local file="$2" - [ "$control_length" = 0 -a "$file_type" != "ubi" -a "$file_type" != "ubifs" -a "$file_type" != "fit" ] && { - echo "Invalid sysupgrade file." - return 1 - } + local gz="$(identify_if_gzip "$file")" + local file_type="$(identify "$file" "" "$gz")" + local control_length=$( (tar xO${gz}f "$file" "sysupgrade-${board_name//,/_}/CONTROL" | wc -c) 2> /dev/null) + + if [ "$control_length" = 0 ]; then + control_length=$( (tar xO${gz}f "$file" "sysupgrade-${board_name//_/,}/CONTROL" | wc -c) 2> /dev/null) + fi + + if [ "$control_length" != 0 ]; then + nand_verify_tar_file "$file" "$gz" || return 1 + else + nand_verify_if_gzip_file "$file" "$gz" || return 1 + if [ "$file_type" != "fit" -a "$file_type" != "ubi" -a "$file_type" != "ubifs" ]; then + echo "invalid sysupgrade file" + return 1 + fi + fi return 0 } diff --git a/lede/package/base-files/files/lib/upgrade/stage2 b/lede/package/base-files/files/lib/upgrade/stage2 index da84698ddd..c6bb150f5f 100755 --- a/lede/package/base-files/files/lib/upgrade/stage2 +++ b/lede/package/base-files/files/lib/upgrade/stage2 @@ -45,7 +45,8 @@ switch_to_ramfs() { mtd partx losetup mkfs.ext4 nandwrite flash_erase \ ubiupdatevol ubiattach ubiblock ubiformat \ ubidetach ubirsvol ubirmvol ubimkvol \ - snapshot snapshot_tool date \ + snapshot snapshot_tool date logger \ + /usr/sbin/fw_printenv /usr/bin/fwtool \ $RAMFS_COPY_LOSETUP $RAMFS_COPY_LVM \ $RAMFS_COPY_BIN do diff --git a/lede/package/kernel/mt76/Makefile b/lede/package/kernel/mt76/Makefile index 8336fcf1b0..6b5041d3c5 100644 --- a/lede/package/kernel/mt76/Makefile +++ b/lede/package/kernel/mt76/Makefile @@ -14,6 +14,10 @@ PKG_SOURCE_DATE:=2022-12-22 PKG_SOURCE_VERSION:=5b509e80384ab019ac11aa90c81ec0dbb5b0d7f2 PKG_MIRROR_HASH:=6fc25df4d28becd010ff4971b23731c08b53e69381a9e4c868091899712f78a9 PATCH_DIR:=./patches-5.4 +else ifdef CONFIG_LINUX_6_1 +PKG_SOURCE_DATE:=2024-02-03 +PKG_SOURCE_VERSION:=9827df56b241601f29bf496b62545713c67afb61 +PKG_MIRROR_HASH:=d758db4228eed55c93fff8f87ec92d482b8507a68698b28dcf273e12b02ddf5f else ifdef CONFIG_LINUX_6_6 PKG_SOURCE_DATE:=2024-02-03 PKG_SOURCE_VERSION:=9827df56b241601f29bf496b62545713c67afb61 diff --git a/lede/package/lean/autocore/files/x86/autocore b/lede/package/lean/autocore/files/x86/autocore index ecae6d7d21..f5d8a0106c 100755 --- a/lede/package/lean/autocore/files/x86/autocore +++ b/lede/package/lean/autocore/files/x86/autocore @@ -66,9 +66,7 @@ start() ethtool -K $c tx-checksum-ipv4 on >/dev/null 2>&1 ethtool -K $c tx-checksum-ipv6 on >/dev/null 2>&1) ethtool -K $c tx-scatter-gather on >/dev/null 2>&1 - ethtool -K $c gso on >/dev/null 2>&1 ethtool -K $c tso on >/dev/null 2>&1 - ethtool -K $c ufo on >/dev/null 2>&1 done [ -f /etc/index.htm ] && mv /etc/index.htm /usr/lib/lua/luci/view/admin_status/index.htm diff --git a/lede/package/system/fstools/Makefile b/lede/package/system/fstools/Makefile index a61d4bb5a0..d54d5f872b 100644 --- a/lede/package/system/fstools/Makefile +++ b/lede/package/system/fstools/Makefile @@ -12,15 +12,16 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/fstools.git -PKG_MIRROR_HASH:=edda9151c73c1adfe369f5e315347344727a540ad57d3e2b41b9f57f9d4313fe -PKG_SOURCE_DATE:=2023-01-22 -PKG_SOURCE_VERSION:=1ea5855e980cd88766dd9f615e78e7dd6edfbb74 +PKG_MIRROR_HASH:=32e39891455b602e9deb367c9ce2d099dc72353fad0bf0433307416925f7b393 +PKG_SOURCE_DATE:=2024-01-22 +PKG_SOURCE_VERSION:=08cd7083cac4bddf88459efa0881ee52858e7d0a CMAKE_INSTALL:=1 PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:= PKG_USE_MIPS16:=0 +PKG_BUILD_FLAGS:=no-mips16 PKG_FLAGS:=nonshared PKG_BUILD_DEPENDS := util-linux @@ -48,7 +49,7 @@ define Package/fstools/config depends on PACKAGE_fstools depends on NAND_SUPPORT bool "Support extroot functionality with UBIFS" - default n + default y help This option makes it possible to use extroot functionality if the root filesystem resides on an UBIFS partition @@ -82,7 +83,7 @@ define Package/block-mount SECTION:=base CATEGORY:=Base system TITLE:=Block device mounting and checking - DEPENDS:=+fstools +ubox +libubox +libuci +libblobmsg-json +libjson-c + DEPENDS:=+ubox +libubox +libuci +libblobmsg-json +libjson-c endef define Package/blockd diff --git a/lede/package/system/fstools/patches/0001-fstools-support-extroot-for-non-MTD-rootfs_data.patch b/lede/package/system/fstools/patches/0001-fstools-support-extroot-for-non-MTD-rootfs_data.patch deleted file mode 100644 index 20a68484d3..0000000000 --- a/lede/package/system/fstools/patches/0001-fstools-support-extroot-for-non-MTD-rootfs_data.patch +++ /dev/null @@ -1,129 +0,0 @@ -From: Qi Liu - -In order to support extroot, block extroot command has to be able to -discover and properly mount the rootfs_data volume in order to discover -the extroot volume. Currently this process can only discover MTD devices. -This patch leverages libfstools in a similar way as mount_root to -discover, initialize, and mount rootfs_data volume. It would enable any -device with non-MTD rootfs_data volume to support extroot, including x86. - -Signed-off-by: Qi Liu ---- - CMakeLists.txt | 4 ++-- - block.c | 40 ++++++++++++++++++++++++++++++++++++++++ - libfstools/fstype.h | 12 ++++++++++++ - libfstools/libfstools.h | 11 +---------- - 4 files changed, 55 insertions(+), 12 deletions(-) - create mode 100644 libfstools/fstype.h - ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -78,9 +78,9 @@ INSTALL(TARGETS blockd RUNTIME DESTINATI - ADD_EXECUTABLE(block block.c probe.c probe-libblkid.c) - IF(DEFINED CMAKE_UBIFS_EXTROOT) - ADD_DEFINITIONS(-DUBIFS_EXTROOT) -- TARGET_LINK_LIBRARIES(block blkid-tiny dl uci ubox ubus blobmsg_json ubi-utils ${json}) -+ TARGET_LINK_LIBRARIES(block fstools blkid-tiny dl uci ubox ubus blobmsg_json ubi-utils ${json}) - ELSE(DEFINED CMAKE_UBIFS_EXTROOT) -- TARGET_LINK_LIBRARIES(block blkid-tiny dl uci ubox ubus blobmsg_json ${json}) -+ TARGET_LINK_LIBRARIES(block fstools blkid-tiny dl uci ubox ubus blobmsg_json ${json}) - ENDIF(DEFINED CMAKE_UBIFS_EXTROOT) - INSTALL(TARGETS block RUNTIME DESTINATION sbin) - ---- a/block.c -+++ b/block.c -@@ -44,6 +44,8 @@ - #include - #include - -+#include "libfstools/fstype.h" -+#include "libfstools/volume.h" - #include "probe.h" - - #define AUTOFS_MOUNT_PATH "/tmp/run/blockd/" -@@ -1696,6 +1698,44 @@ static int main_extroot(int argc, char * - } - #endif - -+ /* Find volume using libfstools */ -+ struct volume *data = volume_find("rootfs_data"); -+ if (data) { -+ volume_init(data); -+ -+ switch (volume_identify(data)) { -+ case FS_EXT4: { -+ char cfg[] = "/tmp/ext4_cfg"; -+ -+ /* Mount volume and try extroot (using fstab from that vol) */ -+ mkdir_p(cfg, 0755); -+ if (!mount(data->blk, cfg, "ext4", MS_NOATIME, NULL)) { -+ err = mount_extroot(cfg); -+ umount2(cfg, MNT_DETACH); -+ } -+ if (err < 0) -+ rmdir("/tmp/overlay"); -+ rmdir(cfg); -+ return err; -+ } -+ -+ case FS_F2FS: { -+ char cfg[] = "/tmp/f2fs_cfg"; -+ -+ /* Mount volume and try extroot (using fstab from that vol) */ -+ mkdir_p(cfg, 0755); -+ if (!mount(data->blk, cfg, "f2fs", MS_NOATIME, NULL)) { -+ err = mount_extroot(cfg); -+ umount2(cfg, MNT_DETACH); -+ } -+ if (err < 0) -+ rmdir("/tmp/overlay"); -+ rmdir(cfg); -+ return err; -+ } -+ } -+ } -+ - /* As a last resort look for /etc/config/fstab on "rootfs" partition */ - return mount_extroot(NULL); - } ---- /dev/null -+++ b/libfstools/fstype.h -@@ -0,0 +1,13 @@ -+#ifndef _FS_TYPE_H__ -+#define _FS_TYPE_H__ -+enum { -+ FS_NONE, -+ FS_SNAPSHOT, -+ FS_JFFS2, -+ FS_DEADCODE, -+ FS_UBIFS, -+ FS_F2FS, -+ FS_EXT4, -+ FS_TARGZ, -+}; -+#endif -\ No newline at end of file ---- a/libfstools/libfstools.h -+++ b/libfstools/libfstools.h -@@ -18,20 +18,10 @@ - #include - #include - #include -+#include "fstype.h" - - struct volume; - --enum { -- FS_NONE, -- FS_SNAPSHOT, -- FS_JFFS2, -- FS_DEADCODE, -- FS_UBIFS, -- FS_F2FS, -- FS_EXT4, -- FS_TARGZ, --}; -- - enum fs_state { - FS_STATE_UNKNOWN, - FS_STATE_PENDING, diff --git a/lede/package/utils/fitblk/Makefile b/lede/package/utils/fitblk/Makefile index cb9e7ebb40..4da4dc46f1 100644 --- a/lede/package/utils/fitblk/Makefile +++ b/lede/package/utils/fitblk/Makefile @@ -16,7 +16,7 @@ define Package/fitblk SECTION:=base CATEGORY:=Base system TITLE:=fitblk firmware release tool - DEPENDS:=@LINUX_6_1 + DEPENDS:=@!LINUX_5_15 endef define Package/fitblk/description diff --git a/lede/target/linux/generic/backport-6.1/301-v6.9-kernel.h-removed-REPEAT_BYTE-from-kernel.h.patch b/lede/target/linux/generic/backport-6.1/301-v6.9-kernel.h-removed-REPEAT_BYTE-from-kernel.h.patch new file mode 100644 index 0000000000..239adff1af --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/301-v6.9-kernel.h-removed-REPEAT_BYTE-from-kernel.h.patch @@ -0,0 +1,161 @@ +From 66a5c40f60f5d88ad8d47ba6a4ba05892853fa1f Mon Sep 17 00:00:00 2001 +From: Tanzir Hasan +Date: Tue, 26 Dec 2023 18:00:00 +0000 +Subject: [PATCH] kernel.h: removed REPEAT_BYTE from kernel.h + +This patch creates wordpart.h and includes it in asm/word-at-a-time.h +for all architectures. WORD_AT_A_TIME_CONSTANTS depends on kernel.h +because of REPEAT_BYTE. Moving this to another header and including it +where necessary allows us to not include the bloated kernel.h. Making +this implicit dependency on REPEAT_BYTE explicit allows for later +improvements in the lib/string.c inclusion list. + +Suggested-by: Al Viro +Suggested-by: Andy Shevchenko +Signed-off-by: Tanzir Hasan +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20231226-libstringheader-v6-1-80aa08c7652c@google.com +Signed-off-by: Kees Cook +--- + arch/arm/include/asm/word-at-a-time.h | 3 ++- + arch/arm64/include/asm/word-at-a-time.h | 3 ++- + arch/powerpc/include/asm/word-at-a-time.h | 4 ++-- + arch/riscv/include/asm/word-at-a-time.h | 3 ++- + arch/s390/include/asm/word-at-a-time.h | 3 ++- + arch/sh/include/asm/word-at-a-time.h | 2 ++ + arch/x86/include/asm/word-at-a-time.h | 3 ++- + arch/x86/kvm/mmu/mmu.c | 1 + + fs/namei.c | 2 +- + include/asm-generic/word-at-a-time.h | 3 ++- + include/linux/kernel.h | 8 -------- + include/linux/wordpart.h | 13 +++++++++++++ + 12 files changed, 31 insertions(+), 17 deletions(-) + create mode 100644 include/linux/wordpart.h + +--- a/arch/arm/include/asm/word-at-a-time.h ++++ b/arch/arm/include/asm/word-at-a-time.h +@@ -8,7 +8,8 @@ + * Little-endian word-at-a-time zero byte handling. + * Heavily based on the x86 algorithm. + */ +-#include ++#include ++#include + + struct word_at_a_time { + const unsigned long one_bits, high_bits; +--- a/arch/arm64/include/asm/word-at-a-time.h ++++ b/arch/arm64/include/asm/word-at-a-time.h +@@ -9,7 +9,8 @@ + + #ifndef __AARCH64EB__ + +-#include ++#include ++#include + + struct word_at_a_time { + const unsigned long one_bits, high_bits; +--- a/arch/powerpc/include/asm/word-at-a-time.h ++++ b/arch/powerpc/include/asm/word-at-a-time.h +@@ -4,8 +4,8 @@ + /* + * Word-at-a-time interfaces for PowerPC. + */ +- +-#include ++#include ++#include + #include + #include + +--- a/arch/sh/include/asm/word-at-a-time.h ++++ b/arch/sh/include/asm/word-at-a-time.h +@@ -5,6 +5,8 @@ + #ifdef CONFIG_CPU_BIG_ENDIAN + # include + #else ++#include ++#include + /* + * Little-endian version cribbed from x86. + */ +--- a/arch/x86/include/asm/word-at-a-time.h ++++ b/arch/x86/include/asm/word-at-a-time.h +@@ -2,7 +2,8 @@ + #ifndef _ASM_WORD_AT_A_TIME_H + #define _ASM_WORD_AT_A_TIME_H + +-#include ++#include ++#include + + /* + * This is largely generic for little-endian machines, but the +--- a/arch/x86/kvm/mmu/mmu.c ++++ b/arch/x86/kvm/mmu/mmu.c +@@ -44,6 +44,7 @@ + #include + #include + #include ++#include + + #include + #include +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -17,8 +17,8 @@ + + #include + #include +-#include + #include ++#include + #include + #include + #include +--- a/include/asm-generic/word-at-a-time.h ++++ b/include/asm-generic/word-at-a-time.h +@@ -2,7 +2,8 @@ + #ifndef _ASM_WORD_AT_A_TIME_H + #define _ASM_WORD_AT_A_TIME_H + +-#include ++#include ++#include + #include + + #ifdef __BIG_ENDIAN +--- a/include/linux/kernel.h ++++ b/include/linux/kernel.h +@@ -36,14 +36,6 @@ + + #define STACK_MAGIC 0xdeadbeef + +-/** +- * REPEAT_BYTE - repeat the value @x multiple times as an unsigned long value +- * @x: value to repeat +- * +- * NOTE: @x is not checked for > 0xff; larger values produce odd results. +- */ +-#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x)) +- + /* generic data direction definitions */ + #define READ 0 + #define WRITE 1 +--- /dev/null ++++ b/include/linux/wordpart.h +@@ -0,0 +1,13 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef _LINUX_WORDPART_H ++#define _LINUX_WORDPART_H ++/** ++ * REPEAT_BYTE - repeat the value @x multiple times as an unsigned long value ++ * @x: value to repeat ++ * ++ * NOTE: @x is not checked for > 0xff; larger values produce odd results. ++ */ ++#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x)) ++ ++#endif // _LINUX_WORDPART_H diff --git a/lede/target/linux/generic/backport-6.1/302-v6.9-kernel.h-Move-upper_-_bits-and-lower_-_bits-to-wordp.patch b/lede/target/linux/generic/backport-6.1/302-v6.9-kernel.h-Move-upper_-_bits-and-lower_-_bits-to-wordp.patch new file mode 100644 index 0000000000..9bbd515852 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/302-v6.9-kernel.h-Move-upper_-_bits-and-lower_-_bits-to-wordp.patch @@ -0,0 +1,107 @@ +From adeb04362d74188c1e22ccb824b15a0a7b3de2f4 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Wed, 14 Feb 2024 19:26:32 +0200 +Subject: [PATCH] kernel.h: Move upper_*_bits() and lower_*_bits() to + wordpart.h + +The wordpart.h header is collecting APIs related to the handling +parts of the word (usually in byte granularity). The upper_*_bits() +and lower_*_bits() are good candidates to be moved to there. + +This helps to clean up header dependency hell with regard to kernel.h +as the latter gathers completely unrelated stuff together and slows +down compilation (especially when it's included into other header). + +Signed-off-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20240214172752.3605073-1-andriy.shevchenko@linux.intel.com +Reviewed-by: Randy Dunlap +Signed-off-by: Kees Cook +--- + include/linux/kernel.h | 30 ++---------------------------- + include/linux/wordpart.h | 29 +++++++++++++++++++++++++++++ + 2 files changed, 31 insertions(+), 28 deletions(-) + +--- a/include/linux/kernel.h ++++ b/include/linux/kernel.h +@@ -30,6 +30,8 @@ + #include + #include + #include ++#include ++ + #include + + #include +@@ -55,34 +57,6 @@ + } \ + ) + +-/** +- * upper_32_bits - return bits 32-63 of a number +- * @n: the number we're accessing +- * +- * A basic shift-right of a 64- or 32-bit quantity. Use this to suppress +- * the "right shift count >= width of type" warning when that quantity is +- * 32-bits. +- */ +-#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16)) +- +-/** +- * lower_32_bits - return bits 0-31 of a number +- * @n: the number we're accessing +- */ +-#define lower_32_bits(n) ((u32)((n) & 0xffffffff)) +- +-/** +- * upper_16_bits - return bits 16-31 of a number +- * @n: the number we're accessing +- */ +-#define upper_16_bits(n) ((u16)((n) >> 16)) +- +-/** +- * lower_16_bits - return bits 0-15 of a number +- * @n: the number we're accessing +- */ +-#define lower_16_bits(n) ((u16)((n) & 0xffff)) +- + struct completion; + struct user; + +--- a/include/linux/wordpart.h ++++ b/include/linux/wordpart.h +@@ -2,6 +2,35 @@ + + #ifndef _LINUX_WORDPART_H + #define _LINUX_WORDPART_H ++ ++/** ++ * upper_32_bits - return bits 32-63 of a number ++ * @n: the number we're accessing ++ * ++ * A basic shift-right of a 64- or 32-bit quantity. Use this to suppress ++ * the "right shift count >= width of type" warning when that quantity is ++ * 32-bits. ++ */ ++#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16)) ++ ++/** ++ * lower_32_bits - return bits 0-31 of a number ++ * @n: the number we're accessing ++ */ ++#define lower_32_bits(n) ((u32)((n) & 0xffffffff)) ++ ++/** ++ * upper_16_bits - return bits 16-31 of a number ++ * @n: the number we're accessing ++ */ ++#define upper_16_bits(n) ((u16)((n) >> 16)) ++ ++/** ++ * lower_16_bits - return bits 0-15 of a number ++ * @n: the number we're accessing ++ */ ++#define lower_16_bits(n) ((u16)((n) & 0xffff)) ++ + /** + * REPEAT_BYTE - repeat the value @x multiple times as an unsigned long value + * @x: value to repeat diff --git a/lede/target/linux/generic/backport-6.1/400-v6.9-mtd-rawnand-brcmnand-Support-write-protection-settin.patch b/lede/target/linux/generic/backport-6.1/400-v6.9-mtd-rawnand-brcmnand-Support-write-protection-settin.patch new file mode 100644 index 0000000000..ba01bac8d2 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/400-v6.9-mtd-rawnand-brcmnand-Support-write-protection-settin.patch @@ -0,0 +1,36 @@ +From 8e7daa85641c9559c113f6b217bdc923397de77c Mon Sep 17 00:00:00 2001 +From: William Zhang +Date: Thu, 22 Feb 2024 19:47:58 -0800 +Subject: [PATCH] mtd: rawnand: brcmnand: Support write protection setting from + dts + +The write protection feature is controlled by the module parameter wp_on +with default set to enabled. But not all the board use this feature +especially in BCMBCA broadband board. And module parameter is not +sufficient as different board can have different option. Add a device +tree property and allow this feature to be configured through the board +dts on per board basis. + +Signed-off-by: William Zhang +Reviewed-by: Florian Fainelli +Reviewed-by: Kamal Dasu +Reviewed-by: David Regan +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20240223034758.13753-14-william.zhang@broadcom.com +--- + drivers/mtd/nand/raw/brcmnand/brcmnand.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c ++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c +@@ -3188,6 +3188,10 @@ int brcmnand_probe(struct platform_devic + /* Disable XOR addressing */ + brcmnand_rmw_reg(ctrl, BRCMNAND_CS_XOR, 0xff, 0, 0); + ++ /* Check if the board connects the WP pin */ ++ if (of_property_read_bool(dn, "brcm,wp-not-connected")) ++ wp_on = 0; ++ + if (ctrl->features & BRCMNAND_HAS_WP) { + /* Permanently disable write protection */ + if (wp_on == 2) diff --git a/lede/target/linux/generic/backport-6.1/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch b/lede/target/linux/generic/backport-6.1/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch index 4de4c7ebd6..5a5e11c8f7 100644 --- a/lede/target/linux/generic/backport-6.1/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch +++ b/lede/target/linux/generic/backport-6.1/408-v6.2-mtd-core-set-ROOT_DEV-for-partitions-marked-as-rootf.patch @@ -10,7 +10,7 @@ This adds support for "linux,rootfs" binding that is used to mark flash partition containing rootfs. It's useful for devices using device tree that don't have bootloader passing root info in cmdline. -Signed-off-by: Rafa? Mi?ecki +Signed-off-by: Rafał Miłecki Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20221022211318.32009-2-zajec5@gmail.com --- diff --git a/lede/target/linux/generic/backport-6.1/410-v6.2-mtd-spi-nor-add-generic-flash-driver.patch b/lede/target/linux/generic/backport-6.1/410-v6.2-mtd-spi-nor-add-generic-flash-driver.patch new file mode 100644 index 0000000000..4978dcedbf --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/410-v6.2-mtd-spi-nor-add-generic-flash-driver.patch @@ -0,0 +1,117 @@ +From 773bbe10449731c9525457873e0c2342e5cf883b Mon Sep 17 00:00:00 2001 +From: Michael Walle +Date: Thu, 11 Aug 2022 00:06:53 +0200 +Subject: [PATCH] mtd: spi-nor: add generic flash driver + +Our SFDP parsing is everything we need to support all basic operations +of a flash device. If the flash isn't found in our in-kernel flash +database, gracefully fall back to a driver described solely by its SFDP +tables. + +Signed-off-by: Michael Walle +Signed-off-by: Tudor Ambarus +Tested-by: Tudor Ambarus +Reviewed-by: Takahiro Kuwano +Link: https://lore.kernel.org/r/20220810220654.1297699-7-michael@walle.cc +--- + drivers/mtd/spi-nor/core.c | 26 ++++++++++++++++++++++++-- + drivers/mtd/spi-nor/core.h | 1 + + drivers/mtd/spi-nor/sfdp.c | 27 +++++++++++++++++++++++++++ + 3 files changed, 52 insertions(+), 2 deletions(-) + +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -1636,6 +1636,16 @@ static const struct spi_nor_manufacturer + &spi_nor_xmc, + }; + ++static const struct flash_info spi_nor_generic_flash = { ++ .name = "spi-nor-generic", ++ /* ++ * JESD216 rev A doesn't specify the page size, therefore we need a ++ * sane default. ++ */ ++ .page_size = 256, ++ .parse_sfdp = true, ++}; ++ + static const struct flash_info *spi_nor_match_id(struct spi_nor *nor, + const u8 *id) + { +@@ -1669,6 +1679,14 @@ static const struct flash_info *spi_nor_ + } + + info = spi_nor_match_id(nor, id); ++ ++ /* Fallback to a generic flash described only by its SFDP data. */ ++ if (!info) { ++ ret = spi_nor_check_sfdp_signature(nor); ++ if (!ret) ++ info = &spi_nor_generic_flash; ++ } ++ + if (!info) { + dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n", + SPI_NOR_MAX_ID_LEN, id); +@@ -2105,8 +2123,12 @@ static int spi_nor_select_pp(struct spi_ + * spi_nor_select_uniform_erase() - select optimum uniform erase type + * @map: the erase map of the SPI NOR + * @wanted_size: the erase type size to search for. Contains the value of +- * info->sector_size or of the "small sector" size in case +- * CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is defined. ++ * info->sector_size, the "small sector" size in case ++ * CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is defined or 0 if ++ * there is no information about the sector size. The ++ * latter is the case if the flash parameters are parsed ++ * solely by SFDP, then the largest supported erase type ++ * is selected. + * + * Once the optimum uniform sector erase command is found, disable all the + * other. +--- a/drivers/mtd/spi-nor/core.h ++++ b/drivers/mtd/spi-nor/core.h +@@ -708,6 +708,8 @@ int spi_nor_controller_ops_read_reg(stru + int spi_nor_controller_ops_write_reg(struct spi_nor *nor, u8 opcode, + const u8 *buf, size_t len); + ++int spi_nor_check_sfdp_signature(struct spi_nor *nor); ++ + static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) + { + return container_of(mtd, struct spi_nor, mtd); +--- a/drivers/mtd/spi-nor/sfdp.c ++++ b/drivers/mtd/spi-nor/sfdp.c +@@ -1250,6 +1250,33 @@ static void spi_nor_post_sfdp_fixups(str + } + + /** ++ * spi_nor_check_sfdp_signature() - check for a valid SFDP signature ++ * @nor: pointer to a 'struct spi_nor' ++ * ++ * Used to detect if the flash supports the RDSFDP command as well as the ++ * presence of a valid SFDP table. ++ * ++ * Return: 0 on success, -errno otherwise. ++ */ ++int spi_nor_check_sfdp_signature(struct spi_nor *nor) ++{ ++ u32 signature; ++ int err; ++ ++ /* Get the SFDP header. */ ++ err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(signature), ++ &signature); ++ if (err < 0) ++ return err; ++ ++ /* Check the SFDP signature. */ ++ if (le32_to_cpu(signature) != SFDP_SIGNATURE) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++/** + * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters. + * @nor: pointer to a 'struct spi_nor' + * diff --git a/lede/target/linux/generic/pending-6.1/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch b/lede/target/linux/generic/backport-6.1/412-v6.3-01-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch similarity index 74% rename from lede/target/linux/generic/pending-6.1/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch rename to lede/target/linux/generic/backport-6.1/412-v6.3-01-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch index ebeeae2f8f..cc05fa6b75 100644 --- a/lede/target/linux/generic/pending-6.1/110-v6.3-0001-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch +++ b/lede/target/linux/generic/backport-6.1/412-v6.3-01-spidev-Add-Silicon-Labs-EM3581-device-compatible.patch @@ -1,13 +1,13 @@ -From f7982c726e02001afc19052fe48f642dfcbc00b2 Mon Sep 17 00:00:00 2001 +From c67d90e058550403a3e6f9b05bfcdcfa12b1815c Mon Sep 17 00:00:00 2001 From: Vincent Tremblay -Date: Mon, 26 Dec 2022 21:10:37 -0500 -Subject: [PATCH 1/2] spidev: Add Silicon Labs EM3581 device compatible +Date: Mon, 26 Dec 2022 21:35:48 -0500 +Subject: [PATCH] spidev: Add Silicon Labs EM3581 device compatible Add compatible string for Silicon Labs EM3581 device. -Note: This patch is adapted from a patch submitted to the for-next branch (v6.3). - Signed-off-by: Vincent Tremblay +Link: https://lore.kernel.org/r/20221227023550.569547-2-vincent@vtremblay.dev +Signed-off-by: Mark Brown --- drivers/spi/spidev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lede/target/linux/generic/pending-6.1/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch b/lede/target/linux/generic/backport-6.1/412-v6.3-02-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch similarity index 74% rename from lede/target/linux/generic/pending-6.1/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch rename to lede/target/linux/generic/backport-6.1/412-v6.3-02-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch index db5b5800f4..59d025e087 100644 --- a/lede/target/linux/generic/pending-6.1/110-v6.3-0002-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch +++ b/lede/target/linux/generic/backport-6.1/412-v6.3-02-spidev-Add-Silicon-Labs-SI3210-device-compatible.patch @@ -1,13 +1,13 @@ -From 536581825219e97fa2ae0c4de35605d2f6311416 Mon Sep 17 00:00:00 2001 +From 6c9d1fd52956c3148e847a214bae9102b1811de5 Mon Sep 17 00:00:00 2001 From: Vincent Tremblay -Date: Tue, 27 Dec 2022 09:00:58 -0500 -Subject: [PATCH 2/2] spidev: Add Silicon Labs SI3210 device compatible +Date: Tue, 27 Dec 2022 09:10:08 -0500 +Subject: [PATCH] spidev: Add Silicon Labs SI3210 device compatible Add compatible string for Silicon Labs SI3210 device. -Note: This patch is adapted from a patch submitted to the for-next branch (v6.3). - Signed-off-by: Vincent Tremblay +Link: https://lore.kernel.org/r/20221227141011.111410-2-vincent@vtremblay.dev +Signed-off-by: Mark Brown --- drivers/spi/spidev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lede/target/linux/generic/backport-6.1/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch b/lede/target/linux/generic/backport-6.1/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch new file mode 100644 index 0000000000..657404196d --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/424-v6.3-mtd-ubi-wire-up-parent-MTD-device.patch @@ -0,0 +1,33 @@ +From 1ecf9e390452e73a362ea7fbde8f3f0db83de856 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 22 Dec 2022 19:33:04 +0000 +Subject: [PATCH] mtd: ubi: wire-up parent MTD device + +Wire up the device parent pointer of UBI devices to their lower MTD +device, typically an MTD partition or whole-chip device. + +The most noticeable change is that in sysfs, previously ubi devices +would be could in /sys/devices/virtual/ubi while after this change they +would be correctly attached to their parent MTD device, e.g. + +/sys/devices/platform/1100d000.spi/spi_master/spi1/spi1.0/mtd/mtd2/ubi0. + +Locating UBI devices using /sys/class/ubi/ of course still works as +well. + +Signed-off-by: Daniel Golle +Signed-off-by: Richard Weinberger +--- + drivers/mtd/ubi/build.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -929,6 +929,7 @@ int ubi_attach_mtd_dev(struct mtd_info * + ubi->dev.release = dev_release; + ubi->dev.class = &ubi_class; + ubi->dev.groups = ubi_dev_groups; ++ ubi->dev.parent = &mtd->dev; + + ubi->mtd = mtd; + ubi->ubi_num = ubi_num; diff --git a/lede/target/linux/generic/backport-6.1/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch b/lede/target/linux/generic/backport-6.1/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch new file mode 100644 index 0000000000..48bf986118 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/425-v6.3-mtd-ubi-block-wire-up-device-parent.patch @@ -0,0 +1,49 @@ +From 05b8773ca33253ea562be145cf3145b05ef19f86 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 22 Dec 2022 19:33:31 +0000 +Subject: [PATCH] mtd: ubi: block: wire-up device parent + +ubiblock devices were previously only identifyable by their name, but +not connected to their parent UBI volume device e.g. in sysfs. +Properly parent ubiblock device as descendant of a UBI volume device +to reflect device model hierachy. + +Signed-off-by: Daniel Golle +Signed-off-by: Richard Weinberger +--- + drivers/mtd/ubi/block.c | 2 +- + drivers/mtd/ubi/kapi.c | 1 + + include/linux/mtd/ubi.h | 1 + + 3 files changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -452,7 +452,7 @@ int ubiblock_create(struct ubi_volume_in + list_add_tail(&dev->list, &ubiblock_devices); + + /* Must be the last step: anyone can call file ops from now on */ +- ret = add_disk(dev->gd); ++ ret = device_add_disk(vi->dev, dev->gd, NULL); + if (ret) + goto out_destroy_wq; + +--- a/drivers/mtd/ubi/kapi.c ++++ b/drivers/mtd/ubi/kapi.c +@@ -79,6 +79,7 @@ void ubi_do_get_volume_info(struct ubi_d + vi->name_len = vol->name_len; + vi->name = vol->name; + vi->cdev = vol->cdev.dev; ++ vi->dev = &vol->dev; + } + + /** +--- a/include/linux/mtd/ubi.h ++++ b/include/linux/mtd/ubi.h +@@ -110,6 +110,7 @@ struct ubi_volume_info { + int name_len; + const char *name; + dev_t cdev; ++ struct device *dev; + }; + + /** diff --git a/lede/target/linux/generic/backport-6.1/424-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch b/lede/target/linux/generic/backport-6.1/426-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch similarity index 100% rename from lede/target/linux/generic/backport-6.1/424-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch rename to lede/target/linux/generic/backport-6.1/426-v6.4-0004-mtd-core-prepare-mtd_otp_nvmem_add-to-handle-EPROBE_.patch diff --git a/lede/target/linux/generic/backport-6.1/702-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch b/lede/target/linux/generic/backport-6.1/702-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch new file mode 100644 index 0000000000..0cad6c53d4 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/702-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch @@ -0,0 +1,2306 @@ +From d2213db3f49bce8e7a87c8de05b9a091f78f654e Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Nov 2023 15:08:41 +0100 +Subject: [PATCH 1/3] net: phy: aquantia: move to separate directory + +Move aquantia PHY driver to separate driectory in preparation for +firmware loading support to keep things tidy. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/Kconfig | 5 +---- + drivers/net/phy/Makefile | 6 +----- + drivers/net/phy/aquantia/Kconfig | 5 +++++ + drivers/net/phy/aquantia/Makefile | 6 ++++++ + drivers/net/phy/{ => aquantia}/aquantia.h | 0 + drivers/net/phy/{ => aquantia}/aquantia_hwmon.c | 0 + drivers/net/phy/{ => aquantia}/aquantia_main.c | 0 + 7 files changed, 13 insertions(+), 9 deletions(-) + create mode 100644 drivers/net/phy/aquantia/Kconfig + create mode 100644 drivers/net/phy/aquantia/Makefile + rename drivers/net/phy/{ => aquantia}/aquantia.h (100%) + rename drivers/net/phy/{ => aquantia}/aquantia_hwmon.c (100%) + rename drivers/net/phy/{ => aquantia}/aquantia_main.c (100%) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -90,10 +90,7 @@ config ADIN1100_PHY + Currently supports the: + - ADIN1100 - Robust,Industrial, Low Power 10BASE-T1L Ethernet PHY + +-config AQUANTIA_PHY +- tristate "Aquantia PHYs" +- help +- Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405 ++source "drivers/net/phy/aquantia/Kconfig" + + config AX88796B_PHY + tristate "Asix PHYs" +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -33,11 +33,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m) + obj-$(CONFIG_ADIN_PHY) += adin.o + obj-$(CONFIG_ADIN1100_PHY) += adin1100.o + obj-$(CONFIG_AMD_PHY) += amd.o +-aquantia-objs += aquantia_main.o +-ifdef CONFIG_HWMON +-aquantia-objs += aquantia_hwmon.o +-endif +-obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o ++obj-$(CONFIG_AQUANTIA_PHY) += aquantia/ + obj-$(CONFIG_AT803X_PHY) += at803x.o + obj-$(CONFIG_AX88796B_PHY) += ax88796b.o + obj-$(CONFIG_BCM54140_PHY) += bcm54140.o +--- /dev/null ++++ b/drivers/net/phy/aquantia/Kconfig +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config AQUANTIA_PHY ++ tristate "Aquantia PHYs" ++ help ++ Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405 +--- /dev/null ++++ b/drivers/net/phy/aquantia/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0 ++aquantia-objs += aquantia_main.o ++ifdef CONFIG_HWMON ++aquantia-objs += aquantia_hwmon.o ++endif ++obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o +--- a/drivers/net/phy/aquantia.h ++++ /dev/null +@@ -1,16 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ +-/* HWMON driver for Aquantia PHY +- * +- * Author: Nikita Yushchenko +- * Author: Andrew Lunn +- * Author: Heiner Kallweit +- */ +- +-#include +-#include +- +-#if IS_REACHABLE(CONFIG_HWMON) +-int aqr_hwmon_probe(struct phy_device *phydev); +-#else +-static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; } +-#endif +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia.h +@@ -0,0 +1,16 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* HWMON driver for Aquantia PHY ++ * ++ * Author: Nikita Yushchenko ++ * Author: Andrew Lunn ++ * Author: Heiner Kallweit ++ */ ++ ++#include ++#include ++ ++#if IS_REACHABLE(CONFIG_HWMON) ++int aqr_hwmon_probe(struct phy_device *phydev); ++#else ++static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; } ++#endif +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia_hwmon.c +@@ -0,0 +1,250 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* HWMON driver for Aquantia PHY ++ * ++ * Author: Nikita Yushchenko ++ * Author: Andrew Lunn ++ * Author: Heiner Kallweit ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "aquantia.h" ++ ++/* Vendor specific 1, MDIO_MMD_VEND2 */ ++#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 ++#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 ++#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 ++#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 ++#define VEND1_THERMAL_STAT1 0xc820 ++#define VEND1_THERMAL_STAT2 0xc821 ++#define VEND1_THERMAL_STAT2_VALID BIT(0) ++#define VEND1_GENERAL_STAT1 0xc830 ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) ++ ++#if IS_REACHABLE(CONFIG_HWMON) ++ ++static umode_t aqr_hwmon_is_visible(const void *data, ++ enum hwmon_sensor_types type, ++ u32 attr, int channel) ++{ ++ if (type != hwmon_temp) ++ return 0; ++ ++ switch (attr) { ++ case hwmon_temp_input: ++ case hwmon_temp_min_alarm: ++ case hwmon_temp_max_alarm: ++ case hwmon_temp_lcrit_alarm: ++ case hwmon_temp_crit_alarm: ++ return 0444; ++ case hwmon_temp_min: ++ case hwmon_temp_max: ++ case hwmon_temp_lcrit: ++ case hwmon_temp_crit: ++ return 0644; ++ default: ++ return 0; ++ } ++} ++ ++static int aqr_hwmon_get(struct phy_device *phydev, int reg, long *value) ++{ ++ int temp = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); ++ ++ if (temp < 0) ++ return temp; ++ ++ /* 16 bit value is 2's complement with LSB = 1/256th degree Celsius */ ++ *value = (s16)temp * 1000 / 256; ++ ++ return 0; ++} ++ ++static int aqr_hwmon_set(struct phy_device *phydev, int reg, long value) ++{ ++ int temp; ++ ++ if (value >= 128000 || value < -128000) ++ return -ERANGE; ++ ++ temp = value * 256 / 1000; ++ ++ /* temp is in s16 range and we're interested in lower 16 bits only */ ++ return phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, (u16)temp); ++} ++ ++static int aqr_hwmon_test_bit(struct phy_device *phydev, int reg, int bit) ++{ ++ int val = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); ++ ++ if (val < 0) ++ return val; ++ ++ return !!(val & bit); ++} ++ ++static int aqr_hwmon_status1(struct phy_device *phydev, int bit, long *value) ++{ ++ int val = aqr_hwmon_test_bit(phydev, VEND1_GENERAL_STAT1, bit); ++ ++ if (val < 0) ++ return val; ++ ++ *value = val; ++ ++ return 0; ++} ++ ++static int aqr_hwmon_read(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long *value) ++{ ++ struct phy_device *phydev = dev_get_drvdata(dev); ++ int reg; ++ ++ if (type != hwmon_temp) ++ return -EOPNOTSUPP; ++ ++ switch (attr) { ++ case hwmon_temp_input: ++ reg = aqr_hwmon_test_bit(phydev, VEND1_THERMAL_STAT2, ++ VEND1_THERMAL_STAT2_VALID); ++ if (reg < 0) ++ return reg; ++ if (!reg) ++ return -EBUSY; ++ ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_STAT1, value); ++ ++ case hwmon_temp_lcrit: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, ++ value); ++ case hwmon_temp_min: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, ++ value); ++ case hwmon_temp_max: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, ++ value); ++ case hwmon_temp_crit: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, ++ value); ++ case hwmon_temp_lcrit_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_LOW_TEMP_FAIL, ++ value); ++ case hwmon_temp_min_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_LOW_TEMP_WARN, ++ value); ++ case hwmon_temp_max_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_HIGH_TEMP_WARN, ++ value); ++ case hwmon_temp_crit_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL, ++ value); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int aqr_hwmon_write(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long value) ++{ ++ struct phy_device *phydev = dev_get_drvdata(dev); ++ ++ if (type != hwmon_temp) ++ return -EOPNOTSUPP; ++ ++ switch (attr) { ++ case hwmon_temp_lcrit: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, ++ value); ++ case hwmon_temp_min: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, ++ value); ++ case hwmon_temp_max: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, ++ value); ++ case hwmon_temp_crit: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, ++ value); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static const struct hwmon_ops aqr_hwmon_ops = { ++ .is_visible = aqr_hwmon_is_visible, ++ .read = aqr_hwmon_read, ++ .write = aqr_hwmon_write, ++}; ++ ++static u32 aqr_hwmon_chip_config[] = { ++ HWMON_C_REGISTER_TZ, ++ 0, ++}; ++ ++static const struct hwmon_channel_info aqr_hwmon_chip = { ++ .type = hwmon_chip, ++ .config = aqr_hwmon_chip_config, ++}; ++ ++static u32 aqr_hwmon_temp_config[] = { ++ HWMON_T_INPUT | ++ HWMON_T_MAX | HWMON_T_MIN | ++ HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM | ++ HWMON_T_CRIT | HWMON_T_LCRIT | ++ HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM, ++ 0, ++}; ++ ++static const struct hwmon_channel_info aqr_hwmon_temp = { ++ .type = hwmon_temp, ++ .config = aqr_hwmon_temp_config, ++}; ++ ++static const struct hwmon_channel_info *aqr_hwmon_info[] = { ++ &aqr_hwmon_chip, ++ &aqr_hwmon_temp, ++ NULL, ++}; ++ ++static const struct hwmon_chip_info aqr_hwmon_chip_info = { ++ .ops = &aqr_hwmon_ops, ++ .info = aqr_hwmon_info, ++}; ++ ++int aqr_hwmon_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct device *hwmon_dev; ++ char *hwmon_name; ++ int i, j; ++ ++ hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); ++ if (!hwmon_name) ++ return -ENOMEM; ++ ++ for (i = j = 0; hwmon_name[i]; i++) { ++ if (isalnum(hwmon_name[i])) { ++ if (i != j) ++ hwmon_name[j] = hwmon_name[i]; ++ j++; ++ } ++ } ++ hwmon_name[j] = '\0'; ++ ++ hwmon_dev = devm_hwmon_device_register_with_info(dev, hwmon_name, ++ phydev, &aqr_hwmon_chip_info, NULL); ++ ++ return PTR_ERR_OR_ZERO(hwmon_dev); ++} ++ ++#endif +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -0,0 +1,842 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Driver for Aquantia PHY ++ * ++ * Author: Shaohui Xie ++ * ++ * Copyright 2015 Freescale Semiconductor, Inc. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "aquantia.h" ++ ++#define PHY_ID_AQ1202 0x03a1b445 ++#define PHY_ID_AQ2104 0x03a1b460 ++#define PHY_ID_AQR105 0x03a1b4a2 ++#define PHY_ID_AQR106 0x03a1b4d0 ++#define PHY_ID_AQR107 0x03a1b4e0 ++#define PHY_ID_AQCS109 0x03a1b5c2 ++#define PHY_ID_AQR405 0x03a1b4b0 ++#define PHY_ID_AQR113C 0x31c31c12 ++ ++#define MDIO_PHYXS_VEND_IF_STATUS 0xe812 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR 0 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX 1 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI 2 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII 3 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI 4 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI 7 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10 ++ ++#define MDIO_AN_VEND_PROV 0xc400 ++#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15) ++#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14) ++#define MDIO_AN_VEND_PROV_5000BASET_FULL BIT(11) ++#define MDIO_AN_VEND_PROV_2500BASET_FULL BIT(10) ++#define MDIO_AN_VEND_PROV_DOWNSHIFT_EN BIT(4) ++#define MDIO_AN_VEND_PROV_DOWNSHIFT_MASK GENMASK(3, 0) ++#define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT 4 ++ ++#define MDIO_AN_TX_VEND_STATUS1 0xc800 ++#define MDIO_AN_TX_VEND_STATUS1_RATE_MASK GENMASK(3, 1) ++#define MDIO_AN_TX_VEND_STATUS1_10BASET 0 ++#define MDIO_AN_TX_VEND_STATUS1_100BASETX 1 ++#define MDIO_AN_TX_VEND_STATUS1_1000BASET 2 ++#define MDIO_AN_TX_VEND_STATUS1_10GBASET 3 ++#define MDIO_AN_TX_VEND_STATUS1_2500BASET 4 ++#define MDIO_AN_TX_VEND_STATUS1_5000BASET 5 ++#define MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX BIT(0) ++ ++#define MDIO_AN_TX_VEND_INT_STATUS1 0xcc00 ++#define MDIO_AN_TX_VEND_INT_STATUS1_DOWNSHIFT BIT(1) ++ ++#define MDIO_AN_TX_VEND_INT_STATUS2 0xcc01 ++#define MDIO_AN_TX_VEND_INT_STATUS2_MASK BIT(0) ++ ++#define MDIO_AN_TX_VEND_INT_MASK2 0xd401 ++#define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0) ++ ++#define MDIO_AN_RX_LP_STAT1 0xe820 ++#define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15) ++#define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14) ++#define MDIO_AN_RX_LP_STAT1_SHORT_REACH BIT(13) ++#define MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT BIT(12) ++#define MDIO_AN_RX_LP_STAT1_AQ_PHY BIT(2) ++ ++#define MDIO_AN_RX_LP_STAT4 0xe823 ++#define MDIO_AN_RX_LP_STAT4_FW_MAJOR GENMASK(15, 8) ++#define MDIO_AN_RX_LP_STAT4_FW_MINOR GENMASK(7, 0) ++ ++#define MDIO_AN_RX_VEND_STAT3 0xe832 ++#define MDIO_AN_RX_VEND_STAT3_AFR BIT(0) ++ ++/* MDIO_MMD_C22EXT */ ++#define MDIO_C22EXT_STAT_SGMII_RX_GOOD_FRAMES 0xd292 ++#define MDIO_C22EXT_STAT_SGMII_RX_BAD_FRAMES 0xd294 ++#define MDIO_C22EXT_STAT_SGMII_RX_FALSE_CARRIER 0xd297 ++#define MDIO_C22EXT_STAT_SGMII_TX_GOOD_FRAMES 0xd313 ++#define MDIO_C22EXT_STAT_SGMII_TX_BAD_FRAMES 0xd315 ++#define MDIO_C22EXT_STAT_SGMII_TX_FALSE_CARRIER 0xd317 ++#define MDIO_C22EXT_STAT_SGMII_TX_COLLISIONS 0xd318 ++#define MDIO_C22EXT_STAT_SGMII_TX_LINE_COLLISIONS 0xd319 ++#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a ++#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b ++ ++/* Vendor specific 1, MDIO_MMD_VEND1 */ ++#define VEND1_GLOBAL_FW_ID 0x0020 ++#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) ++#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) ++ ++#define VEND1_GLOBAL_GEN_STAT2 0xc831 ++#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) ++ ++/* The following registers all have similar layouts; first the registers... */ ++#define VEND1_GLOBAL_CFG_10M 0x0310 ++#define VEND1_GLOBAL_CFG_100M 0x031b ++#define VEND1_GLOBAL_CFG_1G 0x031c ++#define VEND1_GLOBAL_CFG_2_5G 0x031d ++#define VEND1_GLOBAL_CFG_5G 0x031e ++#define VEND1_GLOBAL_CFG_10G 0x031f ++/* ...and now the fields */ ++#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 ++ ++#define VEND1_GLOBAL_RSVD_STAT1 0xc885 ++#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) ++#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) ++ ++#define VEND1_GLOBAL_RSVD_STAT9 0xc88d ++#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) ++#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 ++ ++#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 ++#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 ++ ++#define VEND1_GLOBAL_INT_STD_MASK 0xff00 ++#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) ++#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) ++#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) ++#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) ++#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) ++#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) ++ ++#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 ++#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) ++#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) ++#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) ++#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) ++#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) ++ ++/* Sleep and timeout for checking if the Processor-Intensive ++ * MDIO operation is finished ++ */ ++#define AQR107_OP_IN_PROG_SLEEP 1000 ++#define AQR107_OP_IN_PROG_TIMEOUT 100000 ++ ++struct aqr107_hw_stat { ++ const char *name; ++ int reg; ++ int size; ++}; ++ ++#define SGMII_STAT(n, r, s) { n, MDIO_C22EXT_STAT_SGMII_ ## r, s } ++static const struct aqr107_hw_stat aqr107_hw_stats[] = { ++ SGMII_STAT("sgmii_rx_good_frames", RX_GOOD_FRAMES, 26), ++ SGMII_STAT("sgmii_rx_bad_frames", RX_BAD_FRAMES, 26), ++ SGMII_STAT("sgmii_rx_false_carrier_events", RX_FALSE_CARRIER, 8), ++ SGMII_STAT("sgmii_tx_good_frames", TX_GOOD_FRAMES, 26), ++ SGMII_STAT("sgmii_tx_bad_frames", TX_BAD_FRAMES, 26), ++ SGMII_STAT("sgmii_tx_false_carrier_events", TX_FALSE_CARRIER, 8), ++ SGMII_STAT("sgmii_tx_collisions", TX_COLLISIONS, 8), ++ SGMII_STAT("sgmii_tx_line_collisions", TX_LINE_COLLISIONS, 8), ++ SGMII_STAT("sgmii_tx_frame_alignment_err", TX_FRAME_ALIGN_ERR, 16), ++ SGMII_STAT("sgmii_tx_runt_frames", TX_RUNT_FRAMES, 22), ++}; ++#define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats) ++ ++struct aqr107_priv { ++ u64 sgmii_stats[AQR107_SGMII_STAT_SZ]; ++}; ++ ++static int aqr107_get_sset_count(struct phy_device *phydev) ++{ ++ return AQR107_SGMII_STAT_SZ; ++} ++ ++static void aqr107_get_strings(struct phy_device *phydev, u8 *data) ++{ ++ int i; ++ ++ for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) ++ strscpy(data + i * ETH_GSTRING_LEN, aqr107_hw_stats[i].name, ++ ETH_GSTRING_LEN); ++} ++ ++static u64 aqr107_get_stat(struct phy_device *phydev, int index) ++{ ++ const struct aqr107_hw_stat *stat = aqr107_hw_stats + index; ++ int len_l = min(stat->size, 16); ++ int len_h = stat->size - len_l; ++ u64 ret; ++ int val; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg); ++ if (val < 0) ++ return U64_MAX; ++ ++ ret = val & GENMASK(len_l - 1, 0); ++ if (len_h) { ++ val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg + 1); ++ if (val < 0) ++ return U64_MAX; ++ ++ ret += (val & GENMASK(len_h - 1, 0)) << 16; ++ } ++ ++ return ret; ++} ++ ++static void aqr107_get_stats(struct phy_device *phydev, ++ struct ethtool_stats *stats, u64 *data) ++{ ++ struct aqr107_priv *priv = phydev->priv; ++ u64 val; ++ int i; ++ ++ for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) { ++ val = aqr107_get_stat(phydev, i); ++ if (val == U64_MAX) ++ phydev_err(phydev, "Reading HW Statistics failed for %s\n", ++ aqr107_hw_stats[i].name); ++ else ++ priv->sgmii_stats[i] += val; ++ ++ data[i] = priv->sgmii_stats[i]; ++ } ++} ++ ++static int aqr_config_aneg(struct phy_device *phydev) ++{ ++ bool changed = false; ++ u16 reg; ++ int ret; ++ ++ if (phydev->autoneg == AUTONEG_DISABLE) ++ return genphy_c45_pma_setup_forced(phydev); ++ ++ ret = genphy_c45_an_config_aneg(phydev); ++ if (ret < 0) ++ return ret; ++ if (ret > 0) ++ changed = true; ++ ++ /* Clause 45 has no standardized support for 1000BaseT, therefore ++ * use vendor registers for this mode. ++ */ ++ reg = 0; ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_1000BASET_FULL; ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_1000BASET_HALF; ++ ++ /* Handle the case when the 2.5G and 5G speeds are not advertised */ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_2500BASET_FULL; ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_5000BASET_FULL; ++ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, ++ MDIO_AN_VEND_PROV_1000BASET_HALF | ++ MDIO_AN_VEND_PROV_1000BASET_FULL | ++ MDIO_AN_VEND_PROV_2500BASET_FULL | ++ MDIO_AN_VEND_PROV_5000BASET_FULL, reg); ++ if (ret < 0) ++ return ret; ++ if (ret > 0) ++ changed = true; ++ ++ return genphy_c45_check_and_restart_aneg(phydev, changed); ++} ++ ++static int aqr_config_intr(struct phy_device *phydev) ++{ ++ bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; ++ int err; ++ ++ if (en) { ++ /* Clear any pending interrupts before enabling them */ ++ err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); ++ if (err < 0) ++ return err; ++ } ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_MASK2, ++ en ? MDIO_AN_TX_VEND_INT_MASK2_LINK : 0); ++ if (err < 0) ++ return err; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_STD_MASK, ++ en ? VEND1_GLOBAL_INT_STD_MASK_ALL : 0); ++ if (err < 0) ++ return err; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_VEND_MASK, ++ en ? VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 | ++ VEND1_GLOBAL_INT_VEND_MASK_AN : 0); ++ if (err < 0) ++ return err; ++ ++ if (!en) { ++ /* Clear any pending interrupts after we have disabled them */ ++ err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); ++ if (err < 0) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static irqreturn_t aqr_handle_interrupt(struct phy_device *phydev) ++{ ++ int irq_status; ++ ++ irq_status = phy_read_mmd(phydev, MDIO_MMD_AN, ++ MDIO_AN_TX_VEND_INT_STATUS2); ++ if (irq_status < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ if (!(irq_status & MDIO_AN_TX_VEND_INT_STATUS2_MASK)) ++ return IRQ_NONE; ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ ++static int aqr_read_status(struct phy_device *phydev) ++{ ++ int val; ++ ++ if (phydev->autoneg == AUTONEG_ENABLE) { ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); ++ if (val < 0) ++ return val; ++ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, ++ phydev->lp_advertising, ++ val & MDIO_AN_RX_LP_STAT1_1000BASET_FULL); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, ++ phydev->lp_advertising, ++ val & MDIO_AN_RX_LP_STAT1_1000BASET_HALF); ++ } ++ ++ return genphy_c45_read_status(phydev); ++} ++ ++static int aqr107_read_rate(struct phy_device *phydev) ++{ ++ u32 config_reg; ++ int val; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); ++ if (val < 0) ++ return val; ++ ++ if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX) ++ phydev->duplex = DUPLEX_FULL; ++ else ++ phydev->duplex = DUPLEX_HALF; ++ ++ switch (FIELD_GET(MDIO_AN_TX_VEND_STATUS1_RATE_MASK, val)) { ++ case MDIO_AN_TX_VEND_STATUS1_10BASET: ++ phydev->speed = SPEED_10; ++ config_reg = VEND1_GLOBAL_CFG_10M; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_100BASETX: ++ phydev->speed = SPEED_100; ++ config_reg = VEND1_GLOBAL_CFG_100M; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_1000BASET: ++ phydev->speed = SPEED_1000; ++ config_reg = VEND1_GLOBAL_CFG_1G; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_2500BASET: ++ phydev->speed = SPEED_2500; ++ config_reg = VEND1_GLOBAL_CFG_2_5G; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_5000BASET: ++ phydev->speed = SPEED_5000; ++ config_reg = VEND1_GLOBAL_CFG_5G; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_10GBASET: ++ phydev->speed = SPEED_10000; ++ config_reg = VEND1_GLOBAL_CFG_10G; ++ break; ++ default: ++ phydev->speed = SPEED_UNKNOWN; ++ return 0; ++ } ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, config_reg); ++ if (val < 0) ++ return val; ++ ++ if (FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val) == ++ VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE) ++ phydev->rate_matching = RATE_MATCH_PAUSE; ++ else ++ phydev->rate_matching = RATE_MATCH_NONE; ++ ++ return 0; ++} ++ ++static int aqr107_read_status(struct phy_device *phydev) ++{ ++ int val, ret; ++ ++ ret = aqr_read_status(phydev); ++ if (ret) ++ return ret; ++ ++ if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE) ++ return 0; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_VEND_IF_STATUS); ++ if (val < 0) ++ return val; ++ ++ switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) { ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR: ++ phydev->interface = PHY_INTERFACE_MODE_10GKR; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX: ++ phydev->interface = PHY_INTERFACE_MODE_1000BASEKX; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI: ++ phydev->interface = PHY_INTERFACE_MODE_10GBASER; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII: ++ phydev->interface = PHY_INTERFACE_MODE_USXGMII; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI: ++ phydev->interface = PHY_INTERFACE_MODE_XAUI; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII: ++ phydev->interface = PHY_INTERFACE_MODE_SGMII; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI: ++ phydev->interface = PHY_INTERFACE_MODE_RXAUI; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII: ++ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; ++ break; ++ default: ++ phydev->interface = PHY_INTERFACE_MODE_NA; ++ break; ++ } ++ ++ /* Read possibly downshifted rate from vendor register */ ++ return aqr107_read_rate(phydev); ++} ++ ++static int aqr107_get_downshift(struct phy_device *phydev, u8 *data) ++{ ++ int val, cnt, enable; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV); ++ if (val < 0) ++ return val; ++ ++ enable = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_EN, val); ++ cnt = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); ++ ++ *data = enable && cnt ? cnt : DOWNSHIFT_DEV_DISABLE; ++ ++ return 0; ++} ++ ++static int aqr107_set_downshift(struct phy_device *phydev, u8 cnt) ++{ ++ int val = 0; ++ ++ if (!FIELD_FIT(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt)) ++ return -E2BIG; ++ ++ if (cnt != DOWNSHIFT_DEV_DISABLE) { ++ val = MDIO_AN_VEND_PROV_DOWNSHIFT_EN; ++ val |= FIELD_PREP(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt); ++ } ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, ++ MDIO_AN_VEND_PROV_DOWNSHIFT_EN | ++ MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); ++} ++ ++static int aqr107_get_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return aqr107_get_downshift(phydev, data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int aqr107_set_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, const void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return aqr107_set_downshift(phydev, *(const u8 *)data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++/* If we configure settings whilst firmware is still initializing the chip, ++ * then these settings may be overwritten. Therefore make sure chip ++ * initialization has completed. Use presence of the firmware ID as ++ * indicator for initialization having completed. ++ * The chip also provides a "reset completed" bit, but it's cleared after ++ * read. Therefore function would time out if called again. ++ */ ++static int aqr107_wait_reset_complete(struct phy_device *phydev) ++{ ++ int val; ++ ++ return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_FW_ID, val, val != 0, ++ 20000, 2000000, false); ++} ++ ++static void aqr107_chip_info(struct phy_device *phydev) ++{ ++ u8 fw_major, fw_minor, build_id, prov_id; ++ int val; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID); ++ if (val < 0) ++ return; ++ ++ fw_major = FIELD_GET(VEND1_GLOBAL_FW_ID_MAJOR, val); ++ fw_minor = FIELD_GET(VEND1_GLOBAL_FW_ID_MINOR, val); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT1); ++ if (val < 0) ++ return; ++ ++ build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); ++ prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); ++ ++ phydev_dbg(phydev, "FW %u.%u, Build %u, Provisioning %u\n", ++ fw_major, fw_minor, build_id, prov_id); ++} ++ ++static int aqr107_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Check that the PHY interface type is compatible */ ++ if (phydev->interface != PHY_INTERFACE_MODE_SGMII && ++ phydev->interface != PHY_INTERFACE_MODE_1000BASEKX && ++ phydev->interface != PHY_INTERFACE_MODE_2500BASEX && ++ phydev->interface != PHY_INTERFACE_MODE_XGMII && ++ phydev->interface != PHY_INTERFACE_MODE_USXGMII && ++ phydev->interface != PHY_INTERFACE_MODE_10GKR && ++ phydev->interface != PHY_INTERFACE_MODE_10GBASER && ++ phydev->interface != PHY_INTERFACE_MODE_XAUI && ++ phydev->interface != PHY_INTERFACE_MODE_RXAUI) ++ return -ENODEV; ++ ++ WARN(phydev->interface == PHY_INTERFACE_MODE_XGMII, ++ "Your devicetree is out of date, please update it. The AQR107 family doesn't support XGMII, maybe you mean USXGMII.\n"); ++ ++ ret = aqr107_wait_reset_complete(phydev); ++ if (!ret) ++ aqr107_chip_info(phydev); ++ ++ return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); ++} ++ ++static int aqcs109_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Check that the PHY interface type is compatible */ ++ if (phydev->interface != PHY_INTERFACE_MODE_SGMII && ++ phydev->interface != PHY_INTERFACE_MODE_2500BASEX) ++ return -ENODEV; ++ ++ ret = aqr107_wait_reset_complete(phydev); ++ if (!ret) ++ aqr107_chip_info(phydev); ++ ++ /* AQCS109 belongs to a chip family partially supporting 10G and 5G. ++ * PMA speed ability bits are the same for all members of the family, ++ * AQCS109 however supports speeds up to 2.5G only. ++ */ ++ phy_set_max_speed(phydev, SPEED_2500); ++ ++ return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); ++} ++ ++static void aqr107_link_change_notify(struct phy_device *phydev) ++{ ++ u8 fw_major, fw_minor; ++ bool downshift, short_reach, afr; ++ int mode, val; ++ ++ if (phydev->state != PHY_RUNNING || phydev->autoneg == AUTONEG_DISABLE) ++ return; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); ++ /* call failed or link partner is no Aquantia PHY */ ++ if (val < 0 || !(val & MDIO_AN_RX_LP_STAT1_AQ_PHY)) ++ return; ++ ++ short_reach = val & MDIO_AN_RX_LP_STAT1_SHORT_REACH; ++ downshift = val & MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT4); ++ if (val < 0) ++ return; ++ ++ fw_major = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MAJOR, val); ++ fw_minor = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MINOR, val); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_VEND_STAT3); ++ if (val < 0) ++ return; ++ ++ afr = val & MDIO_AN_RX_VEND_STAT3_AFR; ++ ++ phydev_dbg(phydev, "Link partner is Aquantia PHY, FW %u.%u%s%s%s\n", ++ fw_major, fw_minor, ++ short_reach ? ", short reach mode" : "", ++ downshift ? ", fast-retrain downshift advertised" : "", ++ afr ? ", fast reframe advertised" : ""); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT9); ++ if (val < 0) ++ return; ++ ++ mode = FIELD_GET(VEND1_GLOBAL_RSVD_STAT9_MODE, val); ++ if (mode == VEND1_GLOBAL_RSVD_STAT9_1000BT2) ++ phydev_info(phydev, "Aquantia 1000Base-T2 mode active\n"); ++} ++ ++static int aqr107_wait_processor_intensive_op(struct phy_device *phydev) ++{ ++ int val, err; ++ ++ /* The datasheet notes to wait at least 1ms after issuing a ++ * processor intensive operation before checking. ++ * We cannot use the 'sleep_before_read' parameter of read_poll_timeout ++ * because that just determines the maximum time slept, not the minimum. ++ */ ++ usleep_range(1000, 5000); ++ ++ err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_GEN_STAT2, val, ++ !(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG), ++ AQR107_OP_IN_PROG_SLEEP, ++ AQR107_OP_IN_PROG_TIMEOUT, false); ++ if (err) { ++ phydev_err(phydev, "timeout: processor-intensive MDIO operation\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int aqr107_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface) ++{ ++ if (iface == PHY_INTERFACE_MODE_10GBASER || ++ iface == PHY_INTERFACE_MODE_2500BASEX || ++ iface == PHY_INTERFACE_MODE_NA) ++ return RATE_MATCH_PAUSE; ++ return RATE_MATCH_NONE; ++} ++ ++static int aqr107_suspend(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, ++ MDIO_CTRL1_LPOWER); ++ if (err) ++ return err; ++ ++ return aqr107_wait_processor_intensive_op(phydev); ++} ++ ++static int aqr107_resume(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, ++ MDIO_CTRL1_LPOWER); ++ if (err) ++ return err; ++ ++ return aqr107_wait_processor_intensive_op(phydev); ++} ++ ++static int aqr107_probe(struct phy_device *phydev) ++{ ++ phydev->priv = devm_kzalloc(&phydev->mdio.dev, ++ sizeof(struct aqr107_priv), GFP_KERNEL); ++ if (!phydev->priv) ++ return -ENOMEM; ++ ++ return aqr_hwmon_probe(phydev); ++} ++ ++static struct phy_driver aqr_driver[] = { ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), ++ .name = "Aquantia AQ1202", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQ2104), ++ .name = "Aquantia AQ2104", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR105), ++ .name = "Aquantia AQR105", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR106), ++ .name = "Aquantia AQR106", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR107), ++ .name = "Aquantia AQR107", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), ++ .name = "Aquantia AQCS109", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqcs109_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR405), ++ .name = "Aquantia AQR405", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), ++ .name = "Aquantia AQR113C", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++}; ++ ++module_phy_driver(aqr_driver); ++ ++static struct mdio_device_id __maybe_unused aqr_tbl[] = { ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, aqr_tbl); ++ ++MODULE_DESCRIPTION("Aquantia PHY driver"); ++MODULE_AUTHOR("Shaohui Xie "); ++MODULE_LICENSE("GPL v2"); +--- a/drivers/net/phy/aquantia_hwmon.c ++++ /dev/null +@@ -1,250 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* HWMON driver for Aquantia PHY +- * +- * Author: Nikita Yushchenko +- * Author: Andrew Lunn +- * Author: Heiner Kallweit +- */ +- +-#include +-#include +-#include +-#include +- +-#include "aquantia.h" +- +-/* Vendor specific 1, MDIO_MMD_VEND2 */ +-#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 +-#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 +-#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 +-#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 +-#define VEND1_THERMAL_STAT1 0xc820 +-#define VEND1_THERMAL_STAT2 0xc821 +-#define VEND1_THERMAL_STAT2_VALID BIT(0) +-#define VEND1_GENERAL_STAT1 0xc830 +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) +- +-#if IS_REACHABLE(CONFIG_HWMON) +- +-static umode_t aqr_hwmon_is_visible(const void *data, +- enum hwmon_sensor_types type, +- u32 attr, int channel) +-{ +- if (type != hwmon_temp) +- return 0; +- +- switch (attr) { +- case hwmon_temp_input: +- case hwmon_temp_min_alarm: +- case hwmon_temp_max_alarm: +- case hwmon_temp_lcrit_alarm: +- case hwmon_temp_crit_alarm: +- return 0444; +- case hwmon_temp_min: +- case hwmon_temp_max: +- case hwmon_temp_lcrit: +- case hwmon_temp_crit: +- return 0644; +- default: +- return 0; +- } +-} +- +-static int aqr_hwmon_get(struct phy_device *phydev, int reg, long *value) +-{ +- int temp = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); +- +- if (temp < 0) +- return temp; +- +- /* 16 bit value is 2's complement with LSB = 1/256th degree Celsius */ +- *value = (s16)temp * 1000 / 256; +- +- return 0; +-} +- +-static int aqr_hwmon_set(struct phy_device *phydev, int reg, long value) +-{ +- int temp; +- +- if (value >= 128000 || value < -128000) +- return -ERANGE; +- +- temp = value * 256 / 1000; +- +- /* temp is in s16 range and we're interested in lower 16 bits only */ +- return phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, (u16)temp); +-} +- +-static int aqr_hwmon_test_bit(struct phy_device *phydev, int reg, int bit) +-{ +- int val = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); +- +- if (val < 0) +- return val; +- +- return !!(val & bit); +-} +- +-static int aqr_hwmon_status1(struct phy_device *phydev, int bit, long *value) +-{ +- int val = aqr_hwmon_test_bit(phydev, VEND1_GENERAL_STAT1, bit); +- +- if (val < 0) +- return val; +- +- *value = val; +- +- return 0; +-} +- +-static int aqr_hwmon_read(struct device *dev, enum hwmon_sensor_types type, +- u32 attr, int channel, long *value) +-{ +- struct phy_device *phydev = dev_get_drvdata(dev); +- int reg; +- +- if (type != hwmon_temp) +- return -EOPNOTSUPP; +- +- switch (attr) { +- case hwmon_temp_input: +- reg = aqr_hwmon_test_bit(phydev, VEND1_THERMAL_STAT2, +- VEND1_THERMAL_STAT2_VALID); +- if (reg < 0) +- return reg; +- if (!reg) +- return -EBUSY; +- +- return aqr_hwmon_get(phydev, VEND1_THERMAL_STAT1, value); +- +- case hwmon_temp_lcrit: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, +- value); +- case hwmon_temp_min: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, +- value); +- case hwmon_temp_max: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, +- value); +- case hwmon_temp_crit: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, +- value); +- case hwmon_temp_lcrit_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_LOW_TEMP_FAIL, +- value); +- case hwmon_temp_min_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_LOW_TEMP_WARN, +- value); +- case hwmon_temp_max_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_HIGH_TEMP_WARN, +- value); +- case hwmon_temp_crit_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL, +- value); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int aqr_hwmon_write(struct device *dev, enum hwmon_sensor_types type, +- u32 attr, int channel, long value) +-{ +- struct phy_device *phydev = dev_get_drvdata(dev); +- +- if (type != hwmon_temp) +- return -EOPNOTSUPP; +- +- switch (attr) { +- case hwmon_temp_lcrit: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, +- value); +- case hwmon_temp_min: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, +- value); +- case hwmon_temp_max: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, +- value); +- case hwmon_temp_crit: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, +- value); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static const struct hwmon_ops aqr_hwmon_ops = { +- .is_visible = aqr_hwmon_is_visible, +- .read = aqr_hwmon_read, +- .write = aqr_hwmon_write, +-}; +- +-static u32 aqr_hwmon_chip_config[] = { +- HWMON_C_REGISTER_TZ, +- 0, +-}; +- +-static const struct hwmon_channel_info aqr_hwmon_chip = { +- .type = hwmon_chip, +- .config = aqr_hwmon_chip_config, +-}; +- +-static u32 aqr_hwmon_temp_config[] = { +- HWMON_T_INPUT | +- HWMON_T_MAX | HWMON_T_MIN | +- HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM | +- HWMON_T_CRIT | HWMON_T_LCRIT | +- HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM, +- 0, +-}; +- +-static const struct hwmon_channel_info aqr_hwmon_temp = { +- .type = hwmon_temp, +- .config = aqr_hwmon_temp_config, +-}; +- +-static const struct hwmon_channel_info *aqr_hwmon_info[] = { +- &aqr_hwmon_chip, +- &aqr_hwmon_temp, +- NULL, +-}; +- +-static const struct hwmon_chip_info aqr_hwmon_chip_info = { +- .ops = &aqr_hwmon_ops, +- .info = aqr_hwmon_info, +-}; +- +-int aqr_hwmon_probe(struct phy_device *phydev) +-{ +- struct device *dev = &phydev->mdio.dev; +- struct device *hwmon_dev; +- char *hwmon_name; +- int i, j; +- +- hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); +- if (!hwmon_name) +- return -ENOMEM; +- +- for (i = j = 0; hwmon_name[i]; i++) { +- if (isalnum(hwmon_name[i])) { +- if (i != j) +- hwmon_name[j] = hwmon_name[i]; +- j++; +- } +- } +- hwmon_name[j] = '\0'; +- +- hwmon_dev = devm_hwmon_device_register_with_info(dev, hwmon_name, +- phydev, &aqr_hwmon_chip_info, NULL); +- +- return PTR_ERR_OR_ZERO(hwmon_dev); +-} +- +-#endif +--- a/drivers/net/phy/aquantia_main.c ++++ /dev/null +@@ -1,842 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * Driver for Aquantia PHY +- * +- * Author: Shaohui Xie +- * +- * Copyright 2015 Freescale Semiconductor, Inc. +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-#include "aquantia.h" +- +-#define PHY_ID_AQ1202 0x03a1b445 +-#define PHY_ID_AQ2104 0x03a1b460 +-#define PHY_ID_AQR105 0x03a1b4a2 +-#define PHY_ID_AQR106 0x03a1b4d0 +-#define PHY_ID_AQR107 0x03a1b4e0 +-#define PHY_ID_AQCS109 0x03a1b5c2 +-#define PHY_ID_AQR405 0x03a1b4b0 +-#define PHY_ID_AQR113C 0x31c31c12 +- +-#define MDIO_PHYXS_VEND_IF_STATUS 0xe812 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR 0 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX 1 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI 2 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII 3 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI 4 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI 7 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10 +- +-#define MDIO_AN_VEND_PROV 0xc400 +-#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15) +-#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14) +-#define MDIO_AN_VEND_PROV_5000BASET_FULL BIT(11) +-#define MDIO_AN_VEND_PROV_2500BASET_FULL BIT(10) +-#define MDIO_AN_VEND_PROV_DOWNSHIFT_EN BIT(4) +-#define MDIO_AN_VEND_PROV_DOWNSHIFT_MASK GENMASK(3, 0) +-#define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT 4 +- +-#define MDIO_AN_TX_VEND_STATUS1 0xc800 +-#define MDIO_AN_TX_VEND_STATUS1_RATE_MASK GENMASK(3, 1) +-#define MDIO_AN_TX_VEND_STATUS1_10BASET 0 +-#define MDIO_AN_TX_VEND_STATUS1_100BASETX 1 +-#define MDIO_AN_TX_VEND_STATUS1_1000BASET 2 +-#define MDIO_AN_TX_VEND_STATUS1_10GBASET 3 +-#define MDIO_AN_TX_VEND_STATUS1_2500BASET 4 +-#define MDIO_AN_TX_VEND_STATUS1_5000BASET 5 +-#define MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX BIT(0) +- +-#define MDIO_AN_TX_VEND_INT_STATUS1 0xcc00 +-#define MDIO_AN_TX_VEND_INT_STATUS1_DOWNSHIFT BIT(1) +- +-#define MDIO_AN_TX_VEND_INT_STATUS2 0xcc01 +-#define MDIO_AN_TX_VEND_INT_STATUS2_MASK BIT(0) +- +-#define MDIO_AN_TX_VEND_INT_MASK2 0xd401 +-#define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0) +- +-#define MDIO_AN_RX_LP_STAT1 0xe820 +-#define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15) +-#define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14) +-#define MDIO_AN_RX_LP_STAT1_SHORT_REACH BIT(13) +-#define MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT BIT(12) +-#define MDIO_AN_RX_LP_STAT1_AQ_PHY BIT(2) +- +-#define MDIO_AN_RX_LP_STAT4 0xe823 +-#define MDIO_AN_RX_LP_STAT4_FW_MAJOR GENMASK(15, 8) +-#define MDIO_AN_RX_LP_STAT4_FW_MINOR GENMASK(7, 0) +- +-#define MDIO_AN_RX_VEND_STAT3 0xe832 +-#define MDIO_AN_RX_VEND_STAT3_AFR BIT(0) +- +-/* MDIO_MMD_C22EXT */ +-#define MDIO_C22EXT_STAT_SGMII_RX_GOOD_FRAMES 0xd292 +-#define MDIO_C22EXT_STAT_SGMII_RX_BAD_FRAMES 0xd294 +-#define MDIO_C22EXT_STAT_SGMII_RX_FALSE_CARRIER 0xd297 +-#define MDIO_C22EXT_STAT_SGMII_TX_GOOD_FRAMES 0xd313 +-#define MDIO_C22EXT_STAT_SGMII_TX_BAD_FRAMES 0xd315 +-#define MDIO_C22EXT_STAT_SGMII_TX_FALSE_CARRIER 0xd317 +-#define MDIO_C22EXT_STAT_SGMII_TX_COLLISIONS 0xd318 +-#define MDIO_C22EXT_STAT_SGMII_TX_LINE_COLLISIONS 0xd319 +-#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a +-#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b +- +-/* Vendor specific 1, MDIO_MMD_VEND1 */ +-#define VEND1_GLOBAL_FW_ID 0x0020 +-#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) +-#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) +- +-#define VEND1_GLOBAL_GEN_STAT2 0xc831 +-#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) +- +-/* The following registers all have similar layouts; first the registers... */ +-#define VEND1_GLOBAL_CFG_10M 0x0310 +-#define VEND1_GLOBAL_CFG_100M 0x031b +-#define VEND1_GLOBAL_CFG_1G 0x031c +-#define VEND1_GLOBAL_CFG_2_5G 0x031d +-#define VEND1_GLOBAL_CFG_5G 0x031e +-#define VEND1_GLOBAL_CFG_10G 0x031f +-/* ...and now the fields */ +-#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 +- +-#define VEND1_GLOBAL_RSVD_STAT1 0xc885 +-#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) +-#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) +- +-#define VEND1_GLOBAL_RSVD_STAT9 0xc88d +-#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) +-#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 +- +-#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 +-#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 +- +-#define VEND1_GLOBAL_INT_STD_MASK 0xff00 +-#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) +-#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) +-#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) +-#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) +-#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) +-#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) +- +-#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 +-#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) +-#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) +-#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) +-#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) +-#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) +- +-/* Sleep and timeout for checking if the Processor-Intensive +- * MDIO operation is finished +- */ +-#define AQR107_OP_IN_PROG_SLEEP 1000 +-#define AQR107_OP_IN_PROG_TIMEOUT 100000 +- +-struct aqr107_hw_stat { +- const char *name; +- int reg; +- int size; +-}; +- +-#define SGMII_STAT(n, r, s) { n, MDIO_C22EXT_STAT_SGMII_ ## r, s } +-static const struct aqr107_hw_stat aqr107_hw_stats[] = { +- SGMII_STAT("sgmii_rx_good_frames", RX_GOOD_FRAMES, 26), +- SGMII_STAT("sgmii_rx_bad_frames", RX_BAD_FRAMES, 26), +- SGMII_STAT("sgmii_rx_false_carrier_events", RX_FALSE_CARRIER, 8), +- SGMII_STAT("sgmii_tx_good_frames", TX_GOOD_FRAMES, 26), +- SGMII_STAT("sgmii_tx_bad_frames", TX_BAD_FRAMES, 26), +- SGMII_STAT("sgmii_tx_false_carrier_events", TX_FALSE_CARRIER, 8), +- SGMII_STAT("sgmii_tx_collisions", TX_COLLISIONS, 8), +- SGMII_STAT("sgmii_tx_line_collisions", TX_LINE_COLLISIONS, 8), +- SGMII_STAT("sgmii_tx_frame_alignment_err", TX_FRAME_ALIGN_ERR, 16), +- SGMII_STAT("sgmii_tx_runt_frames", TX_RUNT_FRAMES, 22), +-}; +-#define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats) +- +-struct aqr107_priv { +- u64 sgmii_stats[AQR107_SGMII_STAT_SZ]; +-}; +- +-static int aqr107_get_sset_count(struct phy_device *phydev) +-{ +- return AQR107_SGMII_STAT_SZ; +-} +- +-static void aqr107_get_strings(struct phy_device *phydev, u8 *data) +-{ +- int i; +- +- for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) +- strscpy(data + i * ETH_GSTRING_LEN, aqr107_hw_stats[i].name, +- ETH_GSTRING_LEN); +-} +- +-static u64 aqr107_get_stat(struct phy_device *phydev, int index) +-{ +- const struct aqr107_hw_stat *stat = aqr107_hw_stats + index; +- int len_l = min(stat->size, 16); +- int len_h = stat->size - len_l; +- u64 ret; +- int val; +- +- val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg); +- if (val < 0) +- return U64_MAX; +- +- ret = val & GENMASK(len_l - 1, 0); +- if (len_h) { +- val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg + 1); +- if (val < 0) +- return U64_MAX; +- +- ret += (val & GENMASK(len_h - 1, 0)) << 16; +- } +- +- return ret; +-} +- +-static void aqr107_get_stats(struct phy_device *phydev, +- struct ethtool_stats *stats, u64 *data) +-{ +- struct aqr107_priv *priv = phydev->priv; +- u64 val; +- int i; +- +- for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) { +- val = aqr107_get_stat(phydev, i); +- if (val == U64_MAX) +- phydev_err(phydev, "Reading HW Statistics failed for %s\n", +- aqr107_hw_stats[i].name); +- else +- priv->sgmii_stats[i] += val; +- +- data[i] = priv->sgmii_stats[i]; +- } +-} +- +-static int aqr_config_aneg(struct phy_device *phydev) +-{ +- bool changed = false; +- u16 reg; +- int ret; +- +- if (phydev->autoneg == AUTONEG_DISABLE) +- return genphy_c45_pma_setup_forced(phydev); +- +- ret = genphy_c45_an_config_aneg(phydev); +- if (ret < 0) +- return ret; +- if (ret > 0) +- changed = true; +- +- /* Clause 45 has no standardized support for 1000BaseT, therefore +- * use vendor registers for this mode. +- */ +- reg = 0; +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_1000BASET_FULL; +- +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_1000BASET_HALF; +- +- /* Handle the case when the 2.5G and 5G speeds are not advertised */ +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_2500BASET_FULL; +- +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_5000BASET_FULL; +- +- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, +- MDIO_AN_VEND_PROV_1000BASET_HALF | +- MDIO_AN_VEND_PROV_1000BASET_FULL | +- MDIO_AN_VEND_PROV_2500BASET_FULL | +- MDIO_AN_VEND_PROV_5000BASET_FULL, reg); +- if (ret < 0) +- return ret; +- if (ret > 0) +- changed = true; +- +- return genphy_c45_check_and_restart_aneg(phydev, changed); +-} +- +-static int aqr_config_intr(struct phy_device *phydev) +-{ +- bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; +- int err; +- +- if (en) { +- /* Clear any pending interrupts before enabling them */ +- err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); +- if (err < 0) +- return err; +- } +- +- err = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_MASK2, +- en ? MDIO_AN_TX_VEND_INT_MASK2_LINK : 0); +- if (err < 0) +- return err; +- +- err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_STD_MASK, +- en ? VEND1_GLOBAL_INT_STD_MASK_ALL : 0); +- if (err < 0) +- return err; +- +- err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_VEND_MASK, +- en ? VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 | +- VEND1_GLOBAL_INT_VEND_MASK_AN : 0); +- if (err < 0) +- return err; +- +- if (!en) { +- /* Clear any pending interrupts after we have disabled them */ +- err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); +- if (err < 0) +- return err; +- } +- +- return 0; +-} +- +-static irqreturn_t aqr_handle_interrupt(struct phy_device *phydev) +-{ +- int irq_status; +- +- irq_status = phy_read_mmd(phydev, MDIO_MMD_AN, +- MDIO_AN_TX_VEND_INT_STATUS2); +- if (irq_status < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- if (!(irq_status & MDIO_AN_TX_VEND_INT_STATUS2_MASK)) +- return IRQ_NONE; +- +- phy_trigger_machine(phydev); +- +- return IRQ_HANDLED; +-} +- +-static int aqr_read_status(struct phy_device *phydev) +-{ +- int val; +- +- if (phydev->autoneg == AUTONEG_ENABLE) { +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); +- if (val < 0) +- return val; +- +- linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, +- phydev->lp_advertising, +- val & MDIO_AN_RX_LP_STAT1_1000BASET_FULL); +- linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, +- phydev->lp_advertising, +- val & MDIO_AN_RX_LP_STAT1_1000BASET_HALF); +- } +- +- return genphy_c45_read_status(phydev); +-} +- +-static int aqr107_read_rate(struct phy_device *phydev) +-{ +- u32 config_reg; +- int val; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); +- if (val < 0) +- return val; +- +- if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX) +- phydev->duplex = DUPLEX_FULL; +- else +- phydev->duplex = DUPLEX_HALF; +- +- switch (FIELD_GET(MDIO_AN_TX_VEND_STATUS1_RATE_MASK, val)) { +- case MDIO_AN_TX_VEND_STATUS1_10BASET: +- phydev->speed = SPEED_10; +- config_reg = VEND1_GLOBAL_CFG_10M; +- break; +- case MDIO_AN_TX_VEND_STATUS1_100BASETX: +- phydev->speed = SPEED_100; +- config_reg = VEND1_GLOBAL_CFG_100M; +- break; +- case MDIO_AN_TX_VEND_STATUS1_1000BASET: +- phydev->speed = SPEED_1000; +- config_reg = VEND1_GLOBAL_CFG_1G; +- break; +- case MDIO_AN_TX_VEND_STATUS1_2500BASET: +- phydev->speed = SPEED_2500; +- config_reg = VEND1_GLOBAL_CFG_2_5G; +- break; +- case MDIO_AN_TX_VEND_STATUS1_5000BASET: +- phydev->speed = SPEED_5000; +- config_reg = VEND1_GLOBAL_CFG_5G; +- break; +- case MDIO_AN_TX_VEND_STATUS1_10GBASET: +- phydev->speed = SPEED_10000; +- config_reg = VEND1_GLOBAL_CFG_10G; +- break; +- default: +- phydev->speed = SPEED_UNKNOWN; +- return 0; +- } +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, config_reg); +- if (val < 0) +- return val; +- +- if (FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val) == +- VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE) +- phydev->rate_matching = RATE_MATCH_PAUSE; +- else +- phydev->rate_matching = RATE_MATCH_NONE; +- +- return 0; +-} +- +-static int aqr107_read_status(struct phy_device *phydev) +-{ +- int val, ret; +- +- ret = aqr_read_status(phydev); +- if (ret) +- return ret; +- +- if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE) +- return 0; +- +- val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_VEND_IF_STATUS); +- if (val < 0) +- return val; +- +- switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) { +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR: +- phydev->interface = PHY_INTERFACE_MODE_10GKR; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX: +- phydev->interface = PHY_INTERFACE_MODE_1000BASEKX; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI: +- phydev->interface = PHY_INTERFACE_MODE_10GBASER; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII: +- phydev->interface = PHY_INTERFACE_MODE_USXGMII; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI: +- phydev->interface = PHY_INTERFACE_MODE_XAUI; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII: +- phydev->interface = PHY_INTERFACE_MODE_SGMII; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI: +- phydev->interface = PHY_INTERFACE_MODE_RXAUI; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII: +- phydev->interface = PHY_INTERFACE_MODE_2500BASEX; +- break; +- default: +- phydev->interface = PHY_INTERFACE_MODE_NA; +- break; +- } +- +- /* Read possibly downshifted rate from vendor register */ +- return aqr107_read_rate(phydev); +-} +- +-static int aqr107_get_downshift(struct phy_device *phydev, u8 *data) +-{ +- int val, cnt, enable; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV); +- if (val < 0) +- return val; +- +- enable = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_EN, val); +- cnt = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); +- +- *data = enable && cnt ? cnt : DOWNSHIFT_DEV_DISABLE; +- +- return 0; +-} +- +-static int aqr107_set_downshift(struct phy_device *phydev, u8 cnt) +-{ +- int val = 0; +- +- if (!FIELD_FIT(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt)) +- return -E2BIG; +- +- if (cnt != DOWNSHIFT_DEV_DISABLE) { +- val = MDIO_AN_VEND_PROV_DOWNSHIFT_EN; +- val |= FIELD_PREP(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt); +- } +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, +- MDIO_AN_VEND_PROV_DOWNSHIFT_EN | +- MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); +-} +- +-static int aqr107_get_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return aqr107_get_downshift(phydev, data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int aqr107_set_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, const void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return aqr107_set_downshift(phydev, *(const u8 *)data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-/* If we configure settings whilst firmware is still initializing the chip, +- * then these settings may be overwritten. Therefore make sure chip +- * initialization has completed. Use presence of the firmware ID as +- * indicator for initialization having completed. +- * The chip also provides a "reset completed" bit, but it's cleared after +- * read. Therefore function would time out if called again. +- */ +-static int aqr107_wait_reset_complete(struct phy_device *phydev) +-{ +- int val; +- +- return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, +- VEND1_GLOBAL_FW_ID, val, val != 0, +- 20000, 2000000, false); +-} +- +-static void aqr107_chip_info(struct phy_device *phydev) +-{ +- u8 fw_major, fw_minor, build_id, prov_id; +- int val; +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID); +- if (val < 0) +- return; +- +- fw_major = FIELD_GET(VEND1_GLOBAL_FW_ID_MAJOR, val); +- fw_minor = FIELD_GET(VEND1_GLOBAL_FW_ID_MINOR, val); +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT1); +- if (val < 0) +- return; +- +- build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); +- prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); +- +- phydev_dbg(phydev, "FW %u.%u, Build %u, Provisioning %u\n", +- fw_major, fw_minor, build_id, prov_id); +-} +- +-static int aqr107_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- /* Check that the PHY interface type is compatible */ +- if (phydev->interface != PHY_INTERFACE_MODE_SGMII && +- phydev->interface != PHY_INTERFACE_MODE_1000BASEKX && +- phydev->interface != PHY_INTERFACE_MODE_2500BASEX && +- phydev->interface != PHY_INTERFACE_MODE_XGMII && +- phydev->interface != PHY_INTERFACE_MODE_USXGMII && +- phydev->interface != PHY_INTERFACE_MODE_10GKR && +- phydev->interface != PHY_INTERFACE_MODE_10GBASER && +- phydev->interface != PHY_INTERFACE_MODE_XAUI && +- phydev->interface != PHY_INTERFACE_MODE_RXAUI) +- return -ENODEV; +- +- WARN(phydev->interface == PHY_INTERFACE_MODE_XGMII, +- "Your devicetree is out of date, please update it. The AQR107 family doesn't support XGMII, maybe you mean USXGMII.\n"); +- +- ret = aqr107_wait_reset_complete(phydev); +- if (!ret) +- aqr107_chip_info(phydev); +- +- return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); +-} +- +-static int aqcs109_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- /* Check that the PHY interface type is compatible */ +- if (phydev->interface != PHY_INTERFACE_MODE_SGMII && +- phydev->interface != PHY_INTERFACE_MODE_2500BASEX) +- return -ENODEV; +- +- ret = aqr107_wait_reset_complete(phydev); +- if (!ret) +- aqr107_chip_info(phydev); +- +- /* AQCS109 belongs to a chip family partially supporting 10G and 5G. +- * PMA speed ability bits are the same for all members of the family, +- * AQCS109 however supports speeds up to 2.5G only. +- */ +- phy_set_max_speed(phydev, SPEED_2500); +- +- return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); +-} +- +-static void aqr107_link_change_notify(struct phy_device *phydev) +-{ +- u8 fw_major, fw_minor; +- bool downshift, short_reach, afr; +- int mode, val; +- +- if (phydev->state != PHY_RUNNING || phydev->autoneg == AUTONEG_DISABLE) +- return; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); +- /* call failed or link partner is no Aquantia PHY */ +- if (val < 0 || !(val & MDIO_AN_RX_LP_STAT1_AQ_PHY)) +- return; +- +- short_reach = val & MDIO_AN_RX_LP_STAT1_SHORT_REACH; +- downshift = val & MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT4); +- if (val < 0) +- return; +- +- fw_major = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MAJOR, val); +- fw_minor = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MINOR, val); +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_VEND_STAT3); +- if (val < 0) +- return; +- +- afr = val & MDIO_AN_RX_VEND_STAT3_AFR; +- +- phydev_dbg(phydev, "Link partner is Aquantia PHY, FW %u.%u%s%s%s\n", +- fw_major, fw_minor, +- short_reach ? ", short reach mode" : "", +- downshift ? ", fast-retrain downshift advertised" : "", +- afr ? ", fast reframe advertised" : ""); +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT9); +- if (val < 0) +- return; +- +- mode = FIELD_GET(VEND1_GLOBAL_RSVD_STAT9_MODE, val); +- if (mode == VEND1_GLOBAL_RSVD_STAT9_1000BT2) +- phydev_info(phydev, "Aquantia 1000Base-T2 mode active\n"); +-} +- +-static int aqr107_wait_processor_intensive_op(struct phy_device *phydev) +-{ +- int val, err; +- +- /* The datasheet notes to wait at least 1ms after issuing a +- * processor intensive operation before checking. +- * We cannot use the 'sleep_before_read' parameter of read_poll_timeout +- * because that just determines the maximum time slept, not the minimum. +- */ +- usleep_range(1000, 5000); +- +- err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, +- VEND1_GLOBAL_GEN_STAT2, val, +- !(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG), +- AQR107_OP_IN_PROG_SLEEP, +- AQR107_OP_IN_PROG_TIMEOUT, false); +- if (err) { +- phydev_err(phydev, "timeout: processor-intensive MDIO operation\n"); +- return err; +- } +- +- return 0; +-} +- +-static int aqr107_get_rate_matching(struct phy_device *phydev, +- phy_interface_t iface) +-{ +- if (iface == PHY_INTERFACE_MODE_10GBASER || +- iface == PHY_INTERFACE_MODE_2500BASEX || +- iface == PHY_INTERFACE_MODE_NA) +- return RATE_MATCH_PAUSE; +- return RATE_MATCH_NONE; +-} +- +-static int aqr107_suspend(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, +- MDIO_CTRL1_LPOWER); +- if (err) +- return err; +- +- return aqr107_wait_processor_intensive_op(phydev); +-} +- +-static int aqr107_resume(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, +- MDIO_CTRL1_LPOWER); +- if (err) +- return err; +- +- return aqr107_wait_processor_intensive_op(phydev); +-} +- +-static int aqr107_probe(struct phy_device *phydev) +-{ +- phydev->priv = devm_kzalloc(&phydev->mdio.dev, +- sizeof(struct aqr107_priv), GFP_KERNEL); +- if (!phydev->priv) +- return -ENOMEM; +- +- return aqr_hwmon_probe(phydev); +-} +- +-static struct phy_driver aqr_driver[] = { +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), +- .name = "Aquantia AQ1202", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQ2104), +- .name = "Aquantia AQ2104", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR105), +- .name = "Aquantia AQR105", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR106), +- .name = "Aquantia AQR106", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR107), +- .name = "Aquantia AQR107", +- .probe = aqr107_probe, +- .get_rate_matching = aqr107_get_rate_matching, +- .config_init = aqr107_config_init, +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr107_read_status, +- .get_tunable = aqr107_get_tunable, +- .set_tunable = aqr107_set_tunable, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +- .get_sset_count = aqr107_get_sset_count, +- .get_strings = aqr107_get_strings, +- .get_stats = aqr107_get_stats, +- .link_change_notify = aqr107_link_change_notify, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), +- .name = "Aquantia AQCS109", +- .probe = aqr107_probe, +- .get_rate_matching = aqr107_get_rate_matching, +- .config_init = aqcs109_config_init, +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr107_read_status, +- .get_tunable = aqr107_get_tunable, +- .set_tunable = aqr107_set_tunable, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +- .get_sset_count = aqr107_get_sset_count, +- .get_strings = aqr107_get_strings, +- .get_stats = aqr107_get_stats, +- .link_change_notify = aqr107_link_change_notify, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR405), +- .name = "Aquantia AQR405", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), +- .name = "Aquantia AQR113C", +- .probe = aqr107_probe, +- .get_rate_matching = aqr107_get_rate_matching, +- .config_init = aqr107_config_init, +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr107_read_status, +- .get_tunable = aqr107_get_tunable, +- .set_tunable = aqr107_set_tunable, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +- .get_sset_count = aqr107_get_sset_count, +- .get_strings = aqr107_get_strings, +- .get_stats = aqr107_get_stats, +- .link_change_notify = aqr107_link_change_notify, +-}, +-}; +- +-module_phy_driver(aqr_driver); +- +-static struct mdio_device_id __maybe_unused aqr_tbl[] = { +- { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, +- { } +-}; +- +-MODULE_DEVICE_TABLE(mdio, aqr_tbl); +- +-MODULE_DESCRIPTION("Aquantia PHY driver"); +-MODULE_AUTHOR("Shaohui Xie "); +-MODULE_LICENSE("GPL v2"); diff --git a/lede/target/linux/generic/backport-6.1/702-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch b/lede/target/linux/generic/backport-6.1/702-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch new file mode 100644 index 0000000000..2b94522723 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/702-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch @@ -0,0 +1,183 @@ +From e1fbfa4a995d42e02e22b0dff2f8b4fdee1504b3 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Nov 2023 15:08:42 +0100 +Subject: [PATCH 2/3] net: phy: aquantia: move MMD_VEND define to header + +Move MMD_VEND define to header to clean things up and in preparation for +firmware loading support that require some define placed in +aquantia_main. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia/aquantia.h | 69 +++++++++++++++++++++++ + drivers/net/phy/aquantia/aquantia_hwmon.c | 14 ----- + drivers/net/phy/aquantia/aquantia_main.c | 55 ------------------ + 3 files changed, 69 insertions(+), 69 deletions(-) + +--- a/drivers/net/phy/aquantia/aquantia.h ++++ b/drivers/net/phy/aquantia/aquantia.h +@@ -9,6 +9,75 @@ + #include + #include + ++/* Vendor specific 1, MDIO_MMD_VEND1 */ ++#define VEND1_GLOBAL_FW_ID 0x0020 ++#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) ++#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) ++ ++/* The following registers all have similar layouts; first the registers... */ ++#define VEND1_GLOBAL_CFG_10M 0x0310 ++#define VEND1_GLOBAL_CFG_100M 0x031b ++#define VEND1_GLOBAL_CFG_1G 0x031c ++#define VEND1_GLOBAL_CFG_2_5G 0x031d ++#define VEND1_GLOBAL_CFG_5G 0x031e ++#define VEND1_GLOBAL_CFG_10G 0x031f ++/* ...and now the fields */ ++#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 ++ ++/* Vendor specific 1, MDIO_MMD_VEND2 */ ++#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 ++#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 ++#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 ++#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 ++#define VEND1_THERMAL_STAT1 0xc820 ++#define VEND1_THERMAL_STAT2 0xc821 ++#define VEND1_THERMAL_STAT2_VALID BIT(0) ++#define VEND1_GENERAL_STAT1 0xc830 ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) ++ ++#define VEND1_GLOBAL_GEN_STAT2 0xc831 ++#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) ++ ++#define VEND1_GLOBAL_RSVD_STAT1 0xc885 ++#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) ++#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) ++ ++#define VEND1_GLOBAL_RSVD_STAT9 0xc88d ++#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) ++#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 ++ ++#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 ++#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 ++ ++#define VEND1_GLOBAL_INT_STD_MASK 0xff00 ++#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) ++#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) ++#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) ++#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) ++#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) ++#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) ++ ++#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 ++#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) ++#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) ++#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) ++#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) ++#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) ++ + #if IS_REACHABLE(CONFIG_HWMON) + int aqr_hwmon_probe(struct phy_device *phydev); + #else +--- a/drivers/net/phy/aquantia/aquantia_hwmon.c ++++ b/drivers/net/phy/aquantia/aquantia_hwmon.c +@@ -13,20 +13,6 @@ + + #include "aquantia.h" + +-/* Vendor specific 1, MDIO_MMD_VEND2 */ +-#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 +-#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 +-#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 +-#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 +-#define VEND1_THERMAL_STAT1 0xc820 +-#define VEND1_THERMAL_STAT2 0xc821 +-#define VEND1_THERMAL_STAT2_VALID BIT(0) +-#define VEND1_GENERAL_STAT1 0xc830 +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) +- + #if IS_REACHABLE(CONFIG_HWMON) + + static umode_t aqr_hwmon_is_visible(const void *data, +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -89,61 +89,6 @@ + #define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a + #define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b + +-/* Vendor specific 1, MDIO_MMD_VEND1 */ +-#define VEND1_GLOBAL_FW_ID 0x0020 +-#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) +-#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) +- +-#define VEND1_GLOBAL_GEN_STAT2 0xc831 +-#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) +- +-/* The following registers all have similar layouts; first the registers... */ +-#define VEND1_GLOBAL_CFG_10M 0x0310 +-#define VEND1_GLOBAL_CFG_100M 0x031b +-#define VEND1_GLOBAL_CFG_1G 0x031c +-#define VEND1_GLOBAL_CFG_2_5G 0x031d +-#define VEND1_GLOBAL_CFG_5G 0x031e +-#define VEND1_GLOBAL_CFG_10G 0x031f +-/* ...and now the fields */ +-#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 +- +-#define VEND1_GLOBAL_RSVD_STAT1 0xc885 +-#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) +-#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) +- +-#define VEND1_GLOBAL_RSVD_STAT9 0xc88d +-#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) +-#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 +- +-#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 +-#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 +- +-#define VEND1_GLOBAL_INT_STD_MASK 0xff00 +-#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) +-#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) +-#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) +-#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) +-#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) +-#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) +- +-#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 +-#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) +-#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) +-#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) +-#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) +-#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) +- + /* Sleep and timeout for checking if the Processor-Intensive + * MDIO operation is finished + */ diff --git a/lede/target/linux/generic/backport-6.1/702-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch b/lede/target/linux/generic/backport-6.1/702-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch new file mode 100644 index 0000000000..aa52b3baa6 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/702-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch @@ -0,0 +1,504 @@ +From e93984ebc1c82bd34f7a1b3391efaceee0a8ae96 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 14 Nov 2023 15:08:43 +0100 +Subject: [PATCH 3/3] net: phy: aquantia: add firmware load support + +Aquantia PHY-s require firmware to be loaded before they start operating. +It can be automatically loaded in case when there is a SPI-NOR connected +to Aquantia PHY-s or can be loaded from the host via MDIO. + +This patch adds support for loading the firmware via MDIO as in most cases +there is no SPI-NOR being used to save on cost. +Firmware loading code itself is ported from mainline U-boot with cleanups. + +The firmware has mixed values both in big and little endian. +PHY core itself is big-endian but it expects values to be in little-endian. +The firmware is little-endian but CRC-16 value for it is stored at the end +of firmware in big-endian. + +It seems the PHY does the conversion internally from firmware that is +little-endian to the PHY that is big-endian on using the mailbox +but mailbox returns a big-endian CRC-16 to verify the written data +integrity. + +Co-developed-by: Christian Marangi +Signed-off-by: Robert Marko +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia/Kconfig | 1 + + drivers/net/phy/aquantia/Makefile | 2 +- + drivers/net/phy/aquantia/aquantia.h | 32 ++ + drivers/net/phy/aquantia/aquantia_firmware.c | 370 +++++++++++++++++++ + drivers/net/phy/aquantia/aquantia_main.c | 6 + + 5 files changed, 410 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/phy/aquantia/aquantia_firmware.c + +--- a/drivers/net/phy/aquantia/Kconfig ++++ b/drivers/net/phy/aquantia/Kconfig +@@ -1,5 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0-only + config AQUANTIA_PHY + tristate "Aquantia PHYs" ++ select CRC_CCITT + help + Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405 +--- a/drivers/net/phy/aquantia/Makefile ++++ b/drivers/net/phy/aquantia/Makefile +@@ -1,5 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 +-aquantia-objs += aquantia_main.o ++aquantia-objs += aquantia_main.o aquantia_firmware.o + ifdef CONFIG_HWMON + aquantia-objs += aquantia_hwmon.o + endif +--- a/drivers/net/phy/aquantia/aquantia.h ++++ b/drivers/net/phy/aquantia/aquantia.h +@@ -10,10 +10,35 @@ + #include + + /* Vendor specific 1, MDIO_MMD_VEND1 */ ++#define VEND1_GLOBAL_SC 0x0 ++#define VEND1_GLOBAL_SC_SOFT_RESET BIT(15) ++#define VEND1_GLOBAL_SC_LOW_POWER BIT(11) ++ + #define VEND1_GLOBAL_FW_ID 0x0020 + #define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) + #define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) + ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1 0x0200 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE BIT(15) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE BIT(14) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET BIT(12) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_BUSY BIT(8) ++ ++#define VEND1_GLOBAL_MAILBOX_INTERFACE2 0x0201 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE3 0x0202 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR_MASK GENMASK(15, 0) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR_MASK, (u16)((x) >> 16)) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE4 0x0203 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR_MASK GENMASK(15, 2) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR_MASK, (u16)(x)) ++ ++#define VEND1_GLOBAL_MAILBOX_INTERFACE5 0x0204 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA_MASK GENMASK(15, 0) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA_MASK, (u16)((x) >> 16)) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE6 0x0205 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA_MASK GENMASK(15, 0) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA_MASK, (u16)(x)) ++ + /* The following registers all have similar layouts; first the registers... */ + #define VEND1_GLOBAL_CFG_10M 0x0310 + #define VEND1_GLOBAL_CFG_100M 0x031b +@@ -28,6 +53,11 @@ + #define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 + + /* Vendor specific 1, MDIO_MMD_VEND2 */ ++#define VEND1_GLOBAL_CONTROL2 0xc001 ++#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_RST BIT(15) ++#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD BIT(6) ++#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL BIT(0) ++ + #define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 + #define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 + #define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 +@@ -83,3 +113,5 @@ int aqr_hwmon_probe(struct phy_device *p + #else + static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; } + #endif ++ ++int aqr_firmware_load(struct phy_device *phydev); +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia_firmware.c +@@ -0,0 +1,370 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "aquantia.h" ++ ++#define UP_RESET_SLEEP 100 ++ ++/* addresses of memory segments in the phy */ ++#define DRAM_BASE_ADDR 0x3FFE0000 ++#define IRAM_BASE_ADDR 0x40000000 ++ ++/* firmware image format constants */ ++#define VERSION_STRING_SIZE 0x40 ++#define VERSION_STRING_OFFSET 0x0200 ++/* primary offset is written at an offset from the start of the fw blob */ ++#define PRIMARY_OFFSET_OFFSET 0x8 ++/* primary offset needs to be then added to a base offset */ ++#define PRIMARY_OFFSET_SHIFT 12 ++#define PRIMARY_OFFSET(x) ((x) << PRIMARY_OFFSET_SHIFT) ++#define HEADER_OFFSET 0x300 ++ ++struct aqr_fw_header { ++ u32 padding; ++ u8 iram_offset[3]; ++ u8 iram_size[3]; ++ u8 dram_offset[3]; ++ u8 dram_size[3]; ++} __packed; ++ ++enum aqr_fw_src { ++ AQR_FW_SRC_NVMEM = 0, ++ AQR_FW_SRC_FS, ++}; ++ ++static const char * const aqr_fw_src_string[] = { ++ [AQR_FW_SRC_NVMEM] = "NVMEM", ++ [AQR_FW_SRC_FS] = "FS", ++}; ++ ++/* AQR firmware doesn't have fixed offsets for iram and dram section ++ * but instead provide an header with the offset to use on reading ++ * and parsing the firmware. ++ * ++ * AQR firmware can't be trusted and each offset is validated to be ++ * not negative and be in the size of the firmware itself. ++ */ ++static bool aqr_fw_validate_get(size_t size, size_t offset, size_t get_size) ++{ ++ return offset + get_size <= size; ++} ++ ++static int aqr_fw_get_be16(const u8 *data, size_t offset, size_t size, u16 *value) ++{ ++ if (!aqr_fw_validate_get(size, offset, sizeof(u16))) ++ return -EINVAL; ++ ++ *value = get_unaligned_be16(data + offset); ++ ++ return 0; ++} ++ ++static int aqr_fw_get_le16(const u8 *data, size_t offset, size_t size, u16 *value) ++{ ++ if (!aqr_fw_validate_get(size, offset, sizeof(u16))) ++ return -EINVAL; ++ ++ *value = get_unaligned_le16(data + offset); ++ ++ return 0; ++} ++ ++static int aqr_fw_get_le24(const u8 *data, size_t offset, size_t size, u32 *value) ++{ ++ if (!aqr_fw_validate_get(size, offset, sizeof(u8) * 3)) ++ return -EINVAL; ++ ++ *value = get_unaligned_le24(data + offset); ++ ++ return 0; ++} ++ ++/* load data into the phy's memory */ ++static int aqr_fw_load_memory(struct phy_device *phydev, u32 addr, ++ const u8 *data, size_t len) ++{ ++ u16 crc = 0, up_crc; ++ size_t pos; ++ ++ /* PHY expect addr in LE */ ++ addr = (__force u32)cpu_to_le32(addr); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET); ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE3, ++ VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR(addr)); ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE4, ++ VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR(addr)); ++ ++ /* We assume and enforce the size to be word aligned. ++ * If a firmware that is not word aligned is found, please report upstream. ++ */ ++ for (pos = 0; pos < len; pos += sizeof(u32)) { ++ u32 word; ++ ++ /* FW data is always stored in little-endian */ ++ word = get_unaligned((const u32 *)(data + pos)); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE5, ++ VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(word)); ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE6, ++ VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA(word)); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE | ++ VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE); ++ ++ /* calculate CRC as we load data to the mailbox. ++ * We convert word to big-endian as PHY is BE and mailbox will ++ * return a BE CRC. ++ */ ++ word = (__force u32)cpu_to_be32(word); ++ crc = crc_ccitt_false(crc, (u8 *)&word, sizeof(word)); ++ } ++ ++ up_crc = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE2); ++ if (crc != up_crc) { ++ phydev_err(phydev, "CRC mismatch: calculated 0x%04x PHY 0x%04x\n", ++ crc, up_crc); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int aqr_fw_boot(struct phy_device *phydev, const u8 *data, size_t size, ++ enum aqr_fw_src fw_src) ++{ ++ u16 calculated_crc, read_crc, read_primary_offset; ++ u32 iram_offset = 0, iram_size = 0; ++ u32 dram_offset = 0, dram_size = 0; ++ char version[VERSION_STRING_SIZE]; ++ u32 primary_offset = 0; ++ int ret; ++ ++ /* extract saved CRC at the end of the fw ++ * CRC is saved in big-endian as PHY is BE ++ */ ++ ret = aqr_fw_get_be16(data, size - sizeof(u16), size, &read_crc); ++ if (ret) { ++ phydev_err(phydev, "bad firmware CRC in firmware\n"); ++ return ret; ++ } ++ calculated_crc = crc_ccitt_false(0, data, size - sizeof(u16)); ++ if (read_crc != calculated_crc) { ++ phydev_err(phydev, "bad firmware CRC: file 0x%04x calculated 0x%04x\n", ++ read_crc, calculated_crc); ++ return -EINVAL; ++ } ++ ++ /* Get the primary offset to extract DRAM and IRAM sections. */ ++ ret = aqr_fw_get_le16(data, PRIMARY_OFFSET_OFFSET, size, &read_primary_offset); ++ if (ret) { ++ phydev_err(phydev, "bad primary offset in firmware\n"); ++ return ret; ++ } ++ primary_offset = PRIMARY_OFFSET(read_primary_offset); ++ ++ /* Find the DRAM and IRAM sections within the firmware file. ++ * Make sure the fw_header is correctly in the firmware. ++ */ ++ if (!aqr_fw_validate_get(size, primary_offset + HEADER_OFFSET, ++ sizeof(struct aqr_fw_header))) { ++ phydev_err(phydev, "bad fw_header in firmware\n"); ++ return -EINVAL; ++ } ++ ++ /* offset are in LE and values needs to be converted to cpu endian */ ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, iram_offset), ++ size, &iram_offset); ++ if (ret) { ++ phydev_err(phydev, "bad iram offset in firmware\n"); ++ return ret; ++ } ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, iram_size), ++ size, &iram_size); ++ if (ret) { ++ phydev_err(phydev, "invalid iram size in firmware\n"); ++ return ret; ++ } ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, dram_offset), ++ size, &dram_offset); ++ if (ret) { ++ phydev_err(phydev, "bad dram offset in firmware\n"); ++ return ret; ++ } ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, dram_size), ++ size, &dram_size); ++ if (ret) { ++ phydev_err(phydev, "invalid dram size in firmware\n"); ++ return ret; ++ } ++ ++ /* Increment the offset with the primary offset. ++ * Validate iram/dram offset and size. ++ */ ++ iram_offset += primary_offset; ++ if (iram_size % sizeof(u32)) { ++ phydev_err(phydev, "iram size if not aligned to word size. Please report this upstream!\n"); ++ return -EINVAL; ++ } ++ if (!aqr_fw_validate_get(size, iram_offset, iram_size)) { ++ phydev_err(phydev, "invalid iram offset for iram size\n"); ++ return -EINVAL; ++ } ++ ++ dram_offset += primary_offset; ++ if (dram_size % sizeof(u32)) { ++ phydev_err(phydev, "dram size if not aligned to word size. Please report this upstream!\n"); ++ return -EINVAL; ++ } ++ if (!aqr_fw_validate_get(size, dram_offset, dram_size)) { ++ phydev_err(phydev, "invalid iram offset for iram size\n"); ++ return -EINVAL; ++ } ++ ++ phydev_dbg(phydev, "primary %d IRAM offset=%d size=%d DRAM offset=%d size=%d\n", ++ primary_offset, iram_offset, iram_size, dram_offset, dram_size); ++ ++ if (!aqr_fw_validate_get(size, dram_offset + VERSION_STRING_OFFSET, ++ VERSION_STRING_SIZE)) { ++ phydev_err(phydev, "invalid version in firmware\n"); ++ return -EINVAL; ++ } ++ strscpy(version, (char *)data + dram_offset + VERSION_STRING_OFFSET, ++ VERSION_STRING_SIZE); ++ if (version[0] == '\0') { ++ phydev_err(phydev, "invalid version in firmware\n"); ++ return -EINVAL; ++ } ++ phydev_info(phydev, "loading firmware version '%s' from '%s'\n", version, ++ aqr_fw_src_string[fw_src]); ++ ++ /* stall the microcprocessor */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL | VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD); ++ ++ phydev_dbg(phydev, "loading DRAM 0x%08x from offset=%d size=%d\n", ++ DRAM_BASE_ADDR, dram_offset, dram_size); ++ ret = aqr_fw_load_memory(phydev, DRAM_BASE_ADDR, data + dram_offset, ++ dram_size); ++ if (ret) ++ return ret; ++ ++ phydev_dbg(phydev, "loading IRAM 0x%08x from offset=%d size=%d\n", ++ IRAM_BASE_ADDR, iram_offset, iram_size); ++ ret = aqr_fw_load_memory(phydev, IRAM_BASE_ADDR, data + iram_offset, ++ iram_size); ++ if (ret) ++ return ret; ++ ++ /* make sure soft reset and low power mode are clear */ ++ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_SC, ++ VEND1_GLOBAL_SC_SOFT_RESET | VEND1_GLOBAL_SC_LOW_POWER); ++ ++ /* Release the microprocessor. UP_RESET must be held for 100 usec. */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL | ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD | ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_RST); ++ usleep_range(UP_RESET_SLEEP, UP_RESET_SLEEP * 2); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD); ++ ++ return 0; ++} ++ ++static int aqr_firmware_load_nvmem(struct phy_device *phydev) ++{ ++ struct nvmem_cell *cell; ++ size_t size; ++ u8 *buf; ++ int ret; ++ ++ cell = nvmem_cell_get(&phydev->mdio.dev, "firmware"); ++ if (IS_ERR(cell)) ++ return PTR_ERR(cell); ++ ++ buf = nvmem_cell_read(cell, &size); ++ if (IS_ERR(buf)) { ++ ret = PTR_ERR(buf); ++ goto exit; ++ } ++ ++ ret = aqr_fw_boot(phydev, buf, size, AQR_FW_SRC_NVMEM); ++ if (ret) ++ phydev_err(phydev, "firmware loading failed: %d\n", ret); ++ ++ kfree(buf); ++exit: ++ nvmem_cell_put(cell); ++ ++ return ret; ++} ++ ++static int aqr_firmware_load_fs(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ const struct firmware *fw; ++ const char *fw_name; ++ int ret; ++ ++ ret = of_property_read_string(dev->of_node, "firmware-name", ++ &fw_name); ++ if (ret) ++ return ret; ++ ++ ret = request_firmware(&fw, fw_name, dev); ++ if (ret) { ++ phydev_err(phydev, "failed to find FW file %s (%d)\n", ++ fw_name, ret); ++ return ret; ++ } ++ ++ ret = aqr_fw_boot(phydev, fw->data, fw->size, AQR_FW_SRC_FS); ++ if (ret) ++ phydev_err(phydev, "firmware loading failed: %d\n", ret); ++ ++ release_firmware(fw); ++ ++ return ret; ++} ++ ++int aqr_firmware_load(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Check if the firmware is not already loaded by pooling ++ * the current version returned by the PHY. If 0 is returned, ++ * no firmware is loaded. ++ */ ++ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID); ++ if (ret > 0) ++ goto exit; ++ ++ ret = aqr_firmware_load_nvmem(phydev); ++ if (!ret) ++ goto exit; ++ ++ ret = aqr_firmware_load_fs(phydev); ++ if (ret) ++ return ret; ++ ++exit: ++ return 0; ++} +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -656,11 +656,17 @@ static int aqr107_resume(struct phy_devi + + static int aqr107_probe(struct phy_device *phydev) + { ++ int ret; ++ + phydev->priv = devm_kzalloc(&phydev->mdio.dev, + sizeof(struct aqr107_priv), GFP_KERNEL); + if (!phydev->priv) + return -ENOMEM; + ++ ret = aqr_firmware_load(phydev); ++ if (ret) ++ return ret; ++ + return aqr_hwmon_probe(phydev); + } + diff --git a/lede/target/linux/generic/backport-6.1/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch b/lede/target/linux/generic/backport-6.1/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch new file mode 100644 index 0000000000..ff186742ba --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch @@ -0,0 +1,326 @@ +From 4e4aafcddbbfcdd6eed5780e190fcbfac8b4685a Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Mon, 9 Jan 2023 16:30:41 +0100 +Subject: [PATCH] net: mdio: Add dedicated C45 API to MDIO bus drivers + +Currently C22 and C45 transactions are mixed over a combined API calls +which make use of a special bit in the reg address to indicate if a +C45 transaction should be performed. This makes it impossible to know +if the bus driver actually supports C45. Additionally, many C22 only +drivers don't return -EOPNOTSUPP when asked to perform a C45 +transaction, they mistaking perform a C22 transaction. + +This is the first step to cleanly separate C22 from C45. To maintain +backwards compatibility until all drivers which are capable of +performing C45 are converted to this new API, the helper functions +will fall back to the older API if the new API is not +supported. Eventually this fallback will be removed. + +Signed-off-by: Andrew Lunn +Signed-off-by: Michael Walle +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/mdio_bus.c | 189 +++++++++++++++++++++++++++++++++++++ + include/linux/mdio.h | 39 ++++---- + include/linux/phy.h | 5 + + 3 files changed, 214 insertions(+), 19 deletions(-) + +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -832,6 +832,100 @@ int __mdiobus_modify_changed(struct mii_ + EXPORT_SYMBOL_GPL(__mdiobus_modify_changed); + + /** ++ * __mdiobus_c45_read - Unlocked version of the mdiobus_c45_read function ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to read ++ * ++ * Read a MDIO bus register. Caller must hold the mdio bus lock. ++ * ++ * NOTE: MUST NOT be called from interrupt context. ++ */ ++int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) ++{ ++ int retval; ++ ++ lockdep_assert_held_once(&bus->mdio_lock); ++ ++ if (bus->read_c45) ++ retval = bus->read_c45(bus, addr, devad, regnum); ++ else ++ retval = bus->read(bus, addr, mdiobus_c45_addr(devad, regnum)); ++ ++ trace_mdio_access(bus, 1, addr, regnum, retval, retval); ++ mdiobus_stats_acct(&bus->stats[addr], true, retval); ++ ++ return retval; ++} ++EXPORT_SYMBOL(__mdiobus_c45_read); ++ ++/** ++ * __mdiobus_c45_write - Unlocked version of the mdiobus_write function ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @val: value to write to @regnum ++ * ++ * Write a MDIO bus register. Caller must hold the mdio bus lock. ++ * ++ * NOTE: MUST NOT be called from interrupt context. ++ */ ++int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val) ++{ ++ int err; ++ ++ lockdep_assert_held_once(&bus->mdio_lock); ++ ++ if (bus->write_c45) ++ err = bus->write_c45(bus, addr, devad, regnum, val); ++ else ++ err = bus->write(bus, addr, mdiobus_c45_addr(devad, regnum), ++ val); ++ ++ trace_mdio_access(bus, 0, addr, regnum, val, err); ++ mdiobus_stats_acct(&bus->stats[addr], false, err); ++ ++ return err; ++} ++EXPORT_SYMBOL(__mdiobus_c45_write); ++ ++/** ++ * __mdiobus_c45_modify_changed - Unlocked version of the mdiobus_modify function ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to modify ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ * ++ * Read, modify, and if any change, write the register value back to the ++ * device. Any error returns a negative number. ++ * ++ * NOTE: MUST NOT be called from interrupt context. ++ */ ++static int __mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, ++ int devad, u32 regnum, u16 mask, ++ u16 set) ++{ ++ int new, ret; ++ ++ ret = __mdiobus_c45_read(bus, addr, devad, regnum); ++ if (ret < 0) ++ return ret; ++ ++ new = (ret & ~mask) | set; ++ if (new == ret) ++ return 0; ++ ++ ret = __mdiobus_c45_write(bus, addr, devad, regnum, new); ++ ++ return ret < 0 ? ret : 1; ++} ++ ++/** + * mdiobus_read_nested - Nested version of the mdiobus_read function + * @bus: the mii_bus struct + * @addr: the phy address +@@ -879,6 +973,29 @@ int mdiobus_read(struct mii_bus *bus, in + EXPORT_SYMBOL(mdiobus_read); + + /** ++ * mdiobus_c45_read - Convenience function for reading a given MII mgmt register ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to read ++ * ++ * NOTE: MUST NOT be called from interrupt context, ++ * because the bus read/write functions may wait for an interrupt ++ * to conclude the operation. ++ */ ++int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) ++{ ++ int retval; ++ ++ mutex_lock(&bus->mdio_lock); ++ retval = __mdiobus_c45_read(bus, addr, devad, regnum); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return retval; ++} ++EXPORT_SYMBOL(mdiobus_c45_read); ++ ++/** + * mdiobus_write_nested - Nested version of the mdiobus_write function + * @bus: the mii_bus struct + * @addr: the phy address +@@ -928,6 +1045,31 @@ int mdiobus_write(struct mii_bus *bus, i + EXPORT_SYMBOL(mdiobus_write); + + /** ++ * mdiobus_c45_write - Convenience function for writing a given MII mgmt register ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @val: value to write to @regnum ++ * ++ * NOTE: MUST NOT be called from interrupt context, ++ * because the bus read/write functions may wait for an interrupt ++ * to conclude the operation. ++ */ ++int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val) ++{ ++ int err; ++ ++ mutex_lock(&bus->mdio_lock); ++ err = __mdiobus_c45_write(bus, addr, devad, regnum, val); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return err; ++} ++EXPORT_SYMBOL(mdiobus_c45_write); ++ ++/** + * mdiobus_modify - Convenience function for modifying a given mdio device + * register + * @bus: the mii_bus struct +@@ -949,6 +1091,30 @@ int mdiobus_modify(struct mii_bus *bus, + EXPORT_SYMBOL_GPL(mdiobus_modify); + + /** ++ * mdiobus_c45_modify - Convenience function for modifying a given mdio device ++ * register ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ */ ++int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 mask, u16 set) ++{ ++ int err; ++ ++ mutex_lock(&bus->mdio_lock); ++ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, ++ mask, set); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return err < 0 ? err : 0; ++} ++EXPORT_SYMBOL_GPL(mdiobus_c45_modify); ++ ++/** + * mdiobus_modify_changed - Convenience function for modifying a given mdio + * device register and returning if it changed + * @bus: the mii_bus struct +@@ -971,6 +1137,29 @@ int mdiobus_modify_changed(struct mii_bu + EXPORT_SYMBOL_GPL(mdiobus_modify_changed); + + /** ++ * mdiobus_c45_modify_changed - Convenience function for modifying a given mdio ++ * device register and returning if it changed ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ */ ++int mdiobus_c45_modify_changed(struct mii_bus *bus, int devad, int addr, ++ u32 regnum, u16 mask, u16 set) ++{ ++ int err; ++ ++ mutex_lock(&bus->mdio_lock); ++ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, mask, set); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return err; ++} ++EXPORT_SYMBOL_GPL(mdiobus_c45_modify_changed); ++ ++/** + * mdio_bus_match - determine if given MDIO driver supports the given + * MDIO device + * @dev: target MDIO device +--- a/include/linux/mdio.h ++++ b/include/linux/mdio.h +@@ -423,6 +423,17 @@ int mdiobus_modify(struct mii_bus *bus, + u16 set); + int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, + u16 mask, u16 set); ++int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); ++int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); ++int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val); ++int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val); ++int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 mask, u16 set); ++ ++int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad, ++ u32 regnum, u16 mask, u16 set); + + static inline int mdiodev_read(struct mdio_device *mdiodev, u32 regnum) + { +@@ -463,29 +474,19 @@ static inline u16 mdiobus_c45_devad(u32 + return FIELD_GET(MII_DEVADDR_C45_MASK, regnum); + } + +-static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, +- u16 regnum) +-{ +- return __mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum)); +-} +- +-static inline int __mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad, +- u16 regnum, u16 val) +-{ +- return __mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), +- val); +-} +- +-static inline int mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, +- u16 regnum) ++static inline int mdiodev_c45_modify(struct mdio_device *mdiodev, int devad, ++ u32 regnum, u16 mask, u16 set) + { +- return mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum)); ++ return mdiobus_c45_modify(mdiodev->bus, mdiodev->addr, devad, regnum, ++ mask, set); + } + +-static inline int mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad, +- u16 regnum, u16 val) ++static inline int mdiodev_c45_modify_changed(struct mdio_device *mdiodev, ++ int devad, u32 regnum, u16 mask, ++ u16 set) + { +- return mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), val); ++ return mdiobus_c45_modify_changed(mdiodev->bus, mdiodev->addr, devad, ++ regnum, mask, set); + } + + int mdiobus_register_device(struct mdio_device *mdiodev); +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -364,6 +364,11 @@ struct mii_bus { + int (*read)(struct mii_bus *bus, int addr, int regnum); + /** @write: Perform a write transfer on the bus */ + int (*write)(struct mii_bus *bus, int addr, int regnum, u16 val); ++ /** @read_c45: Perform a C45 read transfer on the bus */ ++ int (*read_c45)(struct mii_bus *bus, int addr, int devnum, int regnum); ++ /** @write_c45: Perform a C45 write transfer on the bus */ ++ int (*write_c45)(struct mii_bus *bus, int addr, int devnum, ++ int regnum, u16 val); + /** @reset: Perform a reset of the bus */ + int (*reset)(struct mii_bus *bus); + diff --git a/lede/target/linux/generic/backport-6.1/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch b/lede/target/linux/generic/backport-6.1/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch new file mode 100644 index 0000000000..80210e6da1 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch @@ -0,0 +1,105 @@ +From 9a0e95e34e9c0a713ddfd48c3a88a20d2bdfd514 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Fri, 11 Aug 2023 13:10:07 +0200 +Subject: [PATCH] net: phy: Introduce PSGMII PHY interface mode + +The PSGMII interface is similar to QSGMII. The main difference +is that the PSGMII interface combines five SGMII lines into a +single link while in QSGMII only four lines are combined. + +Similarly to the QSGMII, this interface mode might also needs +special handling within the MAC driver. + +It is commonly used by Qualcomm with their QCA807x PHY series and +modern WiSoC-s. + +Add definitions for the PHY layer to allow to express this type +of connection between the MAC and PHY. + +Signed-off-by: Gabor Juhos +Signed-off-by: Robert Marko +Signed-off-by: David S. Miller +--- + Documentation/networking/phy.rst | 4 ++++ + drivers/net/phy/phy-core.c | 2 ++ + drivers/net/phy/phylink.c | 3 +++ + include/linux/phy.h | 4 ++++ + 4 files changed, 13 insertions(+) + +--- a/Documentation/networking/phy.rst ++++ b/Documentation/networking/phy.rst +@@ -323,6 +323,10 @@ Some of the interface modes are describe + contrast with the 1000BASE-X phy mode used for Clause 38 and 39 PMDs, this + interface mode has different autonegotiation and only supports full duplex. + ++``PHY_INTERFACE_MODE_PSGMII`` ++ This is the Penta SGMII mode, it is similar to QSGMII but it combines 5 ++ SGMII lines into a single link compared to 4 on QSGMII. ++ + Pause frames / flow control + =========================== + +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -140,6 +140,8 @@ int phy_interface_num_ports(phy_interfac + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + return 4; ++ case PHY_INTERFACE_MODE_PSGMII: ++ return 5; + case PHY_INTERFACE_MODE_MAX: + WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode"); + return 0; +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -187,6 +187,7 @@ static int phylink_interface_max_speed(p + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_SGMII: +@@ -448,6 +449,7 @@ unsigned long phylink_get_capabilities(p + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_SGMII: +@@ -814,6 +816,7 @@ static int phylink_parse_mode(struct phy + + switch (pl->link_config.interface) { + case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_RGMII: +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -103,6 +103,7 @@ extern const int phy_10gbit_features_arr + * @PHY_INTERFACE_MODE_XGMII: 10 gigabit media-independent interface + * @PHY_INTERFACE_MODE_XLGMII:40 gigabit media-independent interface + * @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax ++ * @PHY_INTERFACE_MODE_PSGMII: Penta SGMII + * @PHY_INTERFACE_MODE_QSGMII: Quad SGMII + * @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII + * @PHY_INTERFACE_MODE_100BASEX: 100 BaseX +@@ -140,6 +141,7 @@ typedef enum { + PHY_INTERFACE_MODE_XGMII, + PHY_INTERFACE_MODE_XLGMII, + PHY_INTERFACE_MODE_MOCA, ++ PHY_INTERFACE_MODE_PSGMII, + PHY_INTERFACE_MODE_QSGMII, + PHY_INTERFACE_MODE_TRGMII, + PHY_INTERFACE_MODE_100BASEX, +@@ -247,6 +249,8 @@ static inline const char *phy_modes(phy_ + return "xlgmii"; + case PHY_INTERFACE_MODE_MOCA: + return "moca"; ++ case PHY_INTERFACE_MODE_PSGMII: ++ return "psgmii"; + case PHY_INTERFACE_MODE_QSGMII: + return "qsgmii"; + case PHY_INTERFACE_MODE_TRGMII: diff --git a/lede/target/linux/generic/backport-6.1/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch b/lede/target/linux/generic/backport-6.1/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch new file mode 100644 index 0000000000..7cacb71b18 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch @@ -0,0 +1,32 @@ +From a593a2fcfdfb92cfd0ffc54bc81b07e6bfaaaf46 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Thu, 16 Mar 2023 14:08:26 +0200 +Subject: [PATCH] net: phy: at803x: Replace of_gpio.h with what indeed is used + +of_gpio.h in this driver is solely used as a proxy to other headers. +This is incorrect usage of the of_gpio.h. Replace it .h with what +indeed is used in the code. + +Signed-off-by: Andy Shevchenko +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -13,12 +13,11 @@ + #include + #include + #include +-#include + #include +-#include + #include + #include + #include ++#include + #include + #include + #include diff --git a/lede/target/linux/generic/backport-6.1/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch b/lede/target/linux/generic/backport-6.1/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch new file mode 100644 index 0000000000..dab4928960 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch @@ -0,0 +1,70 @@ +From 8b8bc13d89a7d23d14b0e041c73f037c9db997b1 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:19 +0800 +Subject: [PATCH 1/6] net: phy: at803x: support qca8081 + genphy_c45_pma_read_abilities + +qca8081 PHY supports to use genphy_c45_pma_read_abilities for +getting the PHY features supported except for the autoneg ability + +but autoneg ability exists in MDIO_STAT1 instead of MMD7.1, add it +manually after calling genphy_c45_pma_read_abilities. + +Signed-off-by: Luo Jie +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 28 ++++++++++++++++++---------- + 1 file changed, 18 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -902,15 +902,6 @@ static int at803x_get_features(struct ph + if (err) + return err; + +- if (phydev->drv->phy_id == QCA8081_PHY_ID) { +- err = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_NG_EXTABLE); +- if (err < 0) +- return err; +- +- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported, +- err & MDIO_PMA_NG_EXTABLE_2_5GBT); +- } +- + if (phydev->drv->phy_id != ATH8031_PHY_ID) + return 0; + +@@ -1996,6 +1987,23 @@ static int qca808x_cable_test_get_status + return 0; + } + ++static int qca808x_get_features(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = genphy_c45_pma_read_abilities(phydev); ++ if (ret) ++ return ret; ++ ++ /* The autoneg ability is not existed in bit3 of MMD7.1, ++ * but it is supported by qca808x PHY, so we add it here ++ * manually. ++ */ ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); ++ ++ return 0; ++} ++ + static struct phy_driver at803x_driver[] = { + { + /* Qualcomm Atheros AR8035 */ +@@ -2163,7 +2171,7 @@ static struct phy_driver at803x_driver[] + .set_tunable = at803x_set_tunable, + .set_wol = at803x_set_wol, + .get_wol = at803x_get_wol, +- .get_features = at803x_get_features, ++ .get_features = qca808x_get_features, + .config_aneg = at803x_config_aneg, + .suspend = genphy_suspend, + .resume = genphy_resume, diff --git a/lede/target/linux/generic/backport-6.1/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch b/lede/target/linux/generic/backport-6.1/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch new file mode 100644 index 0000000000..28874068ce --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch @@ -0,0 +1,73 @@ +From f3db55ae860a82e1224a909072783ef850e5d228 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:20 +0800 +Subject: [PATCH 2/6] net: phy: at803x: merge qca8081 slave seed function + +merge the seed enablement and seed value configuration into +one function, since the random seed value is needed to be +configured when the seed is enabled. + +Signed-off-by: Luo Jie +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 29 +++++++++-------------------- + 1 file changed, 9 insertions(+), 20 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1730,24 +1730,19 @@ static int qca808x_phy_fast_retrain_conf + return 0; + } + +-static int qca808x_phy_ms_random_seed_set(struct phy_device *phydev) +-{ +- u16 seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); +- +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_CFG, +- FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value)); +-} +- + static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) + { +- u16 seed_enable = 0; ++ u16 seed_value; + +- if (enable) +- seed_enable = QCA808X_MASTER_SLAVE_SEED_ENABLE; ++ if (!enable) ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, ++ QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); + ++ seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_ENABLE, seed_enable); ++ QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, ++ FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | ++ QCA808X_MASTER_SLAVE_SEED_ENABLE); + } + + static int qca808x_config_init(struct phy_device *phydev) +@@ -1771,12 +1766,7 @@ static int qca808x_config_init(struct ph + if (ret) + return ret; + +- /* Configure lower ramdom seed to make phy linked as slave mode */ +- ret = qca808x_phy_ms_random_seed_set(phydev); +- if (ret) +- return ret; +- +- /* Enable seed */ ++ /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ + ret = qca808x_phy_ms_seed_enable(phydev, true); + if (ret) + return ret; +@@ -1821,7 +1811,6 @@ static int qca808x_read_status(struct ph + if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { + qca808x_phy_ms_seed_enable(phydev, false); + } else { +- qca808x_phy_ms_random_seed_set(phydev); + qca808x_phy_ms_seed_enable(phydev, true); + } + } diff --git a/lede/target/linux/generic/backport-6.1/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch b/lede/target/linux/generic/backport-6.1/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch new file mode 100644 index 0000000000..b91d2cab30 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch @@ -0,0 +1,76 @@ +From 7cc3209558002d95c0d45a1276ba4f5f741eec42 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:21 +0800 +Subject: [PATCH 3/6] net: phy: at803x: enable qca8081 slave seed conditionally + +qca8081 is the single port PHY, the slave prefer mode is used +by default. + +if the phy master perfer mode is configured, the slave seed +configuration should not be enabled, since the slave seed +enablement is for making PHY linked as slave mode easily. + +disable slave seed if the master mode is preferred. + +Signed-off-by: Luo Jie +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1745,6 +1745,12 @@ static int qca808x_phy_ms_seed_enable(st + QCA808X_MASTER_SLAVE_SEED_ENABLE); + } + ++static bool qca808x_is_prefer_master(struct phy_device *phydev) ++{ ++ return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || ++ (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); ++} ++ + static int qca808x_config_init(struct phy_device *phydev) + { + int ret; +@@ -1766,11 +1772,17 @@ static int qca808x_config_init(struct ph + if (ret) + return ret; + +- /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ +- ret = qca808x_phy_ms_seed_enable(phydev, true); +- if (ret) ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) + return ret; + ++ if (!qca808x_is_prefer_master(phydev)) { ++ /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (ret) ++ return ret; ++ } ++ + /* Configure adc threshold as 100mv for the link 10M */ + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, + QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV); +@@ -1802,13 +1814,16 @@ static int qca808x_read_status(struct ph + phydev->interface = PHY_INTERFACE_MODE_SGMII; + } else { + /* generate seed as a lower random value to make PHY linked as SLAVE easily, +- * except for master/slave configuration fault detected. ++ * except for master/slave configuration fault detected or the master mode ++ * preferred. ++ * + * the reason for not putting this code into the function link_change_notify is + * the corner case where the link partner is also the qca8081 PHY and the seed + * value is configured as the same value, the link can't be up and no link change + * occurs. + */ +- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { ++ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || ++ qca808x_is_prefer_master(phydev)) { + qca808x_phy_ms_seed_enable(phydev, false); + } else { + qca808x_phy_ms_seed_enable(phydev, true); diff --git a/lede/target/linux/generic/backport-6.1/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch b/lede/target/linux/generic/backport-6.1/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch new file mode 100644 index 0000000000..b8db89d853 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch @@ -0,0 +1,48 @@ +From fea7cfb83d1a2782e39cd101dd44ed2548539de5 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:22 +0800 +Subject: [PATCH 4/6] net: phy: at803x: support qca8081 1G chip type + +The qca8081 1G chip version does not support 2.5 capability, which +is distinguished from qca8081 2.5G chip according to the bit0 of +register mmd7.0x901d, the 1G version chip also has the same PHY ID +as the normal qca8081 2.5G chip. + +Signed-off-by: Luo Jie +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -272,6 +272,10 @@ + #define QCA808X_CDT_STATUS_STAT_OPEN 2 + #define QCA808X_CDT_STATUS_STAT_SHORT 3 + ++/* QCA808X 1G chip type */ ++#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d ++#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) ++ + MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); +@@ -2005,6 +2009,17 @@ static int qca808x_get_features(struct p + */ + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); + ++ /* As for the qca8081 1G version chip, the 2500baseT ability is also ++ * existed in the bit0 of MMD1.21, we need to remove it manually if ++ * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. ++ */ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); ++ if (ret < 0) ++ return ret; ++ ++ if (QCA808X_PHY_CHIP_TYPE_1G & ret) ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++ + return 0; + } + diff --git a/lede/target/linux/generic/backport-6.1/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch b/lede/target/linux/generic/backport-6.1/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch new file mode 100644 index 0000000000..b54a86e5f5 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch @@ -0,0 +1,98 @@ +From df9401ff3e6eeaa42bfb06761967f1b71f5afce7 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:23 +0800 +Subject: [PATCH 5/6] net: phy: at803x: remove qca8081 1G fast retrain and + slave seed config + +The fast retrain and slave seed configs are only applicable when the 2.5G +ability is supported. + +Signed-off-by: Luo Jie +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 50 +++++++++++++++++++++++++--------------- + 1 file changed, 32 insertions(+), 18 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1755,6 +1755,11 @@ static bool qca808x_is_prefer_master(str + (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); + } + ++static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) ++{ ++ return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++} ++ + static int qca808x_config_init(struct phy_device *phydev) + { + int ret; +@@ -1771,20 +1776,24 @@ static int qca808x_config_init(struct ph + if (ret) + return ret; + +- /* Config the fast retrain for the link 2500M */ +- ret = qca808x_phy_fast_retrain_config(phydev); +- if (ret) +- return ret; +- +- ret = genphy_read_master_slave(phydev); +- if (ret < 0) +- return ret; +- +- if (!qca808x_is_prefer_master(phydev)) { +- /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ +- ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ /* Config the fast retrain for the link 2500M */ ++ ret = qca808x_phy_fast_retrain_config(phydev); + if (ret) + return ret; ++ ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (!qca808x_is_prefer_master(phydev)) { ++ /* Enable seed and configure lower ramdom seed to make phy ++ * linked as slave mode. ++ */ ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (ret) ++ return ret; ++ } + } + + /* Configure adc threshold as 100mv for the link 10M */ +@@ -1826,11 +1835,13 @@ static int qca808x_read_status(struct ph + * value is configured as the same value, the link can't be up and no link change + * occurs. + */ +- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || +- qca808x_is_prefer_master(phydev)) { +- qca808x_phy_ms_seed_enable(phydev, false); +- } else { +- qca808x_phy_ms_seed_enable(phydev, true); ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || ++ qca808x_is_prefer_master(phydev)) { ++ qca808x_phy_ms_seed_enable(phydev, false); ++ } else { ++ qca808x_phy_ms_seed_enable(phydev, true); ++ } + } + } + +@@ -1845,7 +1856,10 @@ static int qca808x_soft_reset(struct phy + if (ret < 0) + return ret; + +- return qca808x_phy_ms_seed_enable(phydev, true); ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ ++ return ret; + } + + static bool qca808x_cdt_fault_length_valid(int cdt_code) diff --git a/lede/target/linux/generic/backport-6.1/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch b/lede/target/linux/generic/backport-6.1/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch new file mode 100644 index 0000000000..e382cf7876 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch @@ -0,0 +1,55 @@ +From 723970affdd8766fa0d91cd34bf2ffc861538b5f Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:24 +0800 +Subject: [PATCH 6/6] net: phy: at803x: add qca8081 fifo reset on the link + changed + +The qca8081 sgmii fifo needs to be reset on link down and +released on the link up in case of any abnormal issue +such as the packet blocked on the PHY. + +Signed-off-by: Luo Jie +Reviewed-by: Andrew Lunn +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -276,6 +276,9 @@ + #define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d + #define QCA808X_PHY_CHIP_TYPE_1G BIT(0) + ++#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 ++#define QCA8081_PHY_FIFO_RSTN BIT(11) ++ + MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); +@@ -2037,6 +2040,16 @@ static int qca808x_get_features(struct p + return 0; + } + ++static void qca808x_link_change_notify(struct phy_device *phydev) ++{ ++ /* Assert interface sgmii fifo on link down, deassert it on link up, ++ * the interface device address is always phy address added by 1. ++ */ ++ mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, ++ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, ++ QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); ++} ++ + static struct phy_driver at803x_driver[] = { + { + /* Qualcomm Atheros AR8035 */ +@@ -2213,6 +2226,7 @@ static struct phy_driver at803x_driver[] + .soft_reset = qca808x_soft_reset, + .cable_test_start = qca808x_cable_test_start, + .cable_test_get_status = qca808x_cable_test_get_status, ++ .link_change_notify = qca808x_link_change_notify, + }, }; + + module_phy_driver(at803x_driver); diff --git a/lede/target/linux/generic/backport-6.1/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch b/lede/target/linux/generic/backport-6.1/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch new file mode 100644 index 0000000000..eb9172b1cc --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch @@ -0,0 +1,69 @@ +From 6a3b8c573b5a152a6aa7a0b54c5e18b84c6ba6f5 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:49 +0100 +Subject: [PATCH 02/13] net: phy: at803x: move disable WOL to specific at8031 + probe + +Move the WOL disable call to specific at8031 probe to make at803x_probe +more generic and drop extra check for PHY ID. + +Keep the same previous behaviour by first calling at803x_probe and then +disabling WOL. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 27 +++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -886,15 +886,6 @@ static int at803x_probe(struct phy_devic + priv->is_fiber = true; + break; + } +- +- /* Disable WoL in 1588 register which is enabled +- * by default +- */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- AT803X_WOL_EN, 0); +- if (ret) +- return ret; + } + + return 0; +@@ -1591,6 +1582,22 @@ static int at803x_cable_test_start(struc + return 0; + } + ++static int at8031_probe(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = at803x_probe(phydev); ++ if (ret) ++ return ret; ++ ++ /* Disable WoL in 1588 register which is enabled ++ * by default ++ */ ++ return phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ AT803X_WOL_EN, 0); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2092,7 +2099,7 @@ static struct phy_driver at803x_driver[] + PHY_ID_MATCH_EXACT(ATH8031_PHY_ID), + .name = "Qualcomm Atheros AR8031/AR8033", + .flags = PHY_POLL_CABLE_TEST, +- .probe = at803x_probe, ++ .probe = at8031_probe, + .config_init = at803x_config_init, + .config_aneg = at803x_config_aneg, + .soft_reset = genphy_soft_reset, diff --git a/lede/target/linux/generic/backport-6.1/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch b/lede/target/linux/generic/backport-6.1/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch new file mode 100644 index 0000000000..5a9d1764f1 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch @@ -0,0 +1,129 @@ +From 07b1ad83b9ed6db1735ba10baf67b7a565ac0cef Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:50 +0100 +Subject: [PATCH 03/13] net: phy: at803x: raname hw_stats functions to qca83xx + specific name + +The function and the struct related to hw_stats were specific to qca83xx +PHY but were called following the convention in the driver of calling +everything with at803x prefix. + +To better organize the code, rename these function a more specific name +to better describe that they are specific to 83xx PHY family. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 44 ++++++++++++++++++++-------------------- + 1 file changed, 22 insertions(+), 22 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -295,7 +295,7 @@ struct at803x_hw_stat { + enum stat_access_type access_type; + }; + +-static struct at803x_hw_stat at803x_hw_stats[] = { ++static struct at803x_hw_stat qca83xx_hw_stats[] = { + { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, + { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, + { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, +@@ -311,7 +311,7 @@ struct at803x_priv { + bool is_1000basex; + struct regulator_dev *vddio_rdev; + struct regulator_dev *vddh_rdev; +- u64 stats[ARRAY_SIZE(at803x_hw_stats)]; ++ u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; + }; + + struct at803x_context { +@@ -529,24 +529,24 @@ static void at803x_get_wol(struct phy_de + wol->wolopts |= WAKE_MAGIC; + } + +-static int at803x_get_sset_count(struct phy_device *phydev) ++static int qca83xx_get_sset_count(struct phy_device *phydev) + { +- return ARRAY_SIZE(at803x_hw_stats); ++ return ARRAY_SIZE(qca83xx_hw_stats); + } + +-static void at803x_get_strings(struct phy_device *phydev, u8 *data) ++static void qca83xx_get_strings(struct phy_device *phydev, u8 *data) + { + int i; + +- for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) { ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) { + strscpy(data + i * ETH_GSTRING_LEN, +- at803x_hw_stats[i].string, ETH_GSTRING_LEN); ++ qca83xx_hw_stats[i].string, ETH_GSTRING_LEN); + } + } + +-static u64 at803x_get_stat(struct phy_device *phydev, int i) ++static u64 qca83xx_get_stat(struct phy_device *phydev, int i) + { +- struct at803x_hw_stat stat = at803x_hw_stats[i]; ++ struct at803x_hw_stat stat = qca83xx_hw_stats[i]; + struct at803x_priv *priv = phydev->priv; + int val; + u64 ret; +@@ -567,13 +567,13 @@ static u64 at803x_get_stat(struct phy_de + return ret; + } + +-static void at803x_get_stats(struct phy_device *phydev, +- struct ethtool_stats *stats, u64 *data) ++static void qca83xx_get_stats(struct phy_device *phydev, ++ struct ethtool_stats *stats, u64 *data) + { + int i; + +- for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) +- data[i] = at803x_get_stat(phydev, i); ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) ++ data[i] = qca83xx_get_stat(phydev, i); + } + + static int at803x_suspend(struct phy_device *phydev) +@@ -2175,9 +2175,9 @@ static struct phy_driver at803x_driver[] + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, + .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, + .suspend = qca83xx_suspend, + .resume = qca83xx_resume, + }, { +@@ -2191,9 +2191,9 @@ static struct phy_driver at803x_driver[] + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, + .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, + .suspend = qca83xx_suspend, + .resume = qca83xx_resume, + }, { +@@ -2207,9 +2207,9 @@ static struct phy_driver at803x_driver[] + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, + .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, + .suspend = qca83xx_suspend, + .resume = qca83xx_resume, + }, { diff --git a/lede/target/linux/generic/backport-6.1/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch b/lede/target/linux/generic/backport-6.1/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch new file mode 100644 index 0000000000..f09142c5ed --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch @@ -0,0 +1,155 @@ +From d43cff3f82336c0bd965ea552232d9f4ddac71a6 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:51 +0100 +Subject: [PATCH 04/13] net: phy: at803x: move qca83xx specific check in + dedicated functions + +Rework qca83xx specific check to dedicated function to tidy things up +and drop useless phy_id check. + +Also drop an useless link_change_notify for QCA8337 as it did nothing an +returned early. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 68 ++++++++++++++++++++++------------------ + 1 file changed, 37 insertions(+), 31 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1623,27 +1623,26 @@ static int qca83xx_config_init(struct ph + break; + } + ++ /* Following original QCA sourcecode set port to prefer master */ ++ phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); ++ ++ return 0; ++} ++ ++static int qca8327_config_init(struct phy_device *phydev) ++{ + /* QCA8327 require DAC amplitude adjustment for 100m set to +6%. + * Disable on init and enable only with 100m speed following + * qca original source code. + */ +- if (phydev->drv->phy_id == QCA8327_A_PHY_ID || +- phydev->drv->phy_id == QCA8327_B_PHY_ID) +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, 0); ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, 0); + +- /* Following original QCA sourcecode set port to prefer master */ +- phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); +- +- return 0; ++ return qca83xx_config_init(phydev); + } + + static void qca83xx_link_change_notify(struct phy_device *phydev) + { +- /* QCA8337 doesn't require DAC Amplitude adjustement */ +- if (phydev->drv->phy_id == QCA8337_PHY_ID) +- return; +- + /* Set DAC Amplitude adjustment to +6% for 100m on link running */ + if (phydev->state == PHY_RUNNING) { + if (phydev->speed == SPEED_100) +@@ -1686,19 +1685,6 @@ static int qca83xx_resume(struct phy_dev + + static int qca83xx_suspend(struct phy_device *phydev) + { +- u16 mask = 0; +- +- /* Only QCA8337 support actual suspend. +- * QCA8327 cause port unreliability when phy suspend +- * is set. +- */ +- if (phydev->drv->phy_id == QCA8337_PHY_ID) { +- genphy_suspend(phydev); +- } else { +- mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); +- phy_modify(phydev, MII_BMCR, mask, 0); +- } +- + at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN, + AT803X_DEBUG_GATE_CLK_IN1000, 0); + +@@ -1709,6 +1695,27 @@ static int qca83xx_suspend(struct phy_de + return 0; + } + ++static int qca8337_suspend(struct phy_device *phydev) ++{ ++ /* Only QCA8337 support actual suspend. */ ++ genphy_suspend(phydev); ++ ++ return qca83xx_suspend(phydev); ++} ++ ++static int qca8327_suspend(struct phy_device *phydev) ++{ ++ u16 mask = 0; ++ ++ /* QCA8327 cause port unreliability when phy suspend ++ * is set. ++ */ ++ mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); ++ phy_modify(phydev, MII_BMCR, mask, 0); ++ ++ return qca83xx_suspend(phydev); ++} ++ + static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) + { + int ret; +@@ -2170,7 +2177,6 @@ static struct phy_driver at803x_driver[] + .phy_id_mask = QCA8K_PHY_ID_MASK, + .name = "Qualcomm Atheros 8337 internal PHY", + /* PHY_GBIT_FEATURES */ +- .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, +@@ -2178,7 +2184,7 @@ static struct phy_driver at803x_driver[] + .get_sset_count = qca83xx_get_sset_count, + .get_strings = qca83xx_get_strings, + .get_stats = qca83xx_get_stats, +- .suspend = qca83xx_suspend, ++ .suspend = qca8337_suspend, + .resume = qca83xx_resume, + }, { + /* QCA8327-A from switch QCA8327-AL1A */ +@@ -2189,12 +2195,12 @@ static struct phy_driver at803x_driver[] + .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, ++ .config_init = qca8327_config_init, + .soft_reset = genphy_soft_reset, + .get_sset_count = qca83xx_get_sset_count, + .get_strings = qca83xx_get_strings, + .get_stats = qca83xx_get_stats, +- .suspend = qca83xx_suspend, ++ .suspend = qca8327_suspend, + .resume = qca83xx_resume, + }, { + /* QCA8327-B from switch QCA8327-BL1A */ +@@ -2205,12 +2211,12 @@ static struct phy_driver at803x_driver[] + .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, ++ .config_init = qca8327_config_init, + .soft_reset = genphy_soft_reset, + .get_sset_count = qca83xx_get_sset_count, + .get_strings = qca83xx_get_strings, + .get_stats = qca83xx_get_stats, +- .suspend = qca83xx_suspend, ++ .suspend = qca8327_suspend, + .resume = qca83xx_resume, + }, { + /* Qualcomm QCA8081 */ diff --git a/lede/target/linux/generic/backport-6.1/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch b/lede/target/linux/generic/backport-6.1/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch new file mode 100644 index 0000000000..a5cc67a8c8 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch @@ -0,0 +1,94 @@ +From 900eef75cc5018e149c52fe305c9c3fe424c52a7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:52 +0100 +Subject: [PATCH 05/13] net: phy: at803x: move specific DT option for at8031 to + specific probe + +Move specific DT options for at8031 to specific probe to tidy things up +and make at803x_parse_dt more generic. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 55 ++++++++++++++++++++++------------------ + 1 file changed, 31 insertions(+), 24 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -825,30 +825,6 @@ static int at803x_parse_dt(struct phy_de + } + } + +- /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping +- * options. +- */ +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- if (of_property_read_bool(node, "qca,keep-pll-enabled")) +- priv->flags |= AT803X_KEEP_PLL_ENABLED; +- +- ret = at8031_register_regulators(phydev); +- if (ret < 0) +- return ret; +- +- ret = devm_regulator_get_enable_optional(&phydev->mdio.dev, +- "vddio"); +- if (ret) { +- phydev_err(phydev, "failed to get VDDIO regulator\n"); +- return ret; +- } +- +- /* Only AR8031/8033 support 1000Base-X for SFP modules */ +- ret = phy_sfp_probe(phydev, &at803x_sfp_ops); +- if (ret < 0) +- return ret; +- } +- + return 0; + } + +@@ -1582,6 +1558,30 @@ static int at803x_cable_test_start(struc + return 0; + } + ++static int at8031_parse_dt(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ struct at803x_priv *priv = phydev->priv; ++ int ret; ++ ++ if (of_property_read_bool(node, "qca,keep-pll-enabled")) ++ priv->flags |= AT803X_KEEP_PLL_ENABLED; ++ ++ ret = at8031_register_regulators(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = devm_regulator_get_enable_optional(&phydev->mdio.dev, ++ "vddio"); ++ if (ret) { ++ phydev_err(phydev, "failed to get VDDIO regulator\n"); ++ return ret; ++ } ++ ++ /* Only AR8031/8033 support 1000Base-X for SFP modules */ ++ return phy_sfp_probe(phydev, &at803x_sfp_ops); ++} ++ + static int at8031_probe(struct phy_device *phydev) + { + int ret; +@@ -1590,6 +1590,13 @@ static int at8031_probe(struct phy_devic + if (ret) + return ret; + ++ /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping ++ * options. ++ */ ++ ret = at8031_parse_dt(phydev); ++ if (ret) ++ return ret; ++ + /* Disable WoL in 1588 register which is enabled + * by default + */ diff --git a/lede/target/linux/generic/backport-6.1/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch b/lede/target/linux/generic/backport-6.1/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch new file mode 100644 index 0000000000..9e10e000e5 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch @@ -0,0 +1,78 @@ +From 25d2ba94005fac18fe68878cddff59a67e115554 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:53 +0100 +Subject: [PATCH 06/13] net: phy: at803x: move specific at8031 probe mode check + to dedicated probe + +Move specific at8031 probe mode check to dedicated probe to make +at803x_probe more generic and keep code tidy. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 39 +++++++++++++++++++-------------------- + 1 file changed, 19 insertions(+), 20 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -844,26 +844,6 @@ static int at803x_probe(struct phy_devic + if (ret) + return ret; + +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); +- int mode_cfg; +- +- if (ccr < 0) +- return ccr; +- mode_cfg = ccr & AT803X_MODE_CFG_MASK; +- +- switch (mode_cfg) { +- case AT803X_MODE_CFG_BX1000_RGMII_50OHM: +- case AT803X_MODE_CFG_BX1000_RGMII_75OHM: +- priv->is_1000basex = true; +- fallthrough; +- case AT803X_MODE_CFG_FX100_RGMII_50OHM: +- case AT803X_MODE_CFG_FX100_RGMII_75OHM: +- priv->is_fiber = true; +- break; +- } +- } +- + return 0; + } + +@@ -1584,6 +1564,9 @@ static int at8031_parse_dt(struct phy_de + + static int at8031_probe(struct phy_device *phydev) + { ++ struct at803x_priv *priv = phydev->priv; ++ int mode_cfg; ++ int ccr; + int ret; + + ret = at803x_probe(phydev); +@@ -1597,6 +1580,22 @@ static int at8031_probe(struct phy_devic + if (ret) + return ret; + ++ ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); ++ if (ccr < 0) ++ return ccr; ++ mode_cfg = ccr & AT803X_MODE_CFG_MASK; ++ ++ switch (mode_cfg) { ++ case AT803X_MODE_CFG_BX1000_RGMII_50OHM: ++ case AT803X_MODE_CFG_BX1000_RGMII_75OHM: ++ priv->is_1000basex = true; ++ fallthrough; ++ case AT803X_MODE_CFG_FX100_RGMII_50OHM: ++ case AT803X_MODE_CFG_FX100_RGMII_75OHM: ++ priv->is_fiber = true; ++ break; ++ } ++ + /* Disable WoL in 1588 register which is enabled + * by default + */ diff --git a/lede/target/linux/generic/backport-6.1/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch b/lede/target/linux/generic/backport-6.1/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch new file mode 100644 index 0000000000..c9ef6df827 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch @@ -0,0 +1,86 @@ +From 3ae3bc426eaf57ca8f53d75777d9a5ef779bc7b7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:54 +0100 +Subject: [PATCH 07/13] net: phy: at803x: move specific at8031 config_init to + dedicated function + +Move specific at8031 config_init to dedicated function to make +at803x_config_init more generic and tidy things up. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 45 ++++++++++++++++++++++------------------ + 1 file changed, 25 insertions(+), 20 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -951,27 +951,8 @@ static int at803x_hibernation_mode_confi + + static int at803x_config_init(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + int ret; + +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- /* Some bootloaders leave the fiber page selected. +- * Switch to the appropriate page (fiber or copper), as otherwise we +- * read the PHY capabilities from the wrong page. +- */ +- phy_lock_mdio_bus(phydev); +- ret = at803x_write_page(phydev, +- priv->is_fiber ? AT803X_PAGE_FIBER : +- AT803X_PAGE_COPPER); +- phy_unlock_mdio_bus(phydev); +- if (ret) +- return ret; +- +- ret = at8031_pll_config(phydev); +- if (ret < 0) +- return ret; +- } +- + /* The RX and TX delay default is: + * after HW reset: RX delay enabled and TX delay disabled + * after SW reset: RX delay enabled, while TX delay retains the +@@ -1604,6 +1585,30 @@ static int at8031_probe(struct phy_devic + AT803X_WOL_EN, 0); + } + ++static int at8031_config_init(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int ret; ++ ++ /* Some bootloaders leave the fiber page selected. ++ * Switch to the appropriate page (fiber or copper), as otherwise we ++ * read the PHY capabilities from the wrong page. ++ */ ++ phy_lock_mdio_bus(phydev); ++ ret = at803x_write_page(phydev, ++ priv->is_fiber ? AT803X_PAGE_FIBER : ++ AT803X_PAGE_COPPER); ++ phy_unlock_mdio_bus(phydev); ++ if (ret) ++ return ret; ++ ++ ret = at8031_pll_config(phydev); ++ if (ret < 0) ++ return ret; ++ ++ return at803x_config_init(phydev); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2113,7 +2118,7 @@ static struct phy_driver at803x_driver[] + .name = "Qualcomm Atheros AR8031/AR8033", + .flags = PHY_POLL_CABLE_TEST, + .probe = at8031_probe, +- .config_init = at803x_config_init, ++ .config_init = at8031_config_init, + .config_aneg = at803x_config_aneg, + .soft_reset = genphy_soft_reset, + .set_wol = at803x_set_wol, diff --git a/lede/target/linux/generic/backport-6.1/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch b/lede/target/linux/generic/backport-6.1/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch new file mode 100644 index 0000000000..6746a4d43c --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch @@ -0,0 +1,92 @@ +From 27b89c9dc1b0393090d68d651b82f30ad2696baa Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:55 +0100 +Subject: [PATCH 08/13] net: phy: at803x: move specific at8031 WOL bits to + dedicated function + +Move specific at8031 WOL enable/disable to dedicated function to make +at803x_set_wol more generic. + +This is needed in preparation for PHY driver split as qca8081 share the +same function to toggle WOL settings. + +In this new implementation WOL module in at8031 is enabled after the +generic interrupt is setup. This should not cause any problem as the +WOL_INT has a separate implementation and only relay on MAC bits. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 42 ++++++++++++++++++++++++---------------- + 1 file changed, 25 insertions(+), 17 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -466,27 +466,11 @@ static int at803x_set_wol(struct phy_dev + phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], + mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); + +- /* Enable WOL function for 1588 */ +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- 0, AT803X_WOL_EN); +- if (ret) +- return ret; +- } + /* Enable WOL interrupt */ + ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); + if (ret) + return ret; + } else { +- /* Disable WoL function for 1588 */ +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- AT803X_WOL_EN, 0); +- if (ret) +- return ret; +- } + /* Disable WOL interrupt */ + ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); + if (ret) +@@ -1609,6 +1593,30 @@ static int at8031_config_init(struct phy + return at803x_config_init(phydev); + } + ++static int at8031_set_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int ret; ++ ++ /* First setup MAC address and enable WOL interrupt */ ++ ret = at803x_set_wol(phydev, wol); ++ if (ret) ++ return ret; ++ ++ if (wol->wolopts & WAKE_MAGIC) ++ /* Enable WOL function for 1588 */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ 0, AT803X_WOL_EN); ++ else ++ /* Disable WoL function for 1588 */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ AT803X_WOL_EN, 0); ++ ++ return ret; ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2121,7 +2129,7 @@ static struct phy_driver at803x_driver[] + .config_init = at8031_config_init, + .config_aneg = at803x_config_aneg, + .soft_reset = genphy_soft_reset, +- .set_wol = at803x_set_wol, ++ .set_wol = at8031_set_wol, + .get_wol = at803x_get_wol, + .suspend = at803x_suspend, + .resume = at803x_resume, diff --git a/lede/target/linux/generic/backport-6.1/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch b/lede/target/linux/generic/backport-6.1/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch new file mode 100644 index 0000000000..0d284c3d24 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch @@ -0,0 +1,78 @@ +From 30dd62191d3dd97c08f7f9dc9ce77ffab457e4fb Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:56 +0100 +Subject: [PATCH 09/13] net: phy: at803x: move specific at8031 config_intr to + dedicated function + +Move specific at8031 config_intr bits to dedicated function to make +at803x_config_initr more generic. + +This is needed in preparation for PHY driver split as qca8081 share the +same function to setup interrupts. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -990,7 +990,6 @@ static int at803x_ack_interrupt(struct p + + static int at803x_config_intr(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + int err; + int value; + +@@ -1007,10 +1006,6 @@ static int at803x_config_intr(struct phy + value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED; + value |= AT803X_INTR_ENABLE_LINK_FAIL; + value |= AT803X_INTR_ENABLE_LINK_SUCCESS; +- if (priv->is_fiber) { +- value |= AT803X_INTR_ENABLE_LINK_FAIL_BX; +- value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX; +- } + + err = phy_write(phydev, AT803X_INTR_ENABLE, value); + } else { +@@ -1617,6 +1612,29 @@ static int at8031_set_wol(struct phy_dev + return ret; + } + ++static int at8031_config_intr(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int err, value = 0; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED && ++ priv->is_fiber) { ++ /* Clear any pending interrupts */ ++ err = at803x_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ value |= AT803X_INTR_ENABLE_LINK_FAIL_BX; ++ value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX; ++ ++ err = phy_set_bits(phydev, AT803X_INTR_ENABLE, value); ++ if (err) ++ return err; ++ } ++ ++ return at803x_config_intr(phydev); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2137,7 +2155,7 @@ static struct phy_driver at803x_driver[] + .write_page = at803x_write_page, + .get_features = at803x_get_features, + .read_status = at803x_read_status, +- .config_intr = at803x_config_intr, ++ .config_intr = at8031_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, diff --git a/lede/target/linux/generic/backport-6.1/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch b/lede/target/linux/generic/backport-6.1/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch new file mode 100644 index 0000000000..210949ea81 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch @@ -0,0 +1,78 @@ +From a5ab9d8e7ae0da8328ac1637a9755311508dc8ab Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:57 +0100 +Subject: [PATCH 10/13] net: phy: at803x: make at8031 related DT functions name + more specific + +Rename at8031 related DT function name to a more specific name +referencing they are only related to at8031 and not to the generic +at803x PHY family. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -583,7 +583,7 @@ static int at803x_resume(struct phy_devi + return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0); + } + +-static int at803x_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, ++static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) + { + struct phy_device *phydev = rdev_get_drvdata(rdev); +@@ -596,7 +596,7 @@ static int at803x_rgmii_reg_set_voltage_ + AT803X_DEBUG_RGMII_1V8, 0); + } + +-static int at803x_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) ++static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) + { + struct phy_device *phydev = rdev_get_drvdata(rdev); + int val; +@@ -610,8 +610,8 @@ static int at803x_rgmii_reg_get_voltage_ + + static const struct regulator_ops vddio_regulator_ops = { + .list_voltage = regulator_list_voltage_table, +- .set_voltage_sel = at803x_rgmii_reg_set_voltage_sel, +- .get_voltage_sel = at803x_rgmii_reg_get_voltage_sel, ++ .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, ++ .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, + }; + + static const unsigned int vddio_voltage_table[] = { +@@ -666,7 +666,7 @@ static int at8031_register_regulators(st + return 0; + } + +-static int at803x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) + { + struct phy_device *phydev = upstream; + __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); +@@ -710,10 +710,10 @@ static int at803x_sfp_insert(void *upstr + return 0; + } + +-static const struct sfp_upstream_ops at803x_sfp_ops = { ++static const struct sfp_upstream_ops at8031_sfp_ops = { + .attach = phy_sfp_attach, + .detach = phy_sfp_detach, +- .module_insert = at803x_sfp_insert, ++ .module_insert = at8031_sfp_insert, + }; + + static int at803x_parse_dt(struct phy_device *phydev) +@@ -1519,7 +1519,7 @@ static int at8031_parse_dt(struct phy_de + } + + /* Only AR8031/8033 support 1000Base-X for SFP modules */ +- return phy_sfp_probe(phydev, &at803x_sfp_ops); ++ return phy_sfp_probe(phydev, &at8031_sfp_ops); + } + + static int at8031_probe(struct phy_device *phydev) diff --git a/lede/target/linux/generic/backport-6.1/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch b/lede/target/linux/generic/backport-6.1/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch new file mode 100644 index 0000000000..5856b59751 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch @@ -0,0 +1,297 @@ +From f932a6dc8bae0dae9645b5b1b4c65aed8a8acb2a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:58 +0100 +Subject: [PATCH 11/13] net: phy: at803x: move at8031 functions in dedicated + section + +Move at8031 functions in dedicated section with dedicated at8031 +parse_dt and probe. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 266 +++++++++++++++++++-------------------- + 1 file changed, 133 insertions(+), 133 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -583,139 +583,6 @@ static int at803x_resume(struct phy_devi + return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0); + } + +-static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, +- unsigned int selector) +-{ +- struct phy_device *phydev = rdev_get_drvdata(rdev); +- +- if (selector) +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- 0, AT803X_DEBUG_RGMII_1V8); +- else +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- AT803X_DEBUG_RGMII_1V8, 0); +-} +- +-static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) +-{ +- struct phy_device *phydev = rdev_get_drvdata(rdev); +- int val; +- +- val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F); +- if (val < 0) +- return val; +- +- return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0; +-} +- +-static const struct regulator_ops vddio_regulator_ops = { +- .list_voltage = regulator_list_voltage_table, +- .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, +- .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, +-}; +- +-static const unsigned int vddio_voltage_table[] = { +- 1500000, +- 1800000, +-}; +- +-static const struct regulator_desc vddio_desc = { +- .name = "vddio", +- .of_match = of_match_ptr("vddio-regulator"), +- .n_voltages = ARRAY_SIZE(vddio_voltage_table), +- .volt_table = vddio_voltage_table, +- .ops = &vddio_regulator_ops, +- .type = REGULATOR_VOLTAGE, +- .owner = THIS_MODULE, +-}; +- +-static const struct regulator_ops vddh_regulator_ops = { +-}; +- +-static const struct regulator_desc vddh_desc = { +- .name = "vddh", +- .of_match = of_match_ptr("vddh-regulator"), +- .n_voltages = 1, +- .fixed_uV = 2500000, +- .ops = &vddh_regulator_ops, +- .type = REGULATOR_VOLTAGE, +- .owner = THIS_MODULE, +-}; +- +-static int at8031_register_regulators(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- struct device *dev = &phydev->mdio.dev; +- struct regulator_config config = { }; +- +- config.dev = dev; +- config.driver_data = phydev; +- +- priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config); +- if (IS_ERR(priv->vddio_rdev)) { +- phydev_err(phydev, "failed to register VDDIO regulator\n"); +- return PTR_ERR(priv->vddio_rdev); +- } +- +- priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config); +- if (IS_ERR(priv->vddh_rdev)) { +- phydev_err(phydev, "failed to register VDDH regulator\n"); +- return PTR_ERR(priv->vddh_rdev); +- } +- +- return 0; +-} +- +-static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) +-{ +- struct phy_device *phydev = upstream; +- __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); +- __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); +- DECLARE_PHY_INTERFACE_MASK(interfaces); +- phy_interface_t iface; +- +- linkmode_zero(phy_support); +- phylink_set(phy_support, 1000baseX_Full); +- phylink_set(phy_support, 1000baseT_Full); +- phylink_set(phy_support, Autoneg); +- phylink_set(phy_support, Pause); +- phylink_set(phy_support, Asym_Pause); +- +- linkmode_zero(sfp_support); +- sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces); +- /* Some modules support 10G modes as well as others we support. +- * Mask out non-supported modes so the correct interface is picked. +- */ +- linkmode_and(sfp_support, phy_support, sfp_support); +- +- if (linkmode_empty(sfp_support)) { +- dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); +- return -EINVAL; +- } +- +- iface = sfp_select_interface(phydev->sfp_bus, sfp_support); +- +- /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes +- * interface for use with SFP modules. +- * However, some copper modules detected as having a preferred SGMII +- * interface do default to and function in 1000Base-X mode, so just +- * print a warning and allow such modules, as they may have some chance +- * of working. +- */ +- if (iface == PHY_INTERFACE_MODE_SGMII) +- dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); +- else if (iface != PHY_INTERFACE_MODE_1000BASEX) +- return -EINVAL; +- +- return 0; +-} +- +-static const struct sfp_upstream_ops at8031_sfp_ops = { +- .attach = phy_sfp_attach, +- .detach = phy_sfp_detach, +- .module_insert = at8031_sfp_insert, +-}; +- + static int at803x_parse_dt(struct phy_device *phydev) + { + struct device_node *node = phydev->mdio.dev.of_node; +@@ -1498,6 +1365,139 @@ static int at803x_cable_test_start(struc + return 0; + } + ++static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, ++ unsigned int selector) ++{ ++ struct phy_device *phydev = rdev_get_drvdata(rdev); ++ ++ if (selector) ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ 0, AT803X_DEBUG_RGMII_1V8); ++ else ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ AT803X_DEBUG_RGMII_1V8, 0); ++} ++ ++static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) ++{ ++ struct phy_device *phydev = rdev_get_drvdata(rdev); ++ int val; ++ ++ val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F); ++ if (val < 0) ++ return val; ++ ++ return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0; ++} ++ ++static const struct regulator_ops vddio_regulator_ops = { ++ .list_voltage = regulator_list_voltage_table, ++ .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, ++ .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, ++}; ++ ++static const unsigned int vddio_voltage_table[] = { ++ 1500000, ++ 1800000, ++}; ++ ++static const struct regulator_desc vddio_desc = { ++ .name = "vddio", ++ .of_match = of_match_ptr("vddio-regulator"), ++ .n_voltages = ARRAY_SIZE(vddio_voltage_table), ++ .volt_table = vddio_voltage_table, ++ .ops = &vddio_regulator_ops, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct regulator_ops vddh_regulator_ops = { ++}; ++ ++static const struct regulator_desc vddh_desc = { ++ .name = "vddh", ++ .of_match = of_match_ptr("vddh-regulator"), ++ .n_voltages = 1, ++ .fixed_uV = 2500000, ++ .ops = &vddh_regulator_ops, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++}; ++ ++static int at8031_register_regulators(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ struct device *dev = &phydev->mdio.dev; ++ struct regulator_config config = { }; ++ ++ config.dev = dev; ++ config.driver_data = phydev; ++ ++ priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config); ++ if (IS_ERR(priv->vddio_rdev)) { ++ phydev_err(phydev, "failed to register VDDIO regulator\n"); ++ return PTR_ERR(priv->vddio_rdev); ++ } ++ ++ priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config); ++ if (IS_ERR(priv->vddh_rdev)) { ++ phydev_err(phydev, "failed to register VDDH regulator\n"); ++ return PTR_ERR(priv->vddh_rdev); ++ } ++ ++ return 0; ++} ++ ++static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++{ ++ struct phy_device *phydev = upstream; ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); ++ DECLARE_PHY_INTERFACE_MASK(interfaces); ++ phy_interface_t iface; ++ ++ linkmode_zero(phy_support); ++ phylink_set(phy_support, 1000baseX_Full); ++ phylink_set(phy_support, 1000baseT_Full); ++ phylink_set(phy_support, Autoneg); ++ phylink_set(phy_support, Pause); ++ phylink_set(phy_support, Asym_Pause); ++ ++ linkmode_zero(sfp_support); ++ sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces); ++ /* Some modules support 10G modes as well as others we support. ++ * Mask out non-supported modes so the correct interface is picked. ++ */ ++ linkmode_and(sfp_support, phy_support, sfp_support); ++ ++ if (linkmode_empty(sfp_support)) { ++ dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); ++ return -EINVAL; ++ } ++ ++ iface = sfp_select_interface(phydev->sfp_bus, sfp_support); ++ ++ /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes ++ * interface for use with SFP modules. ++ * However, some copper modules detected as having a preferred SGMII ++ * interface do default to and function in 1000Base-X mode, so just ++ * print a warning and allow such modules, as they may have some chance ++ * of working. ++ */ ++ if (iface == PHY_INTERFACE_MODE_SGMII) ++ dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); ++ else if (iface != PHY_INTERFACE_MODE_1000BASEX) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static const struct sfp_upstream_ops at8031_sfp_ops = { ++ .attach = phy_sfp_attach, ++ .detach = phy_sfp_detach, ++ .module_insert = at8031_sfp_insert, ++}; ++ + static int at8031_parse_dt(struct phy_device *phydev) + { + struct device_node *node = phydev->mdio.dev.of_node; diff --git a/lede/target/linux/generic/backport-6.1/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch b/lede/target/linux/generic/backport-6.1/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch new file mode 100644 index 0000000000..0a822c6d37 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch @@ -0,0 +1,114 @@ +From 21a2802a8365cfa82cc02187c1f95136d85592ad Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:59 +0100 +Subject: [PATCH 12/13] net: phy: at803x: move at8035 specific DT parse to + dedicated probe + +Move at8035 specific DT parse for clock out frequency to dedicated probe +to make at803x probe function more generic. + +This is to tidy code and no behaviour change are intended. + +Detection logic is changed, we check if the clk 25m mask is set and if +it's not zero, we assume the qca,clk-out-frequency property is set. + +The property is checked in the generic at803x_parse_dt called by +at803x_probe. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 60 +++++++++++++++++++++++++++------------- + 1 file changed, 41 insertions(+), 19 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -638,23 +638,6 @@ static int at803x_parse_dt(struct phy_de + + priv->clk_25m_reg |= FIELD_PREP(AT803X_CLK_OUT_MASK, sel); + priv->clk_25m_mask |= AT803X_CLK_OUT_MASK; +- +- /* Fixup for the AR8030/AR8035. This chip has another mask and +- * doesn't support the DSP reference. Eg. the lowest bit of the +- * mask. The upper two bits select the same frequencies. Mask +- * the lowest bit here. +- * +- * Warning: +- * There was no datasheet for the AR8030 available so this is +- * just a guess. But the AR8035 is listed as pin compatible +- * to the AR8030 so there might be a good chance it works on +- * the AR8030 too. +- */ +- if (phydev->drv->phy_id == ATH8030_PHY_ID || +- phydev->drv->phy_id == ATH8035_PHY_ID) { +- priv->clk_25m_reg &= AT8035_CLK_OUT_MASK; +- priv->clk_25m_mask &= AT8035_CLK_OUT_MASK; +- } + } + + ret = of_property_read_u32(node, "qca,clk-out-strength", &strength); +@@ -1635,6 +1618,45 @@ static int at8031_config_intr(struct phy + return at803x_config_intr(phydev); + } + ++static int at8035_parse_dt(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ /* Mask is set by the generic at803x_parse_dt ++ * if property is set. Assume property is set ++ * with the mask not zero. ++ */ ++ if (priv->clk_25m_mask) { ++ /* Fixup for the AR8030/AR8035. This chip has another mask and ++ * doesn't support the DSP reference. Eg. the lowest bit of the ++ * mask. The upper two bits select the same frequencies. Mask ++ * the lowest bit here. ++ * ++ * Warning: ++ * There was no datasheet for the AR8030 available so this is ++ * just a guess. But the AR8035 is listed as pin compatible ++ * to the AR8030 so there might be a good chance it works on ++ * the AR8030 too. ++ */ ++ priv->clk_25m_reg &= AT8035_CLK_OUT_MASK; ++ priv->clk_25m_mask &= AT8035_CLK_OUT_MASK; ++ } ++ ++ return 0; ++} ++ ++/* AR8030 and AR8035 shared the same special mask for clk_25m */ ++static int at8035_probe(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = at803x_probe(phydev); ++ if (ret) ++ return ret; ++ ++ return at8035_parse_dt(phydev); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2107,7 +2129,7 @@ static struct phy_driver at803x_driver[] + PHY_ID_MATCH_EXACT(ATH8035_PHY_ID), + .name = "Qualcomm Atheros AR8035", + .flags = PHY_POLL_CABLE_TEST, +- .probe = at803x_probe, ++ .probe = at8035_probe, + .config_aneg = at803x_config_aneg, + .config_init = at803x_config_init, + .soft_reset = genphy_soft_reset, +@@ -2128,7 +2150,7 @@ static struct phy_driver at803x_driver[] + .phy_id = ATH8030_PHY_ID, + .name = "Qualcomm Atheros AR8030", + .phy_id_mask = AT8030_PHY_ID_MASK, +- .probe = at803x_probe, ++ .probe = at8035_probe, + .config_init = at803x_config_init, + .link_change_notify = at803x_link_change_notify, + .set_wol = at803x_set_wol, diff --git a/lede/target/linux/generic/backport-6.1/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch b/lede/target/linux/generic/backport-6.1/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch new file mode 100644 index 0000000000..e1ba6ec2d0 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch @@ -0,0 +1,219 @@ +From ef9df47b449e32e06501a11272809be49019bdb6 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:52:00 +0100 +Subject: [PATCH 13/13] net: phy: at803x: drop specific PHY ID check from cable + test functions + +Drop specific PHY ID check for cable test functions for at803x. This is +done to make functions more generic. While at it better describe what +the functions does by using more symbolic function names. + +PHYs that requires to set additional reg are moved to specific function +calling the more generic one. + +cdt_start and cdt_wait_for_completion are changed to take an additional +arg to pass specific values specific to the PHY. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 95 +++++++++++++++++++++------------------- + 1 file changed, 50 insertions(+), 45 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1222,31 +1222,16 @@ static int at803x_cdt_fault_length(u16 s + return (dt * 824) / 10; + } + +-static int at803x_cdt_start(struct phy_device *phydev, int pair) ++static int at803x_cdt_start(struct phy_device *phydev, ++ u32 cdt_start) + { +- u16 cdt; +- +- /* qca8081 takes the different bit 15 to enable CDT test */ +- if (phydev->drv->phy_id == QCA8081_PHY_ID) +- cdt = QCA808X_CDT_ENABLE_TEST | +- QCA808X_CDT_LENGTH_UNIT | +- QCA808X_CDT_INTER_CHECK_DIS; +- else +- cdt = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) | +- AT803X_CDT_ENABLE_TEST; +- +- return phy_write(phydev, AT803X_CDT, cdt); ++ return phy_write(phydev, AT803X_CDT, cdt_start); + } + +-static int at803x_cdt_wait_for_completion(struct phy_device *phydev) ++static int at803x_cdt_wait_for_completion(struct phy_device *phydev, ++ u32 cdt_en) + { + int val, ret; +- u16 cdt_en; +- +- if (phydev->drv->phy_id == QCA8081_PHY_ID) +- cdt_en = QCA808X_CDT_ENABLE_TEST; +- else +- cdt_en = AT803X_CDT_ENABLE_TEST; + + /* One test run takes about 25ms */ + ret = phy_read_poll_timeout(phydev, AT803X_CDT, val, +@@ -1266,11 +1251,13 @@ static int at803x_cable_test_one_pair(st + }; + int ret, val; + +- ret = at803x_cdt_start(phydev, pair); ++ val = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) | ++ AT803X_CDT_ENABLE_TEST; ++ ret = at803x_cdt_start(phydev, val); + if (ret) + return ret; + +- ret = at803x_cdt_wait_for_completion(phydev); ++ ret = at803x_cdt_wait_for_completion(phydev, AT803X_CDT_ENABLE_TEST); + if (ret) + return ret; + +@@ -1292,19 +1279,11 @@ static int at803x_cable_test_one_pair(st + } + + static int at803x_cable_test_get_status(struct phy_device *phydev, +- bool *finished) ++ bool *finished, unsigned long pair_mask) + { +- unsigned long pair_mask; + int retries = 20; + int pair, ret; + +- if (phydev->phy_id == ATH9331_PHY_ID || +- phydev->phy_id == ATH8032_PHY_ID || +- phydev->phy_id == QCA9561_PHY_ID) +- pair_mask = 0x3; +- else +- pair_mask = 0xf; +- + *finished = false; + + /* According to the datasheet the CDT can be performed when +@@ -1331,7 +1310,7 @@ static int at803x_cable_test_get_status( + return 0; + } + +-static int at803x_cable_test_start(struct phy_device *phydev) ++static void at803x_cable_test_autoneg(struct phy_device *phydev) + { + /* Enable auto-negotiation, but advertise no capabilities, no link + * will be established. A restart of the auto-negotiation is not +@@ -1339,11 +1318,11 @@ static int at803x_cable_test_start(struc + */ + phy_write(phydev, MII_BMCR, BMCR_ANENABLE); + phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA); +- if (phydev->phy_id != ATH9331_PHY_ID && +- phydev->phy_id != ATH8032_PHY_ID && +- phydev->phy_id != QCA9561_PHY_ID) +- phy_write(phydev, MII_CTRL1000, 0); ++} + ++static int at803x_cable_test_start(struct phy_device *phydev) ++{ ++ at803x_cable_test_autoneg(phydev); + /* we do all the (time consuming) work later */ + return 0; + } +@@ -1618,6 +1597,29 @@ static int at8031_config_intr(struct phy + return at803x_config_intr(phydev); + } + ++/* AR8031 and AR8035 share the same cable test get status reg */ ++static int at8031_cable_test_get_status(struct phy_device *phydev, ++ bool *finished) ++{ ++ return at803x_cable_test_get_status(phydev, finished, 0xf); ++} ++ ++/* AR8031 and AR8035 share the same cable test start logic */ ++static int at8031_cable_test_start(struct phy_device *phydev) ++{ ++ at803x_cable_test_autoneg(phydev); ++ phy_write(phydev, MII_CTRL1000, 0); ++ /* we do all the (time consuming) work later */ ++ return 0; ++} ++ ++/* AR8032, AR9331 and QCA9561 share the same cable test get status reg */ ++static int at8032_cable_test_get_status(struct phy_device *phydev, ++ bool *finished) ++{ ++ return at803x_cable_test_get_status(phydev, finished, 0x3); ++} ++ + static int at8035_parse_dt(struct phy_device *phydev) + { + struct at803x_priv *priv = phydev->priv; +@@ -2041,11 +2043,14 @@ static int qca808x_cable_test_get_status + + *finished = false; + +- ret = at803x_cdt_start(phydev, 0); ++ val = QCA808X_CDT_ENABLE_TEST | ++ QCA808X_CDT_LENGTH_UNIT | ++ QCA808X_CDT_INTER_CHECK_DIS; ++ ret = at803x_cdt_start(phydev, val); + if (ret) + return ret; + +- ret = at803x_cdt_wait_for_completion(phydev); ++ ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); + if (ret) + return ret; + +@@ -2143,8 +2148,8 @@ static struct phy_driver at803x_driver[] + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, +- .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_start = at8031_cable_test_start, ++ .cable_test_get_status = at8031_cable_test_get_status, + }, { + /* Qualcomm Atheros AR8030 */ + .phy_id = ATH8030_PHY_ID, +@@ -2181,8 +2186,8 @@ static struct phy_driver at803x_driver[] + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, +- .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_start = at8031_cable_test_start, ++ .cable_test_get_status = at8031_cable_test_get_status, + }, { + /* Qualcomm Atheros AR8032 */ + PHY_ID_MATCH_EXACT(ATH8032_PHY_ID), +@@ -2197,7 +2202,7 @@ static struct phy_driver at803x_driver[] + .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_get_status = at8032_cable_test_get_status, + }, { + /* ATHEROS AR9331 */ + PHY_ID_MATCH_EXACT(ATH9331_PHY_ID), +@@ -2210,7 +2215,7 @@ static struct phy_driver at803x_driver[] + .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_get_status = at8032_cable_test_get_status, + .read_status = at803x_read_status, + .soft_reset = genphy_soft_reset, + .config_aneg = at803x_config_aneg, +@@ -2226,7 +2231,7 @@ static struct phy_driver at803x_driver[] + .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_get_status = at8032_cable_test_get_status, + .read_status = at803x_read_status, + .soft_reset = genphy_soft_reset, + .config_aneg = at803x_config_aneg, diff --git a/lede/target/linux/generic/backport-6.1/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch b/lede/target/linux/generic/backport-6.1/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch new file mode 100644 index 0000000000..0bb3673c02 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch @@ -0,0 +1,116 @@ +From 8e732f1c6f2dc5e18f766d0f1b11df9db2dd044a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 14 Dec 2023 01:44:31 +0100 +Subject: [PATCH 1/2] net: phy: at803x: move specific qca808x config_aneg to + dedicated function + +Move specific qca808x config_aneg to dedicated function to permit easier +split of qca808x portion from at803x driver. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 66 ++++++++++++++++++++++++---------------- + 1 file changed, 40 insertions(+), 26 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1045,9 +1045,8 @@ static int at803x_config_mdix(struct phy + FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val)); + } + +-static int at803x_config_aneg(struct phy_device *phydev) ++static int at803x_prepare_config_aneg(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + int ret; + + ret = at803x_config_mdix(phydev, phydev->mdix_ctrl); +@@ -1064,33 +1063,22 @@ static int at803x_config_aneg(struct phy + return ret; + } + +- if (priv->is_1000basex) +- return genphy_c37_config_aneg(phydev); +- +- /* Do not restart auto-negotiation by setting ret to 0 defautly, +- * when calling __genphy_config_aneg later. +- */ +- ret = 0; +- +- if (phydev->drv->phy_id == QCA8081_PHY_ID) { +- int phy_ctrl = 0; ++ return 0; ++} + +- /* The reg MII_BMCR also needs to be configured for force mode, the +- * genphy_config_aneg is also needed. +- */ +- if (phydev->autoneg == AUTONEG_DISABLE) +- genphy_c45_pma_setup_forced(phydev); ++static int at803x_config_aneg(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int ret; + +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) +- phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; ++ ret = at803x_prepare_config_aneg(phydev); ++ if (ret) ++ return ret; + +- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, +- MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); +- if (ret < 0) +- return ret; +- } ++ if (priv->is_1000basex) ++ return genphy_c37_config_aneg(phydev); + +- return __genphy_config_aneg(phydev, ret); ++ return genphy_config_aneg(phydev); + } + + static int at803x_get_downshift(struct phy_device *phydev, u8 *d) +@@ -2118,6 +2106,32 @@ static int qca808x_get_features(struct p + return 0; + } + ++static int qca808x_config_aneg(struct phy_device *phydev) ++{ ++ int phy_ctrl = 0; ++ int ret; ++ ++ ret = at803x_prepare_config_aneg(phydev); ++ if (ret) ++ return ret; ++ ++ /* The reg MII_BMCR also needs to be configured for force mode, the ++ * genphy_config_aneg is also needed. ++ */ ++ if (phydev->autoneg == AUTONEG_DISABLE) ++ genphy_c45_pma_setup_forced(phydev); ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) ++ phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; ++ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, ++ MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); ++ if (ret < 0) ++ return ret; ++ ++ return __genphy_config_aneg(phydev, ret); ++} ++ + static void qca808x_link_change_notify(struct phy_device *phydev) + { + /* Assert interface sgmii fifo on link down, deassert it on link up, +@@ -2295,7 +2309,7 @@ static struct phy_driver at803x_driver[] + .set_wol = at803x_set_wol, + .get_wol = at803x_get_wol, + .get_features = qca808x_get_features, +- .config_aneg = at803x_config_aneg, ++ .config_aneg = qca808x_config_aneg, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_status = qca808x_read_status, diff --git a/lede/target/linux/generic/backport-6.1/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch b/lede/target/linux/generic/backport-6.1/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch new file mode 100644 index 0000000000..54ca3bdfc8 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch @@ -0,0 +1,97 @@ +From 38eb804e8458ba181a03a0498ce4bf84eebd1931 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 14 Dec 2023 01:44:32 +0100 +Subject: [PATCH 2/2] net: phy: at803x: make read specific status function more + generic + +Rework read specific status function to be more generic. The function +apply different speed mask based on the PHY ID. Make it more generic by +adding an additional arg to pass the specific speed (ss) mask and use +the provided mask to parse the speed value. + +This is needed to permit an easier deatch of qca808x code from the +at803x driver. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 26 ++++++++++++++++++-------- + 1 file changed, 18 insertions(+), 8 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -301,6 +301,11 @@ static struct at803x_hw_stat qca83xx_hw_ + { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, + }; + ++struct at803x_ss_mask { ++ u16 speed_mask; ++ u8 speed_shift; ++}; ++ + struct at803x_priv { + int flags; + u16 clk_25m_reg; +@@ -921,7 +926,8 @@ static void at803x_link_change_notify(st + } + } + +-static int at803x_read_specific_status(struct phy_device *phydev) ++static int at803x_read_specific_status(struct phy_device *phydev, ++ struct at803x_ss_mask ss_mask) + { + int ss; + +@@ -940,11 +946,8 @@ static int at803x_read_specific_status(s + if (sfc < 0) + return sfc; + +- /* qca8081 takes the different bits for speed value from at803x */ +- if (phydev->drv->phy_id == QCA8081_PHY_ID) +- speed = FIELD_GET(QCA808X_SS_SPEED_MASK, ss); +- else +- speed = FIELD_GET(AT803X_SS_SPEED_MASK, ss); ++ speed = ss & ss_mask.speed_mask; ++ speed >>= ss_mask.speed_shift; + + switch (speed) { + case AT803X_SS_SPEED_10: +@@ -989,6 +992,7 @@ static int at803x_read_specific_status(s + static int at803x_read_status(struct phy_device *phydev) + { + struct at803x_priv *priv = phydev->priv; ++ struct at803x_ss_mask ss_mask = { 0 }; + int err, old_link = phydev->link; + + if (priv->is_1000basex) +@@ -1012,7 +1016,9 @@ static int at803x_read_status(struct phy + if (err < 0) + return err; + +- err = at803x_read_specific_status(phydev); ++ ss_mask.speed_mask = AT803X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK); ++ err = at803x_read_specific_status(phydev, ss_mask); + if (err < 0) + return err; + +@@ -1869,6 +1875,7 @@ static int qca808x_config_init(struct ph + + static int qca808x_read_status(struct phy_device *phydev) + { ++ struct at803x_ss_mask ss_mask = { 0 }; + int ret; + + ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); +@@ -1882,7 +1889,10 @@ static int qca808x_read_status(struct ph + if (ret) + return ret; + +- ret = at803x_read_specific_status(phydev); ++ /* qca8081 takes the different bits for speed value from at803x */ ++ ss_mask.speed_mask = QCA808X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(QCA808X_SS_SPEED_MASK); ++ ret = at803x_read_specific_status(phydev, ss_mask); + if (ret < 0) + return ret; + diff --git a/lede/target/linux/generic/backport-6.1/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch b/lede/target/linux/generic/backport-6.1/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch new file mode 100644 index 0000000000..8097a33e49 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch @@ -0,0 +1,27 @@ +From fc9d7264ddc32eaa647d6bfcdc25cdf9f786fde0 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 18 Dec 2023 00:27:39 +0100 +Subject: [PATCH 1/2] net: phy: at803x: remove extra space after cast + +Remove extra space after cast as reported by checkpatch to keep code +clean. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20231217232739.27065-1-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/at803x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -462,7 +462,7 @@ static int at803x_set_wol(struct phy_dev + if (!ndev) + return -ENODEV; + +- mac = (const u8 *) ndev->dev_addr; ++ mac = (const u8 *)ndev->dev_addr; + + if (!is_valid_ether_addr(mac)) + return -EINVAL; diff --git a/lede/target/linux/generic/backport-6.1/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch b/lede/target/linux/generic/backport-6.1/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch new file mode 100644 index 0000000000..b8d4591087 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch @@ -0,0 +1,38 @@ +From 3ab5720881a924fb6405d9e6a3b09f1026467c47 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 18 Dec 2023 00:25:08 +0100 +Subject: [PATCH 2/2] net: phy: at803x: replace msleep(1) with usleep_range + +Replace msleep(1) with usleep_range as suggested by timers-howto guide. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20231217232508.26470-1-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/at803x.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -916,9 +916,9 @@ static void at803x_link_change_notify(st + at803x_context_save(phydev, &context); + + phy_device_reset(phydev, 1); +- msleep(1); ++ usleep_range(1000, 2000); + phy_device_reset(phydev, 0); +- msleep(1); ++ usleep_range(1000, 2000); + + at803x_context_restore(phydev, &context); + +@@ -1733,7 +1733,7 @@ static int qca83xx_resume(struct phy_dev + if (ret) + return ret; + +- msleep(1); ++ usleep_range(1000, 2000); + + return 0; + } diff --git a/lede/target/linux/generic/backport-6.1/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch b/lede/target/linux/generic/backport-6.1/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch new file mode 100644 index 0000000000..776b7bb43f --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch @@ -0,0 +1,152 @@ +From 7961ef1fa10ec35ad6923fb5751877116e4b035b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 19 Dec 2023 21:21:24 +0100 +Subject: [PATCH] net: phy: at803x: better align function varibles to open + parenthesis + +Better align function variables to open parenthesis as suggested by +checkpatch script for qca808x function to make code cleaner. + +For cable_test_get_status function some additional rework was needed to +handle too long functions. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 67 ++++++++++++++++++++++------------------ + 1 file changed, 37 insertions(+), 30 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1781,27 +1781,27 @@ static int qca808x_phy_fast_retrain_conf + return ret; + + phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1, +- QCA808X_TOP_OPTION1_DATA); ++ QCA808X_TOP_OPTION1_DATA); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB, +- QCA808X_MSE_THRESHOLD_20DB_VALUE); ++ QCA808X_MSE_THRESHOLD_20DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB, +- QCA808X_MSE_THRESHOLD_17DB_VALUE); ++ QCA808X_MSE_THRESHOLD_17DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB, +- QCA808X_MSE_THRESHOLD_27DB_VALUE); ++ QCA808X_MSE_THRESHOLD_27DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB, +- QCA808X_MSE_THRESHOLD_28DB_VALUE); ++ QCA808X_MSE_THRESHOLD_28DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1, +- QCA808X_MMD3_DEBUG_1_VALUE); ++ QCA808X_MMD3_DEBUG_1_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4, +- QCA808X_MMD3_DEBUG_4_VALUE); ++ QCA808X_MMD3_DEBUG_4_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5, +- QCA808X_MMD3_DEBUG_5_VALUE); ++ QCA808X_MMD3_DEBUG_5_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3, +- QCA808X_MMD3_DEBUG_3_VALUE); ++ QCA808X_MMD3_DEBUG_3_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6, +- QCA808X_MMD3_DEBUG_6_VALUE); ++ QCA808X_MMD3_DEBUG_6_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2, +- QCA808X_MMD3_DEBUG_2_VALUE); ++ QCA808X_MMD3_DEBUG_2_VALUE); + + return 0; + } +@@ -1838,13 +1838,14 @@ static int qca808x_config_init(struct ph + + /* Active adc&vga on 802.3az for the link 1000M and 100M */ + ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, +- QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); ++ QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); + if (ret) + return ret; + + /* Adjust the threshold on 802.3az for the link 1000M */ + ret = phy_write_mmd(phydev, MDIO_MMD_PCS, +- QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, QCA808X_MMD3_AZ_TRAINING_VAL); ++ QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, ++ QCA808X_MMD3_AZ_TRAINING_VAL); + if (ret) + return ret; + +@@ -1870,7 +1871,8 @@ static int qca808x_config_init(struct ph + + /* Configure adc threshold as 100mv for the link 10M */ + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, +- QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV); ++ QCA808X_ADC_THRESHOLD_MASK, ++ QCA808X_ADC_THRESHOLD_100MV); + } + + static int qca808x_read_status(struct phy_device *phydev) +@@ -1883,7 +1885,7 @@ static int qca808x_read_status(struct ph + return ret; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising, +- ret & MDIO_AN_10GBT_STAT_LP2_5G); ++ ret & MDIO_AN_10GBT_STAT_LP2_5G); + + ret = genphy_read_status(phydev); + if (ret) +@@ -1913,7 +1915,7 @@ static int qca808x_read_status(struct ph + */ + if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { + if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || +- qca808x_is_prefer_master(phydev)) { ++ qca808x_is_prefer_master(phydev)) { + qca808x_phy_ms_seed_enable(phydev, false); + } else { + qca808x_phy_ms_seed_enable(phydev, true); +@@ -2070,18 +2072,22 @@ static int qca808x_cable_test_get_status + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D, + qca808x_cable_test_result_trans(pair_d)); + +- if (qca808x_cdt_fault_length_valid(pair_a)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A)); +- if (qca808x_cdt_fault_length_valid(pair_b)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B)); +- if (qca808x_cdt_fault_length_valid(pair_c)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C)); +- if (qca808x_cdt_fault_length_valid(pair_d)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D)); ++ if (qca808x_cdt_fault_length_valid(pair_a)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, val); ++ } ++ if (qca808x_cdt_fault_length_valid(pair_b)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B, val); ++ } ++ if (qca808x_cdt_fault_length_valid(pair_c)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C, val); ++ } ++ if (qca808x_cdt_fault_length_valid(pair_d)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D, val); ++ } + + *finished = true; + +@@ -2148,8 +2154,9 @@ static void qca808x_link_change_notify(s + * the interface device address is always phy address added by 1. + */ + mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, +- MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, +- QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); ++ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, ++ QCA8081_PHY_FIFO_RSTN, ++ phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); + } + + static struct phy_driver at803x_driver[] = { diff --git a/lede/target/linux/generic/backport-6.1/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch b/lede/target/linux/generic/backport-6.1/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch new file mode 100644 index 0000000000..d7196da46e --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch @@ -0,0 +1,62 @@ +From 22eb276098da820d9440fad22901f9b74ed4d659 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:38 +0100 +Subject: [PATCH 1/4] net: phy: at803x: generalize cdt fault length function + +Generalize cable test fault length function since they all base on the +same magic values (already reverse engineered to understand the meaning +of it) to have consistenct values on every PHY. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1192,10 +1192,8 @@ static bool at803x_cdt_fault_length_vali + return false; + } + +-static int at803x_cdt_fault_length(u16 status) ++static int at803x_cdt_fault_length(int dt) + { +- int dt; +- + /* According to the datasheet the distance to the fault is + * DELTA_TIME * 0.824 meters. + * +@@ -1211,8 +1209,6 @@ static int at803x_cdt_fault_length(u16 s + * With a VF of 0.69 we get the factor 0.824 mentioned in the + * datasheet. + */ +- dt = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, status); +- + return (dt * 824) / 10; + } + +@@ -1265,9 +1261,11 @@ static int at803x_cable_test_one_pair(st + ethnl_cable_test_result(phydev, ethtool_pair[pair], + at803x_cable_test_result_trans(val)); + +- if (at803x_cdt_fault_length_valid(val)) ++ if (at803x_cdt_fault_length_valid(val)) { ++ val = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, val); + ethnl_cable_test_fault_length(phydev, ethtool_pair[pair], + at803x_cdt_fault_length(val)); ++ } + + return 1; + } +@@ -1992,7 +1990,8 @@ static int qca808x_cdt_fault_length(stru + if (val < 0) + return val; + +- return (FIELD_GET(QCA808X_CDT_DIAG_LENGTH, val) * 824) / 10; ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH, val); ++ return at803x_cdt_fault_length(val); + } + + static int qca808x_cable_test_start(struct phy_device *phydev) diff --git a/lede/target/linux/generic/backport-6.1/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch b/lede/target/linux/generic/backport-6.1/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch new file mode 100644 index 0000000000..5d38fe7e91 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch @@ -0,0 +1,118 @@ +From e0e9ada1df6133513249861c1d91c1dbefd9383b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:39 +0100 +Subject: [PATCH 2/4] net: phy: at803x: refactor qca808x cable test get status + function + +Refactor qca808x cable test get status function to remove code +duplication and clean things up. + +The same logic is applied to each pair hence it can be generalized and +moved to a common function. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 80 ++++++++++++++++++++++++---------------- + 1 file changed, 49 insertions(+), 31 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -2035,10 +2035,43 @@ static int qca808x_cable_test_start(stru + return 0; + } + ++static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, ++ u16 status) ++{ ++ u16 pair_code; ++ int length; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ ethnl_cable_test_result(phydev, pair, ++ qca808x_cable_test_result_trans(pair_code)); ++ ++ if (qca808x_cdt_fault_length_valid(pair_code)) { ++ length = qca808x_cdt_fault_length(phydev, pair); ++ ethnl_cable_test_fault_length(phydev, pair, length); ++ } ++ ++ return 0; ++} ++ + static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) + { + int ret, val; +- int pair_a, pair_b, pair_c, pair_d; + + *finished = false; + +@@ -2057,36 +2090,21 @@ static int qca808x_cable_test_get_status + if (val < 0) + return val; + +- pair_a = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, val); +- pair_b = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, val); +- pair_c = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, val); +- pair_d = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, val); +- +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, +- qca808x_cable_test_result_trans(pair_a)); +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_B, +- qca808x_cable_test_result_trans(pair_b)); +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_C, +- qca808x_cable_test_result_trans(pair_c)); +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D, +- qca808x_cable_test_result_trans(pair_d)); +- +- if (qca808x_cdt_fault_length_valid(pair_a)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, val); +- } +- if (qca808x_cdt_fault_length_valid(pair_b)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B, val); +- } +- if (qca808x_cdt_fault_length_valid(pair_c)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C, val); +- } +- if (qca808x_cdt_fault_length_valid(pair_d)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D, val); +- } ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); ++ if (ret) ++ return ret; + + *finished = true; + diff --git a/lede/target/linux/generic/backport-6.1/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch b/lede/target/linux/generic/backport-6.1/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch new file mode 100644 index 0000000000..d5793860a9 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch @@ -0,0 +1,182 @@ +From ea73e5ea442ee2aade67b1fb1233ccb3cbea2ceb Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:40 +0100 +Subject: [PATCH 3/4] net: phy: at803x: add support for cdt cross short test + for qca808x + +QCA808x PHY Family supports Cable Diagnostic Test also for Cross Pair +Short. + +Add all the define to make enable and support these additional tests. + +Cross Short test was previously disabled by default, this is now changed +and enabled by default. In this mode, the mask changed a bit and length +is shifted based on the fault condition. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 86 ++++++++++++++++++++++++++++++++-------- + 1 file changed, 69 insertions(+), 17 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -254,6 +254,7 @@ + + #define QCA808X_CDT_ENABLE_TEST BIT(15) + #define QCA808X_CDT_INTER_CHECK_DIS BIT(13) ++#define QCA808X_CDT_STATUS BIT(11) + #define QCA808X_CDT_LENGTH_UNIT BIT(10) + + #define QCA808X_MMD3_CDT_STATUS 0x8064 +@@ -261,16 +262,44 @@ + #define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 + #define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 + #define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 +-#define QCA808X_CDT_DIAG_LENGTH GENMASK(7, 0) ++#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) ++#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) + + #define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) + #define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) + #define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) + #define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) +-#define QCA808X_CDT_STATUS_STAT_FAIL 0 +-#define QCA808X_CDT_STATUS_STAT_NORMAL 1 +-#define QCA808X_CDT_STATUS_STAT_OPEN 2 +-#define QCA808X_CDT_STATUS_STAT_SHORT 3 ++ ++#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) ++#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) ++#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) ++#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) ++#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) ++ ++#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) ++#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) ++ ++/* NORMAL are MDI with type set to 0 */ ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++ ++/* Added for reference of existence but should be handled by wait_for_completion already */ ++#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) + + /* QCA808X 1G chip type */ + #define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d +@@ -1941,8 +1970,17 @@ static int qca808x_soft_reset(struct phy + static bool qca808x_cdt_fault_length_valid(int cdt_code) + { + switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_SHORT: +- case QCA808X_CDT_STATUS_STAT_OPEN: ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: + return true; + default: + return false; +@@ -1954,17 +1992,28 @@ static int qca808x_cable_test_result_tra + switch (cdt_code) { + case QCA808X_CDT_STATUS_STAT_NORMAL: + return ETHTOOL_A_CABLE_RESULT_CODE_OK; +- case QCA808X_CDT_STATUS_STAT_SHORT: ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: + return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; +- case QCA808X_CDT_STATUS_STAT_OPEN: ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: + return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; + case QCA808X_CDT_STATUS_STAT_FAIL: + default: + return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; + } + } + +-static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair) ++static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, ++ int result) + { + int val; + u32 cdt_length_reg = 0; +@@ -1990,7 +2039,11 @@ static int qca808x_cdt_fault_length(stru + if (val < 0) + return val; + +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH, val); ++ if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); ++ else ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); ++ + return at803x_cdt_fault_length(val); + } + +@@ -2038,8 +2091,8 @@ static int qca808x_cable_test_start(stru + static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, + u16 status) + { ++ int length, result; + u16 pair_code; +- int length; + + switch (pair) { + case ETHTOOL_A_CABLE_PAIR_A: +@@ -2058,11 +2111,11 @@ static int qca808x_cable_test_get_pair_s + return -EINVAL; + } + +- ethnl_cable_test_result(phydev, pair, +- qca808x_cable_test_result_trans(pair_code)); ++ result = qca808x_cable_test_result_trans(pair_code); ++ ethnl_cable_test_result(phydev, pair, result); + + if (qca808x_cdt_fault_length_valid(pair_code)) { +- length = qca808x_cdt_fault_length(phydev, pair); ++ length = qca808x_cdt_fault_length(phydev, pair, result); + ethnl_cable_test_fault_length(phydev, pair, length); + } + +@@ -2076,8 +2129,7 @@ static int qca808x_cable_test_get_status + *finished = false; + + val = QCA808X_CDT_ENABLE_TEST | +- QCA808X_CDT_LENGTH_UNIT | +- QCA808X_CDT_INTER_CHECK_DIS; ++ QCA808X_CDT_LENGTH_UNIT; + ret = at803x_cdt_start(phydev, val); + if (ret) + return ret; diff --git a/lede/target/linux/generic/backport-6.1/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch b/lede/target/linux/generic/backport-6.1/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch new file mode 100644 index 0000000000..c146e502fe --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch @@ -0,0 +1,62 @@ +From c34d9452d4e5d98a655d7b625e85466320885416 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:41 +0100 +Subject: [PATCH 4/4] net: phy: at803x: make read_status more generic + +Make read_status more generic in preparation on moving it to shared +library as other PHY Family Driver will have the exact same +implementation. + +The only specific part was a check for AR8031/33 if 1000basex was used. +The check is moved to a dedicated function specific for those PHYs. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1020,13 +1020,9 @@ static int at803x_read_specific_status(s + + static int at803x_read_status(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + struct at803x_ss_mask ss_mask = { 0 }; + int err, old_link = phydev->link; + +- if (priv->is_1000basex) +- return genphy_c37_read_status(phydev); +- + /* Update the link, but return if there was an error */ + err = genphy_update_link(phydev); + if (err) +@@ -1618,6 +1614,17 @@ static int at8031_config_intr(struct phy + return at803x_config_intr(phydev); + } + ++/* AR8031 and AR8033 share the same read status logic */ ++static int at8031_read_status(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ if (priv->is_1000basex) ++ return genphy_c37_read_status(phydev); ++ ++ return at803x_read_status(phydev); ++} ++ + /* AR8031 and AR8035 share the same cable test get status reg */ + static int at8031_cable_test_get_status(struct phy_device *phydev, + bool *finished) +@@ -2281,7 +2288,7 @@ static struct phy_driver at803x_driver[] + .read_page = at803x_read_page, + .write_page = at803x_write_page, + .get_features = at803x_get_features, +- .read_status = at803x_read_status, ++ .read_status = at8031_read_status, + .config_intr = at8031_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, diff --git a/lede/target/linux/generic/backport-6.1/712-v6.9-net-phy-at803x-add-LED-support-for-qca808x.patch b/lede/target/linux/generic/backport-6.1/712-v6.9-net-phy-at803x-add-LED-support-for-qca808x.patch new file mode 100644 index 0000000000..36675e7588 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/712-v6.9-net-phy-at803x-add-LED-support-for-qca808x.patch @@ -0,0 +1,408 @@ +From 7196062b64ee470b91015f3d2e82d225948258ea Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 25 Jan 2024 21:37:01 +0100 +Subject: [PATCH 5/5] net: phy: at803x: add LED support for qca808x + +Add LED support for QCA8081 PHY. + +Documentation for this LEDs PHY is very scarce even with NDA access +to Documentation for OEMs. Only the blink pattern are documented and are +very confusing most of the time. No documentation is present about +forcing the LED on/off or to always blink. + +Those settings were reversed by poking the regs and trying to find the +correct bits to trigger these modes. Some bits mode are not clear and +maybe the documentation option are not 100% correct. For the sake of LED +support the reversed option are enough to add support for current LED +APIs. + +Supported HW control modes are: +- tx +- rx +- link_10 +- link_100 +- link_1000 +- link_2500 +- half_duplex +- full_duplex + +Also add support for LED polarity set to set LED polarity to active +high or low. QSDK sets this value to high by default but PHY reset value +doesn't have this enabled by default. + +QSDK also sets 2 additional bits but their usage is not clear, info about +this is added in the header. It was verified that for correct function +of the LED if active high is needed, only BIT 6 is needed. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240125203702.4552-6-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/at803x.c | 327 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 327 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -301,6 +301,87 @@ + /* Added for reference of existence but should be handled by wait_for_completion already */ + #define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) + ++#define QCA808X_MMD7_LED_GLOBAL 0x8073 ++#define QCA808X_LED_BLINK_1 GENMASK(11, 6) ++#define QCA808X_LED_BLINK_2 GENMASK(5, 0) ++/* Values are the same for both BLINK_1 and BLINK_2 */ ++#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3) ++#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0) ++#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1) ++#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2) ++#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3) ++#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4) ++#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5) ++#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6) ++#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7) ++#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0) ++#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0) ++#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1) ++#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2) ++#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3) ++#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4) ++#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5) ++#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6) ++#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7) ++ ++#define QCA808X_MMD7_LED2_CTRL 0x8074 ++#define QCA808X_MMD7_LED2_FORCE_CTRL 0x8075 ++#define QCA808X_MMD7_LED1_CTRL 0x8076 ++#define QCA808X_MMD7_LED1_FORCE_CTRL 0x8077 ++#define QCA808X_MMD7_LED0_CTRL 0x8078 ++#define QCA808X_MMD7_LED_CTRL(x) (0x8078 - ((x) * 2)) ++ ++/* LED hw control pattern is the same for every LED */ ++#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) ++#define QCA808X_LED_SPEED2500_ON BIT(15) ++#define QCA808X_LED_SPEED2500_BLINK BIT(14) ++/* Follow blink trigger even if duplex or speed condition doesn't match */ ++#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) ++#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) ++#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) ++#define QCA808X_LED_TX_BLINK BIT(10) ++#define QCA808X_LED_RX_BLINK BIT(9) ++#define QCA808X_LED_TX_ON_10MS BIT(8) ++#define QCA808X_LED_RX_ON_10MS BIT(7) ++#define QCA808X_LED_SPEED1000_ON BIT(6) ++#define QCA808X_LED_SPEED100_ON BIT(5) ++#define QCA808X_LED_SPEED10_ON BIT(4) ++#define QCA808X_LED_COLLISION_BLINK BIT(3) ++#define QCA808X_LED_SPEED1000_BLINK BIT(2) ++#define QCA808X_LED_SPEED100_BLINK BIT(1) ++#define QCA808X_LED_SPEED10_BLINK BIT(0) ++ ++#define QCA808X_MMD7_LED0_FORCE_CTRL 0x8079 ++#define QCA808X_MMD7_LED_FORCE_CTRL(x) (0x8079 - ((x) * 2)) ++ ++/* LED force ctrl is the same for every LED ++ * No documentation exist for this, not even internal one ++ * with NDA as QCOM gives only info about configuring ++ * hw control pattern rules and doesn't indicate any way ++ * to force the LED to specific mode. ++ * These define comes from reverse and testing and maybe ++ * lack of some info or some info are not entirely correct. ++ * For the basic LED control and hw control these finding ++ * are enough to support LED control in all the required APIs. ++ * ++ * On doing some comparison with implementation with qca807x, ++ * it was found that it's 1:1 equal to it and confirms all the ++ * reverse done. It was also found further specification with the ++ * force mode and the blink modes. ++ */ ++#define QCA808X_LED_FORCE_EN BIT(15) ++#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13) ++#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3) ++#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2) ++#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1) ++#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0) ++ ++#define QCA808X_MMD7_LED_POLARITY_CTRL 0x901a ++/* QSDK sets by default 0x46 to this reg that sets BIT 6 for ++ * LED to active high. It's not clear what BIT 3 and BIT 4 does. ++ */ ++#define QCA808X_LED_ACTIVE_HIGH BIT(6) ++ + /* QCA808X 1G chip type */ + #define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d + #define QCA808X_PHY_CHIP_TYPE_1G BIT(0) +@@ -346,6 +427,7 @@ struct at803x_priv { + struct regulator_dev *vddio_rdev; + struct regulator_dev *vddh_rdev; + u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; ++ int led_polarity_mode; + }; + + struct at803x_context { +@@ -706,6 +788,9 @@ static int at803x_probe(struct phy_devic + if (!priv) + return -ENOMEM; + ++ /* Init LED polarity mode to -1 */ ++ priv->led_polarity_mode = -1; ++ + phydev->priv = priv; + + ret = at803x_parse_dt(phydev); +@@ -2235,6 +2320,242 @@ static void qca808x_link_change_notify(s + phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); + } + ++static int qca808x_led_parse_netdev(struct phy_device *phydev, unsigned long rules, ++ u16 *offload_trigger) ++{ ++ /* Parsing specific to netdev trigger */ ++ if (test_bit(TRIGGER_NETDEV_TX, &rules)) ++ *offload_trigger |= QCA808X_LED_TX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_RX, &rules)) ++ *offload_trigger |= QCA808X_LED_RX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED10_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED100_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED1000_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_2500, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED2500_ON; ++ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_HALF_DUPLEX_ON; ++ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_FULL_DUPLEX_ON; ++ ++ if (rules && !*offload_trigger) ++ return -EOPNOTSUPP; ++ ++ /* Enable BLINK_CHECK_BYPASS by default to make the LED ++ * blink even with duplex or speed mode not enabled. ++ */ ++ *offload_trigger |= QCA808X_LED_BLINK_CHECK_BYPASS; ++ ++ return 0; ++} ++ ++static int qca808x_led_hw_control_enable(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN); ++} ++ ++static int qca808x_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 offload_trigger = 0; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ return qca808x_led_parse_netdev(phydev, rules, &offload_trigger); ++} ++ ++static int qca808x_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 reg, offload_trigger = 0; ++ int ret; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ ret = qca808x_led_parse_netdev(phydev, rules, &offload_trigger); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_led_hw_control_enable(phydev, index); ++ if (ret) ++ return ret; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_PATTERN_MASK, ++ offload_trigger); ++} ++ ++static bool qca808x_led_hw_control_status(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ int val; ++ ++ if (index > 2) ++ return false; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ ++ return !(val & QCA808X_LED_FORCE_EN); ++} ++ ++static int qca808x_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ u16 reg; ++ int val; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ /* Check if we have hw control enabled */ ++ if (qca808x_led_hw_control_status(phydev, index)) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ if (val & QCA808X_LED_TX_BLINK) ++ set_bit(TRIGGER_NETDEV_TX, rules); ++ if (val & QCA808X_LED_RX_BLINK) ++ set_bit(TRIGGER_NETDEV_RX, rules); ++ if (val & QCA808X_LED_SPEED10_ON) ++ set_bit(TRIGGER_NETDEV_LINK_10, rules); ++ if (val & QCA808X_LED_SPEED100_ON) ++ set_bit(TRIGGER_NETDEV_LINK_100, rules); ++ if (val & QCA808X_LED_SPEED1000_ON) ++ set_bit(TRIGGER_NETDEV_LINK_1000, rules); ++ if (val & QCA808X_LED_SPEED2500_ON) ++ set_bit(TRIGGER_NETDEV_LINK_2500, rules); ++ if (val & QCA808X_LED_HALF_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); ++ if (val & QCA808X_LED_FULL_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); ++ ++ return 0; ++} ++ ++static int qca808x_led_hw_control_reset(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_PATTERN_MASK); ++} ++ ++static int qca808x_led_brightness_set(struct phy_device *phydev, ++ u8 index, enum led_brightness value) ++{ ++ u16 reg; ++ int ret; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ if (!value) { ++ ret = qca808x_led_hw_control_reset(phydev, index); ++ if (ret) ++ return ret; ++ } ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | value ? QCA808X_LED_FORCE_ON : ++ QCA808X_LED_FORCE_OFF); ++} ++ ++static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ int ret; ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ /* Set blink to 50% off, 50% on at 4Hz by default */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL, ++ QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK, ++ QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50); ++ if (ret) ++ return ret; ++ ++ /* We use BLINK_1 for normal blinking */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1); ++ if (ret) ++ return ret; ++ ++ /* We set blink to 4Hz, aka 250ms */ ++ *delay_on = 250 / 2; ++ *delay_off = 250 / 2; ++ ++ return 0; ++} ++ ++static int qca808x_led_polarity_set(struct phy_device *phydev, int index, ++ unsigned long modes) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ bool active_low = false; ++ u32 mode; ++ ++ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { ++ switch (mode) { ++ case PHY_LED_ACTIVE_LOW: ++ active_low = true; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ /* PHY polarity is global and can't be set per LED. ++ * To detect this, check if last requested polarity mode ++ * match the new one. ++ */ ++ if (priv->led_polarity_mode >= 0 && ++ priv->led_polarity_mode != active_low) { ++ phydev_err(phydev, "PHY polarity is global. Mismatched polarity on different LED\n"); ++ return -EINVAL; ++ } ++ ++ /* Save the last PHY polarity mode */ ++ priv->led_polarity_mode = active_low; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, ++ QCA808X_MMD7_LED_POLARITY_CTRL, ++ QCA808X_LED_ACTIVE_HIGH, ++ active_low ? 0 : QCA808X_LED_ACTIVE_HIGH); ++} ++ + static struct phy_driver at803x_driver[] = { + { + /* Qualcomm Atheros AR8035 */ +@@ -2411,6 +2732,12 @@ static struct phy_driver at803x_driver[] + .cable_test_start = qca808x_cable_test_start, + .cable_test_get_status = qca808x_cable_test_get_status, + .link_change_notify = qca808x_link_change_notify, ++ .led_brightness_set = qca808x_led_brightness_set, ++ .led_blink_set = qca808x_led_blink_set, ++ .led_hw_is_supported = qca808x_led_hw_is_supported, ++ .led_hw_control_set = qca808x_led_hw_control_set, ++ .led_hw_control_get = qca808x_led_hw_control_get, ++ .led_polarity_set = qca808x_led_polarity_set, + }, }; + + module_phy_driver(at803x_driver); diff --git a/lede/target/linux/generic/backport-6.1/713-v6.9-01-net-phy-move-at803x-PHY-driver-to-dedicated-director.patch b/lede/target/linux/generic/backport-6.1/713-v6.9-01-net-phy-move-at803x-PHY-driver-to-dedicated-director.patch new file mode 100644 index 0000000000..8c9babea7b --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/713-v6.9-01-net-phy-move-at803x-PHY-driver-to-dedicated-director.patch @@ -0,0 +1,5598 @@ +From 9e56ff53b4115875667760445b028357848b4748 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 Jan 2024 15:15:19 +0100 +Subject: [PATCH 1/5] net: phy: move at803x PHY driver to dedicated directory + +In preparation for addition of other Qcom PHY and to tidy things up, +move the at803x PHY driver to dedicated directory. + +The same order in the Kconfig selection is saved. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240129141600.2592-2-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/Kconfig | 7 +------ + drivers/net/phy/Makefile | 2 +- + drivers/net/phy/qcom/Kconfig | 7 +++++++ + drivers/net/phy/qcom/Makefile | 2 ++ + drivers/net/phy/{ => qcom}/at803x.c | 0 + 5 files changed, 11 insertions(+), 7 deletions(-) + create mode 100644 drivers/net/phy/qcom/Kconfig + create mode 100644 drivers/net/phy/qcom/Makefile + rename drivers/net/phy/{ => qcom}/at803x.c (100%) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -277,12 +277,7 @@ config NXP_TJA11XX_PHY + help + Currently supports the NXP TJA1100 and TJA1101 PHY. + +-config AT803X_PHY +- tristate "Qualcomm Atheros AR803X PHYs and QCA833x PHYs" +- depends on REGULATOR +- help +- Currently supports the AR8030, AR8031, AR8033, AR8035 and internal +- QCA8337(Internal qca8k PHY) model ++source "drivers/net/phy/qcom/Kconfig" + + config QSEMI_PHY + tristate "Quality Semiconductor PHYs" +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -34,7 +34,6 @@ obj-$(CONFIG_ADIN_PHY) += adin.o + obj-$(CONFIG_ADIN1100_PHY) += adin1100.o + obj-$(CONFIG_AMD_PHY) += amd.o + obj-$(CONFIG_AQUANTIA_PHY) += aquantia/ +-obj-$(CONFIG_AT803X_PHY) += at803x.o + obj-$(CONFIG_AX88796B_PHY) += ax88796b.o + obj-$(CONFIG_BCM54140_PHY) += bcm54140.o + obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o +@@ -75,6 +74,7 @@ obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm + obj-$(CONFIG_NATIONAL_PHY) += national.o + obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp-c45-tja11xx.o + obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o ++obj-y += qcom/ + obj-$(CONFIG_QSEMI_PHY) += qsemi.o + obj-$(CONFIG_REALTEK_PHY) += realtek.o + obj-$(CONFIG_RENESAS_PHY) += uPD60620.o +--- /dev/null ++++ b/drivers/net/phy/qcom/Kconfig +@@ -0,0 +1,7 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config AT803X_PHY ++ tristate "Qualcomm Atheros AR803X PHYs and QCA833x PHYs" ++ depends on REGULATOR ++ help ++ Currently supports the AR8030, AR8031, AR8033, AR8035 and internal ++ QCA8337(Internal qca8k PHY) model +--- /dev/null ++++ b/drivers/net/phy/qcom/Makefile +@@ -0,0 +1,2 @@ ++# SPDX-License-Identifier: GPL-2.0 ++obj-$(CONFIG_AT803X_PHY) += at803x.o +--- a/drivers/net/phy/at803x.c ++++ /dev/null +@@ -1,2759 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0+ +-/* +- * drivers/net/phy/at803x.c +- * +- * Driver for Qualcomm Atheros AR803x PHY +- * +- * Author: Matus Ujhelyi +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10 +-#define AT803X_SFC_ASSERT_CRS BIT(11) +-#define AT803X_SFC_FORCE_LINK BIT(10) +-#define AT803X_SFC_MDI_CROSSOVER_MODE_M GENMASK(6, 5) +-#define AT803X_SFC_AUTOMATIC_CROSSOVER 0x3 +-#define AT803X_SFC_MANUAL_MDIX 0x1 +-#define AT803X_SFC_MANUAL_MDI 0x0 +-#define AT803X_SFC_SQE_TEST BIT(2) +-#define AT803X_SFC_POLARITY_REVERSAL BIT(1) +-#define AT803X_SFC_DISABLE_JABBER BIT(0) +- +-#define AT803X_SPECIFIC_STATUS 0x11 +-#define AT803X_SS_SPEED_MASK GENMASK(15, 14) +-#define AT803X_SS_SPEED_1000 2 +-#define AT803X_SS_SPEED_100 1 +-#define AT803X_SS_SPEED_10 0 +-#define AT803X_SS_DUPLEX BIT(13) +-#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11) +-#define AT803X_SS_MDIX BIT(6) +- +-#define QCA808X_SS_SPEED_MASK GENMASK(9, 7) +-#define QCA808X_SS_SPEED_2500 4 +- +-#define AT803X_INTR_ENABLE 0x12 +-#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15) +-#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14) +-#define AT803X_INTR_ENABLE_DUPLEX_CHANGED BIT(13) +-#define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12) +-#define AT803X_INTR_ENABLE_LINK_FAIL BIT(11) +-#define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10) +-#define AT803X_INTR_ENABLE_LINK_FAIL_BX BIT(8) +-#define AT803X_INTR_ENABLE_LINK_SUCCESS_BX BIT(7) +-#define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5) +-#define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1) +-#define AT803X_INTR_ENABLE_WOL BIT(0) +- +-#define AT803X_INTR_STATUS 0x13 +- +-#define AT803X_SMART_SPEED 0x14 +-#define AT803X_SMART_SPEED_ENABLE BIT(5) +-#define AT803X_SMART_SPEED_RETRY_LIMIT_MASK GENMASK(4, 2) +-#define AT803X_SMART_SPEED_BYPASS_TIMER BIT(1) +-#define AT803X_CDT 0x16 +-#define AT803X_CDT_MDI_PAIR_MASK GENMASK(9, 8) +-#define AT803X_CDT_ENABLE_TEST BIT(0) +-#define AT803X_CDT_STATUS 0x1c +-#define AT803X_CDT_STATUS_STAT_NORMAL 0 +-#define AT803X_CDT_STATUS_STAT_SHORT 1 +-#define AT803X_CDT_STATUS_STAT_OPEN 2 +-#define AT803X_CDT_STATUS_STAT_FAIL 3 +-#define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8) +-#define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0) +-#define AT803X_LED_CONTROL 0x18 +- +-#define AT803X_PHY_MMD3_WOL_CTRL 0x8012 +-#define AT803X_WOL_EN BIT(5) +-#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C +-#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B +-#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A +-#define AT803X_REG_CHIP_CONFIG 0x1f +-#define AT803X_BT_BX_REG_SEL 0x8000 +- +-#define AT803X_DEBUG_ADDR 0x1D +-#define AT803X_DEBUG_DATA 0x1E +- +-#define AT803X_MODE_CFG_MASK 0x0F +-#define AT803X_MODE_CFG_BASET_RGMII 0x00 +-#define AT803X_MODE_CFG_BASET_SGMII 0x01 +-#define AT803X_MODE_CFG_BX1000_RGMII_50OHM 0x02 +-#define AT803X_MODE_CFG_BX1000_RGMII_75OHM 0x03 +-#define AT803X_MODE_CFG_BX1000_CONV_50OHM 0x04 +-#define AT803X_MODE_CFG_BX1000_CONV_75OHM 0x05 +-#define AT803X_MODE_CFG_FX100_RGMII_50OHM 0x06 +-#define AT803X_MODE_CFG_FX100_CONV_50OHM 0x07 +-#define AT803X_MODE_CFG_RGMII_AUTO_MDET 0x0B +-#define AT803X_MODE_CFG_FX100_RGMII_75OHM 0x0E +-#define AT803X_MODE_CFG_FX100_CONV_75OHM 0x0F +- +-#define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/ +-#define AT803X_PSSR_MR_AN_COMPLETE 0x0200 +- +-#define AT803X_DEBUG_ANALOG_TEST_CTRL 0x00 +-#define QCA8327_DEBUG_MANU_CTRL_EN BIT(2) +-#define QCA8337_DEBUG_MANU_CTRL_EN GENMASK(3, 2) +-#define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15) +- +-#define AT803X_DEBUG_SYSTEM_CTRL_MODE 0x05 +-#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) +- +-#define AT803X_DEBUG_REG_HIB_CTRL 0x0b +-#define AT803X_DEBUG_HIB_CTRL_SEL_RST_80U BIT(10) +-#define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13) +-#define AT803X_DEBUG_HIB_CTRL_PS_HIB_EN BIT(15) +- +-#define AT803X_DEBUG_REG_3C 0x3C +- +-#define AT803X_DEBUG_REG_GREEN 0x3D +-#define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6) +- +-#define AT803X_DEBUG_REG_1F 0x1F +-#define AT803X_DEBUG_PLL_ON BIT(2) +-#define AT803X_DEBUG_RGMII_1V8 BIT(3) +- +-#define MDIO_AZ_DEBUG 0x800D +- +-/* AT803x supports either the XTAL input pad, an internal PLL or the +- * DSP as clock reference for the clock output pad. The XTAL reference +- * is only used for 25 MHz output, all other frequencies need the PLL. +- * The DSP as a clock reference is used in synchronous ethernet +- * applications. +- * +- * By default the PLL is only enabled if there is a link. Otherwise +- * the PHY will go into low power state and disabled the PLL. You can +- * set the PLL_ON bit (see debug register 0x1f) to keep the PLL always +- * enabled. +- */ +-#define AT803X_MMD7_CLK25M 0x8016 +-#define AT803X_CLK_OUT_MASK GENMASK(4, 2) +-#define AT803X_CLK_OUT_25MHZ_XTAL 0 +-#define AT803X_CLK_OUT_25MHZ_DSP 1 +-#define AT803X_CLK_OUT_50MHZ_PLL 2 +-#define AT803X_CLK_OUT_50MHZ_DSP 3 +-#define AT803X_CLK_OUT_62_5MHZ_PLL 4 +-#define AT803X_CLK_OUT_62_5MHZ_DSP 5 +-#define AT803X_CLK_OUT_125MHZ_PLL 6 +-#define AT803X_CLK_OUT_125MHZ_DSP 7 +- +-/* The AR8035 has another mask which is compatible with the AR8031/AR8033 mask +- * but doesn't support choosing between XTAL/PLL and DSP. +- */ +-#define AT8035_CLK_OUT_MASK GENMASK(4, 3) +- +-#define AT803X_CLK_OUT_STRENGTH_MASK GENMASK(8, 7) +-#define AT803X_CLK_OUT_STRENGTH_FULL 0 +-#define AT803X_CLK_OUT_STRENGTH_HALF 1 +-#define AT803X_CLK_OUT_STRENGTH_QUARTER 2 +- +-#define AT803X_DEFAULT_DOWNSHIFT 5 +-#define AT803X_MIN_DOWNSHIFT 2 +-#define AT803X_MAX_DOWNSHIFT 9 +- +-#define AT803X_MMD3_SMARTEEE_CTL1 0x805b +-#define AT803X_MMD3_SMARTEEE_CTL2 0x805c +-#define AT803X_MMD3_SMARTEEE_CTL3 0x805d +-#define AT803X_MMD3_SMARTEEE_CTL3_LPI_EN BIT(8) +- +-#define ATH9331_PHY_ID 0x004dd041 +-#define ATH8030_PHY_ID 0x004dd076 +-#define ATH8031_PHY_ID 0x004dd074 +-#define ATH8032_PHY_ID 0x004dd023 +-#define ATH8035_PHY_ID 0x004dd072 +-#define AT8030_PHY_ID_MASK 0xffffffef +- +-#define QCA8081_PHY_ID 0x004dd101 +- +-#define QCA8327_A_PHY_ID 0x004dd033 +-#define QCA8327_B_PHY_ID 0x004dd034 +-#define QCA8337_PHY_ID 0x004dd036 +-#define QCA9561_PHY_ID 0x004dd042 +-#define QCA8K_PHY_ID_MASK 0xffffffff +- +-#define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0) +- +-#define AT803X_PAGE_FIBER 0 +-#define AT803X_PAGE_COPPER 1 +- +-/* don't turn off internal PLL */ +-#define AT803X_KEEP_PLL_ENABLED BIT(0) +-#define AT803X_DISABLE_SMARTEEE BIT(1) +- +-/* disable hibernation mode */ +-#define AT803X_DISABLE_HIBERNATION_MODE BIT(2) +- +-/* ADC threshold */ +-#define QCA808X_PHY_DEBUG_ADC_THRESHOLD 0x2c80 +-#define QCA808X_ADC_THRESHOLD_MASK GENMASK(7, 0) +-#define QCA808X_ADC_THRESHOLD_80MV 0 +-#define QCA808X_ADC_THRESHOLD_100MV 0xf0 +-#define QCA808X_ADC_THRESHOLD_200MV 0x0f +-#define QCA808X_ADC_THRESHOLD_300MV 0xff +- +-/* CLD control */ +-#define QCA808X_PHY_MMD3_ADDR_CLD_CTRL7 0x8007 +-#define QCA808X_8023AZ_AFE_CTRL_MASK GENMASK(8, 4) +-#define QCA808X_8023AZ_AFE_EN 0x90 +- +-/* AZ control */ +-#define QCA808X_PHY_MMD3_AZ_TRAINING_CTRL 0x8008 +-#define QCA808X_MMD3_AZ_TRAINING_VAL 0x1c32 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB 0x8014 +-#define QCA808X_MSE_THRESHOLD_20DB_VALUE 0x529 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB 0x800E +-#define QCA808X_MSE_THRESHOLD_17DB_VALUE 0x341 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB 0x801E +-#define QCA808X_MSE_THRESHOLD_27DB_VALUE 0x419 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB 0x8020 +-#define QCA808X_MSE_THRESHOLD_28DB_VALUE 0x341 +- +-#define QCA808X_PHY_MMD7_TOP_OPTION1 0x901c +-#define QCA808X_TOP_OPTION1_DATA 0x0 +- +-#define QCA808X_PHY_MMD3_DEBUG_1 0xa100 +-#define QCA808X_MMD3_DEBUG_1_VALUE 0x9203 +-#define QCA808X_PHY_MMD3_DEBUG_2 0xa101 +-#define QCA808X_MMD3_DEBUG_2_VALUE 0x48ad +-#define QCA808X_PHY_MMD3_DEBUG_3 0xa103 +-#define QCA808X_MMD3_DEBUG_3_VALUE 0x1698 +-#define QCA808X_PHY_MMD3_DEBUG_4 0xa105 +-#define QCA808X_MMD3_DEBUG_4_VALUE 0x8001 +-#define QCA808X_PHY_MMD3_DEBUG_5 0xa106 +-#define QCA808X_MMD3_DEBUG_5_VALUE 0x1111 +-#define QCA808X_PHY_MMD3_DEBUG_6 0xa011 +-#define QCA808X_MMD3_DEBUG_6_VALUE 0x5f85 +- +-/* master/slave seed config */ +-#define QCA808X_PHY_DEBUG_LOCAL_SEED 9 +-#define QCA808X_MASTER_SLAVE_SEED_ENABLE BIT(1) +-#define QCA808X_MASTER_SLAVE_SEED_CFG GENMASK(12, 2) +-#define QCA808X_MASTER_SLAVE_SEED_RANGE 0x32 +- +-/* Hibernation yields lower power consumpiton in contrast with normal operation mode. +- * when the copper cable is unplugged, the PHY enters into hibernation mode in about 10s. +- */ +-#define QCA808X_DBG_AN_TEST 0xb +-#define QCA808X_HIBERNATION_EN BIT(15) +- +-#define QCA808X_CDT_ENABLE_TEST BIT(15) +-#define QCA808X_CDT_INTER_CHECK_DIS BIT(13) +-#define QCA808X_CDT_STATUS BIT(11) +-#define QCA808X_CDT_LENGTH_UNIT BIT(10) +- +-#define QCA808X_MMD3_CDT_STATUS 0x8064 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 +-#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) +-#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) +- +-#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) +-#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) +-#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) +-#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) +- +-#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) +-#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) +-#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) +-#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) +-#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) +- +-#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) +-#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) +-#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) +-#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) +- +-/* NORMAL are MDI with type set to 0 */ +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI1) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI1) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI2) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI2) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI3) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI3) +- +-/* Added for reference of existence but should be handled by wait_for_completion already */ +-#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) +- +-#define QCA808X_MMD7_LED_GLOBAL 0x8073 +-#define QCA808X_LED_BLINK_1 GENMASK(11, 6) +-#define QCA808X_LED_BLINK_2 GENMASK(5, 0) +-/* Values are the same for both BLINK_1 and BLINK_2 */ +-#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3) +-#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0) +-#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1) +-#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2) +-#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3) +-#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4) +-#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5) +-#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6) +-#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7) +-#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0) +-#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0) +-#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1) +-#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2) +-#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3) +-#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4) +-#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5) +-#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6) +-#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7) +- +-#define QCA808X_MMD7_LED2_CTRL 0x8074 +-#define QCA808X_MMD7_LED2_FORCE_CTRL 0x8075 +-#define QCA808X_MMD7_LED1_CTRL 0x8076 +-#define QCA808X_MMD7_LED1_FORCE_CTRL 0x8077 +-#define QCA808X_MMD7_LED0_CTRL 0x8078 +-#define QCA808X_MMD7_LED_CTRL(x) (0x8078 - ((x) * 2)) +- +-/* LED hw control pattern is the same for every LED */ +-#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) +-#define QCA808X_LED_SPEED2500_ON BIT(15) +-#define QCA808X_LED_SPEED2500_BLINK BIT(14) +-/* Follow blink trigger even if duplex or speed condition doesn't match */ +-#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) +-#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) +-#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) +-#define QCA808X_LED_TX_BLINK BIT(10) +-#define QCA808X_LED_RX_BLINK BIT(9) +-#define QCA808X_LED_TX_ON_10MS BIT(8) +-#define QCA808X_LED_RX_ON_10MS BIT(7) +-#define QCA808X_LED_SPEED1000_ON BIT(6) +-#define QCA808X_LED_SPEED100_ON BIT(5) +-#define QCA808X_LED_SPEED10_ON BIT(4) +-#define QCA808X_LED_COLLISION_BLINK BIT(3) +-#define QCA808X_LED_SPEED1000_BLINK BIT(2) +-#define QCA808X_LED_SPEED100_BLINK BIT(1) +-#define QCA808X_LED_SPEED10_BLINK BIT(0) +- +-#define QCA808X_MMD7_LED0_FORCE_CTRL 0x8079 +-#define QCA808X_MMD7_LED_FORCE_CTRL(x) (0x8079 - ((x) * 2)) +- +-/* LED force ctrl is the same for every LED +- * No documentation exist for this, not even internal one +- * with NDA as QCOM gives only info about configuring +- * hw control pattern rules and doesn't indicate any way +- * to force the LED to specific mode. +- * These define comes from reverse and testing and maybe +- * lack of some info or some info are not entirely correct. +- * For the basic LED control and hw control these finding +- * are enough to support LED control in all the required APIs. +- * +- * On doing some comparison with implementation with qca807x, +- * it was found that it's 1:1 equal to it and confirms all the +- * reverse done. It was also found further specification with the +- * force mode and the blink modes. +- */ +-#define QCA808X_LED_FORCE_EN BIT(15) +-#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13) +-#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3) +-#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2) +-#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1) +-#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0) +- +-#define QCA808X_MMD7_LED_POLARITY_CTRL 0x901a +-/* QSDK sets by default 0x46 to this reg that sets BIT 6 for +- * LED to active high. It's not clear what BIT 3 and BIT 4 does. +- */ +-#define QCA808X_LED_ACTIVE_HIGH BIT(6) +- +-/* QCA808X 1G chip type */ +-#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d +-#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) +- +-#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 +-#define QCA8081_PHY_FIFO_RSTN BIT(11) +- +-MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); +-MODULE_AUTHOR("Matus Ujhelyi"); +-MODULE_LICENSE("GPL"); +- +-enum stat_access_type { +- PHY, +- MMD +-}; +- +-struct at803x_hw_stat { +- const char *string; +- u8 reg; +- u32 mask; +- enum stat_access_type access_type; +-}; +- +-static struct at803x_hw_stat qca83xx_hw_stats[] = { +- { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, +- { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, +- { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, +-}; +- +-struct at803x_ss_mask { +- u16 speed_mask; +- u8 speed_shift; +-}; +- +-struct at803x_priv { +- int flags; +- u16 clk_25m_reg; +- u16 clk_25m_mask; +- u8 smarteee_lpi_tw_1g; +- u8 smarteee_lpi_tw_100m; +- bool is_fiber; +- bool is_1000basex; +- struct regulator_dev *vddio_rdev; +- struct regulator_dev *vddh_rdev; +- u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; +- int led_polarity_mode; +-}; +- +-struct at803x_context { +- u16 bmcr; +- u16 advertise; +- u16 control1000; +- u16 int_enable; +- u16 smart_speed; +- u16 led_control; +-}; +- +-static int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data) +-{ +- int ret; +- +- ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); +- if (ret < 0) +- return ret; +- +- return phy_write(phydev, AT803X_DEBUG_DATA, data); +-} +- +-static int at803x_debug_reg_read(struct phy_device *phydev, u16 reg) +-{ +- int ret; +- +- ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); +- if (ret < 0) +- return ret; +- +- return phy_read(phydev, AT803X_DEBUG_DATA); +-} +- +-static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, +- u16 clear, u16 set) +-{ +- u16 val; +- int ret; +- +- ret = at803x_debug_reg_read(phydev, reg); +- if (ret < 0) +- return ret; +- +- val = ret & 0xffff; +- val &= ~clear; +- val |= set; +- +- return phy_write(phydev, AT803X_DEBUG_DATA, val); +-} +- +-static int at803x_write_page(struct phy_device *phydev, int page) +-{ +- int mask; +- int set; +- +- if (page == AT803X_PAGE_COPPER) { +- set = AT803X_BT_BX_REG_SEL; +- mask = 0; +- } else { +- set = 0; +- mask = AT803X_BT_BX_REG_SEL; +- } +- +- return __phy_modify(phydev, AT803X_REG_CHIP_CONFIG, mask, set); +-} +- +-static int at803x_read_page(struct phy_device *phydev) +-{ +- int ccr = __phy_read(phydev, AT803X_REG_CHIP_CONFIG); +- +- if (ccr < 0) +- return ccr; +- +- if (ccr & AT803X_BT_BX_REG_SEL) +- return AT803X_PAGE_COPPER; +- +- return AT803X_PAGE_FIBER; +-} +- +-static int at803x_enable_rx_delay(struct phy_device *phydev) +-{ +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0, +- AT803X_DEBUG_RX_CLK_DLY_EN); +-} +- +-static int at803x_enable_tx_delay(struct phy_device *phydev) +-{ +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0, +- AT803X_DEBUG_TX_CLK_DLY_EN); +-} +- +-static int at803x_disable_rx_delay(struct phy_device *phydev) +-{ +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- AT803X_DEBUG_RX_CLK_DLY_EN, 0); +-} +- +-static int at803x_disable_tx_delay(struct phy_device *phydev) +-{ +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, +- AT803X_DEBUG_TX_CLK_DLY_EN, 0); +-} +- +-/* save relevant PHY registers to private copy */ +-static void at803x_context_save(struct phy_device *phydev, +- struct at803x_context *context) +-{ +- context->bmcr = phy_read(phydev, MII_BMCR); +- context->advertise = phy_read(phydev, MII_ADVERTISE); +- context->control1000 = phy_read(phydev, MII_CTRL1000); +- context->int_enable = phy_read(phydev, AT803X_INTR_ENABLE); +- context->smart_speed = phy_read(phydev, AT803X_SMART_SPEED); +- context->led_control = phy_read(phydev, AT803X_LED_CONTROL); +-} +- +-/* restore relevant PHY registers from private copy */ +-static void at803x_context_restore(struct phy_device *phydev, +- const struct at803x_context *context) +-{ +- phy_write(phydev, MII_BMCR, context->bmcr); +- phy_write(phydev, MII_ADVERTISE, context->advertise); +- phy_write(phydev, MII_CTRL1000, context->control1000); +- phy_write(phydev, AT803X_INTR_ENABLE, context->int_enable); +- phy_write(phydev, AT803X_SMART_SPEED, context->smart_speed); +- phy_write(phydev, AT803X_LED_CONTROL, context->led_control); +-} +- +-static int at803x_set_wol(struct phy_device *phydev, +- struct ethtool_wolinfo *wol) +-{ +- int ret, irq_enabled; +- +- if (wol->wolopts & WAKE_MAGIC) { +- struct net_device *ndev = phydev->attached_dev; +- const u8 *mac; +- unsigned int i; +- static const unsigned int offsets[] = { +- AT803X_LOC_MAC_ADDR_32_47_OFFSET, +- AT803X_LOC_MAC_ADDR_16_31_OFFSET, +- AT803X_LOC_MAC_ADDR_0_15_OFFSET, +- }; +- +- if (!ndev) +- return -ENODEV; +- +- mac = (const u8 *)ndev->dev_addr; +- +- if (!is_valid_ether_addr(mac)) +- return -EINVAL; +- +- for (i = 0; i < 3; i++) +- phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], +- mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); +- +- /* Enable WOL interrupt */ +- ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); +- if (ret) +- return ret; +- } else { +- /* Disable WOL interrupt */ +- ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); +- if (ret) +- return ret; +- } +- +- /* Clear WOL status */ +- ret = phy_read(phydev, AT803X_INTR_STATUS); +- if (ret < 0) +- return ret; +- +- /* Check if there are other interrupts except for WOL triggered when PHY is +- * in interrupt mode, only the interrupts enabled by AT803X_INTR_ENABLE can +- * be passed up to the interrupt PIN. +- */ +- irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE); +- if (irq_enabled < 0) +- return irq_enabled; +- +- irq_enabled &= ~AT803X_INTR_ENABLE_WOL; +- if (ret & irq_enabled && !phy_polling_mode(phydev)) +- phy_trigger_machine(phydev); +- +- return 0; +-} +- +-static void at803x_get_wol(struct phy_device *phydev, +- struct ethtool_wolinfo *wol) +-{ +- int value; +- +- wol->supported = WAKE_MAGIC; +- wol->wolopts = 0; +- +- value = phy_read(phydev, AT803X_INTR_ENABLE); +- if (value < 0) +- return; +- +- if (value & AT803X_INTR_ENABLE_WOL) +- wol->wolopts |= WAKE_MAGIC; +-} +- +-static int qca83xx_get_sset_count(struct phy_device *phydev) +-{ +- return ARRAY_SIZE(qca83xx_hw_stats); +-} +- +-static void qca83xx_get_strings(struct phy_device *phydev, u8 *data) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) { +- strscpy(data + i * ETH_GSTRING_LEN, +- qca83xx_hw_stats[i].string, ETH_GSTRING_LEN); +- } +-} +- +-static u64 qca83xx_get_stat(struct phy_device *phydev, int i) +-{ +- struct at803x_hw_stat stat = qca83xx_hw_stats[i]; +- struct at803x_priv *priv = phydev->priv; +- int val; +- u64 ret; +- +- if (stat.access_type == MMD) +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg); +- else +- val = phy_read(phydev, stat.reg); +- +- if (val < 0) { +- ret = U64_MAX; +- } else { +- val = val & stat.mask; +- priv->stats[i] += val; +- ret = priv->stats[i]; +- } +- +- return ret; +-} +- +-static void qca83xx_get_stats(struct phy_device *phydev, +- struct ethtool_stats *stats, u64 *data) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) +- data[i] = qca83xx_get_stat(phydev, i); +-} +- +-static int at803x_suspend(struct phy_device *phydev) +-{ +- int value; +- int wol_enabled; +- +- value = phy_read(phydev, AT803X_INTR_ENABLE); +- wol_enabled = value & AT803X_INTR_ENABLE_WOL; +- +- if (wol_enabled) +- value = BMCR_ISOLATE; +- else +- value = BMCR_PDOWN; +- +- phy_modify(phydev, MII_BMCR, 0, value); +- +- return 0; +-} +- +-static int at803x_resume(struct phy_device *phydev) +-{ +- return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0); +-} +- +-static int at803x_parse_dt(struct phy_device *phydev) +-{ +- struct device_node *node = phydev->mdio.dev.of_node; +- struct at803x_priv *priv = phydev->priv; +- u32 freq, strength, tw; +- unsigned int sel; +- int ret; +- +- if (!IS_ENABLED(CONFIG_OF_MDIO)) +- return 0; +- +- if (of_property_read_bool(node, "qca,disable-smarteee")) +- priv->flags |= AT803X_DISABLE_SMARTEEE; +- +- if (of_property_read_bool(node, "qca,disable-hibernation-mode")) +- priv->flags |= AT803X_DISABLE_HIBERNATION_MODE; +- +- if (!of_property_read_u32(node, "qca,smarteee-tw-us-1g", &tw)) { +- if (!tw || tw > 255) { +- phydev_err(phydev, "invalid qca,smarteee-tw-us-1g\n"); +- return -EINVAL; +- } +- priv->smarteee_lpi_tw_1g = tw; +- } +- +- if (!of_property_read_u32(node, "qca,smarteee-tw-us-100m", &tw)) { +- if (!tw || tw > 255) { +- phydev_err(phydev, "invalid qca,smarteee-tw-us-100m\n"); +- return -EINVAL; +- } +- priv->smarteee_lpi_tw_100m = tw; +- } +- +- ret = of_property_read_u32(node, "qca,clk-out-frequency", &freq); +- if (!ret) { +- switch (freq) { +- case 25000000: +- sel = AT803X_CLK_OUT_25MHZ_XTAL; +- break; +- case 50000000: +- sel = AT803X_CLK_OUT_50MHZ_PLL; +- break; +- case 62500000: +- sel = AT803X_CLK_OUT_62_5MHZ_PLL; +- break; +- case 125000000: +- sel = AT803X_CLK_OUT_125MHZ_PLL; +- break; +- default: +- phydev_err(phydev, "invalid qca,clk-out-frequency\n"); +- return -EINVAL; +- } +- +- priv->clk_25m_reg |= FIELD_PREP(AT803X_CLK_OUT_MASK, sel); +- priv->clk_25m_mask |= AT803X_CLK_OUT_MASK; +- } +- +- ret = of_property_read_u32(node, "qca,clk-out-strength", &strength); +- if (!ret) { +- priv->clk_25m_mask |= AT803X_CLK_OUT_STRENGTH_MASK; +- switch (strength) { +- case AR803X_STRENGTH_FULL: +- priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_FULL; +- break; +- case AR803X_STRENGTH_HALF: +- priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_HALF; +- break; +- case AR803X_STRENGTH_QUARTER: +- priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_QUARTER; +- break; +- default: +- phydev_err(phydev, "invalid qca,clk-out-strength\n"); +- return -EINVAL; +- } +- } +- +- return 0; +-} +- +-static int at803x_probe(struct phy_device *phydev) +-{ +- struct device *dev = &phydev->mdio.dev; +- struct at803x_priv *priv; +- int ret; +- +- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- +- /* Init LED polarity mode to -1 */ +- priv->led_polarity_mode = -1; +- +- phydev->priv = priv; +- +- ret = at803x_parse_dt(phydev); +- if (ret) +- return ret; +- +- return 0; +-} +- +-static int at803x_get_features(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- int err; +- +- err = genphy_read_abilities(phydev); +- if (err) +- return err; +- +- if (phydev->drv->phy_id != ATH8031_PHY_ID) +- return 0; +- +- /* AR8031/AR8033 have different status registers +- * for copper and fiber operation. However, the +- * extended status register is the same for both +- * operation modes. +- * +- * As a result of that, ESTATUS_1000_XFULL is set +- * to 1 even when operating in copper TP mode. +- * +- * Remove this mode from the supported link modes +- * when not operating in 1000BaseX mode. +- */ +- if (!priv->is_1000basex) +- linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, +- phydev->supported); +- +- return 0; +-} +- +-static int at803x_smarteee_config(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- u16 mask = 0, val = 0; +- int ret; +- +- if (priv->flags & AT803X_DISABLE_SMARTEEE) +- return phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_MMD3_SMARTEEE_CTL3, +- AT803X_MMD3_SMARTEEE_CTL3_LPI_EN, 0); +- +- if (priv->smarteee_lpi_tw_1g) { +- mask |= 0xff00; +- val |= priv->smarteee_lpi_tw_1g << 8; +- } +- if (priv->smarteee_lpi_tw_100m) { +- mask |= 0x00ff; +- val |= priv->smarteee_lpi_tw_100m; +- } +- if (!mask) +- return 0; +- +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL1, +- mask, val); +- if (ret) +- return ret; +- +- return phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL3, +- AT803X_MMD3_SMARTEEE_CTL3_LPI_EN, +- AT803X_MMD3_SMARTEEE_CTL3_LPI_EN); +-} +- +-static int at803x_clk_out_config(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- +- if (!priv->clk_25m_mask) +- return 0; +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, AT803X_MMD7_CLK25M, +- priv->clk_25m_mask, priv->clk_25m_reg); +-} +- +-static int at8031_pll_config(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- +- /* The default after hardware reset is PLL OFF. After a soft reset, the +- * values are retained. +- */ +- if (priv->flags & AT803X_KEEP_PLL_ENABLED) +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- 0, AT803X_DEBUG_PLL_ON); +- else +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- AT803X_DEBUG_PLL_ON, 0); +-} +- +-static int at803x_hibernation_mode_config(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- +- /* The default after hardware reset is hibernation mode enabled. After +- * software reset, the value is retained. +- */ +- if (!(priv->flags & AT803X_DISABLE_HIBERNATION_MODE)) +- return 0; +- +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, +- AT803X_DEBUG_HIB_CTRL_PS_HIB_EN, 0); +-} +- +-static int at803x_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- /* The RX and TX delay default is: +- * after HW reset: RX delay enabled and TX delay disabled +- * after SW reset: RX delay enabled, while TX delay retains the +- * value before reset. +- */ +- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || +- phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) +- ret = at803x_enable_rx_delay(phydev); +- else +- ret = at803x_disable_rx_delay(phydev); +- if (ret < 0) +- return ret; +- +- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || +- phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) +- ret = at803x_enable_tx_delay(phydev); +- else +- ret = at803x_disable_tx_delay(phydev); +- if (ret < 0) +- return ret; +- +- ret = at803x_smarteee_config(phydev); +- if (ret < 0) +- return ret; +- +- ret = at803x_clk_out_config(phydev); +- if (ret < 0) +- return ret; +- +- ret = at803x_hibernation_mode_config(phydev); +- if (ret < 0) +- return ret; +- +- /* Ar803x extended next page bit is enabled by default. Cisco +- * multigig switches read this bit and attempt to negotiate 10Gbps +- * rates even if the next page bit is disabled. This is incorrect +- * behaviour but we still need to accommodate it. XNP is only needed +- * for 10Gbps support, so disable XNP. +- */ +- return phy_modify(phydev, MII_ADVERTISE, MDIO_AN_CTRL1_XNP, 0); +-} +- +-static int at803x_ack_interrupt(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_read(phydev, AT803X_INTR_STATUS); +- +- return (err < 0) ? err : 0; +-} +- +-static int at803x_config_intr(struct phy_device *phydev) +-{ +- int err; +- int value; +- +- value = phy_read(phydev, AT803X_INTR_ENABLE); +- +- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { +- /* Clear any pending interrupts */ +- err = at803x_ack_interrupt(phydev); +- if (err) +- return err; +- +- value |= AT803X_INTR_ENABLE_AUTONEG_ERR; +- value |= AT803X_INTR_ENABLE_SPEED_CHANGED; +- value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED; +- value |= AT803X_INTR_ENABLE_LINK_FAIL; +- value |= AT803X_INTR_ENABLE_LINK_SUCCESS; +- +- err = phy_write(phydev, AT803X_INTR_ENABLE, value); +- } else { +- err = phy_write(phydev, AT803X_INTR_ENABLE, 0); +- if (err) +- return err; +- +- /* Clear any pending interrupts */ +- err = at803x_ack_interrupt(phydev); +- } +- +- return err; +-} +- +-static irqreturn_t at803x_handle_interrupt(struct phy_device *phydev) +-{ +- int irq_status, int_enabled; +- +- irq_status = phy_read(phydev, AT803X_INTR_STATUS); +- if (irq_status < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- /* Read the current enabled interrupts */ +- int_enabled = phy_read(phydev, AT803X_INTR_ENABLE); +- if (int_enabled < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- /* See if this was one of our enabled interrupts */ +- if (!(irq_status & int_enabled)) +- return IRQ_NONE; +- +- phy_trigger_machine(phydev); +- +- return IRQ_HANDLED; +-} +- +-static void at803x_link_change_notify(struct phy_device *phydev) +-{ +- /* +- * Conduct a hardware reset for AT8030 every time a link loss is +- * signalled. This is necessary to circumvent a hardware bug that +- * occurs when the cable is unplugged while TX packets are pending +- * in the FIFO. In such cases, the FIFO enters an error mode it +- * cannot recover from by software. +- */ +- if (phydev->state == PHY_NOLINK && phydev->mdio.reset_gpio) { +- struct at803x_context context; +- +- at803x_context_save(phydev, &context); +- +- phy_device_reset(phydev, 1); +- usleep_range(1000, 2000); +- phy_device_reset(phydev, 0); +- usleep_range(1000, 2000); +- +- at803x_context_restore(phydev, &context); +- +- phydev_dbg(phydev, "%s(): phy was reset\n", __func__); +- } +-} +- +-static int at803x_read_specific_status(struct phy_device *phydev, +- struct at803x_ss_mask ss_mask) +-{ +- int ss; +- +- /* Read the AT8035 PHY-Specific Status register, which indicates the +- * speed and duplex that the PHY is actually using, irrespective of +- * whether we are in autoneg mode or not. +- */ +- ss = phy_read(phydev, AT803X_SPECIFIC_STATUS); +- if (ss < 0) +- return ss; +- +- if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) { +- int sfc, speed; +- +- sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL); +- if (sfc < 0) +- return sfc; +- +- speed = ss & ss_mask.speed_mask; +- speed >>= ss_mask.speed_shift; +- +- switch (speed) { +- case AT803X_SS_SPEED_10: +- phydev->speed = SPEED_10; +- break; +- case AT803X_SS_SPEED_100: +- phydev->speed = SPEED_100; +- break; +- case AT803X_SS_SPEED_1000: +- phydev->speed = SPEED_1000; +- break; +- case QCA808X_SS_SPEED_2500: +- phydev->speed = SPEED_2500; +- break; +- } +- if (ss & AT803X_SS_DUPLEX) +- phydev->duplex = DUPLEX_FULL; +- else +- phydev->duplex = DUPLEX_HALF; +- +- if (ss & AT803X_SS_MDIX) +- phydev->mdix = ETH_TP_MDI_X; +- else +- phydev->mdix = ETH_TP_MDI; +- +- switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) { +- case AT803X_SFC_MANUAL_MDI: +- phydev->mdix_ctrl = ETH_TP_MDI; +- break; +- case AT803X_SFC_MANUAL_MDIX: +- phydev->mdix_ctrl = ETH_TP_MDI_X; +- break; +- case AT803X_SFC_AUTOMATIC_CROSSOVER: +- phydev->mdix_ctrl = ETH_TP_MDI_AUTO; +- break; +- } +- } +- +- return 0; +-} +- +-static int at803x_read_status(struct phy_device *phydev) +-{ +- struct at803x_ss_mask ss_mask = { 0 }; +- int err, old_link = phydev->link; +- +- /* Update the link, but return if there was an error */ +- err = genphy_update_link(phydev); +- if (err) +- return err; +- +- /* why bother the PHY if nothing can have changed */ +- if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) +- return 0; +- +- phydev->speed = SPEED_UNKNOWN; +- phydev->duplex = DUPLEX_UNKNOWN; +- phydev->pause = 0; +- phydev->asym_pause = 0; +- +- err = genphy_read_lpa(phydev); +- if (err < 0) +- return err; +- +- ss_mask.speed_mask = AT803X_SS_SPEED_MASK; +- ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK); +- err = at803x_read_specific_status(phydev, ss_mask); +- if (err < 0) +- return err; +- +- if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) +- phy_resolve_aneg_pause(phydev); +- +- return 0; +-} +- +-static int at803x_config_mdix(struct phy_device *phydev, u8 ctrl) +-{ +- u16 val; +- +- switch (ctrl) { +- case ETH_TP_MDI: +- val = AT803X_SFC_MANUAL_MDI; +- break; +- case ETH_TP_MDI_X: +- val = AT803X_SFC_MANUAL_MDIX; +- break; +- case ETH_TP_MDI_AUTO: +- val = AT803X_SFC_AUTOMATIC_CROSSOVER; +- break; +- default: +- return 0; +- } +- +- return phy_modify_changed(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL, +- AT803X_SFC_MDI_CROSSOVER_MODE_M, +- FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val)); +-} +- +-static int at803x_prepare_config_aneg(struct phy_device *phydev) +-{ +- int ret; +- +- ret = at803x_config_mdix(phydev, phydev->mdix_ctrl); +- if (ret < 0) +- return ret; +- +- /* Changes of the midx bits are disruptive to the normal operation; +- * therefore any changes to these registers must be followed by a +- * software reset to take effect. +- */ +- if (ret == 1) { +- ret = genphy_soft_reset(phydev); +- if (ret < 0) +- return ret; +- } +- +- return 0; +-} +- +-static int at803x_config_aneg(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- int ret; +- +- ret = at803x_prepare_config_aneg(phydev); +- if (ret) +- return ret; +- +- if (priv->is_1000basex) +- return genphy_c37_config_aneg(phydev); +- +- return genphy_config_aneg(phydev); +-} +- +-static int at803x_get_downshift(struct phy_device *phydev, u8 *d) +-{ +- int val; +- +- val = phy_read(phydev, AT803X_SMART_SPEED); +- if (val < 0) +- return val; +- +- if (val & AT803X_SMART_SPEED_ENABLE) +- *d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2; +- else +- *d = DOWNSHIFT_DEV_DISABLE; +- +- return 0; +-} +- +-static int at803x_set_downshift(struct phy_device *phydev, u8 cnt) +-{ +- u16 mask, set; +- int ret; +- +- switch (cnt) { +- case DOWNSHIFT_DEV_DEFAULT_COUNT: +- cnt = AT803X_DEFAULT_DOWNSHIFT; +- fallthrough; +- case AT803X_MIN_DOWNSHIFT ... AT803X_MAX_DOWNSHIFT: +- set = AT803X_SMART_SPEED_ENABLE | +- AT803X_SMART_SPEED_BYPASS_TIMER | +- FIELD_PREP(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, cnt - 2); +- mask = AT803X_SMART_SPEED_RETRY_LIMIT_MASK; +- break; +- case DOWNSHIFT_DEV_DISABLE: +- set = 0; +- mask = AT803X_SMART_SPEED_ENABLE | +- AT803X_SMART_SPEED_BYPASS_TIMER; +- break; +- default: +- return -EINVAL; +- } +- +- ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set); +- +- /* After changing the smart speed settings, we need to perform a +- * software reset, use phy_init_hw() to make sure we set the +- * reapply any values which might got lost during software reset. +- */ +- if (ret == 1) +- ret = phy_init_hw(phydev); +- +- return ret; +-} +- +-static int at803x_get_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return at803x_get_downshift(phydev, data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int at803x_set_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, const void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return at803x_set_downshift(phydev, *(const u8 *)data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int at803x_cable_test_result_trans(u16 status) +-{ +- switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) { +- case AT803X_CDT_STATUS_STAT_NORMAL: +- return ETHTOOL_A_CABLE_RESULT_CODE_OK; +- case AT803X_CDT_STATUS_STAT_SHORT: +- return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; +- case AT803X_CDT_STATUS_STAT_OPEN: +- return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; +- case AT803X_CDT_STATUS_STAT_FAIL: +- default: +- return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; +- } +-} +- +-static bool at803x_cdt_test_failed(u16 status) +-{ +- return FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status) == +- AT803X_CDT_STATUS_STAT_FAIL; +-} +- +-static bool at803x_cdt_fault_length_valid(u16 status) +-{ +- switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) { +- case AT803X_CDT_STATUS_STAT_OPEN: +- case AT803X_CDT_STATUS_STAT_SHORT: +- return true; +- } +- return false; +-} +- +-static int at803x_cdt_fault_length(int dt) +-{ +- /* According to the datasheet the distance to the fault is +- * DELTA_TIME * 0.824 meters. +- * +- * The author suspect the correct formula is: +- * +- * fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2 +- * +- * where c is the speed of light, VF is the velocity factor of +- * the twisted pair cable, 125MHz the counter frequency and +- * we need to divide by 2 because the hardware will measure the +- * round trip time to the fault and back to the PHY. +- * +- * With a VF of 0.69 we get the factor 0.824 mentioned in the +- * datasheet. +- */ +- return (dt * 824) / 10; +-} +- +-static int at803x_cdt_start(struct phy_device *phydev, +- u32 cdt_start) +-{ +- return phy_write(phydev, AT803X_CDT, cdt_start); +-} +- +-static int at803x_cdt_wait_for_completion(struct phy_device *phydev, +- u32 cdt_en) +-{ +- int val, ret; +- +- /* One test run takes about 25ms */ +- ret = phy_read_poll_timeout(phydev, AT803X_CDT, val, +- !(val & cdt_en), +- 30000, 100000, true); +- +- return ret < 0 ? ret : 0; +-} +- +-static int at803x_cable_test_one_pair(struct phy_device *phydev, int pair) +-{ +- static const int ethtool_pair[] = { +- ETHTOOL_A_CABLE_PAIR_A, +- ETHTOOL_A_CABLE_PAIR_B, +- ETHTOOL_A_CABLE_PAIR_C, +- ETHTOOL_A_CABLE_PAIR_D, +- }; +- int ret, val; +- +- val = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) | +- AT803X_CDT_ENABLE_TEST; +- ret = at803x_cdt_start(phydev, val); +- if (ret) +- return ret; +- +- ret = at803x_cdt_wait_for_completion(phydev, AT803X_CDT_ENABLE_TEST); +- if (ret) +- return ret; +- +- val = phy_read(phydev, AT803X_CDT_STATUS); +- if (val < 0) +- return val; +- +- if (at803x_cdt_test_failed(val)) +- return 0; +- +- ethnl_cable_test_result(phydev, ethtool_pair[pair], +- at803x_cable_test_result_trans(val)); +- +- if (at803x_cdt_fault_length_valid(val)) { +- val = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, val); +- ethnl_cable_test_fault_length(phydev, ethtool_pair[pair], +- at803x_cdt_fault_length(val)); +- } +- +- return 1; +-} +- +-static int at803x_cable_test_get_status(struct phy_device *phydev, +- bool *finished, unsigned long pair_mask) +-{ +- int retries = 20; +- int pair, ret; +- +- *finished = false; +- +- /* According to the datasheet the CDT can be performed when +- * there is no link partner or when the link partner is +- * auto-negotiating. Starting the test will restart the AN +- * automatically. It seems that doing this repeatedly we will +- * get a slot where our link partner won't disturb our +- * measurement. +- */ +- while (pair_mask && retries--) { +- for_each_set_bit(pair, &pair_mask, 4) { +- ret = at803x_cable_test_one_pair(phydev, pair); +- if (ret < 0) +- return ret; +- if (ret) +- clear_bit(pair, &pair_mask); +- } +- if (pair_mask) +- msleep(250); +- } +- +- *finished = true; +- +- return 0; +-} +- +-static void at803x_cable_test_autoneg(struct phy_device *phydev) +-{ +- /* Enable auto-negotiation, but advertise no capabilities, no link +- * will be established. A restart of the auto-negotiation is not +- * required, because the cable test will automatically break the link. +- */ +- phy_write(phydev, MII_BMCR, BMCR_ANENABLE); +- phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA); +-} +- +-static int at803x_cable_test_start(struct phy_device *phydev) +-{ +- at803x_cable_test_autoneg(phydev); +- /* we do all the (time consuming) work later */ +- return 0; +-} +- +-static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, +- unsigned int selector) +-{ +- struct phy_device *phydev = rdev_get_drvdata(rdev); +- +- if (selector) +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- 0, AT803X_DEBUG_RGMII_1V8); +- else +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- AT803X_DEBUG_RGMII_1V8, 0); +-} +- +-static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) +-{ +- struct phy_device *phydev = rdev_get_drvdata(rdev); +- int val; +- +- val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F); +- if (val < 0) +- return val; +- +- return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0; +-} +- +-static const struct regulator_ops vddio_regulator_ops = { +- .list_voltage = regulator_list_voltage_table, +- .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, +- .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, +-}; +- +-static const unsigned int vddio_voltage_table[] = { +- 1500000, +- 1800000, +-}; +- +-static const struct regulator_desc vddio_desc = { +- .name = "vddio", +- .of_match = of_match_ptr("vddio-regulator"), +- .n_voltages = ARRAY_SIZE(vddio_voltage_table), +- .volt_table = vddio_voltage_table, +- .ops = &vddio_regulator_ops, +- .type = REGULATOR_VOLTAGE, +- .owner = THIS_MODULE, +-}; +- +-static const struct regulator_ops vddh_regulator_ops = { +-}; +- +-static const struct regulator_desc vddh_desc = { +- .name = "vddh", +- .of_match = of_match_ptr("vddh-regulator"), +- .n_voltages = 1, +- .fixed_uV = 2500000, +- .ops = &vddh_regulator_ops, +- .type = REGULATOR_VOLTAGE, +- .owner = THIS_MODULE, +-}; +- +-static int at8031_register_regulators(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- struct device *dev = &phydev->mdio.dev; +- struct regulator_config config = { }; +- +- config.dev = dev; +- config.driver_data = phydev; +- +- priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config); +- if (IS_ERR(priv->vddio_rdev)) { +- phydev_err(phydev, "failed to register VDDIO regulator\n"); +- return PTR_ERR(priv->vddio_rdev); +- } +- +- priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config); +- if (IS_ERR(priv->vddh_rdev)) { +- phydev_err(phydev, "failed to register VDDH regulator\n"); +- return PTR_ERR(priv->vddh_rdev); +- } +- +- return 0; +-} +- +-static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) +-{ +- struct phy_device *phydev = upstream; +- __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); +- __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); +- DECLARE_PHY_INTERFACE_MASK(interfaces); +- phy_interface_t iface; +- +- linkmode_zero(phy_support); +- phylink_set(phy_support, 1000baseX_Full); +- phylink_set(phy_support, 1000baseT_Full); +- phylink_set(phy_support, Autoneg); +- phylink_set(phy_support, Pause); +- phylink_set(phy_support, Asym_Pause); +- +- linkmode_zero(sfp_support); +- sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces); +- /* Some modules support 10G modes as well as others we support. +- * Mask out non-supported modes so the correct interface is picked. +- */ +- linkmode_and(sfp_support, phy_support, sfp_support); +- +- if (linkmode_empty(sfp_support)) { +- dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); +- return -EINVAL; +- } +- +- iface = sfp_select_interface(phydev->sfp_bus, sfp_support); +- +- /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes +- * interface for use with SFP modules. +- * However, some copper modules detected as having a preferred SGMII +- * interface do default to and function in 1000Base-X mode, so just +- * print a warning and allow such modules, as they may have some chance +- * of working. +- */ +- if (iface == PHY_INTERFACE_MODE_SGMII) +- dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); +- else if (iface != PHY_INTERFACE_MODE_1000BASEX) +- return -EINVAL; +- +- return 0; +-} +- +-static const struct sfp_upstream_ops at8031_sfp_ops = { +- .attach = phy_sfp_attach, +- .detach = phy_sfp_detach, +- .module_insert = at8031_sfp_insert, +-}; +- +-static int at8031_parse_dt(struct phy_device *phydev) +-{ +- struct device_node *node = phydev->mdio.dev.of_node; +- struct at803x_priv *priv = phydev->priv; +- int ret; +- +- if (of_property_read_bool(node, "qca,keep-pll-enabled")) +- priv->flags |= AT803X_KEEP_PLL_ENABLED; +- +- ret = at8031_register_regulators(phydev); +- if (ret < 0) +- return ret; +- +- ret = devm_regulator_get_enable_optional(&phydev->mdio.dev, +- "vddio"); +- if (ret) { +- phydev_err(phydev, "failed to get VDDIO regulator\n"); +- return ret; +- } +- +- /* Only AR8031/8033 support 1000Base-X for SFP modules */ +- return phy_sfp_probe(phydev, &at8031_sfp_ops); +-} +- +-static int at8031_probe(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- int mode_cfg; +- int ccr; +- int ret; +- +- ret = at803x_probe(phydev); +- if (ret) +- return ret; +- +- /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping +- * options. +- */ +- ret = at8031_parse_dt(phydev); +- if (ret) +- return ret; +- +- ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); +- if (ccr < 0) +- return ccr; +- mode_cfg = ccr & AT803X_MODE_CFG_MASK; +- +- switch (mode_cfg) { +- case AT803X_MODE_CFG_BX1000_RGMII_50OHM: +- case AT803X_MODE_CFG_BX1000_RGMII_75OHM: +- priv->is_1000basex = true; +- fallthrough; +- case AT803X_MODE_CFG_FX100_RGMII_50OHM: +- case AT803X_MODE_CFG_FX100_RGMII_75OHM: +- priv->is_fiber = true; +- break; +- } +- +- /* Disable WoL in 1588 register which is enabled +- * by default +- */ +- return phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- AT803X_WOL_EN, 0); +-} +- +-static int at8031_config_init(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- int ret; +- +- /* Some bootloaders leave the fiber page selected. +- * Switch to the appropriate page (fiber or copper), as otherwise we +- * read the PHY capabilities from the wrong page. +- */ +- phy_lock_mdio_bus(phydev); +- ret = at803x_write_page(phydev, +- priv->is_fiber ? AT803X_PAGE_FIBER : +- AT803X_PAGE_COPPER); +- phy_unlock_mdio_bus(phydev); +- if (ret) +- return ret; +- +- ret = at8031_pll_config(phydev); +- if (ret < 0) +- return ret; +- +- return at803x_config_init(phydev); +-} +- +-static int at8031_set_wol(struct phy_device *phydev, +- struct ethtool_wolinfo *wol) +-{ +- int ret; +- +- /* First setup MAC address and enable WOL interrupt */ +- ret = at803x_set_wol(phydev, wol); +- if (ret) +- return ret; +- +- if (wol->wolopts & WAKE_MAGIC) +- /* Enable WOL function for 1588 */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- 0, AT803X_WOL_EN); +- else +- /* Disable WoL function for 1588 */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- AT803X_WOL_EN, 0); +- +- return ret; +-} +- +-static int at8031_config_intr(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- int err, value = 0; +- +- if (phydev->interrupts == PHY_INTERRUPT_ENABLED && +- priv->is_fiber) { +- /* Clear any pending interrupts */ +- err = at803x_ack_interrupt(phydev); +- if (err) +- return err; +- +- value |= AT803X_INTR_ENABLE_LINK_FAIL_BX; +- value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX; +- +- err = phy_set_bits(phydev, AT803X_INTR_ENABLE, value); +- if (err) +- return err; +- } +- +- return at803x_config_intr(phydev); +-} +- +-/* AR8031 and AR8033 share the same read status logic */ +-static int at8031_read_status(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- +- if (priv->is_1000basex) +- return genphy_c37_read_status(phydev); +- +- return at803x_read_status(phydev); +-} +- +-/* AR8031 and AR8035 share the same cable test get status reg */ +-static int at8031_cable_test_get_status(struct phy_device *phydev, +- bool *finished) +-{ +- return at803x_cable_test_get_status(phydev, finished, 0xf); +-} +- +-/* AR8031 and AR8035 share the same cable test start logic */ +-static int at8031_cable_test_start(struct phy_device *phydev) +-{ +- at803x_cable_test_autoneg(phydev); +- phy_write(phydev, MII_CTRL1000, 0); +- /* we do all the (time consuming) work later */ +- return 0; +-} +- +-/* AR8032, AR9331 and QCA9561 share the same cable test get status reg */ +-static int at8032_cable_test_get_status(struct phy_device *phydev, +- bool *finished) +-{ +- return at803x_cable_test_get_status(phydev, finished, 0x3); +-} +- +-static int at8035_parse_dt(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- +- /* Mask is set by the generic at803x_parse_dt +- * if property is set. Assume property is set +- * with the mask not zero. +- */ +- if (priv->clk_25m_mask) { +- /* Fixup for the AR8030/AR8035. This chip has another mask and +- * doesn't support the DSP reference. Eg. the lowest bit of the +- * mask. The upper two bits select the same frequencies. Mask +- * the lowest bit here. +- * +- * Warning: +- * There was no datasheet for the AR8030 available so this is +- * just a guess. But the AR8035 is listed as pin compatible +- * to the AR8030 so there might be a good chance it works on +- * the AR8030 too. +- */ +- priv->clk_25m_reg &= AT8035_CLK_OUT_MASK; +- priv->clk_25m_mask &= AT8035_CLK_OUT_MASK; +- } +- +- return 0; +-} +- +-/* AR8030 and AR8035 shared the same special mask for clk_25m */ +-static int at8035_probe(struct phy_device *phydev) +-{ +- int ret; +- +- ret = at803x_probe(phydev); +- if (ret) +- return ret; +- +- return at8035_parse_dt(phydev); +-} +- +-static int qca83xx_config_init(struct phy_device *phydev) +-{ +- u8 switch_revision; +- +- switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK; +- +- switch (switch_revision) { +- case 1: +- /* For 100M waveform */ +- at803x_debug_reg_write(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0x02ea); +- /* Turn on Gigabit clock */ +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x68a0); +- break; +- +- case 2: +- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0); +- fallthrough; +- case 4: +- phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f); +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x6860); +- at803x_debug_reg_write(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0x2c46); +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000); +- break; +- } +- +- /* Following original QCA sourcecode set port to prefer master */ +- phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); +- +- return 0; +-} +- +-static int qca8327_config_init(struct phy_device *phydev) +-{ +- /* QCA8327 require DAC amplitude adjustment for 100m set to +6%. +- * Disable on init and enable only with 100m speed following +- * qca original source code. +- */ +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, 0); +- +- return qca83xx_config_init(phydev); +-} +- +-static void qca83xx_link_change_notify(struct phy_device *phydev) +-{ +- /* Set DAC Amplitude adjustment to +6% for 100m on link running */ +- if (phydev->state == PHY_RUNNING) { +- if (phydev->speed == SPEED_100) +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, +- QCA8327_DEBUG_MANU_CTRL_EN); +- } else { +- /* Reset DAC Amplitude adjustment */ +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, 0); +- } +-} +- +-static int qca83xx_resume(struct phy_device *phydev) +-{ +- int ret, val; +- +- /* Skip reset if not suspended */ +- if (!phydev->suspended) +- return 0; +- +- /* Reinit the port, reset values set by suspend */ +- qca83xx_config_init(phydev); +- +- /* Reset the port on port resume */ +- phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); +- +- /* On resume from suspend the switch execute a reset and +- * restart auto-negotiation. Wait for reset to complete. +- */ +- ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET), +- 50000, 600000, true); +- if (ret) +- return ret; +- +- usleep_range(1000, 2000); +- +- return 0; +-} +- +-static int qca83xx_suspend(struct phy_device *phydev) +-{ +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN, +- AT803X_DEBUG_GATE_CLK_IN1000, 0); +- +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, +- AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE | +- AT803X_DEBUG_HIB_CTRL_SEL_RST_80U, 0); +- +- return 0; +-} +- +-static int qca8337_suspend(struct phy_device *phydev) +-{ +- /* Only QCA8337 support actual suspend. */ +- genphy_suspend(phydev); +- +- return qca83xx_suspend(phydev); +-} +- +-static int qca8327_suspend(struct phy_device *phydev) +-{ +- u16 mask = 0; +- +- /* QCA8327 cause port unreliability when phy suspend +- * is set. +- */ +- mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); +- phy_modify(phydev, MII_BMCR, mask, 0); +- +- return qca83xx_suspend(phydev); +-} +- +-static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) +-{ +- int ret; +- +- /* Enable fast retrain */ +- ret = genphy_c45_fast_retrain(phydev, true); +- if (ret) +- return ret; +- +- phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1, +- QCA808X_TOP_OPTION1_DATA); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB, +- QCA808X_MSE_THRESHOLD_20DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB, +- QCA808X_MSE_THRESHOLD_17DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB, +- QCA808X_MSE_THRESHOLD_27DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB, +- QCA808X_MSE_THRESHOLD_28DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1, +- QCA808X_MMD3_DEBUG_1_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4, +- QCA808X_MMD3_DEBUG_4_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5, +- QCA808X_MMD3_DEBUG_5_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3, +- QCA808X_MMD3_DEBUG_3_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6, +- QCA808X_MMD3_DEBUG_6_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2, +- QCA808X_MMD3_DEBUG_2_VALUE); +- +- return 0; +-} +- +-static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) +-{ +- u16 seed_value; +- +- if (!enable) +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); +- +- seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, +- FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | +- QCA808X_MASTER_SLAVE_SEED_ENABLE); +-} +- +-static bool qca808x_is_prefer_master(struct phy_device *phydev) +-{ +- return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || +- (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); +-} +- +-static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) +-{ +- return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); +-} +- +-static int qca808x_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- /* Active adc&vga on 802.3az for the link 1000M and 100M */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, +- QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); +- if (ret) +- return ret; +- +- /* Adjust the threshold on 802.3az for the link 1000M */ +- ret = phy_write_mmd(phydev, MDIO_MMD_PCS, +- QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, +- QCA808X_MMD3_AZ_TRAINING_VAL); +- if (ret) +- return ret; +- +- if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { +- /* Config the fast retrain for the link 2500M */ +- ret = qca808x_phy_fast_retrain_config(phydev); +- if (ret) +- return ret; +- +- ret = genphy_read_master_slave(phydev); +- if (ret < 0) +- return ret; +- +- if (!qca808x_is_prefer_master(phydev)) { +- /* Enable seed and configure lower ramdom seed to make phy +- * linked as slave mode. +- */ +- ret = qca808x_phy_ms_seed_enable(phydev, true); +- if (ret) +- return ret; +- } +- } +- +- /* Configure adc threshold as 100mv for the link 10M */ +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, +- QCA808X_ADC_THRESHOLD_MASK, +- QCA808X_ADC_THRESHOLD_100MV); +-} +- +-static int qca808x_read_status(struct phy_device *phydev) +-{ +- struct at803x_ss_mask ss_mask = { 0 }; +- int ret; +- +- ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); +- if (ret < 0) +- return ret; +- +- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising, +- ret & MDIO_AN_10GBT_STAT_LP2_5G); +- +- ret = genphy_read_status(phydev); +- if (ret) +- return ret; +- +- /* qca8081 takes the different bits for speed value from at803x */ +- ss_mask.speed_mask = QCA808X_SS_SPEED_MASK; +- ss_mask.speed_shift = __bf_shf(QCA808X_SS_SPEED_MASK); +- ret = at803x_read_specific_status(phydev, ss_mask); +- if (ret < 0) +- return ret; +- +- if (phydev->link) { +- if (phydev->speed == SPEED_2500) +- phydev->interface = PHY_INTERFACE_MODE_2500BASEX; +- else +- phydev->interface = PHY_INTERFACE_MODE_SGMII; +- } else { +- /* generate seed as a lower random value to make PHY linked as SLAVE easily, +- * except for master/slave configuration fault detected or the master mode +- * preferred. +- * +- * the reason for not putting this code into the function link_change_notify is +- * the corner case where the link partner is also the qca8081 PHY and the seed +- * value is configured as the same value, the link can't be up and no link change +- * occurs. +- */ +- if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { +- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || +- qca808x_is_prefer_master(phydev)) { +- qca808x_phy_ms_seed_enable(phydev, false); +- } else { +- qca808x_phy_ms_seed_enable(phydev, true); +- } +- } +- } +- +- return 0; +-} +- +-static int qca808x_soft_reset(struct phy_device *phydev) +-{ +- int ret; +- +- ret = genphy_soft_reset(phydev); +- if (ret < 0) +- return ret; +- +- if (qca808x_has_fast_retrain_or_slave_seed(phydev)) +- ret = qca808x_phy_ms_seed_enable(phydev, true); +- +- return ret; +-} +- +-static bool qca808x_cdt_fault_length_valid(int cdt_code) +-{ +- switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: +- return true; +- default: +- return false; +- } +-} +- +-static int qca808x_cable_test_result_trans(int cdt_code) +-{ +- switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_NORMAL: +- return ETHTOOL_A_CABLE_RESULT_CODE_OK; +- case QCA808X_CDT_STATUS_STAT_SAME_SHORT: +- return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; +- case QCA808X_CDT_STATUS_STAT_SAME_OPEN: +- return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: +- return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; +- case QCA808X_CDT_STATUS_STAT_FAIL: +- default: +- return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; +- } +-} +- +-static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, +- int result) +-{ +- int val; +- u32 cdt_length_reg = 0; +- +- switch (pair) { +- case ETHTOOL_A_CABLE_PAIR_A: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A; +- break; +- case ETHTOOL_A_CABLE_PAIR_B: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B; +- break; +- case ETHTOOL_A_CABLE_PAIR_C: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C; +- break; +- case ETHTOOL_A_CABLE_PAIR_D: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D; +- break; +- default: +- return -EINVAL; +- } +- +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg); +- if (val < 0) +- return val; +- +- if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); +- else +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); +- +- return at803x_cdt_fault_length(val); +-} +- +-static int qca808x_cable_test_start(struct phy_device *phydev) +-{ +- int ret; +- +- /* perform CDT with the following configs: +- * 1. disable hibernation. +- * 2. force PHY working in MDI mode. +- * 3. for PHY working in 1000BaseT. +- * 4. configure the threshold. +- */ +- +- ret = at803x_debug_reg_mask(phydev, QCA808X_DBG_AN_TEST, QCA808X_HIBERNATION_EN, 0); +- if (ret < 0) +- return ret; +- +- ret = at803x_config_mdix(phydev, ETH_TP_MDI); +- if (ret < 0) +- return ret; +- +- /* Force 1000base-T needs to configure PMA/PMD and MII_BMCR */ +- phydev->duplex = DUPLEX_FULL; +- phydev->speed = SPEED_1000; +- ret = genphy_c45_pma_setup_forced(phydev); +- if (ret < 0) +- return ret; +- +- ret = genphy_setup_forced(phydev); +- if (ret < 0) +- return ret; +- +- /* configure the thresholds for open, short, pair ok test */ +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8074, 0xc040); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8076, 0xc040); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8077, 0xa060); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8078, 0xc050); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807a, 0xc060); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807e, 0xb060); +- +- return 0; +-} +- +-static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, +- u16 status) +-{ +- int length, result; +- u16 pair_code; +- +- switch (pair) { +- case ETHTOOL_A_CABLE_PAIR_A: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_B: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_C: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_D: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); +- break; +- default: +- return -EINVAL; +- } +- +- result = qca808x_cable_test_result_trans(pair_code); +- ethnl_cable_test_result(phydev, pair, result); +- +- if (qca808x_cdt_fault_length_valid(pair_code)) { +- length = qca808x_cdt_fault_length(phydev, pair, result); +- ethnl_cable_test_fault_length(phydev, pair, length); +- } +- +- return 0; +-} +- +-static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) +-{ +- int ret, val; +- +- *finished = false; +- +- val = QCA808X_CDT_ENABLE_TEST | +- QCA808X_CDT_LENGTH_UNIT; +- ret = at803x_cdt_start(phydev, val); +- if (ret) +- return ret; +- +- ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); +- if (ret) +- return ret; +- +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS); +- if (val < 0) +- return val; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); +- if (ret) +- return ret; +- +- *finished = true; +- +- return 0; +-} +- +-static int qca808x_get_features(struct phy_device *phydev) +-{ +- int ret; +- +- ret = genphy_c45_pma_read_abilities(phydev); +- if (ret) +- return ret; +- +- /* The autoneg ability is not existed in bit3 of MMD7.1, +- * but it is supported by qca808x PHY, so we add it here +- * manually. +- */ +- linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); +- +- /* As for the qca8081 1G version chip, the 2500baseT ability is also +- * existed in the bit0 of MMD1.21, we need to remove it manually if +- * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. +- */ +- ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); +- if (ret < 0) +- return ret; +- +- if (QCA808X_PHY_CHIP_TYPE_1G & ret) +- linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); +- +- return 0; +-} +- +-static int qca808x_config_aneg(struct phy_device *phydev) +-{ +- int phy_ctrl = 0; +- int ret; +- +- ret = at803x_prepare_config_aneg(phydev); +- if (ret) +- return ret; +- +- /* The reg MII_BMCR also needs to be configured for force mode, the +- * genphy_config_aneg is also needed. +- */ +- if (phydev->autoneg == AUTONEG_DISABLE) +- genphy_c45_pma_setup_forced(phydev); +- +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) +- phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; +- +- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, +- MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); +- if (ret < 0) +- return ret; +- +- return __genphy_config_aneg(phydev, ret); +-} +- +-static void qca808x_link_change_notify(struct phy_device *phydev) +-{ +- /* Assert interface sgmii fifo on link down, deassert it on link up, +- * the interface device address is always phy address added by 1. +- */ +- mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, +- MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, +- QCA8081_PHY_FIFO_RSTN, +- phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); +-} +- +-static int qca808x_led_parse_netdev(struct phy_device *phydev, unsigned long rules, +- u16 *offload_trigger) +-{ +- /* Parsing specific to netdev trigger */ +- if (test_bit(TRIGGER_NETDEV_TX, &rules)) +- *offload_trigger |= QCA808X_LED_TX_BLINK; +- if (test_bit(TRIGGER_NETDEV_RX, &rules)) +- *offload_trigger |= QCA808X_LED_RX_BLINK; +- if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED10_ON; +- if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED100_ON; +- if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED1000_ON; +- if (test_bit(TRIGGER_NETDEV_LINK_2500, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED2500_ON; +- if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) +- *offload_trigger |= QCA808X_LED_HALF_DUPLEX_ON; +- if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) +- *offload_trigger |= QCA808X_LED_FULL_DUPLEX_ON; +- +- if (rules && !*offload_trigger) +- return -EOPNOTSUPP; +- +- /* Enable BLINK_CHECK_BYPASS by default to make the LED +- * blink even with duplex or speed mode not enabled. +- */ +- *offload_trigger |= QCA808X_LED_BLINK_CHECK_BYPASS; +- +- return 0; +-} +- +-static int qca808x_led_hw_control_enable(struct phy_device *phydev, u8 index) +-{ +- u16 reg; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN); +-} +- +-static int qca808x_led_hw_is_supported(struct phy_device *phydev, u8 index, +- unsigned long rules) +-{ +- u16 offload_trigger = 0; +- +- if (index > 2) +- return -EINVAL; +- +- return qca808x_led_parse_netdev(phydev, rules, &offload_trigger); +-} +- +-static int qca808x_led_hw_control_set(struct phy_device *phydev, u8 index, +- unsigned long rules) +-{ +- u16 reg, offload_trigger = 0; +- int ret; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_CTRL(index); +- +- ret = qca808x_led_parse_netdev(phydev, rules, &offload_trigger); +- if (ret) +- return ret; +- +- ret = qca808x_led_hw_control_enable(phydev, index); +- if (ret) +- return ret; +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_PATTERN_MASK, +- offload_trigger); +-} +- +-static bool qca808x_led_hw_control_status(struct phy_device *phydev, u8 index) +-{ +- u16 reg; +- int val; +- +- if (index > 2) +- return false; +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); +- +- return !(val & QCA808X_LED_FORCE_EN); +-} +- +-static int qca808x_led_hw_control_get(struct phy_device *phydev, u8 index, +- unsigned long *rules) +-{ +- u16 reg; +- int val; +- +- if (index > 2) +- return -EINVAL; +- +- /* Check if we have hw control enabled */ +- if (qca808x_led_hw_control_status(phydev, index)) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_CTRL(index); +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); +- if (val & QCA808X_LED_TX_BLINK) +- set_bit(TRIGGER_NETDEV_TX, rules); +- if (val & QCA808X_LED_RX_BLINK) +- set_bit(TRIGGER_NETDEV_RX, rules); +- if (val & QCA808X_LED_SPEED10_ON) +- set_bit(TRIGGER_NETDEV_LINK_10, rules); +- if (val & QCA808X_LED_SPEED100_ON) +- set_bit(TRIGGER_NETDEV_LINK_100, rules); +- if (val & QCA808X_LED_SPEED1000_ON) +- set_bit(TRIGGER_NETDEV_LINK_1000, rules); +- if (val & QCA808X_LED_SPEED2500_ON) +- set_bit(TRIGGER_NETDEV_LINK_2500, rules); +- if (val & QCA808X_LED_HALF_DUPLEX_ON) +- set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); +- if (val & QCA808X_LED_FULL_DUPLEX_ON) +- set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); +- +- return 0; +-} +- +-static int qca808x_led_hw_control_reset(struct phy_device *phydev, u8 index) +-{ +- u16 reg; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_CTRL(index); +- +- return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_PATTERN_MASK); +-} +- +-static int qca808x_led_brightness_set(struct phy_device *phydev, +- u8 index, enum led_brightness value) +-{ +- u16 reg; +- int ret; +- +- if (index > 2) +- return -EINVAL; +- +- if (!value) { +- ret = qca808x_led_hw_control_reset(phydev, index); +- if (ret) +- return ret; +- } +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, +- QCA808X_LED_FORCE_EN | value ? QCA808X_LED_FORCE_ON : +- QCA808X_LED_FORCE_OFF); +-} +- +-static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, +- unsigned long *delay_on, +- unsigned long *delay_off) +-{ +- int ret; +- u16 reg; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- /* Set blink to 50% off, 50% on at 4Hz by default */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL, +- QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK, +- QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50); +- if (ret) +- return ret; +- +- /* We use BLINK_1 for normal blinking */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1); +- if (ret) +- return ret; +- +- /* We set blink to 4Hz, aka 250ms */ +- *delay_on = 250 / 2; +- *delay_off = 250 / 2; +- +- return 0; +-} +- +-static int qca808x_led_polarity_set(struct phy_device *phydev, int index, +- unsigned long modes) +-{ +- struct at803x_priv *priv = phydev->priv; +- bool active_low = false; +- u32 mode; +- +- for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { +- switch (mode) { +- case PHY_LED_ACTIVE_LOW: +- active_low = true; +- break; +- default: +- return -EINVAL; +- } +- } +- +- /* PHY polarity is global and can't be set per LED. +- * To detect this, check if last requested polarity mode +- * match the new one. +- */ +- if (priv->led_polarity_mode >= 0 && +- priv->led_polarity_mode != active_low) { +- phydev_err(phydev, "PHY polarity is global. Mismatched polarity on different LED\n"); +- return -EINVAL; +- } +- +- /* Save the last PHY polarity mode */ +- priv->led_polarity_mode = active_low; +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, +- QCA808X_MMD7_LED_POLARITY_CTRL, +- QCA808X_LED_ACTIVE_HIGH, +- active_low ? 0 : QCA808X_LED_ACTIVE_HIGH); +-} +- +-static struct phy_driver at803x_driver[] = { +-{ +- /* Qualcomm Atheros AR8035 */ +- PHY_ID_MATCH_EXACT(ATH8035_PHY_ID), +- .name = "Qualcomm Atheros AR8035", +- .flags = PHY_POLL_CABLE_TEST, +- .probe = at8035_probe, +- .config_aneg = at803x_config_aneg, +- .config_init = at803x_config_init, +- .soft_reset = genphy_soft_reset, +- .set_wol = at803x_set_wol, +- .get_wol = at803x_get_wol, +- .suspend = at803x_suspend, +- .resume = at803x_resume, +- /* PHY_GBIT_FEATURES */ +- .read_status = at803x_read_status, +- .config_intr = at803x_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +- .get_tunable = at803x_get_tunable, +- .set_tunable = at803x_set_tunable, +- .cable_test_start = at8031_cable_test_start, +- .cable_test_get_status = at8031_cable_test_get_status, +-}, { +- /* Qualcomm Atheros AR8030 */ +- .phy_id = ATH8030_PHY_ID, +- .name = "Qualcomm Atheros AR8030", +- .phy_id_mask = AT8030_PHY_ID_MASK, +- .probe = at8035_probe, +- .config_init = at803x_config_init, +- .link_change_notify = at803x_link_change_notify, +- .set_wol = at803x_set_wol, +- .get_wol = at803x_get_wol, +- .suspend = at803x_suspend, +- .resume = at803x_resume, +- /* PHY_BASIC_FEATURES */ +- .config_intr = at803x_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +-}, { +- /* Qualcomm Atheros AR8031/AR8033 */ +- PHY_ID_MATCH_EXACT(ATH8031_PHY_ID), +- .name = "Qualcomm Atheros AR8031/AR8033", +- .flags = PHY_POLL_CABLE_TEST, +- .probe = at8031_probe, +- .config_init = at8031_config_init, +- .config_aneg = at803x_config_aneg, +- .soft_reset = genphy_soft_reset, +- .set_wol = at8031_set_wol, +- .get_wol = at803x_get_wol, +- .suspend = at803x_suspend, +- .resume = at803x_resume, +- .read_page = at803x_read_page, +- .write_page = at803x_write_page, +- .get_features = at803x_get_features, +- .read_status = at8031_read_status, +- .config_intr = at8031_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +- .get_tunable = at803x_get_tunable, +- .set_tunable = at803x_set_tunable, +- .cable_test_start = at8031_cable_test_start, +- .cable_test_get_status = at8031_cable_test_get_status, +-}, { +- /* Qualcomm Atheros AR8032 */ +- PHY_ID_MATCH_EXACT(ATH8032_PHY_ID), +- .name = "Qualcomm Atheros AR8032", +- .probe = at803x_probe, +- .flags = PHY_POLL_CABLE_TEST, +- .config_init = at803x_config_init, +- .link_change_notify = at803x_link_change_notify, +- .suspend = at803x_suspend, +- .resume = at803x_resume, +- /* PHY_BASIC_FEATURES */ +- .config_intr = at803x_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +- .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at8032_cable_test_get_status, +-}, { +- /* ATHEROS AR9331 */ +- PHY_ID_MATCH_EXACT(ATH9331_PHY_ID), +- .name = "Qualcomm Atheros AR9331 built-in PHY", +- .probe = at803x_probe, +- .suspend = at803x_suspend, +- .resume = at803x_resume, +- .flags = PHY_POLL_CABLE_TEST, +- /* PHY_BASIC_FEATURES */ +- .config_intr = at803x_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +- .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at8032_cable_test_get_status, +- .read_status = at803x_read_status, +- .soft_reset = genphy_soft_reset, +- .config_aneg = at803x_config_aneg, +-}, { +- /* Qualcomm Atheros QCA9561 */ +- PHY_ID_MATCH_EXACT(QCA9561_PHY_ID), +- .name = "Qualcomm Atheros QCA9561 built-in PHY", +- .probe = at803x_probe, +- .suspend = at803x_suspend, +- .resume = at803x_resume, +- .flags = PHY_POLL_CABLE_TEST, +- /* PHY_BASIC_FEATURES */ +- .config_intr = at803x_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +- .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at8032_cable_test_get_status, +- .read_status = at803x_read_status, +- .soft_reset = genphy_soft_reset, +- .config_aneg = at803x_config_aneg, +-}, { +- /* QCA8337 */ +- .phy_id = QCA8337_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "Qualcomm Atheros 8337 internal PHY", +- /* PHY_GBIT_FEATURES */ +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = qca83xx_get_sset_count, +- .get_strings = qca83xx_get_strings, +- .get_stats = qca83xx_get_stats, +- .suspend = qca8337_suspend, +- .resume = qca83xx_resume, +-}, { +- /* QCA8327-A from switch QCA8327-AL1A */ +- .phy_id = QCA8327_A_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "Qualcomm Atheros 8327-A internal PHY", +- /* PHY_GBIT_FEATURES */ +- .link_change_notify = qca83xx_link_change_notify, +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca8327_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = qca83xx_get_sset_count, +- .get_strings = qca83xx_get_strings, +- .get_stats = qca83xx_get_stats, +- .suspend = qca8327_suspend, +- .resume = qca83xx_resume, +-}, { +- /* QCA8327-B from switch QCA8327-BL1A */ +- .phy_id = QCA8327_B_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "Qualcomm Atheros 8327-B internal PHY", +- /* PHY_GBIT_FEATURES */ +- .link_change_notify = qca83xx_link_change_notify, +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca8327_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = qca83xx_get_sset_count, +- .get_strings = qca83xx_get_strings, +- .get_stats = qca83xx_get_stats, +- .suspend = qca8327_suspend, +- .resume = qca83xx_resume, +-}, { +- /* Qualcomm QCA8081 */ +- PHY_ID_MATCH_EXACT(QCA8081_PHY_ID), +- .name = "Qualcomm QCA8081", +- .flags = PHY_POLL_CABLE_TEST, +- .probe = at803x_probe, +- .config_intr = at803x_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +- .get_tunable = at803x_get_tunable, +- .set_tunable = at803x_set_tunable, +- .set_wol = at803x_set_wol, +- .get_wol = at803x_get_wol, +- .get_features = qca808x_get_features, +- .config_aneg = qca808x_config_aneg, +- .suspend = genphy_suspend, +- .resume = genphy_resume, +- .read_status = qca808x_read_status, +- .config_init = qca808x_config_init, +- .soft_reset = qca808x_soft_reset, +- .cable_test_start = qca808x_cable_test_start, +- .cable_test_get_status = qca808x_cable_test_get_status, +- .link_change_notify = qca808x_link_change_notify, +- .led_brightness_set = qca808x_led_brightness_set, +- .led_blink_set = qca808x_led_blink_set, +- .led_hw_is_supported = qca808x_led_hw_is_supported, +- .led_hw_control_set = qca808x_led_hw_control_set, +- .led_hw_control_get = qca808x_led_hw_control_get, +- .led_polarity_set = qca808x_led_polarity_set, +-}, }; +- +-module_phy_driver(at803x_driver); +- +-static struct mdio_device_id __maybe_unused atheros_tbl[] = { +- { ATH8030_PHY_ID, AT8030_PHY_ID_MASK }, +- { PHY_ID_MATCH_EXACT(ATH8031_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) }, +- { } +-}; +- +-MODULE_DEVICE_TABLE(mdio, atheros_tbl); +--- /dev/null ++++ b/drivers/net/phy/qcom/at803x.c +@@ -0,0 +1,2759 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * drivers/net/phy/at803x.c ++ * ++ * Driver for Qualcomm Atheros AR803x PHY ++ * ++ * Author: Matus Ujhelyi ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10 ++#define AT803X_SFC_ASSERT_CRS BIT(11) ++#define AT803X_SFC_FORCE_LINK BIT(10) ++#define AT803X_SFC_MDI_CROSSOVER_MODE_M GENMASK(6, 5) ++#define AT803X_SFC_AUTOMATIC_CROSSOVER 0x3 ++#define AT803X_SFC_MANUAL_MDIX 0x1 ++#define AT803X_SFC_MANUAL_MDI 0x0 ++#define AT803X_SFC_SQE_TEST BIT(2) ++#define AT803X_SFC_POLARITY_REVERSAL BIT(1) ++#define AT803X_SFC_DISABLE_JABBER BIT(0) ++ ++#define AT803X_SPECIFIC_STATUS 0x11 ++#define AT803X_SS_SPEED_MASK GENMASK(15, 14) ++#define AT803X_SS_SPEED_1000 2 ++#define AT803X_SS_SPEED_100 1 ++#define AT803X_SS_SPEED_10 0 ++#define AT803X_SS_DUPLEX BIT(13) ++#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11) ++#define AT803X_SS_MDIX BIT(6) ++ ++#define QCA808X_SS_SPEED_MASK GENMASK(9, 7) ++#define QCA808X_SS_SPEED_2500 4 ++ ++#define AT803X_INTR_ENABLE 0x12 ++#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15) ++#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14) ++#define AT803X_INTR_ENABLE_DUPLEX_CHANGED BIT(13) ++#define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12) ++#define AT803X_INTR_ENABLE_LINK_FAIL BIT(11) ++#define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10) ++#define AT803X_INTR_ENABLE_LINK_FAIL_BX BIT(8) ++#define AT803X_INTR_ENABLE_LINK_SUCCESS_BX BIT(7) ++#define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5) ++#define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1) ++#define AT803X_INTR_ENABLE_WOL BIT(0) ++ ++#define AT803X_INTR_STATUS 0x13 ++ ++#define AT803X_SMART_SPEED 0x14 ++#define AT803X_SMART_SPEED_ENABLE BIT(5) ++#define AT803X_SMART_SPEED_RETRY_LIMIT_MASK GENMASK(4, 2) ++#define AT803X_SMART_SPEED_BYPASS_TIMER BIT(1) ++#define AT803X_CDT 0x16 ++#define AT803X_CDT_MDI_PAIR_MASK GENMASK(9, 8) ++#define AT803X_CDT_ENABLE_TEST BIT(0) ++#define AT803X_CDT_STATUS 0x1c ++#define AT803X_CDT_STATUS_STAT_NORMAL 0 ++#define AT803X_CDT_STATUS_STAT_SHORT 1 ++#define AT803X_CDT_STATUS_STAT_OPEN 2 ++#define AT803X_CDT_STATUS_STAT_FAIL 3 ++#define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8) ++#define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0) ++#define AT803X_LED_CONTROL 0x18 ++ ++#define AT803X_PHY_MMD3_WOL_CTRL 0x8012 ++#define AT803X_WOL_EN BIT(5) ++#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C ++#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B ++#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A ++#define AT803X_REG_CHIP_CONFIG 0x1f ++#define AT803X_BT_BX_REG_SEL 0x8000 ++ ++#define AT803X_DEBUG_ADDR 0x1D ++#define AT803X_DEBUG_DATA 0x1E ++ ++#define AT803X_MODE_CFG_MASK 0x0F ++#define AT803X_MODE_CFG_BASET_RGMII 0x00 ++#define AT803X_MODE_CFG_BASET_SGMII 0x01 ++#define AT803X_MODE_CFG_BX1000_RGMII_50OHM 0x02 ++#define AT803X_MODE_CFG_BX1000_RGMII_75OHM 0x03 ++#define AT803X_MODE_CFG_BX1000_CONV_50OHM 0x04 ++#define AT803X_MODE_CFG_BX1000_CONV_75OHM 0x05 ++#define AT803X_MODE_CFG_FX100_RGMII_50OHM 0x06 ++#define AT803X_MODE_CFG_FX100_CONV_50OHM 0x07 ++#define AT803X_MODE_CFG_RGMII_AUTO_MDET 0x0B ++#define AT803X_MODE_CFG_FX100_RGMII_75OHM 0x0E ++#define AT803X_MODE_CFG_FX100_CONV_75OHM 0x0F ++ ++#define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/ ++#define AT803X_PSSR_MR_AN_COMPLETE 0x0200 ++ ++#define AT803X_DEBUG_ANALOG_TEST_CTRL 0x00 ++#define QCA8327_DEBUG_MANU_CTRL_EN BIT(2) ++#define QCA8337_DEBUG_MANU_CTRL_EN GENMASK(3, 2) ++#define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15) ++ ++#define AT803X_DEBUG_SYSTEM_CTRL_MODE 0x05 ++#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) ++ ++#define AT803X_DEBUG_REG_HIB_CTRL 0x0b ++#define AT803X_DEBUG_HIB_CTRL_SEL_RST_80U BIT(10) ++#define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13) ++#define AT803X_DEBUG_HIB_CTRL_PS_HIB_EN BIT(15) ++ ++#define AT803X_DEBUG_REG_3C 0x3C ++ ++#define AT803X_DEBUG_REG_GREEN 0x3D ++#define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6) ++ ++#define AT803X_DEBUG_REG_1F 0x1F ++#define AT803X_DEBUG_PLL_ON BIT(2) ++#define AT803X_DEBUG_RGMII_1V8 BIT(3) ++ ++#define MDIO_AZ_DEBUG 0x800D ++ ++/* AT803x supports either the XTAL input pad, an internal PLL or the ++ * DSP as clock reference for the clock output pad. The XTAL reference ++ * is only used for 25 MHz output, all other frequencies need the PLL. ++ * The DSP as a clock reference is used in synchronous ethernet ++ * applications. ++ * ++ * By default the PLL is only enabled if there is a link. Otherwise ++ * the PHY will go into low power state and disabled the PLL. You can ++ * set the PLL_ON bit (see debug register 0x1f) to keep the PLL always ++ * enabled. ++ */ ++#define AT803X_MMD7_CLK25M 0x8016 ++#define AT803X_CLK_OUT_MASK GENMASK(4, 2) ++#define AT803X_CLK_OUT_25MHZ_XTAL 0 ++#define AT803X_CLK_OUT_25MHZ_DSP 1 ++#define AT803X_CLK_OUT_50MHZ_PLL 2 ++#define AT803X_CLK_OUT_50MHZ_DSP 3 ++#define AT803X_CLK_OUT_62_5MHZ_PLL 4 ++#define AT803X_CLK_OUT_62_5MHZ_DSP 5 ++#define AT803X_CLK_OUT_125MHZ_PLL 6 ++#define AT803X_CLK_OUT_125MHZ_DSP 7 ++ ++/* The AR8035 has another mask which is compatible with the AR8031/AR8033 mask ++ * but doesn't support choosing between XTAL/PLL and DSP. ++ */ ++#define AT8035_CLK_OUT_MASK GENMASK(4, 3) ++ ++#define AT803X_CLK_OUT_STRENGTH_MASK GENMASK(8, 7) ++#define AT803X_CLK_OUT_STRENGTH_FULL 0 ++#define AT803X_CLK_OUT_STRENGTH_HALF 1 ++#define AT803X_CLK_OUT_STRENGTH_QUARTER 2 ++ ++#define AT803X_DEFAULT_DOWNSHIFT 5 ++#define AT803X_MIN_DOWNSHIFT 2 ++#define AT803X_MAX_DOWNSHIFT 9 ++ ++#define AT803X_MMD3_SMARTEEE_CTL1 0x805b ++#define AT803X_MMD3_SMARTEEE_CTL2 0x805c ++#define AT803X_MMD3_SMARTEEE_CTL3 0x805d ++#define AT803X_MMD3_SMARTEEE_CTL3_LPI_EN BIT(8) ++ ++#define ATH9331_PHY_ID 0x004dd041 ++#define ATH8030_PHY_ID 0x004dd076 ++#define ATH8031_PHY_ID 0x004dd074 ++#define ATH8032_PHY_ID 0x004dd023 ++#define ATH8035_PHY_ID 0x004dd072 ++#define AT8030_PHY_ID_MASK 0xffffffef ++ ++#define QCA8081_PHY_ID 0x004dd101 ++ ++#define QCA8327_A_PHY_ID 0x004dd033 ++#define QCA8327_B_PHY_ID 0x004dd034 ++#define QCA8337_PHY_ID 0x004dd036 ++#define QCA9561_PHY_ID 0x004dd042 ++#define QCA8K_PHY_ID_MASK 0xffffffff ++ ++#define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0) ++ ++#define AT803X_PAGE_FIBER 0 ++#define AT803X_PAGE_COPPER 1 ++ ++/* don't turn off internal PLL */ ++#define AT803X_KEEP_PLL_ENABLED BIT(0) ++#define AT803X_DISABLE_SMARTEEE BIT(1) ++ ++/* disable hibernation mode */ ++#define AT803X_DISABLE_HIBERNATION_MODE BIT(2) ++ ++/* ADC threshold */ ++#define QCA808X_PHY_DEBUG_ADC_THRESHOLD 0x2c80 ++#define QCA808X_ADC_THRESHOLD_MASK GENMASK(7, 0) ++#define QCA808X_ADC_THRESHOLD_80MV 0 ++#define QCA808X_ADC_THRESHOLD_100MV 0xf0 ++#define QCA808X_ADC_THRESHOLD_200MV 0x0f ++#define QCA808X_ADC_THRESHOLD_300MV 0xff ++ ++/* CLD control */ ++#define QCA808X_PHY_MMD3_ADDR_CLD_CTRL7 0x8007 ++#define QCA808X_8023AZ_AFE_CTRL_MASK GENMASK(8, 4) ++#define QCA808X_8023AZ_AFE_EN 0x90 ++ ++/* AZ control */ ++#define QCA808X_PHY_MMD3_AZ_TRAINING_CTRL 0x8008 ++#define QCA808X_MMD3_AZ_TRAINING_VAL 0x1c32 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB 0x8014 ++#define QCA808X_MSE_THRESHOLD_20DB_VALUE 0x529 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB 0x800E ++#define QCA808X_MSE_THRESHOLD_17DB_VALUE 0x341 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB 0x801E ++#define QCA808X_MSE_THRESHOLD_27DB_VALUE 0x419 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB 0x8020 ++#define QCA808X_MSE_THRESHOLD_28DB_VALUE 0x341 ++ ++#define QCA808X_PHY_MMD7_TOP_OPTION1 0x901c ++#define QCA808X_TOP_OPTION1_DATA 0x0 ++ ++#define QCA808X_PHY_MMD3_DEBUG_1 0xa100 ++#define QCA808X_MMD3_DEBUG_1_VALUE 0x9203 ++#define QCA808X_PHY_MMD3_DEBUG_2 0xa101 ++#define QCA808X_MMD3_DEBUG_2_VALUE 0x48ad ++#define QCA808X_PHY_MMD3_DEBUG_3 0xa103 ++#define QCA808X_MMD3_DEBUG_3_VALUE 0x1698 ++#define QCA808X_PHY_MMD3_DEBUG_4 0xa105 ++#define QCA808X_MMD3_DEBUG_4_VALUE 0x8001 ++#define QCA808X_PHY_MMD3_DEBUG_5 0xa106 ++#define QCA808X_MMD3_DEBUG_5_VALUE 0x1111 ++#define QCA808X_PHY_MMD3_DEBUG_6 0xa011 ++#define QCA808X_MMD3_DEBUG_6_VALUE 0x5f85 ++ ++/* master/slave seed config */ ++#define QCA808X_PHY_DEBUG_LOCAL_SEED 9 ++#define QCA808X_MASTER_SLAVE_SEED_ENABLE BIT(1) ++#define QCA808X_MASTER_SLAVE_SEED_CFG GENMASK(12, 2) ++#define QCA808X_MASTER_SLAVE_SEED_RANGE 0x32 ++ ++/* Hibernation yields lower power consumpiton in contrast with normal operation mode. ++ * when the copper cable is unplugged, the PHY enters into hibernation mode in about 10s. ++ */ ++#define QCA808X_DBG_AN_TEST 0xb ++#define QCA808X_HIBERNATION_EN BIT(15) ++ ++#define QCA808X_CDT_ENABLE_TEST BIT(15) ++#define QCA808X_CDT_INTER_CHECK_DIS BIT(13) ++#define QCA808X_CDT_STATUS BIT(11) ++#define QCA808X_CDT_LENGTH_UNIT BIT(10) ++ ++#define QCA808X_MMD3_CDT_STATUS 0x8064 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 ++#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) ++#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) ++ ++#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) ++#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) ++#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) ++#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) ++ ++#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) ++#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) ++#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) ++#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) ++#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) ++ ++#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) ++#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) ++ ++/* NORMAL are MDI with type set to 0 */ ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++ ++/* Added for reference of existence but should be handled by wait_for_completion already */ ++#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) ++ ++#define QCA808X_MMD7_LED_GLOBAL 0x8073 ++#define QCA808X_LED_BLINK_1 GENMASK(11, 6) ++#define QCA808X_LED_BLINK_2 GENMASK(5, 0) ++/* Values are the same for both BLINK_1 and BLINK_2 */ ++#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3) ++#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0) ++#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1) ++#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2) ++#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3) ++#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4) ++#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5) ++#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6) ++#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7) ++#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0) ++#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0) ++#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1) ++#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2) ++#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3) ++#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4) ++#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5) ++#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6) ++#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7) ++ ++#define QCA808X_MMD7_LED2_CTRL 0x8074 ++#define QCA808X_MMD7_LED2_FORCE_CTRL 0x8075 ++#define QCA808X_MMD7_LED1_CTRL 0x8076 ++#define QCA808X_MMD7_LED1_FORCE_CTRL 0x8077 ++#define QCA808X_MMD7_LED0_CTRL 0x8078 ++#define QCA808X_MMD7_LED_CTRL(x) (0x8078 - ((x) * 2)) ++ ++/* LED hw control pattern is the same for every LED */ ++#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) ++#define QCA808X_LED_SPEED2500_ON BIT(15) ++#define QCA808X_LED_SPEED2500_BLINK BIT(14) ++/* Follow blink trigger even if duplex or speed condition doesn't match */ ++#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) ++#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) ++#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) ++#define QCA808X_LED_TX_BLINK BIT(10) ++#define QCA808X_LED_RX_BLINK BIT(9) ++#define QCA808X_LED_TX_ON_10MS BIT(8) ++#define QCA808X_LED_RX_ON_10MS BIT(7) ++#define QCA808X_LED_SPEED1000_ON BIT(6) ++#define QCA808X_LED_SPEED100_ON BIT(5) ++#define QCA808X_LED_SPEED10_ON BIT(4) ++#define QCA808X_LED_COLLISION_BLINK BIT(3) ++#define QCA808X_LED_SPEED1000_BLINK BIT(2) ++#define QCA808X_LED_SPEED100_BLINK BIT(1) ++#define QCA808X_LED_SPEED10_BLINK BIT(0) ++ ++#define QCA808X_MMD7_LED0_FORCE_CTRL 0x8079 ++#define QCA808X_MMD7_LED_FORCE_CTRL(x) (0x8079 - ((x) * 2)) ++ ++/* LED force ctrl is the same for every LED ++ * No documentation exist for this, not even internal one ++ * with NDA as QCOM gives only info about configuring ++ * hw control pattern rules and doesn't indicate any way ++ * to force the LED to specific mode. ++ * These define comes from reverse and testing and maybe ++ * lack of some info or some info are not entirely correct. ++ * For the basic LED control and hw control these finding ++ * are enough to support LED control in all the required APIs. ++ * ++ * On doing some comparison with implementation with qca807x, ++ * it was found that it's 1:1 equal to it and confirms all the ++ * reverse done. It was also found further specification with the ++ * force mode and the blink modes. ++ */ ++#define QCA808X_LED_FORCE_EN BIT(15) ++#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13) ++#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3) ++#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2) ++#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1) ++#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0) ++ ++#define QCA808X_MMD7_LED_POLARITY_CTRL 0x901a ++/* QSDK sets by default 0x46 to this reg that sets BIT 6 for ++ * LED to active high. It's not clear what BIT 3 and BIT 4 does. ++ */ ++#define QCA808X_LED_ACTIVE_HIGH BIT(6) ++ ++/* QCA808X 1G chip type */ ++#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d ++#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) ++ ++#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 ++#define QCA8081_PHY_FIFO_RSTN BIT(11) ++ ++MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); ++MODULE_AUTHOR("Matus Ujhelyi"); ++MODULE_LICENSE("GPL"); ++ ++enum stat_access_type { ++ PHY, ++ MMD ++}; ++ ++struct at803x_hw_stat { ++ const char *string; ++ u8 reg; ++ u32 mask; ++ enum stat_access_type access_type; ++}; ++ ++static struct at803x_hw_stat qca83xx_hw_stats[] = { ++ { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, ++ { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, ++ { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, ++}; ++ ++struct at803x_ss_mask { ++ u16 speed_mask; ++ u8 speed_shift; ++}; ++ ++struct at803x_priv { ++ int flags; ++ u16 clk_25m_reg; ++ u16 clk_25m_mask; ++ u8 smarteee_lpi_tw_1g; ++ u8 smarteee_lpi_tw_100m; ++ bool is_fiber; ++ bool is_1000basex; ++ struct regulator_dev *vddio_rdev; ++ struct regulator_dev *vddh_rdev; ++ u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; ++ int led_polarity_mode; ++}; ++ ++struct at803x_context { ++ u16 bmcr; ++ u16 advertise; ++ u16 control1000; ++ u16 int_enable; ++ u16 smart_speed; ++ u16 led_control; ++}; ++ ++static int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data) ++{ ++ int ret; ++ ++ ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); ++ if (ret < 0) ++ return ret; ++ ++ return phy_write(phydev, AT803X_DEBUG_DATA, data); ++} ++ ++static int at803x_debug_reg_read(struct phy_device *phydev, u16 reg) ++{ ++ int ret; ++ ++ ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); ++ if (ret < 0) ++ return ret; ++ ++ return phy_read(phydev, AT803X_DEBUG_DATA); ++} ++ ++static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, ++ u16 clear, u16 set) ++{ ++ u16 val; ++ int ret; ++ ++ ret = at803x_debug_reg_read(phydev, reg); ++ if (ret < 0) ++ return ret; ++ ++ val = ret & 0xffff; ++ val &= ~clear; ++ val |= set; ++ ++ return phy_write(phydev, AT803X_DEBUG_DATA, val); ++} ++ ++static int at803x_write_page(struct phy_device *phydev, int page) ++{ ++ int mask; ++ int set; ++ ++ if (page == AT803X_PAGE_COPPER) { ++ set = AT803X_BT_BX_REG_SEL; ++ mask = 0; ++ } else { ++ set = 0; ++ mask = AT803X_BT_BX_REG_SEL; ++ } ++ ++ return __phy_modify(phydev, AT803X_REG_CHIP_CONFIG, mask, set); ++} ++ ++static int at803x_read_page(struct phy_device *phydev) ++{ ++ int ccr = __phy_read(phydev, AT803X_REG_CHIP_CONFIG); ++ ++ if (ccr < 0) ++ return ccr; ++ ++ if (ccr & AT803X_BT_BX_REG_SEL) ++ return AT803X_PAGE_COPPER; ++ ++ return AT803X_PAGE_FIBER; ++} ++ ++static int at803x_enable_rx_delay(struct phy_device *phydev) ++{ ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0, ++ AT803X_DEBUG_RX_CLK_DLY_EN); ++} ++ ++static int at803x_enable_tx_delay(struct phy_device *phydev) ++{ ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0, ++ AT803X_DEBUG_TX_CLK_DLY_EN); ++} ++ ++static int at803x_disable_rx_delay(struct phy_device *phydev) ++{ ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ AT803X_DEBUG_RX_CLK_DLY_EN, 0); ++} ++ ++static int at803x_disable_tx_delay(struct phy_device *phydev) ++{ ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, ++ AT803X_DEBUG_TX_CLK_DLY_EN, 0); ++} ++ ++/* save relevant PHY registers to private copy */ ++static void at803x_context_save(struct phy_device *phydev, ++ struct at803x_context *context) ++{ ++ context->bmcr = phy_read(phydev, MII_BMCR); ++ context->advertise = phy_read(phydev, MII_ADVERTISE); ++ context->control1000 = phy_read(phydev, MII_CTRL1000); ++ context->int_enable = phy_read(phydev, AT803X_INTR_ENABLE); ++ context->smart_speed = phy_read(phydev, AT803X_SMART_SPEED); ++ context->led_control = phy_read(phydev, AT803X_LED_CONTROL); ++} ++ ++/* restore relevant PHY registers from private copy */ ++static void at803x_context_restore(struct phy_device *phydev, ++ const struct at803x_context *context) ++{ ++ phy_write(phydev, MII_BMCR, context->bmcr); ++ phy_write(phydev, MII_ADVERTISE, context->advertise); ++ phy_write(phydev, MII_CTRL1000, context->control1000); ++ phy_write(phydev, AT803X_INTR_ENABLE, context->int_enable); ++ phy_write(phydev, AT803X_SMART_SPEED, context->smart_speed); ++ phy_write(phydev, AT803X_LED_CONTROL, context->led_control); ++} ++ ++static int at803x_set_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int ret, irq_enabled; ++ ++ if (wol->wolopts & WAKE_MAGIC) { ++ struct net_device *ndev = phydev->attached_dev; ++ const u8 *mac; ++ unsigned int i; ++ static const unsigned int offsets[] = { ++ AT803X_LOC_MAC_ADDR_32_47_OFFSET, ++ AT803X_LOC_MAC_ADDR_16_31_OFFSET, ++ AT803X_LOC_MAC_ADDR_0_15_OFFSET, ++ }; ++ ++ if (!ndev) ++ return -ENODEV; ++ ++ mac = (const u8 *)ndev->dev_addr; ++ ++ if (!is_valid_ether_addr(mac)) ++ return -EINVAL; ++ ++ for (i = 0; i < 3; i++) ++ phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], ++ mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); ++ ++ /* Enable WOL interrupt */ ++ ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); ++ if (ret) ++ return ret; ++ } else { ++ /* Disable WOL interrupt */ ++ ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); ++ if (ret) ++ return ret; ++ } ++ ++ /* Clear WOL status */ ++ ret = phy_read(phydev, AT803X_INTR_STATUS); ++ if (ret < 0) ++ return ret; ++ ++ /* Check if there are other interrupts except for WOL triggered when PHY is ++ * in interrupt mode, only the interrupts enabled by AT803X_INTR_ENABLE can ++ * be passed up to the interrupt PIN. ++ */ ++ irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE); ++ if (irq_enabled < 0) ++ return irq_enabled; ++ ++ irq_enabled &= ~AT803X_INTR_ENABLE_WOL; ++ if (ret & irq_enabled && !phy_polling_mode(phydev)) ++ phy_trigger_machine(phydev); ++ ++ return 0; ++} ++ ++static void at803x_get_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int value; ++ ++ wol->supported = WAKE_MAGIC; ++ wol->wolopts = 0; ++ ++ value = phy_read(phydev, AT803X_INTR_ENABLE); ++ if (value < 0) ++ return; ++ ++ if (value & AT803X_INTR_ENABLE_WOL) ++ wol->wolopts |= WAKE_MAGIC; ++} ++ ++static int qca83xx_get_sset_count(struct phy_device *phydev) ++{ ++ return ARRAY_SIZE(qca83xx_hw_stats); ++} ++ ++static void qca83xx_get_strings(struct phy_device *phydev, u8 *data) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) { ++ strscpy(data + i * ETH_GSTRING_LEN, ++ qca83xx_hw_stats[i].string, ETH_GSTRING_LEN); ++ } ++} ++ ++static u64 qca83xx_get_stat(struct phy_device *phydev, int i) ++{ ++ struct at803x_hw_stat stat = qca83xx_hw_stats[i]; ++ struct at803x_priv *priv = phydev->priv; ++ int val; ++ u64 ret; ++ ++ if (stat.access_type == MMD) ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg); ++ else ++ val = phy_read(phydev, stat.reg); ++ ++ if (val < 0) { ++ ret = U64_MAX; ++ } else { ++ val = val & stat.mask; ++ priv->stats[i] += val; ++ ret = priv->stats[i]; ++ } ++ ++ return ret; ++} ++ ++static void qca83xx_get_stats(struct phy_device *phydev, ++ struct ethtool_stats *stats, u64 *data) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) ++ data[i] = qca83xx_get_stat(phydev, i); ++} ++ ++static int at803x_suspend(struct phy_device *phydev) ++{ ++ int value; ++ int wol_enabled; ++ ++ value = phy_read(phydev, AT803X_INTR_ENABLE); ++ wol_enabled = value & AT803X_INTR_ENABLE_WOL; ++ ++ if (wol_enabled) ++ value = BMCR_ISOLATE; ++ else ++ value = BMCR_PDOWN; ++ ++ phy_modify(phydev, MII_BMCR, 0, value); ++ ++ return 0; ++} ++ ++static int at803x_resume(struct phy_device *phydev) ++{ ++ return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0); ++} ++ ++static int at803x_parse_dt(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ struct at803x_priv *priv = phydev->priv; ++ u32 freq, strength, tw; ++ unsigned int sel; ++ int ret; ++ ++ if (!IS_ENABLED(CONFIG_OF_MDIO)) ++ return 0; ++ ++ if (of_property_read_bool(node, "qca,disable-smarteee")) ++ priv->flags |= AT803X_DISABLE_SMARTEEE; ++ ++ if (of_property_read_bool(node, "qca,disable-hibernation-mode")) ++ priv->flags |= AT803X_DISABLE_HIBERNATION_MODE; ++ ++ if (!of_property_read_u32(node, "qca,smarteee-tw-us-1g", &tw)) { ++ if (!tw || tw > 255) { ++ phydev_err(phydev, "invalid qca,smarteee-tw-us-1g\n"); ++ return -EINVAL; ++ } ++ priv->smarteee_lpi_tw_1g = tw; ++ } ++ ++ if (!of_property_read_u32(node, "qca,smarteee-tw-us-100m", &tw)) { ++ if (!tw || tw > 255) { ++ phydev_err(phydev, "invalid qca,smarteee-tw-us-100m\n"); ++ return -EINVAL; ++ } ++ priv->smarteee_lpi_tw_100m = tw; ++ } ++ ++ ret = of_property_read_u32(node, "qca,clk-out-frequency", &freq); ++ if (!ret) { ++ switch (freq) { ++ case 25000000: ++ sel = AT803X_CLK_OUT_25MHZ_XTAL; ++ break; ++ case 50000000: ++ sel = AT803X_CLK_OUT_50MHZ_PLL; ++ break; ++ case 62500000: ++ sel = AT803X_CLK_OUT_62_5MHZ_PLL; ++ break; ++ case 125000000: ++ sel = AT803X_CLK_OUT_125MHZ_PLL; ++ break; ++ default: ++ phydev_err(phydev, "invalid qca,clk-out-frequency\n"); ++ return -EINVAL; ++ } ++ ++ priv->clk_25m_reg |= FIELD_PREP(AT803X_CLK_OUT_MASK, sel); ++ priv->clk_25m_mask |= AT803X_CLK_OUT_MASK; ++ } ++ ++ ret = of_property_read_u32(node, "qca,clk-out-strength", &strength); ++ if (!ret) { ++ priv->clk_25m_mask |= AT803X_CLK_OUT_STRENGTH_MASK; ++ switch (strength) { ++ case AR803X_STRENGTH_FULL: ++ priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_FULL; ++ break; ++ case AR803X_STRENGTH_HALF: ++ priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_HALF; ++ break; ++ case AR803X_STRENGTH_QUARTER: ++ priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_QUARTER; ++ break; ++ default: ++ phydev_err(phydev, "invalid qca,clk-out-strength\n"); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++static int at803x_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct at803x_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ /* Init LED polarity mode to -1 */ ++ priv->led_polarity_mode = -1; ++ ++ phydev->priv = priv; ++ ++ ret = at803x_parse_dt(phydev); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int at803x_get_features(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int err; ++ ++ err = genphy_read_abilities(phydev); ++ if (err) ++ return err; ++ ++ if (phydev->drv->phy_id != ATH8031_PHY_ID) ++ return 0; ++ ++ /* AR8031/AR8033 have different status registers ++ * for copper and fiber operation. However, the ++ * extended status register is the same for both ++ * operation modes. ++ * ++ * As a result of that, ESTATUS_1000_XFULL is set ++ * to 1 even when operating in copper TP mode. ++ * ++ * Remove this mode from the supported link modes ++ * when not operating in 1000BaseX mode. ++ */ ++ if (!priv->is_1000basex) ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, ++ phydev->supported); ++ ++ return 0; ++} ++ ++static int at803x_smarteee_config(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ u16 mask = 0, val = 0; ++ int ret; ++ ++ if (priv->flags & AT803X_DISABLE_SMARTEEE) ++ return phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_MMD3_SMARTEEE_CTL3, ++ AT803X_MMD3_SMARTEEE_CTL3_LPI_EN, 0); ++ ++ if (priv->smarteee_lpi_tw_1g) { ++ mask |= 0xff00; ++ val |= priv->smarteee_lpi_tw_1g << 8; ++ } ++ if (priv->smarteee_lpi_tw_100m) { ++ mask |= 0x00ff; ++ val |= priv->smarteee_lpi_tw_100m; ++ } ++ if (!mask) ++ return 0; ++ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL1, ++ mask, val); ++ if (ret) ++ return ret; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL3, ++ AT803X_MMD3_SMARTEEE_CTL3_LPI_EN, ++ AT803X_MMD3_SMARTEEE_CTL3_LPI_EN); ++} ++ ++static int at803x_clk_out_config(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ if (!priv->clk_25m_mask) ++ return 0; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, AT803X_MMD7_CLK25M, ++ priv->clk_25m_mask, priv->clk_25m_reg); ++} ++ ++static int at8031_pll_config(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ /* The default after hardware reset is PLL OFF. After a soft reset, the ++ * values are retained. ++ */ ++ if (priv->flags & AT803X_KEEP_PLL_ENABLED) ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ 0, AT803X_DEBUG_PLL_ON); ++ else ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ AT803X_DEBUG_PLL_ON, 0); ++} ++ ++static int at803x_hibernation_mode_config(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ /* The default after hardware reset is hibernation mode enabled. After ++ * software reset, the value is retained. ++ */ ++ if (!(priv->flags & AT803X_DISABLE_HIBERNATION_MODE)) ++ return 0; ++ ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, ++ AT803X_DEBUG_HIB_CTRL_PS_HIB_EN, 0); ++} ++ ++static int at803x_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* The RX and TX delay default is: ++ * after HW reset: RX delay enabled and TX delay disabled ++ * after SW reset: RX delay enabled, while TX delay retains the ++ * value before reset. ++ */ ++ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || ++ phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ++ ret = at803x_enable_rx_delay(phydev); ++ else ++ ret = at803x_disable_rx_delay(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || ++ phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) ++ ret = at803x_enable_tx_delay(phydev); ++ else ++ ret = at803x_disable_tx_delay(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = at803x_smarteee_config(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = at803x_clk_out_config(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = at803x_hibernation_mode_config(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* Ar803x extended next page bit is enabled by default. Cisco ++ * multigig switches read this bit and attempt to negotiate 10Gbps ++ * rates even if the next page bit is disabled. This is incorrect ++ * behaviour but we still need to accommodate it. XNP is only needed ++ * for 10Gbps support, so disable XNP. ++ */ ++ return phy_modify(phydev, MII_ADVERTISE, MDIO_AN_CTRL1_XNP, 0); ++} ++ ++static int at803x_ack_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_read(phydev, AT803X_INTR_STATUS); ++ ++ return (err < 0) ? err : 0; ++} ++ ++static int at803x_config_intr(struct phy_device *phydev) ++{ ++ int err; ++ int value; ++ ++ value = phy_read(phydev, AT803X_INTR_ENABLE); ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { ++ /* Clear any pending interrupts */ ++ err = at803x_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ value |= AT803X_INTR_ENABLE_AUTONEG_ERR; ++ value |= AT803X_INTR_ENABLE_SPEED_CHANGED; ++ value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED; ++ value |= AT803X_INTR_ENABLE_LINK_FAIL; ++ value |= AT803X_INTR_ENABLE_LINK_SUCCESS; ++ ++ err = phy_write(phydev, AT803X_INTR_ENABLE, value); ++ } else { ++ err = phy_write(phydev, AT803X_INTR_ENABLE, 0); ++ if (err) ++ return err; ++ ++ /* Clear any pending interrupts */ ++ err = at803x_ack_interrupt(phydev); ++ } ++ ++ return err; ++} ++ ++static irqreturn_t at803x_handle_interrupt(struct phy_device *phydev) ++{ ++ int irq_status, int_enabled; ++ ++ irq_status = phy_read(phydev, AT803X_INTR_STATUS); ++ if (irq_status < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ /* Read the current enabled interrupts */ ++ int_enabled = phy_read(phydev, AT803X_INTR_ENABLE); ++ if (int_enabled < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ /* See if this was one of our enabled interrupts */ ++ if (!(irq_status & int_enabled)) ++ return IRQ_NONE; ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ ++static void at803x_link_change_notify(struct phy_device *phydev) ++{ ++ /* ++ * Conduct a hardware reset for AT8030 every time a link loss is ++ * signalled. This is necessary to circumvent a hardware bug that ++ * occurs when the cable is unplugged while TX packets are pending ++ * in the FIFO. In such cases, the FIFO enters an error mode it ++ * cannot recover from by software. ++ */ ++ if (phydev->state == PHY_NOLINK && phydev->mdio.reset_gpio) { ++ struct at803x_context context; ++ ++ at803x_context_save(phydev, &context); ++ ++ phy_device_reset(phydev, 1); ++ usleep_range(1000, 2000); ++ phy_device_reset(phydev, 0); ++ usleep_range(1000, 2000); ++ ++ at803x_context_restore(phydev, &context); ++ ++ phydev_dbg(phydev, "%s(): phy was reset\n", __func__); ++ } ++} ++ ++static int at803x_read_specific_status(struct phy_device *phydev, ++ struct at803x_ss_mask ss_mask) ++{ ++ int ss; ++ ++ /* Read the AT8035 PHY-Specific Status register, which indicates the ++ * speed and duplex that the PHY is actually using, irrespective of ++ * whether we are in autoneg mode or not. ++ */ ++ ss = phy_read(phydev, AT803X_SPECIFIC_STATUS); ++ if (ss < 0) ++ return ss; ++ ++ if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) { ++ int sfc, speed; ++ ++ sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL); ++ if (sfc < 0) ++ return sfc; ++ ++ speed = ss & ss_mask.speed_mask; ++ speed >>= ss_mask.speed_shift; ++ ++ switch (speed) { ++ case AT803X_SS_SPEED_10: ++ phydev->speed = SPEED_10; ++ break; ++ case AT803X_SS_SPEED_100: ++ phydev->speed = SPEED_100; ++ break; ++ case AT803X_SS_SPEED_1000: ++ phydev->speed = SPEED_1000; ++ break; ++ case QCA808X_SS_SPEED_2500: ++ phydev->speed = SPEED_2500; ++ break; ++ } ++ if (ss & AT803X_SS_DUPLEX) ++ phydev->duplex = DUPLEX_FULL; ++ else ++ phydev->duplex = DUPLEX_HALF; ++ ++ if (ss & AT803X_SS_MDIX) ++ phydev->mdix = ETH_TP_MDI_X; ++ else ++ phydev->mdix = ETH_TP_MDI; ++ ++ switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) { ++ case AT803X_SFC_MANUAL_MDI: ++ phydev->mdix_ctrl = ETH_TP_MDI; ++ break; ++ case AT803X_SFC_MANUAL_MDIX: ++ phydev->mdix_ctrl = ETH_TP_MDI_X; ++ break; ++ case AT803X_SFC_AUTOMATIC_CROSSOVER: ++ phydev->mdix_ctrl = ETH_TP_MDI_AUTO; ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++static int at803x_read_status(struct phy_device *phydev) ++{ ++ struct at803x_ss_mask ss_mask = { 0 }; ++ int err, old_link = phydev->link; ++ ++ /* Update the link, but return if there was an error */ ++ err = genphy_update_link(phydev); ++ if (err) ++ return err; ++ ++ /* why bother the PHY if nothing can have changed */ ++ if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) ++ return 0; ++ ++ phydev->speed = SPEED_UNKNOWN; ++ phydev->duplex = DUPLEX_UNKNOWN; ++ phydev->pause = 0; ++ phydev->asym_pause = 0; ++ ++ err = genphy_read_lpa(phydev); ++ if (err < 0) ++ return err; ++ ++ ss_mask.speed_mask = AT803X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK); ++ err = at803x_read_specific_status(phydev, ss_mask); ++ if (err < 0) ++ return err; ++ ++ if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) ++ phy_resolve_aneg_pause(phydev); ++ ++ return 0; ++} ++ ++static int at803x_config_mdix(struct phy_device *phydev, u8 ctrl) ++{ ++ u16 val; ++ ++ switch (ctrl) { ++ case ETH_TP_MDI: ++ val = AT803X_SFC_MANUAL_MDI; ++ break; ++ case ETH_TP_MDI_X: ++ val = AT803X_SFC_MANUAL_MDIX; ++ break; ++ case ETH_TP_MDI_AUTO: ++ val = AT803X_SFC_AUTOMATIC_CROSSOVER; ++ break; ++ default: ++ return 0; ++ } ++ ++ return phy_modify_changed(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL, ++ AT803X_SFC_MDI_CROSSOVER_MODE_M, ++ FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val)); ++} ++ ++static int at803x_prepare_config_aneg(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = at803x_config_mdix(phydev, phydev->mdix_ctrl); ++ if (ret < 0) ++ return ret; ++ ++ /* Changes of the midx bits are disruptive to the normal operation; ++ * therefore any changes to these registers must be followed by a ++ * software reset to take effect. ++ */ ++ if (ret == 1) { ++ ret = genphy_soft_reset(phydev); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int at803x_config_aneg(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int ret; ++ ++ ret = at803x_prepare_config_aneg(phydev); ++ if (ret) ++ return ret; ++ ++ if (priv->is_1000basex) ++ return genphy_c37_config_aneg(phydev); ++ ++ return genphy_config_aneg(phydev); ++} ++ ++static int at803x_get_downshift(struct phy_device *phydev, u8 *d) ++{ ++ int val; ++ ++ val = phy_read(phydev, AT803X_SMART_SPEED); ++ if (val < 0) ++ return val; ++ ++ if (val & AT803X_SMART_SPEED_ENABLE) ++ *d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2; ++ else ++ *d = DOWNSHIFT_DEV_DISABLE; ++ ++ return 0; ++} ++ ++static int at803x_set_downshift(struct phy_device *phydev, u8 cnt) ++{ ++ u16 mask, set; ++ int ret; ++ ++ switch (cnt) { ++ case DOWNSHIFT_DEV_DEFAULT_COUNT: ++ cnt = AT803X_DEFAULT_DOWNSHIFT; ++ fallthrough; ++ case AT803X_MIN_DOWNSHIFT ... AT803X_MAX_DOWNSHIFT: ++ set = AT803X_SMART_SPEED_ENABLE | ++ AT803X_SMART_SPEED_BYPASS_TIMER | ++ FIELD_PREP(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, cnt - 2); ++ mask = AT803X_SMART_SPEED_RETRY_LIMIT_MASK; ++ break; ++ case DOWNSHIFT_DEV_DISABLE: ++ set = 0; ++ mask = AT803X_SMART_SPEED_ENABLE | ++ AT803X_SMART_SPEED_BYPASS_TIMER; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set); ++ ++ /* After changing the smart speed settings, we need to perform a ++ * software reset, use phy_init_hw() to make sure we set the ++ * reapply any values which might got lost during software reset. ++ */ ++ if (ret == 1) ++ ret = phy_init_hw(phydev); ++ ++ return ret; ++} ++ ++static int at803x_get_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return at803x_get_downshift(phydev, data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int at803x_set_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, const void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return at803x_set_downshift(phydev, *(const u8 *)data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int at803x_cable_test_result_trans(u16 status) ++{ ++ switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) { ++ case AT803X_CDT_STATUS_STAT_NORMAL: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OK; ++ case AT803X_CDT_STATUS_STAT_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; ++ case AT803X_CDT_STATUS_STAT_OPEN: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; ++ case AT803X_CDT_STATUS_STAT_FAIL: ++ default: ++ return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; ++ } ++} ++ ++static bool at803x_cdt_test_failed(u16 status) ++{ ++ return FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status) == ++ AT803X_CDT_STATUS_STAT_FAIL; ++} ++ ++static bool at803x_cdt_fault_length_valid(u16 status) ++{ ++ switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) { ++ case AT803X_CDT_STATUS_STAT_OPEN: ++ case AT803X_CDT_STATUS_STAT_SHORT: ++ return true; ++ } ++ return false; ++} ++ ++static int at803x_cdt_fault_length(int dt) ++{ ++ /* According to the datasheet the distance to the fault is ++ * DELTA_TIME * 0.824 meters. ++ * ++ * The author suspect the correct formula is: ++ * ++ * fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2 ++ * ++ * where c is the speed of light, VF is the velocity factor of ++ * the twisted pair cable, 125MHz the counter frequency and ++ * we need to divide by 2 because the hardware will measure the ++ * round trip time to the fault and back to the PHY. ++ * ++ * With a VF of 0.69 we get the factor 0.824 mentioned in the ++ * datasheet. ++ */ ++ return (dt * 824) / 10; ++} ++ ++static int at803x_cdt_start(struct phy_device *phydev, ++ u32 cdt_start) ++{ ++ return phy_write(phydev, AT803X_CDT, cdt_start); ++} ++ ++static int at803x_cdt_wait_for_completion(struct phy_device *phydev, ++ u32 cdt_en) ++{ ++ int val, ret; ++ ++ /* One test run takes about 25ms */ ++ ret = phy_read_poll_timeout(phydev, AT803X_CDT, val, ++ !(val & cdt_en), ++ 30000, 100000, true); ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static int at803x_cable_test_one_pair(struct phy_device *phydev, int pair) ++{ ++ static const int ethtool_pair[] = { ++ ETHTOOL_A_CABLE_PAIR_A, ++ ETHTOOL_A_CABLE_PAIR_B, ++ ETHTOOL_A_CABLE_PAIR_C, ++ ETHTOOL_A_CABLE_PAIR_D, ++ }; ++ int ret, val; ++ ++ val = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) | ++ AT803X_CDT_ENABLE_TEST; ++ ret = at803x_cdt_start(phydev, val); ++ if (ret) ++ return ret; ++ ++ ret = at803x_cdt_wait_for_completion(phydev, AT803X_CDT_ENABLE_TEST); ++ if (ret) ++ return ret; ++ ++ val = phy_read(phydev, AT803X_CDT_STATUS); ++ if (val < 0) ++ return val; ++ ++ if (at803x_cdt_test_failed(val)) ++ return 0; ++ ++ ethnl_cable_test_result(phydev, ethtool_pair[pair], ++ at803x_cable_test_result_trans(val)); ++ ++ if (at803x_cdt_fault_length_valid(val)) { ++ val = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, val); ++ ethnl_cable_test_fault_length(phydev, ethtool_pair[pair], ++ at803x_cdt_fault_length(val)); ++ } ++ ++ return 1; ++} ++ ++static int at803x_cable_test_get_status(struct phy_device *phydev, ++ bool *finished, unsigned long pair_mask) ++{ ++ int retries = 20; ++ int pair, ret; ++ ++ *finished = false; ++ ++ /* According to the datasheet the CDT can be performed when ++ * there is no link partner or when the link partner is ++ * auto-negotiating. Starting the test will restart the AN ++ * automatically. It seems that doing this repeatedly we will ++ * get a slot where our link partner won't disturb our ++ * measurement. ++ */ ++ while (pair_mask && retries--) { ++ for_each_set_bit(pair, &pair_mask, 4) { ++ ret = at803x_cable_test_one_pair(phydev, pair); ++ if (ret < 0) ++ return ret; ++ if (ret) ++ clear_bit(pair, &pair_mask); ++ } ++ if (pair_mask) ++ msleep(250); ++ } ++ ++ *finished = true; ++ ++ return 0; ++} ++ ++static void at803x_cable_test_autoneg(struct phy_device *phydev) ++{ ++ /* Enable auto-negotiation, but advertise no capabilities, no link ++ * will be established. A restart of the auto-negotiation is not ++ * required, because the cable test will automatically break the link. ++ */ ++ phy_write(phydev, MII_BMCR, BMCR_ANENABLE); ++ phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA); ++} ++ ++static int at803x_cable_test_start(struct phy_device *phydev) ++{ ++ at803x_cable_test_autoneg(phydev); ++ /* we do all the (time consuming) work later */ ++ return 0; ++} ++ ++static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, ++ unsigned int selector) ++{ ++ struct phy_device *phydev = rdev_get_drvdata(rdev); ++ ++ if (selector) ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ 0, AT803X_DEBUG_RGMII_1V8); ++ else ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ AT803X_DEBUG_RGMII_1V8, 0); ++} ++ ++static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) ++{ ++ struct phy_device *phydev = rdev_get_drvdata(rdev); ++ int val; ++ ++ val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F); ++ if (val < 0) ++ return val; ++ ++ return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0; ++} ++ ++static const struct regulator_ops vddio_regulator_ops = { ++ .list_voltage = regulator_list_voltage_table, ++ .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, ++ .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, ++}; ++ ++static const unsigned int vddio_voltage_table[] = { ++ 1500000, ++ 1800000, ++}; ++ ++static const struct regulator_desc vddio_desc = { ++ .name = "vddio", ++ .of_match = of_match_ptr("vddio-regulator"), ++ .n_voltages = ARRAY_SIZE(vddio_voltage_table), ++ .volt_table = vddio_voltage_table, ++ .ops = &vddio_regulator_ops, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct regulator_ops vddh_regulator_ops = { ++}; ++ ++static const struct regulator_desc vddh_desc = { ++ .name = "vddh", ++ .of_match = of_match_ptr("vddh-regulator"), ++ .n_voltages = 1, ++ .fixed_uV = 2500000, ++ .ops = &vddh_regulator_ops, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++}; ++ ++static int at8031_register_regulators(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ struct device *dev = &phydev->mdio.dev; ++ struct regulator_config config = { }; ++ ++ config.dev = dev; ++ config.driver_data = phydev; ++ ++ priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config); ++ if (IS_ERR(priv->vddio_rdev)) { ++ phydev_err(phydev, "failed to register VDDIO regulator\n"); ++ return PTR_ERR(priv->vddio_rdev); ++ } ++ ++ priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config); ++ if (IS_ERR(priv->vddh_rdev)) { ++ phydev_err(phydev, "failed to register VDDH regulator\n"); ++ return PTR_ERR(priv->vddh_rdev); ++ } ++ ++ return 0; ++} ++ ++static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++{ ++ struct phy_device *phydev = upstream; ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); ++ DECLARE_PHY_INTERFACE_MASK(interfaces); ++ phy_interface_t iface; ++ ++ linkmode_zero(phy_support); ++ phylink_set(phy_support, 1000baseX_Full); ++ phylink_set(phy_support, 1000baseT_Full); ++ phylink_set(phy_support, Autoneg); ++ phylink_set(phy_support, Pause); ++ phylink_set(phy_support, Asym_Pause); ++ ++ linkmode_zero(sfp_support); ++ sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces); ++ /* Some modules support 10G modes as well as others we support. ++ * Mask out non-supported modes so the correct interface is picked. ++ */ ++ linkmode_and(sfp_support, phy_support, sfp_support); ++ ++ if (linkmode_empty(sfp_support)) { ++ dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); ++ return -EINVAL; ++ } ++ ++ iface = sfp_select_interface(phydev->sfp_bus, sfp_support); ++ ++ /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes ++ * interface for use with SFP modules. ++ * However, some copper modules detected as having a preferred SGMII ++ * interface do default to and function in 1000Base-X mode, so just ++ * print a warning and allow such modules, as they may have some chance ++ * of working. ++ */ ++ if (iface == PHY_INTERFACE_MODE_SGMII) ++ dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); ++ else if (iface != PHY_INTERFACE_MODE_1000BASEX) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static const struct sfp_upstream_ops at8031_sfp_ops = { ++ .attach = phy_sfp_attach, ++ .detach = phy_sfp_detach, ++ .module_insert = at8031_sfp_insert, ++}; ++ ++static int at8031_parse_dt(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ struct at803x_priv *priv = phydev->priv; ++ int ret; ++ ++ if (of_property_read_bool(node, "qca,keep-pll-enabled")) ++ priv->flags |= AT803X_KEEP_PLL_ENABLED; ++ ++ ret = at8031_register_regulators(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = devm_regulator_get_enable_optional(&phydev->mdio.dev, ++ "vddio"); ++ if (ret) { ++ phydev_err(phydev, "failed to get VDDIO regulator\n"); ++ return ret; ++ } ++ ++ /* Only AR8031/8033 support 1000Base-X for SFP modules */ ++ return phy_sfp_probe(phydev, &at8031_sfp_ops); ++} ++ ++static int at8031_probe(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int mode_cfg; ++ int ccr; ++ int ret; ++ ++ ret = at803x_probe(phydev); ++ if (ret) ++ return ret; ++ ++ /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping ++ * options. ++ */ ++ ret = at8031_parse_dt(phydev); ++ if (ret) ++ return ret; ++ ++ ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); ++ if (ccr < 0) ++ return ccr; ++ mode_cfg = ccr & AT803X_MODE_CFG_MASK; ++ ++ switch (mode_cfg) { ++ case AT803X_MODE_CFG_BX1000_RGMII_50OHM: ++ case AT803X_MODE_CFG_BX1000_RGMII_75OHM: ++ priv->is_1000basex = true; ++ fallthrough; ++ case AT803X_MODE_CFG_FX100_RGMII_50OHM: ++ case AT803X_MODE_CFG_FX100_RGMII_75OHM: ++ priv->is_fiber = true; ++ break; ++ } ++ ++ /* Disable WoL in 1588 register which is enabled ++ * by default ++ */ ++ return phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ AT803X_WOL_EN, 0); ++} ++ ++static int at8031_config_init(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int ret; ++ ++ /* Some bootloaders leave the fiber page selected. ++ * Switch to the appropriate page (fiber or copper), as otherwise we ++ * read the PHY capabilities from the wrong page. ++ */ ++ phy_lock_mdio_bus(phydev); ++ ret = at803x_write_page(phydev, ++ priv->is_fiber ? AT803X_PAGE_FIBER : ++ AT803X_PAGE_COPPER); ++ phy_unlock_mdio_bus(phydev); ++ if (ret) ++ return ret; ++ ++ ret = at8031_pll_config(phydev); ++ if (ret < 0) ++ return ret; ++ ++ return at803x_config_init(phydev); ++} ++ ++static int at8031_set_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int ret; ++ ++ /* First setup MAC address and enable WOL interrupt */ ++ ret = at803x_set_wol(phydev, wol); ++ if (ret) ++ return ret; ++ ++ if (wol->wolopts & WAKE_MAGIC) ++ /* Enable WOL function for 1588 */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ 0, AT803X_WOL_EN); ++ else ++ /* Disable WoL function for 1588 */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ AT803X_WOL_EN, 0); ++ ++ return ret; ++} ++ ++static int at8031_config_intr(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int err, value = 0; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED && ++ priv->is_fiber) { ++ /* Clear any pending interrupts */ ++ err = at803x_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ value |= AT803X_INTR_ENABLE_LINK_FAIL_BX; ++ value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX; ++ ++ err = phy_set_bits(phydev, AT803X_INTR_ENABLE, value); ++ if (err) ++ return err; ++ } ++ ++ return at803x_config_intr(phydev); ++} ++ ++/* AR8031 and AR8033 share the same read status logic */ ++static int at8031_read_status(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ if (priv->is_1000basex) ++ return genphy_c37_read_status(phydev); ++ ++ return at803x_read_status(phydev); ++} ++ ++/* AR8031 and AR8035 share the same cable test get status reg */ ++static int at8031_cable_test_get_status(struct phy_device *phydev, ++ bool *finished) ++{ ++ return at803x_cable_test_get_status(phydev, finished, 0xf); ++} ++ ++/* AR8031 and AR8035 share the same cable test start logic */ ++static int at8031_cable_test_start(struct phy_device *phydev) ++{ ++ at803x_cable_test_autoneg(phydev); ++ phy_write(phydev, MII_CTRL1000, 0); ++ /* we do all the (time consuming) work later */ ++ return 0; ++} ++ ++/* AR8032, AR9331 and QCA9561 share the same cable test get status reg */ ++static int at8032_cable_test_get_status(struct phy_device *phydev, ++ bool *finished) ++{ ++ return at803x_cable_test_get_status(phydev, finished, 0x3); ++} ++ ++static int at8035_parse_dt(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ /* Mask is set by the generic at803x_parse_dt ++ * if property is set. Assume property is set ++ * with the mask not zero. ++ */ ++ if (priv->clk_25m_mask) { ++ /* Fixup for the AR8030/AR8035. This chip has another mask and ++ * doesn't support the DSP reference. Eg. the lowest bit of the ++ * mask. The upper two bits select the same frequencies. Mask ++ * the lowest bit here. ++ * ++ * Warning: ++ * There was no datasheet for the AR8030 available so this is ++ * just a guess. But the AR8035 is listed as pin compatible ++ * to the AR8030 so there might be a good chance it works on ++ * the AR8030 too. ++ */ ++ priv->clk_25m_reg &= AT8035_CLK_OUT_MASK; ++ priv->clk_25m_mask &= AT8035_CLK_OUT_MASK; ++ } ++ ++ return 0; ++} ++ ++/* AR8030 and AR8035 shared the same special mask for clk_25m */ ++static int at8035_probe(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = at803x_probe(phydev); ++ if (ret) ++ return ret; ++ ++ return at8035_parse_dt(phydev); ++} ++ ++static int qca83xx_config_init(struct phy_device *phydev) ++{ ++ u8 switch_revision; ++ ++ switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK; ++ ++ switch (switch_revision) { ++ case 1: ++ /* For 100M waveform */ ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0x02ea); ++ /* Turn on Gigabit clock */ ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x68a0); ++ break; ++ ++ case 2: ++ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0); ++ fallthrough; ++ case 4: ++ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x6860); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0x2c46); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000); ++ break; ++ } ++ ++ /* Following original QCA sourcecode set port to prefer master */ ++ phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); ++ ++ return 0; ++} ++ ++static int qca8327_config_init(struct phy_device *phydev) ++{ ++ /* QCA8327 require DAC amplitude adjustment for 100m set to +6%. ++ * Disable on init and enable only with 100m speed following ++ * qca original source code. ++ */ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, 0); ++ ++ return qca83xx_config_init(phydev); ++} ++ ++static void qca83xx_link_change_notify(struct phy_device *phydev) ++{ ++ /* Set DAC Amplitude adjustment to +6% for 100m on link running */ ++ if (phydev->state == PHY_RUNNING) { ++ if (phydev->speed == SPEED_100) ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, ++ QCA8327_DEBUG_MANU_CTRL_EN); ++ } else { ++ /* Reset DAC Amplitude adjustment */ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, 0); ++ } ++} ++ ++static int qca83xx_resume(struct phy_device *phydev) ++{ ++ int ret, val; ++ ++ /* Skip reset if not suspended */ ++ if (!phydev->suspended) ++ return 0; ++ ++ /* Reinit the port, reset values set by suspend */ ++ qca83xx_config_init(phydev); ++ ++ /* Reset the port on port resume */ ++ phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); ++ ++ /* On resume from suspend the switch execute a reset and ++ * restart auto-negotiation. Wait for reset to complete. ++ */ ++ ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET), ++ 50000, 600000, true); ++ if (ret) ++ return ret; ++ ++ usleep_range(1000, 2000); ++ ++ return 0; ++} ++ ++static int qca83xx_suspend(struct phy_device *phydev) ++{ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN, ++ AT803X_DEBUG_GATE_CLK_IN1000, 0); ++ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, ++ AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE | ++ AT803X_DEBUG_HIB_CTRL_SEL_RST_80U, 0); ++ ++ return 0; ++} ++ ++static int qca8337_suspend(struct phy_device *phydev) ++{ ++ /* Only QCA8337 support actual suspend. */ ++ genphy_suspend(phydev); ++ ++ return qca83xx_suspend(phydev); ++} ++ ++static int qca8327_suspend(struct phy_device *phydev) ++{ ++ u16 mask = 0; ++ ++ /* QCA8327 cause port unreliability when phy suspend ++ * is set. ++ */ ++ mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); ++ phy_modify(phydev, MII_BMCR, mask, 0); ++ ++ return qca83xx_suspend(phydev); ++} ++ ++static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Enable fast retrain */ ++ ret = genphy_c45_fast_retrain(phydev, true); ++ if (ret) ++ return ret; ++ ++ phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1, ++ QCA808X_TOP_OPTION1_DATA); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB, ++ QCA808X_MSE_THRESHOLD_20DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB, ++ QCA808X_MSE_THRESHOLD_17DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB, ++ QCA808X_MSE_THRESHOLD_27DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB, ++ QCA808X_MSE_THRESHOLD_28DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1, ++ QCA808X_MMD3_DEBUG_1_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4, ++ QCA808X_MMD3_DEBUG_4_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5, ++ QCA808X_MMD3_DEBUG_5_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3, ++ QCA808X_MMD3_DEBUG_3_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6, ++ QCA808X_MMD3_DEBUG_6_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2, ++ QCA808X_MMD3_DEBUG_2_VALUE); ++ ++ return 0; ++} ++ ++static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) ++{ ++ u16 seed_value; ++ ++ if (!enable) ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, ++ QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); ++ ++ seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, ++ QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, ++ FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | ++ QCA808X_MASTER_SLAVE_SEED_ENABLE); ++} ++ ++static bool qca808x_is_prefer_master(struct phy_device *phydev) ++{ ++ return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || ++ (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); ++} ++ ++static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) ++{ ++ return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++} ++ ++static int qca808x_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Active adc&vga on 802.3az for the link 1000M and 100M */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, ++ QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); ++ if (ret) ++ return ret; ++ ++ /* Adjust the threshold on 802.3az for the link 1000M */ ++ ret = phy_write_mmd(phydev, MDIO_MMD_PCS, ++ QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, ++ QCA808X_MMD3_AZ_TRAINING_VAL); ++ if (ret) ++ return ret; ++ ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ /* Config the fast retrain for the link 2500M */ ++ ret = qca808x_phy_fast_retrain_config(phydev); ++ if (ret) ++ return ret; ++ ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (!qca808x_is_prefer_master(phydev)) { ++ /* Enable seed and configure lower ramdom seed to make phy ++ * linked as slave mode. ++ */ ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ /* Configure adc threshold as 100mv for the link 10M */ ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, ++ QCA808X_ADC_THRESHOLD_MASK, ++ QCA808X_ADC_THRESHOLD_100MV); ++} ++ ++static int qca808x_read_status(struct phy_device *phydev) ++{ ++ struct at803x_ss_mask ss_mask = { 0 }; ++ int ret; ++ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); ++ if (ret < 0) ++ return ret; ++ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising, ++ ret & MDIO_AN_10GBT_STAT_LP2_5G); ++ ++ ret = genphy_read_status(phydev); ++ if (ret) ++ return ret; ++ ++ /* qca8081 takes the different bits for speed value from at803x */ ++ ss_mask.speed_mask = QCA808X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(QCA808X_SS_SPEED_MASK); ++ ret = at803x_read_specific_status(phydev, ss_mask); ++ if (ret < 0) ++ return ret; ++ ++ if (phydev->link) { ++ if (phydev->speed == SPEED_2500) ++ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; ++ else ++ phydev->interface = PHY_INTERFACE_MODE_SGMII; ++ } else { ++ /* generate seed as a lower random value to make PHY linked as SLAVE easily, ++ * except for master/slave configuration fault detected or the master mode ++ * preferred. ++ * ++ * the reason for not putting this code into the function link_change_notify is ++ * the corner case where the link partner is also the qca8081 PHY and the seed ++ * value is configured as the same value, the link can't be up and no link change ++ * occurs. ++ */ ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || ++ qca808x_is_prefer_master(phydev)) { ++ qca808x_phy_ms_seed_enable(phydev, false); ++ } else { ++ qca808x_phy_ms_seed_enable(phydev, true); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static int qca808x_soft_reset(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = genphy_soft_reset(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ ++ return ret; ++} ++ ++static bool qca808x_cdt_fault_length_valid(int cdt_code) ++{ ++ switch (cdt_code) { ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static int qca808x_cable_test_result_trans(int cdt_code) ++{ ++ switch (cdt_code) { ++ case QCA808X_CDT_STATUS_STAT_NORMAL: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OK; ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; ++ case QCA808X_CDT_STATUS_STAT_FAIL: ++ default: ++ return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; ++ } ++} ++ ++static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, ++ int result) ++{ ++ int val; ++ u32 cdt_length_reg = 0; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg); ++ if (val < 0) ++ return val; ++ ++ if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); ++ else ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); ++ ++ return at803x_cdt_fault_length(val); ++} ++ ++static int qca808x_cable_test_start(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* perform CDT with the following configs: ++ * 1. disable hibernation. ++ * 2. force PHY working in MDI mode. ++ * 3. for PHY working in 1000BaseT. ++ * 4. configure the threshold. ++ */ ++ ++ ret = at803x_debug_reg_mask(phydev, QCA808X_DBG_AN_TEST, QCA808X_HIBERNATION_EN, 0); ++ if (ret < 0) ++ return ret; ++ ++ ret = at803x_config_mdix(phydev, ETH_TP_MDI); ++ if (ret < 0) ++ return ret; ++ ++ /* Force 1000base-T needs to configure PMA/PMD and MII_BMCR */ ++ phydev->duplex = DUPLEX_FULL; ++ phydev->speed = SPEED_1000; ++ ret = genphy_c45_pma_setup_forced(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = genphy_setup_forced(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* configure the thresholds for open, short, pair ok test */ ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8074, 0xc040); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8076, 0xc040); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8077, 0xa060); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8078, 0xc050); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807a, 0xc060); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807e, 0xb060); ++ ++ return 0; ++} ++ ++static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, ++ u16 status) ++{ ++ int length, result; ++ u16 pair_code; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ result = qca808x_cable_test_result_trans(pair_code); ++ ethnl_cable_test_result(phydev, pair, result); ++ ++ if (qca808x_cdt_fault_length_valid(pair_code)) { ++ length = qca808x_cdt_fault_length(phydev, pair, result); ++ ethnl_cable_test_fault_length(phydev, pair, length); ++ } ++ ++ return 0; ++} ++ ++static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) ++{ ++ int ret, val; ++ ++ *finished = false; ++ ++ val = QCA808X_CDT_ENABLE_TEST | ++ QCA808X_CDT_LENGTH_UNIT; ++ ret = at803x_cdt_start(phydev, val); ++ if (ret) ++ return ret; ++ ++ ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); ++ if (ret) ++ return ret; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS); ++ if (val < 0) ++ return val; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); ++ if (ret) ++ return ret; ++ ++ *finished = true; ++ ++ return 0; ++} ++ ++static int qca808x_get_features(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = genphy_c45_pma_read_abilities(phydev); ++ if (ret) ++ return ret; ++ ++ /* The autoneg ability is not existed in bit3 of MMD7.1, ++ * but it is supported by qca808x PHY, so we add it here ++ * manually. ++ */ ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); ++ ++ /* As for the qca8081 1G version chip, the 2500baseT ability is also ++ * existed in the bit0 of MMD1.21, we need to remove it manually if ++ * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. ++ */ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); ++ if (ret < 0) ++ return ret; ++ ++ if (QCA808X_PHY_CHIP_TYPE_1G & ret) ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++ ++ return 0; ++} ++ ++static int qca808x_config_aneg(struct phy_device *phydev) ++{ ++ int phy_ctrl = 0; ++ int ret; ++ ++ ret = at803x_prepare_config_aneg(phydev); ++ if (ret) ++ return ret; ++ ++ /* The reg MII_BMCR also needs to be configured for force mode, the ++ * genphy_config_aneg is also needed. ++ */ ++ if (phydev->autoneg == AUTONEG_DISABLE) ++ genphy_c45_pma_setup_forced(phydev); ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) ++ phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; ++ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, ++ MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); ++ if (ret < 0) ++ return ret; ++ ++ return __genphy_config_aneg(phydev, ret); ++} ++ ++static void qca808x_link_change_notify(struct phy_device *phydev) ++{ ++ /* Assert interface sgmii fifo on link down, deassert it on link up, ++ * the interface device address is always phy address added by 1. ++ */ ++ mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, ++ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, ++ QCA8081_PHY_FIFO_RSTN, ++ phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); ++} ++ ++static int qca808x_led_parse_netdev(struct phy_device *phydev, unsigned long rules, ++ u16 *offload_trigger) ++{ ++ /* Parsing specific to netdev trigger */ ++ if (test_bit(TRIGGER_NETDEV_TX, &rules)) ++ *offload_trigger |= QCA808X_LED_TX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_RX, &rules)) ++ *offload_trigger |= QCA808X_LED_RX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED10_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED100_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED1000_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_2500, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED2500_ON; ++ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_HALF_DUPLEX_ON; ++ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_FULL_DUPLEX_ON; ++ ++ if (rules && !*offload_trigger) ++ return -EOPNOTSUPP; ++ ++ /* Enable BLINK_CHECK_BYPASS by default to make the LED ++ * blink even with duplex or speed mode not enabled. ++ */ ++ *offload_trigger |= QCA808X_LED_BLINK_CHECK_BYPASS; ++ ++ return 0; ++} ++ ++static int qca808x_led_hw_control_enable(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN); ++} ++ ++static int qca808x_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 offload_trigger = 0; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ return qca808x_led_parse_netdev(phydev, rules, &offload_trigger); ++} ++ ++static int qca808x_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 reg, offload_trigger = 0; ++ int ret; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ ret = qca808x_led_parse_netdev(phydev, rules, &offload_trigger); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_led_hw_control_enable(phydev, index); ++ if (ret) ++ return ret; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_PATTERN_MASK, ++ offload_trigger); ++} ++ ++static bool qca808x_led_hw_control_status(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ int val; ++ ++ if (index > 2) ++ return false; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ ++ return !(val & QCA808X_LED_FORCE_EN); ++} ++ ++static int qca808x_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ u16 reg; ++ int val; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ /* Check if we have hw control enabled */ ++ if (qca808x_led_hw_control_status(phydev, index)) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ if (val & QCA808X_LED_TX_BLINK) ++ set_bit(TRIGGER_NETDEV_TX, rules); ++ if (val & QCA808X_LED_RX_BLINK) ++ set_bit(TRIGGER_NETDEV_RX, rules); ++ if (val & QCA808X_LED_SPEED10_ON) ++ set_bit(TRIGGER_NETDEV_LINK_10, rules); ++ if (val & QCA808X_LED_SPEED100_ON) ++ set_bit(TRIGGER_NETDEV_LINK_100, rules); ++ if (val & QCA808X_LED_SPEED1000_ON) ++ set_bit(TRIGGER_NETDEV_LINK_1000, rules); ++ if (val & QCA808X_LED_SPEED2500_ON) ++ set_bit(TRIGGER_NETDEV_LINK_2500, rules); ++ if (val & QCA808X_LED_HALF_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); ++ if (val & QCA808X_LED_FULL_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); ++ ++ return 0; ++} ++ ++static int qca808x_led_hw_control_reset(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_PATTERN_MASK); ++} ++ ++static int qca808x_led_brightness_set(struct phy_device *phydev, ++ u8 index, enum led_brightness value) ++{ ++ u16 reg; ++ int ret; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ if (!value) { ++ ret = qca808x_led_hw_control_reset(phydev, index); ++ if (ret) ++ return ret; ++ } ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | value ? QCA808X_LED_FORCE_ON : ++ QCA808X_LED_FORCE_OFF); ++} ++ ++static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ int ret; ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ /* Set blink to 50% off, 50% on at 4Hz by default */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL, ++ QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK, ++ QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50); ++ if (ret) ++ return ret; ++ ++ /* We use BLINK_1 for normal blinking */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1); ++ if (ret) ++ return ret; ++ ++ /* We set blink to 4Hz, aka 250ms */ ++ *delay_on = 250 / 2; ++ *delay_off = 250 / 2; ++ ++ return 0; ++} ++ ++static int qca808x_led_polarity_set(struct phy_device *phydev, int index, ++ unsigned long modes) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ bool active_low = false; ++ u32 mode; ++ ++ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { ++ switch (mode) { ++ case PHY_LED_ACTIVE_LOW: ++ active_low = true; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ /* PHY polarity is global and can't be set per LED. ++ * To detect this, check if last requested polarity mode ++ * match the new one. ++ */ ++ if (priv->led_polarity_mode >= 0 && ++ priv->led_polarity_mode != active_low) { ++ phydev_err(phydev, "PHY polarity is global. Mismatched polarity on different LED\n"); ++ return -EINVAL; ++ } ++ ++ /* Save the last PHY polarity mode */ ++ priv->led_polarity_mode = active_low; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, ++ QCA808X_MMD7_LED_POLARITY_CTRL, ++ QCA808X_LED_ACTIVE_HIGH, ++ active_low ? 0 : QCA808X_LED_ACTIVE_HIGH); ++} ++ ++static struct phy_driver at803x_driver[] = { ++{ ++ /* Qualcomm Atheros AR8035 */ ++ PHY_ID_MATCH_EXACT(ATH8035_PHY_ID), ++ .name = "Qualcomm Atheros AR8035", ++ .flags = PHY_POLL_CABLE_TEST, ++ .probe = at8035_probe, ++ .config_aneg = at803x_config_aneg, ++ .config_init = at803x_config_init, ++ .soft_reset = genphy_soft_reset, ++ .set_wol = at803x_set_wol, ++ .get_wol = at803x_get_wol, ++ .suspend = at803x_suspend, ++ .resume = at803x_resume, ++ /* PHY_GBIT_FEATURES */ ++ .read_status = at803x_read_status, ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .get_tunable = at803x_get_tunable, ++ .set_tunable = at803x_set_tunable, ++ .cable_test_start = at8031_cable_test_start, ++ .cable_test_get_status = at8031_cable_test_get_status, ++}, { ++ /* Qualcomm Atheros AR8030 */ ++ .phy_id = ATH8030_PHY_ID, ++ .name = "Qualcomm Atheros AR8030", ++ .phy_id_mask = AT8030_PHY_ID_MASK, ++ .probe = at8035_probe, ++ .config_init = at803x_config_init, ++ .link_change_notify = at803x_link_change_notify, ++ .set_wol = at803x_set_wol, ++ .get_wol = at803x_get_wol, ++ .suspend = at803x_suspend, ++ .resume = at803x_resume, ++ /* PHY_BASIC_FEATURES */ ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++}, { ++ /* Qualcomm Atheros AR8031/AR8033 */ ++ PHY_ID_MATCH_EXACT(ATH8031_PHY_ID), ++ .name = "Qualcomm Atheros AR8031/AR8033", ++ .flags = PHY_POLL_CABLE_TEST, ++ .probe = at8031_probe, ++ .config_init = at8031_config_init, ++ .config_aneg = at803x_config_aneg, ++ .soft_reset = genphy_soft_reset, ++ .set_wol = at8031_set_wol, ++ .get_wol = at803x_get_wol, ++ .suspend = at803x_suspend, ++ .resume = at803x_resume, ++ .read_page = at803x_read_page, ++ .write_page = at803x_write_page, ++ .get_features = at803x_get_features, ++ .read_status = at8031_read_status, ++ .config_intr = at8031_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .get_tunable = at803x_get_tunable, ++ .set_tunable = at803x_set_tunable, ++ .cable_test_start = at8031_cable_test_start, ++ .cable_test_get_status = at8031_cable_test_get_status, ++}, { ++ /* Qualcomm Atheros AR8032 */ ++ PHY_ID_MATCH_EXACT(ATH8032_PHY_ID), ++ .name = "Qualcomm Atheros AR8032", ++ .probe = at803x_probe, ++ .flags = PHY_POLL_CABLE_TEST, ++ .config_init = at803x_config_init, ++ .link_change_notify = at803x_link_change_notify, ++ .suspend = at803x_suspend, ++ .resume = at803x_resume, ++ /* PHY_BASIC_FEATURES */ ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .cable_test_start = at803x_cable_test_start, ++ .cable_test_get_status = at8032_cable_test_get_status, ++}, { ++ /* ATHEROS AR9331 */ ++ PHY_ID_MATCH_EXACT(ATH9331_PHY_ID), ++ .name = "Qualcomm Atheros AR9331 built-in PHY", ++ .probe = at803x_probe, ++ .suspend = at803x_suspend, ++ .resume = at803x_resume, ++ .flags = PHY_POLL_CABLE_TEST, ++ /* PHY_BASIC_FEATURES */ ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .cable_test_start = at803x_cable_test_start, ++ .cable_test_get_status = at8032_cable_test_get_status, ++ .read_status = at803x_read_status, ++ .soft_reset = genphy_soft_reset, ++ .config_aneg = at803x_config_aneg, ++}, { ++ /* Qualcomm Atheros QCA9561 */ ++ PHY_ID_MATCH_EXACT(QCA9561_PHY_ID), ++ .name = "Qualcomm Atheros QCA9561 built-in PHY", ++ .probe = at803x_probe, ++ .suspend = at803x_suspend, ++ .resume = at803x_resume, ++ .flags = PHY_POLL_CABLE_TEST, ++ /* PHY_BASIC_FEATURES */ ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .cable_test_start = at803x_cable_test_start, ++ .cable_test_get_status = at8032_cable_test_get_status, ++ .read_status = at803x_read_status, ++ .soft_reset = genphy_soft_reset, ++ .config_aneg = at803x_config_aneg, ++}, { ++ /* QCA8337 */ ++ .phy_id = QCA8337_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8337 internal PHY", ++ /* PHY_GBIT_FEATURES */ ++ .probe = at803x_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca83xx_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, ++ .suspend = qca8337_suspend, ++ .resume = qca83xx_resume, ++}, { ++ /* QCA8327-A from switch QCA8327-AL1A */ ++ .phy_id = QCA8327_A_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8327-A internal PHY", ++ /* PHY_GBIT_FEATURES */ ++ .link_change_notify = qca83xx_link_change_notify, ++ .probe = at803x_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca8327_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, ++ .suspend = qca8327_suspend, ++ .resume = qca83xx_resume, ++}, { ++ /* QCA8327-B from switch QCA8327-BL1A */ ++ .phy_id = QCA8327_B_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8327-B internal PHY", ++ /* PHY_GBIT_FEATURES */ ++ .link_change_notify = qca83xx_link_change_notify, ++ .probe = at803x_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca8327_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, ++ .suspend = qca8327_suspend, ++ .resume = qca83xx_resume, ++}, { ++ /* Qualcomm QCA8081 */ ++ PHY_ID_MATCH_EXACT(QCA8081_PHY_ID), ++ .name = "Qualcomm QCA8081", ++ .flags = PHY_POLL_CABLE_TEST, ++ .probe = at803x_probe, ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .get_tunable = at803x_get_tunable, ++ .set_tunable = at803x_set_tunable, ++ .set_wol = at803x_set_wol, ++ .get_wol = at803x_get_wol, ++ .get_features = qca808x_get_features, ++ .config_aneg = qca808x_config_aneg, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .read_status = qca808x_read_status, ++ .config_init = qca808x_config_init, ++ .soft_reset = qca808x_soft_reset, ++ .cable_test_start = qca808x_cable_test_start, ++ .cable_test_get_status = qca808x_cable_test_get_status, ++ .link_change_notify = qca808x_link_change_notify, ++ .led_brightness_set = qca808x_led_brightness_set, ++ .led_blink_set = qca808x_led_blink_set, ++ .led_hw_is_supported = qca808x_led_hw_is_supported, ++ .led_hw_control_set = qca808x_led_hw_control_set, ++ .led_hw_control_get = qca808x_led_hw_control_get, ++ .led_polarity_set = qca808x_led_polarity_set, ++}, }; ++ ++module_phy_driver(at803x_driver); ++ ++static struct mdio_device_id __maybe_unused atheros_tbl[] = { ++ { ATH8030_PHY_ID, AT8030_PHY_ID_MASK }, ++ { PHY_ID_MATCH_EXACT(ATH8031_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, atheros_tbl); diff --git a/lede/target/linux/generic/backport-6.1/713-v6.9-02-net-phy-qcom-create-and-move-functions-to-shared-lib.patch b/lede/target/linux/generic/backport-6.1/713-v6.9-02-net-phy-qcom-create-and-move-functions-to-shared-lib.patch new file mode 100644 index 0000000000..7d0e1f4a28 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/713-v6.9-02-net-phy-qcom-create-and-move-functions-to-shared-lib.patch @@ -0,0 +1,243 @@ +From 6fb760972c49490b03f3db2ad64cf30bdd28c54a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 Jan 2024 15:15:20 +0100 +Subject: [PATCH 2/5] net: phy: qcom: create and move functions to shared + library + +Create and move functions to shared library in preparation for qca83xx +PHY Family to be detached from at803x driver. + +Only the shared defines are moved to the shared qcom.h header. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240129141600.2592-3-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/qcom/Kconfig | 4 ++ + drivers/net/phy/qcom/Makefile | 1 + + drivers/net/phy/qcom/at803x.c | 69 +---------------------------- + drivers/net/phy/qcom/qcom-phy-lib.c | 53 ++++++++++++++++++++++ + drivers/net/phy/qcom/qcom.h | 34 ++++++++++++++ + 5 files changed, 94 insertions(+), 67 deletions(-) + create mode 100644 drivers/net/phy/qcom/qcom-phy-lib.c + create mode 100644 drivers/net/phy/qcom/qcom.h + +--- a/drivers/net/phy/qcom/Kconfig ++++ b/drivers/net/phy/qcom/Kconfig +@@ -1,6 +1,10 @@ + # SPDX-License-Identifier: GPL-2.0-only ++config QCOM_NET_PHYLIB ++ tristate ++ + config AT803X_PHY + tristate "Qualcomm Atheros AR803X PHYs and QCA833x PHYs" ++ select QCOM_NET_PHYLIB + depends on REGULATOR + help + Currently supports the AR8030, AR8031, AR8033, AR8035 and internal +--- a/drivers/net/phy/qcom/Makefile ++++ b/drivers/net/phy/qcom/Makefile +@@ -1,2 +1,3 @@ + # SPDX-License-Identifier: GPL-2.0 ++obj-$(CONFIG_QCOM_NET_PHYLIB) += qcom-phy-lib.o + obj-$(CONFIG_AT803X_PHY) += at803x.o +--- a/drivers/net/phy/qcom/at803x.c ++++ b/drivers/net/phy/qcom/at803x.c +@@ -22,6 +22,8 @@ + #include + #include + ++#include "qcom.h" ++ + #define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10 + #define AT803X_SFC_ASSERT_CRS BIT(11) + #define AT803X_SFC_FORCE_LINK BIT(10) +@@ -84,9 +86,6 @@ + #define AT803X_REG_CHIP_CONFIG 0x1f + #define AT803X_BT_BX_REG_SEL 0x8000 + +-#define AT803X_DEBUG_ADDR 0x1D +-#define AT803X_DEBUG_DATA 0x1E +- + #define AT803X_MODE_CFG_MASK 0x0F + #define AT803X_MODE_CFG_BASET_RGMII 0x00 + #define AT803X_MODE_CFG_BASET_SGMII 0x01 +@@ -103,19 +102,6 @@ + #define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/ + #define AT803X_PSSR_MR_AN_COMPLETE 0x0200 + +-#define AT803X_DEBUG_ANALOG_TEST_CTRL 0x00 +-#define QCA8327_DEBUG_MANU_CTRL_EN BIT(2) +-#define QCA8337_DEBUG_MANU_CTRL_EN GENMASK(3, 2) +-#define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15) +- +-#define AT803X_DEBUG_SYSTEM_CTRL_MODE 0x05 +-#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) +- +-#define AT803X_DEBUG_REG_HIB_CTRL 0x0b +-#define AT803X_DEBUG_HIB_CTRL_SEL_RST_80U BIT(10) +-#define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13) +-#define AT803X_DEBUG_HIB_CTRL_PS_HIB_EN BIT(15) +- + #define AT803X_DEBUG_REG_3C 0x3C + + #define AT803X_DEBUG_REG_GREEN 0x3D +@@ -393,18 +379,6 @@ MODULE_DESCRIPTION("Qualcomm Atheros AR8 + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); + +-enum stat_access_type { +- PHY, +- MMD +-}; +- +-struct at803x_hw_stat { +- const char *string; +- u8 reg; +- u32 mask; +- enum stat_access_type access_type; +-}; +- + static struct at803x_hw_stat qca83xx_hw_stats[] = { + { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, + { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, +@@ -439,45 +413,6 @@ struct at803x_context { + u16 led_control; + }; + +-static int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data) +-{ +- int ret; +- +- ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); +- if (ret < 0) +- return ret; +- +- return phy_write(phydev, AT803X_DEBUG_DATA, data); +-} +- +-static int at803x_debug_reg_read(struct phy_device *phydev, u16 reg) +-{ +- int ret; +- +- ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); +- if (ret < 0) +- return ret; +- +- return phy_read(phydev, AT803X_DEBUG_DATA); +-} +- +-static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, +- u16 clear, u16 set) +-{ +- u16 val; +- int ret; +- +- ret = at803x_debug_reg_read(phydev, reg); +- if (ret < 0) +- return ret; +- +- val = ret & 0xffff; +- val &= ~clear; +- val |= set; +- +- return phy_write(phydev, AT803X_DEBUG_DATA, val); +-} +- + static int at803x_write_page(struct phy_device *phydev, int page) + { + int mask; +--- /dev/null ++++ b/drivers/net/phy/qcom/qcom-phy-lib.c +@@ -0,0 +1,53 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++ ++#include "qcom.h" ++ ++MODULE_DESCRIPTION("Qualcomm PHY driver Common Functions"); ++MODULE_AUTHOR("Matus Ujhelyi"); ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_LICENSE("GPL"); ++ ++int at803x_debug_reg_read(struct phy_device *phydev, u16 reg) ++{ ++ int ret; ++ ++ ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); ++ if (ret < 0) ++ return ret; ++ ++ return phy_read(phydev, AT803X_DEBUG_DATA); ++} ++EXPORT_SYMBOL_GPL(at803x_debug_reg_read); ++ ++int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, ++ u16 clear, u16 set) ++{ ++ u16 val; ++ int ret; ++ ++ ret = at803x_debug_reg_read(phydev, reg); ++ if (ret < 0) ++ return ret; ++ ++ val = ret & 0xffff; ++ val &= ~clear; ++ val |= set; ++ ++ return phy_write(phydev, AT803X_DEBUG_DATA, val); ++} ++EXPORT_SYMBOL_GPL(at803x_debug_reg_mask); ++ ++int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data) ++{ ++ int ret; ++ ++ ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg); ++ if (ret < 0) ++ return ret; ++ ++ return phy_write(phydev, AT803X_DEBUG_DATA, data); ++} ++EXPORT_SYMBOL_GPL(at803x_debug_reg_write); +--- /dev/null ++++ b/drivers/net/phy/qcom/qcom.h +@@ -0,0 +1,34 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#define AT803X_DEBUG_ADDR 0x1D ++#define AT803X_DEBUG_DATA 0x1E ++ ++#define AT803X_DEBUG_ANALOG_TEST_CTRL 0x00 ++#define QCA8327_DEBUG_MANU_CTRL_EN BIT(2) ++#define QCA8337_DEBUG_MANU_CTRL_EN GENMASK(3, 2) ++#define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15) ++ ++#define AT803X_DEBUG_SYSTEM_CTRL_MODE 0x05 ++#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) ++ ++#define AT803X_DEBUG_REG_HIB_CTRL 0x0b ++#define AT803X_DEBUG_HIB_CTRL_SEL_RST_80U BIT(10) ++#define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13) ++#define AT803X_DEBUG_HIB_CTRL_PS_HIB_EN BIT(15) ++ ++enum stat_access_type { ++ PHY, ++ MMD ++}; ++ ++struct at803x_hw_stat { ++ const char *string; ++ u8 reg; ++ u32 mask; ++ enum stat_access_type access_type; ++}; ++ ++int at803x_debug_reg_read(struct phy_device *phydev, u16 reg); ++int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, ++ u16 clear, u16 set); ++int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data); diff --git a/lede/target/linux/generic/backport-6.1/713-v6.9-03-net-phy-qcom-deatch-qca83xx-PHY-driver-from-at803x.patch b/lede/target/linux/generic/backport-6.1/713-v6.9-03-net-phy-qcom-deatch-qca83xx-PHY-driver-from-at803x.patch new file mode 100644 index 0000000000..6ac09dcb9a --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/713-v6.9-03-net-phy-qcom-deatch-qca83xx-PHY-driver-from-at803x.patch @@ -0,0 +1,638 @@ +From 2e45d404d99d43bb7127b74b5dea8818df64996c Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 Jan 2024 15:15:21 +0100 +Subject: [PATCH 3/5] net: phy: qcom: deatch qca83xx PHY driver from at803x + +Deatch qca83xx PHY driver from at803x. + +The QCA83xx PHYs implement specific function and doesn't use generic +at803x so it can be detached from the driver and moved to a dedicated +one. + +Probe function and priv struct is reimplemented to allocate and use +only the qca83xx specific data. Unused data from at803x PHY driver +are dropped from at803x priv struct. + +This is to make slimmer PHY drivers instead of including lots of bloat +that would never be used in specific SoC. + +A new Kconfig flag QCA83XX_PHY is introduced to compile the new +introduced PHY driver. + +As the Kconfig name starts with Qualcomm the same order is kept. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240129141600.2592-4-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/qcom/Kconfig | 11 +- + drivers/net/phy/qcom/Makefile | 1 + + drivers/net/phy/qcom/at803x.c | 235 ---------------------------- + drivers/net/phy/qcom/qca83xx.c | 275 +++++++++++++++++++++++++++++++++ + 4 files changed, 284 insertions(+), 238 deletions(-) + create mode 100644 drivers/net/phy/qcom/qca83xx.c + +--- a/drivers/net/phy/qcom/Kconfig ++++ b/drivers/net/phy/qcom/Kconfig +@@ -3,9 +3,14 @@ config QCOM_NET_PHYLIB + tristate + + config AT803X_PHY +- tristate "Qualcomm Atheros AR803X PHYs and QCA833x PHYs" ++ tristate "Qualcomm Atheros AR803X PHYs" + select QCOM_NET_PHYLIB + depends on REGULATOR + help +- Currently supports the AR8030, AR8031, AR8033, AR8035 and internal +- QCA8337(Internal qca8k PHY) model ++ Currently supports the AR8030, AR8031, AR8033, AR8035 model ++ ++config QCA83XX_PHY ++ tristate "Qualcomm Atheros QCA833x PHYs" ++ select QCOM_NET_PHYLIB ++ help ++ Currently supports the internal QCA8337(Internal qca8k PHY) model +--- a/drivers/net/phy/qcom/Makefile ++++ b/drivers/net/phy/qcom/Makefile +@@ -1,3 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 + obj-$(CONFIG_QCOM_NET_PHYLIB) += qcom-phy-lib.o + obj-$(CONFIG_AT803X_PHY) += at803x.o ++obj-$(CONFIG_QCA83XX_PHY) += qca83xx.o +--- a/drivers/net/phy/qcom/at803x.c ++++ b/drivers/net/phy/qcom/at803x.c +@@ -102,17 +102,10 @@ + #define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/ + #define AT803X_PSSR_MR_AN_COMPLETE 0x0200 + +-#define AT803X_DEBUG_REG_3C 0x3C +- +-#define AT803X_DEBUG_REG_GREEN 0x3D +-#define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6) +- + #define AT803X_DEBUG_REG_1F 0x1F + #define AT803X_DEBUG_PLL_ON BIT(2) + #define AT803X_DEBUG_RGMII_1V8 BIT(3) + +-#define MDIO_AZ_DEBUG 0x800D +- + /* AT803x supports either the XTAL input pad, an internal PLL or the + * DSP as clock reference for the clock output pad. The XTAL reference + * is only used for 25 MHz output, all other frequencies need the PLL. +@@ -163,13 +156,7 @@ + + #define QCA8081_PHY_ID 0x004dd101 + +-#define QCA8327_A_PHY_ID 0x004dd033 +-#define QCA8327_B_PHY_ID 0x004dd034 +-#define QCA8337_PHY_ID 0x004dd036 + #define QCA9561_PHY_ID 0x004dd042 +-#define QCA8K_PHY_ID_MASK 0xffffffff +- +-#define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0) + + #define AT803X_PAGE_FIBER 0 + #define AT803X_PAGE_COPPER 1 +@@ -379,12 +366,6 @@ MODULE_DESCRIPTION("Qualcomm Atheros AR8 + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); + +-static struct at803x_hw_stat qca83xx_hw_stats[] = { +- { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, +- { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, +- { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, +-}; +- + struct at803x_ss_mask { + u16 speed_mask; + u8 speed_shift; +@@ -400,7 +381,6 @@ struct at803x_priv { + bool is_1000basex; + struct regulator_dev *vddio_rdev; + struct regulator_dev *vddh_rdev; +- u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; + int led_polarity_mode; + }; + +@@ -564,53 +544,6 @@ static void at803x_get_wol(struct phy_de + wol->wolopts |= WAKE_MAGIC; + } + +-static int qca83xx_get_sset_count(struct phy_device *phydev) +-{ +- return ARRAY_SIZE(qca83xx_hw_stats); +-} +- +-static void qca83xx_get_strings(struct phy_device *phydev, u8 *data) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) { +- strscpy(data + i * ETH_GSTRING_LEN, +- qca83xx_hw_stats[i].string, ETH_GSTRING_LEN); +- } +-} +- +-static u64 qca83xx_get_stat(struct phy_device *phydev, int i) +-{ +- struct at803x_hw_stat stat = qca83xx_hw_stats[i]; +- struct at803x_priv *priv = phydev->priv; +- int val; +- u64 ret; +- +- if (stat.access_type == MMD) +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg); +- else +- val = phy_read(phydev, stat.reg); +- +- if (val < 0) { +- ret = U64_MAX; +- } else { +- val = val & stat.mask; +- priv->stats[i] += val; +- ret = priv->stats[i]; +- } +- +- return ret; +-} +- +-static void qca83xx_get_stats(struct phy_device *phydev, +- struct ethtool_stats *stats, u64 *data) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) +- data[i] = qca83xx_get_stat(phydev, i); +-} +- + static int at803x_suspend(struct phy_device *phydev) + { + int value; +@@ -1707,124 +1640,6 @@ static int at8035_probe(struct phy_devic + return at8035_parse_dt(phydev); + } + +-static int qca83xx_config_init(struct phy_device *phydev) +-{ +- u8 switch_revision; +- +- switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK; +- +- switch (switch_revision) { +- case 1: +- /* For 100M waveform */ +- at803x_debug_reg_write(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0x02ea); +- /* Turn on Gigabit clock */ +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x68a0); +- break; +- +- case 2: +- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0); +- fallthrough; +- case 4: +- phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f); +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x6860); +- at803x_debug_reg_write(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0x2c46); +- at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000); +- break; +- } +- +- /* Following original QCA sourcecode set port to prefer master */ +- phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); +- +- return 0; +-} +- +-static int qca8327_config_init(struct phy_device *phydev) +-{ +- /* QCA8327 require DAC amplitude adjustment for 100m set to +6%. +- * Disable on init and enable only with 100m speed following +- * qca original source code. +- */ +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, 0); +- +- return qca83xx_config_init(phydev); +-} +- +-static void qca83xx_link_change_notify(struct phy_device *phydev) +-{ +- /* Set DAC Amplitude adjustment to +6% for 100m on link running */ +- if (phydev->state == PHY_RUNNING) { +- if (phydev->speed == SPEED_100) +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, +- QCA8327_DEBUG_MANU_CTRL_EN); +- } else { +- /* Reset DAC Amplitude adjustment */ +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, 0); +- } +-} +- +-static int qca83xx_resume(struct phy_device *phydev) +-{ +- int ret, val; +- +- /* Skip reset if not suspended */ +- if (!phydev->suspended) +- return 0; +- +- /* Reinit the port, reset values set by suspend */ +- qca83xx_config_init(phydev); +- +- /* Reset the port on port resume */ +- phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); +- +- /* On resume from suspend the switch execute a reset and +- * restart auto-negotiation. Wait for reset to complete. +- */ +- ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET), +- 50000, 600000, true); +- if (ret) +- return ret; +- +- usleep_range(1000, 2000); +- +- return 0; +-} +- +-static int qca83xx_suspend(struct phy_device *phydev) +-{ +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN, +- AT803X_DEBUG_GATE_CLK_IN1000, 0); +- +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, +- AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE | +- AT803X_DEBUG_HIB_CTRL_SEL_RST_80U, 0); +- +- return 0; +-} +- +-static int qca8337_suspend(struct phy_device *phydev) +-{ +- /* Only QCA8337 support actual suspend. */ +- genphy_suspend(phydev); +- +- return qca83xx_suspend(phydev); +-} +- +-static int qca8327_suspend(struct phy_device *phydev) +-{ +- u16 mask = 0; +- +- /* QCA8327 cause port unreliability when phy suspend +- * is set. +- */ +- mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); +- phy_modify(phydev, MII_BMCR, mask, 0); +- +- return qca83xx_suspend(phydev); +-} +- + static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) + { + int ret; +@@ -2599,53 +2414,6 @@ static struct phy_driver at803x_driver[] + .soft_reset = genphy_soft_reset, + .config_aneg = at803x_config_aneg, + }, { +- /* QCA8337 */ +- .phy_id = QCA8337_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "Qualcomm Atheros 8337 internal PHY", +- /* PHY_GBIT_FEATURES */ +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = qca83xx_get_sset_count, +- .get_strings = qca83xx_get_strings, +- .get_stats = qca83xx_get_stats, +- .suspend = qca8337_suspend, +- .resume = qca83xx_resume, +-}, { +- /* QCA8327-A from switch QCA8327-AL1A */ +- .phy_id = QCA8327_A_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "Qualcomm Atheros 8327-A internal PHY", +- /* PHY_GBIT_FEATURES */ +- .link_change_notify = qca83xx_link_change_notify, +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca8327_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = qca83xx_get_sset_count, +- .get_strings = qca83xx_get_strings, +- .get_stats = qca83xx_get_stats, +- .suspend = qca8327_suspend, +- .resume = qca83xx_resume, +-}, { +- /* QCA8327-B from switch QCA8327-BL1A */ +- .phy_id = QCA8327_B_PHY_ID, +- .phy_id_mask = QCA8K_PHY_ID_MASK, +- .name = "Qualcomm Atheros 8327-B internal PHY", +- /* PHY_GBIT_FEATURES */ +- .link_change_notify = qca83xx_link_change_notify, +- .probe = at803x_probe, +- .flags = PHY_IS_INTERNAL, +- .config_init = qca8327_config_init, +- .soft_reset = genphy_soft_reset, +- .get_sset_count = qca83xx_get_sset_count, +- .get_strings = qca83xx_get_strings, +- .get_stats = qca83xx_get_stats, +- .suspend = qca8327_suspend, +- .resume = qca83xx_resume, +-}, { + /* Qualcomm QCA8081 */ + PHY_ID_MATCH_EXACT(QCA8081_PHY_ID), + .name = "Qualcomm QCA8081", +@@ -2683,9 +2451,6 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) }, + { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) }, + { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) }, + { PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) }, + { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) }, + { } +--- /dev/null ++++ b/drivers/net/phy/qcom/qca83xx.c +@@ -0,0 +1,275 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++ ++#include ++#include ++ ++#include "qcom.h" ++ ++#define AT803X_DEBUG_REG_3C 0x3C ++ ++#define AT803X_DEBUG_REG_GREEN 0x3D ++#define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6) ++ ++#define MDIO_AZ_DEBUG 0x800D ++ ++#define QCA8327_A_PHY_ID 0x004dd033 ++#define QCA8327_B_PHY_ID 0x004dd034 ++#define QCA8337_PHY_ID 0x004dd036 ++#define QCA8K_PHY_ID_MASK 0xffffffff ++ ++#define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0) ++ ++static struct at803x_hw_stat qca83xx_hw_stats[] = { ++ { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, ++ { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, ++ { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, ++}; ++ ++struct qca83xx_priv { ++ u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; ++}; ++ ++MODULE_DESCRIPTION("Qualcomm Atheros QCA83XX PHY driver"); ++MODULE_AUTHOR("Matus Ujhelyi"); ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_LICENSE("GPL"); ++ ++static int qca83xx_get_sset_count(struct phy_device *phydev) ++{ ++ return ARRAY_SIZE(qca83xx_hw_stats); ++} ++ ++static void qca83xx_get_strings(struct phy_device *phydev, u8 *data) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) { ++ strscpy(data + i * ETH_GSTRING_LEN, ++ qca83xx_hw_stats[i].string, ETH_GSTRING_LEN); ++ } ++} ++ ++static u64 qca83xx_get_stat(struct phy_device *phydev, int i) ++{ ++ struct at803x_hw_stat stat = qca83xx_hw_stats[i]; ++ struct qca83xx_priv *priv = phydev->priv; ++ int val; ++ u64 ret; ++ ++ if (stat.access_type == MMD) ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg); ++ else ++ val = phy_read(phydev, stat.reg); ++ ++ if (val < 0) { ++ ret = U64_MAX; ++ } else { ++ val = val & stat.mask; ++ priv->stats[i] += val; ++ ret = priv->stats[i]; ++ } ++ ++ return ret; ++} ++ ++static void qca83xx_get_stats(struct phy_device *phydev, ++ struct ethtool_stats *stats, u64 *data) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) ++ data[i] = qca83xx_get_stat(phydev, i); ++} ++ ++static int qca83xx_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct qca83xx_priv *priv; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ phydev->priv = priv; ++ ++ return 0; ++} ++ ++static int qca83xx_config_init(struct phy_device *phydev) ++{ ++ u8 switch_revision; ++ ++ switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK; ++ ++ switch (switch_revision) { ++ case 1: ++ /* For 100M waveform */ ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0x02ea); ++ /* Turn on Gigabit clock */ ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x68a0); ++ break; ++ ++ case 2: ++ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0); ++ fallthrough; ++ case 4: ++ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x6860); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0x2c46); ++ at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000); ++ break; ++ } ++ ++ /* Following original QCA sourcecode set port to prefer master */ ++ phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); ++ ++ return 0; ++} ++ ++static int qca8327_config_init(struct phy_device *phydev) ++{ ++ /* QCA8327 require DAC amplitude adjustment for 100m set to +6%. ++ * Disable on init and enable only with 100m speed following ++ * qca original source code. ++ */ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, 0); ++ ++ return qca83xx_config_init(phydev); ++} ++ ++static void qca83xx_link_change_notify(struct phy_device *phydev) ++{ ++ /* Set DAC Amplitude adjustment to +6% for 100m on link running */ ++ if (phydev->state == PHY_RUNNING) { ++ if (phydev->speed == SPEED_100) ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, ++ QCA8327_DEBUG_MANU_CTRL_EN); ++ } else { ++ /* Reset DAC Amplitude adjustment */ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, 0); ++ } ++} ++ ++static int qca83xx_resume(struct phy_device *phydev) ++{ ++ int ret, val; ++ ++ /* Skip reset if not suspended */ ++ if (!phydev->suspended) ++ return 0; ++ ++ /* Reinit the port, reset values set by suspend */ ++ qca83xx_config_init(phydev); ++ ++ /* Reset the port on port resume */ ++ phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); ++ ++ /* On resume from suspend the switch execute a reset and ++ * restart auto-negotiation. Wait for reset to complete. ++ */ ++ ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET), ++ 50000, 600000, true); ++ if (ret) ++ return ret; ++ ++ usleep_range(1000, 2000); ++ ++ return 0; ++} ++ ++static int qca83xx_suspend(struct phy_device *phydev) ++{ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN, ++ AT803X_DEBUG_GATE_CLK_IN1000, 0); ++ ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL, ++ AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE | ++ AT803X_DEBUG_HIB_CTRL_SEL_RST_80U, 0); ++ ++ return 0; ++} ++ ++static int qca8337_suspend(struct phy_device *phydev) ++{ ++ /* Only QCA8337 support actual suspend. */ ++ genphy_suspend(phydev); ++ ++ return qca83xx_suspend(phydev); ++} ++ ++static int qca8327_suspend(struct phy_device *phydev) ++{ ++ u16 mask = 0; ++ ++ /* QCA8327 cause port unreliability when phy suspend ++ * is set. ++ */ ++ mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); ++ phy_modify(phydev, MII_BMCR, mask, 0); ++ ++ return qca83xx_suspend(phydev); ++} ++ ++static struct phy_driver qca83xx_driver[] = { ++{ ++ /* QCA8337 */ ++ .phy_id = QCA8337_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8337 internal PHY", ++ /* PHY_GBIT_FEATURES */ ++ .probe = qca83xx_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca83xx_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, ++ .suspend = qca8337_suspend, ++ .resume = qca83xx_resume, ++}, { ++ /* QCA8327-A from switch QCA8327-AL1A */ ++ .phy_id = QCA8327_A_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8327-A internal PHY", ++ /* PHY_GBIT_FEATURES */ ++ .link_change_notify = qca83xx_link_change_notify, ++ .probe = qca83xx_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca8327_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, ++ .suspend = qca8327_suspend, ++ .resume = qca83xx_resume, ++}, { ++ /* QCA8327-B from switch QCA8327-BL1A */ ++ .phy_id = QCA8327_B_PHY_ID, ++ .phy_id_mask = QCA8K_PHY_ID_MASK, ++ .name = "Qualcomm Atheros 8327-B internal PHY", ++ /* PHY_GBIT_FEATURES */ ++ .link_change_notify = qca83xx_link_change_notify, ++ .probe = qca83xx_probe, ++ .flags = PHY_IS_INTERNAL, ++ .config_init = qca8327_config_init, ++ .soft_reset = genphy_soft_reset, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, ++ .suspend = qca8327_suspend, ++ .resume = qca83xx_resume, ++}, }; ++ ++module_phy_driver(qca83xx_driver); ++ ++static struct mdio_device_id __maybe_unused qca83xx_tbl[] = { ++ { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) }, ++ { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, qca83xx_tbl); diff --git a/lede/target/linux/generic/backport-6.1/713-v6.9-04-net-phy-qcom-move-additional-functions-to-shared-lib.patch b/lede/target/linux/generic/backport-6.1/713-v6.9-04-net-phy-qcom-move-additional-functions-to-shared-lib.patch new file mode 100644 index 0000000000..9c43ad13b4 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/713-v6.9-04-net-phy-qcom-move-additional-functions-to-shared-lib.patch @@ -0,0 +1,1014 @@ +From 249d2b80e4db0e38503ed0ec2af6c7401bc099b9 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 Jan 2024 15:15:22 +0100 +Subject: [PATCH 4/5] net: phy: qcom: move additional functions to shared + library + +Move additional functions to shared library in preparation for qca808x +PHY Family to be detached from at803x driver. + +Only the shared defines are moved to the shared qcom.h header. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240129141600.2592-5-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/qcom/at803x.c | 426 +--------------------------- + drivers/net/phy/qcom/qcom-phy-lib.c | 376 ++++++++++++++++++++++++ + drivers/net/phy/qcom/qcom.h | 86 ++++++ + 3 files changed, 463 insertions(+), 425 deletions(-) + +--- a/drivers/net/phy/qcom/at803x.c ++++ b/drivers/net/phy/qcom/at803x.c +@@ -24,65 +24,11 @@ + + #include "qcom.h" + +-#define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10 +-#define AT803X_SFC_ASSERT_CRS BIT(11) +-#define AT803X_SFC_FORCE_LINK BIT(10) +-#define AT803X_SFC_MDI_CROSSOVER_MODE_M GENMASK(6, 5) +-#define AT803X_SFC_AUTOMATIC_CROSSOVER 0x3 +-#define AT803X_SFC_MANUAL_MDIX 0x1 +-#define AT803X_SFC_MANUAL_MDI 0x0 +-#define AT803X_SFC_SQE_TEST BIT(2) +-#define AT803X_SFC_POLARITY_REVERSAL BIT(1) +-#define AT803X_SFC_DISABLE_JABBER BIT(0) +- +-#define AT803X_SPECIFIC_STATUS 0x11 +-#define AT803X_SS_SPEED_MASK GENMASK(15, 14) +-#define AT803X_SS_SPEED_1000 2 +-#define AT803X_SS_SPEED_100 1 +-#define AT803X_SS_SPEED_10 0 +-#define AT803X_SS_DUPLEX BIT(13) +-#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11) +-#define AT803X_SS_MDIX BIT(6) +- +-#define QCA808X_SS_SPEED_MASK GENMASK(9, 7) +-#define QCA808X_SS_SPEED_2500 4 +- +-#define AT803X_INTR_ENABLE 0x12 +-#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15) +-#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14) +-#define AT803X_INTR_ENABLE_DUPLEX_CHANGED BIT(13) +-#define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12) +-#define AT803X_INTR_ENABLE_LINK_FAIL BIT(11) +-#define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10) +-#define AT803X_INTR_ENABLE_LINK_FAIL_BX BIT(8) +-#define AT803X_INTR_ENABLE_LINK_SUCCESS_BX BIT(7) +-#define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5) +-#define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1) +-#define AT803X_INTR_ENABLE_WOL BIT(0) +- +-#define AT803X_INTR_STATUS 0x13 +- +-#define AT803X_SMART_SPEED 0x14 +-#define AT803X_SMART_SPEED_ENABLE BIT(5) +-#define AT803X_SMART_SPEED_RETRY_LIMIT_MASK GENMASK(4, 2) +-#define AT803X_SMART_SPEED_BYPASS_TIMER BIT(1) +-#define AT803X_CDT 0x16 +-#define AT803X_CDT_MDI_PAIR_MASK GENMASK(9, 8) +-#define AT803X_CDT_ENABLE_TEST BIT(0) +-#define AT803X_CDT_STATUS 0x1c +-#define AT803X_CDT_STATUS_STAT_NORMAL 0 +-#define AT803X_CDT_STATUS_STAT_SHORT 1 +-#define AT803X_CDT_STATUS_STAT_OPEN 2 +-#define AT803X_CDT_STATUS_STAT_FAIL 3 +-#define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8) +-#define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0) + #define AT803X_LED_CONTROL 0x18 + + #define AT803X_PHY_MMD3_WOL_CTRL 0x8012 + #define AT803X_WOL_EN BIT(5) +-#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C +-#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B +-#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A ++ + #define AT803X_REG_CHIP_CONFIG 0x1f + #define AT803X_BT_BX_REG_SEL 0x8000 + +@@ -138,10 +84,6 @@ + #define AT803X_CLK_OUT_STRENGTH_HALF 1 + #define AT803X_CLK_OUT_STRENGTH_QUARTER 2 + +-#define AT803X_DEFAULT_DOWNSHIFT 5 +-#define AT803X_MIN_DOWNSHIFT 2 +-#define AT803X_MAX_DOWNSHIFT 9 +- + #define AT803X_MMD3_SMARTEEE_CTL1 0x805b + #define AT803X_MMD3_SMARTEEE_CTL2 0x805c + #define AT803X_MMD3_SMARTEEE_CTL3 0x805d +@@ -366,11 +308,6 @@ MODULE_DESCRIPTION("Qualcomm Atheros AR8 + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); + +-struct at803x_ss_mask { +- u16 speed_mask; +- u8 speed_shift; +-}; +- + struct at803x_priv { + int flags; + u16 clk_25m_reg; +@@ -470,80 +407,6 @@ static void at803x_context_restore(struc + phy_write(phydev, AT803X_LED_CONTROL, context->led_control); + } + +-static int at803x_set_wol(struct phy_device *phydev, +- struct ethtool_wolinfo *wol) +-{ +- int ret, irq_enabled; +- +- if (wol->wolopts & WAKE_MAGIC) { +- struct net_device *ndev = phydev->attached_dev; +- const u8 *mac; +- unsigned int i; +- static const unsigned int offsets[] = { +- AT803X_LOC_MAC_ADDR_32_47_OFFSET, +- AT803X_LOC_MAC_ADDR_16_31_OFFSET, +- AT803X_LOC_MAC_ADDR_0_15_OFFSET, +- }; +- +- if (!ndev) +- return -ENODEV; +- +- mac = (const u8 *)ndev->dev_addr; +- +- if (!is_valid_ether_addr(mac)) +- return -EINVAL; +- +- for (i = 0; i < 3; i++) +- phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], +- mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); +- +- /* Enable WOL interrupt */ +- ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); +- if (ret) +- return ret; +- } else { +- /* Disable WOL interrupt */ +- ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); +- if (ret) +- return ret; +- } +- +- /* Clear WOL status */ +- ret = phy_read(phydev, AT803X_INTR_STATUS); +- if (ret < 0) +- return ret; +- +- /* Check if there are other interrupts except for WOL triggered when PHY is +- * in interrupt mode, only the interrupts enabled by AT803X_INTR_ENABLE can +- * be passed up to the interrupt PIN. +- */ +- irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE); +- if (irq_enabled < 0) +- return irq_enabled; +- +- irq_enabled &= ~AT803X_INTR_ENABLE_WOL; +- if (ret & irq_enabled && !phy_polling_mode(phydev)) +- phy_trigger_machine(phydev); +- +- return 0; +-} +- +-static void at803x_get_wol(struct phy_device *phydev, +- struct ethtool_wolinfo *wol) +-{ +- int value; +- +- wol->supported = WAKE_MAGIC; +- wol->wolopts = 0; +- +- value = phy_read(phydev, AT803X_INTR_ENABLE); +- if (value < 0) +- return; +- +- if (value & AT803X_INTR_ENABLE_WOL) +- wol->wolopts |= WAKE_MAGIC; +-} +- + static int at803x_suspend(struct phy_device *phydev) + { + int value; +@@ -816,73 +679,6 @@ static int at803x_config_init(struct phy + return phy_modify(phydev, MII_ADVERTISE, MDIO_AN_CTRL1_XNP, 0); + } + +-static int at803x_ack_interrupt(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_read(phydev, AT803X_INTR_STATUS); +- +- return (err < 0) ? err : 0; +-} +- +-static int at803x_config_intr(struct phy_device *phydev) +-{ +- int err; +- int value; +- +- value = phy_read(phydev, AT803X_INTR_ENABLE); +- +- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { +- /* Clear any pending interrupts */ +- err = at803x_ack_interrupt(phydev); +- if (err) +- return err; +- +- value |= AT803X_INTR_ENABLE_AUTONEG_ERR; +- value |= AT803X_INTR_ENABLE_SPEED_CHANGED; +- value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED; +- value |= AT803X_INTR_ENABLE_LINK_FAIL; +- value |= AT803X_INTR_ENABLE_LINK_SUCCESS; +- +- err = phy_write(phydev, AT803X_INTR_ENABLE, value); +- } else { +- err = phy_write(phydev, AT803X_INTR_ENABLE, 0); +- if (err) +- return err; +- +- /* Clear any pending interrupts */ +- err = at803x_ack_interrupt(phydev); +- } +- +- return err; +-} +- +-static irqreturn_t at803x_handle_interrupt(struct phy_device *phydev) +-{ +- int irq_status, int_enabled; +- +- irq_status = phy_read(phydev, AT803X_INTR_STATUS); +- if (irq_status < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- /* Read the current enabled interrupts */ +- int_enabled = phy_read(phydev, AT803X_INTR_ENABLE); +- if (int_enabled < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- /* See if this was one of our enabled interrupts */ +- if (!(irq_status & int_enabled)) +- return IRQ_NONE; +- +- phy_trigger_machine(phydev); +- +- return IRQ_HANDLED; +-} +- + static void at803x_link_change_notify(struct phy_device *phydev) + { + /* +@@ -908,69 +704,6 @@ static void at803x_link_change_notify(st + } + } + +-static int at803x_read_specific_status(struct phy_device *phydev, +- struct at803x_ss_mask ss_mask) +-{ +- int ss; +- +- /* Read the AT8035 PHY-Specific Status register, which indicates the +- * speed and duplex that the PHY is actually using, irrespective of +- * whether we are in autoneg mode or not. +- */ +- ss = phy_read(phydev, AT803X_SPECIFIC_STATUS); +- if (ss < 0) +- return ss; +- +- if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) { +- int sfc, speed; +- +- sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL); +- if (sfc < 0) +- return sfc; +- +- speed = ss & ss_mask.speed_mask; +- speed >>= ss_mask.speed_shift; +- +- switch (speed) { +- case AT803X_SS_SPEED_10: +- phydev->speed = SPEED_10; +- break; +- case AT803X_SS_SPEED_100: +- phydev->speed = SPEED_100; +- break; +- case AT803X_SS_SPEED_1000: +- phydev->speed = SPEED_1000; +- break; +- case QCA808X_SS_SPEED_2500: +- phydev->speed = SPEED_2500; +- break; +- } +- if (ss & AT803X_SS_DUPLEX) +- phydev->duplex = DUPLEX_FULL; +- else +- phydev->duplex = DUPLEX_HALF; +- +- if (ss & AT803X_SS_MDIX) +- phydev->mdix = ETH_TP_MDI_X; +- else +- phydev->mdix = ETH_TP_MDI; +- +- switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) { +- case AT803X_SFC_MANUAL_MDI: +- phydev->mdix_ctrl = ETH_TP_MDI; +- break; +- case AT803X_SFC_MANUAL_MDIX: +- phydev->mdix_ctrl = ETH_TP_MDI_X; +- break; +- case AT803X_SFC_AUTOMATIC_CROSSOVER: +- phydev->mdix_ctrl = ETH_TP_MDI_AUTO; +- break; +- } +- } +- +- return 0; +-} +- + static int at803x_read_status(struct phy_device *phydev) + { + struct at803x_ss_mask ss_mask = { 0 }; +@@ -1006,50 +739,6 @@ static int at803x_read_status(struct phy + return 0; + } + +-static int at803x_config_mdix(struct phy_device *phydev, u8 ctrl) +-{ +- u16 val; +- +- switch (ctrl) { +- case ETH_TP_MDI: +- val = AT803X_SFC_MANUAL_MDI; +- break; +- case ETH_TP_MDI_X: +- val = AT803X_SFC_MANUAL_MDIX; +- break; +- case ETH_TP_MDI_AUTO: +- val = AT803X_SFC_AUTOMATIC_CROSSOVER; +- break; +- default: +- return 0; +- } +- +- return phy_modify_changed(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL, +- AT803X_SFC_MDI_CROSSOVER_MODE_M, +- FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val)); +-} +- +-static int at803x_prepare_config_aneg(struct phy_device *phydev) +-{ +- int ret; +- +- ret = at803x_config_mdix(phydev, phydev->mdix_ctrl); +- if (ret < 0) +- return ret; +- +- /* Changes of the midx bits are disruptive to the normal operation; +- * therefore any changes to these registers must be followed by a +- * software reset to take effect. +- */ +- if (ret == 1) { +- ret = genphy_soft_reset(phydev); +- if (ret < 0) +- return ret; +- } +- +- return 0; +-} +- + static int at803x_config_aneg(struct phy_device *phydev) + { + struct at803x_priv *priv = phydev->priv; +@@ -1065,80 +754,6 @@ static int at803x_config_aneg(struct phy + return genphy_config_aneg(phydev); + } + +-static int at803x_get_downshift(struct phy_device *phydev, u8 *d) +-{ +- int val; +- +- val = phy_read(phydev, AT803X_SMART_SPEED); +- if (val < 0) +- return val; +- +- if (val & AT803X_SMART_SPEED_ENABLE) +- *d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2; +- else +- *d = DOWNSHIFT_DEV_DISABLE; +- +- return 0; +-} +- +-static int at803x_set_downshift(struct phy_device *phydev, u8 cnt) +-{ +- u16 mask, set; +- int ret; +- +- switch (cnt) { +- case DOWNSHIFT_DEV_DEFAULT_COUNT: +- cnt = AT803X_DEFAULT_DOWNSHIFT; +- fallthrough; +- case AT803X_MIN_DOWNSHIFT ... AT803X_MAX_DOWNSHIFT: +- set = AT803X_SMART_SPEED_ENABLE | +- AT803X_SMART_SPEED_BYPASS_TIMER | +- FIELD_PREP(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, cnt - 2); +- mask = AT803X_SMART_SPEED_RETRY_LIMIT_MASK; +- break; +- case DOWNSHIFT_DEV_DISABLE: +- set = 0; +- mask = AT803X_SMART_SPEED_ENABLE | +- AT803X_SMART_SPEED_BYPASS_TIMER; +- break; +- default: +- return -EINVAL; +- } +- +- ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set); +- +- /* After changing the smart speed settings, we need to perform a +- * software reset, use phy_init_hw() to make sure we set the +- * reapply any values which might got lost during software reset. +- */ +- if (ret == 1) +- ret = phy_init_hw(phydev); +- +- return ret; +-} +- +-static int at803x_get_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return at803x_get_downshift(phydev, data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int at803x_set_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, const void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return at803x_set_downshift(phydev, *(const u8 *)data); +- default: +- return -EOPNOTSUPP; +- } +-} +- + static int at803x_cable_test_result_trans(u16 status) + { + switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) { +@@ -1170,45 +785,6 @@ static bool at803x_cdt_fault_length_vali + return false; + } + +-static int at803x_cdt_fault_length(int dt) +-{ +- /* According to the datasheet the distance to the fault is +- * DELTA_TIME * 0.824 meters. +- * +- * The author suspect the correct formula is: +- * +- * fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2 +- * +- * where c is the speed of light, VF is the velocity factor of +- * the twisted pair cable, 125MHz the counter frequency and +- * we need to divide by 2 because the hardware will measure the +- * round trip time to the fault and back to the PHY. +- * +- * With a VF of 0.69 we get the factor 0.824 mentioned in the +- * datasheet. +- */ +- return (dt * 824) / 10; +-} +- +-static int at803x_cdt_start(struct phy_device *phydev, +- u32 cdt_start) +-{ +- return phy_write(phydev, AT803X_CDT, cdt_start); +-} +- +-static int at803x_cdt_wait_for_completion(struct phy_device *phydev, +- u32 cdt_en) +-{ +- int val, ret; +- +- /* One test run takes about 25ms */ +- ret = phy_read_poll_timeout(phydev, AT803X_CDT, val, +- !(val & cdt_en), +- 30000, 100000, true); +- +- return ret < 0 ? ret : 0; +-} +- + static int at803x_cable_test_one_pair(struct phy_device *phydev, int pair) + { + static const int ethtool_pair[] = { +--- a/drivers/net/phy/qcom/qcom-phy-lib.c ++++ b/drivers/net/phy/qcom/qcom-phy-lib.c +@@ -3,6 +3,9 @@ + #include + #include + ++#include ++#include ++ + #include "qcom.h" + + MODULE_DESCRIPTION("Qualcomm PHY driver Common Functions"); +@@ -51,3 +54,376 @@ int at803x_debug_reg_write(struct phy_de + return phy_write(phydev, AT803X_DEBUG_DATA, data); + } + EXPORT_SYMBOL_GPL(at803x_debug_reg_write); ++ ++int at803x_set_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int ret, irq_enabled; ++ ++ if (wol->wolopts & WAKE_MAGIC) { ++ struct net_device *ndev = phydev->attached_dev; ++ const u8 *mac; ++ unsigned int i; ++ static const unsigned int offsets[] = { ++ AT803X_LOC_MAC_ADDR_32_47_OFFSET, ++ AT803X_LOC_MAC_ADDR_16_31_OFFSET, ++ AT803X_LOC_MAC_ADDR_0_15_OFFSET, ++ }; ++ ++ if (!ndev) ++ return -ENODEV; ++ ++ mac = (const u8 *)ndev->dev_addr; ++ ++ if (!is_valid_ether_addr(mac)) ++ return -EINVAL; ++ ++ for (i = 0; i < 3; i++) ++ phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], ++ mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); ++ ++ /* Enable WOL interrupt */ ++ ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); ++ if (ret) ++ return ret; ++ } else { ++ /* Disable WOL interrupt */ ++ ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); ++ if (ret) ++ return ret; ++ } ++ ++ /* Clear WOL status */ ++ ret = phy_read(phydev, AT803X_INTR_STATUS); ++ if (ret < 0) ++ return ret; ++ ++ /* Check if there are other interrupts except for WOL triggered when PHY is ++ * in interrupt mode, only the interrupts enabled by AT803X_INTR_ENABLE can ++ * be passed up to the interrupt PIN. ++ */ ++ irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE); ++ if (irq_enabled < 0) ++ return irq_enabled; ++ ++ irq_enabled &= ~AT803X_INTR_ENABLE_WOL; ++ if (ret & irq_enabled && !phy_polling_mode(phydev)) ++ phy_trigger_machine(phydev); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(at803x_set_wol); ++ ++void at803x_get_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int value; ++ ++ wol->supported = WAKE_MAGIC; ++ wol->wolopts = 0; ++ ++ value = phy_read(phydev, AT803X_INTR_ENABLE); ++ if (value < 0) ++ return; ++ ++ if (value & AT803X_INTR_ENABLE_WOL) ++ wol->wolopts |= WAKE_MAGIC; ++} ++EXPORT_SYMBOL_GPL(at803x_get_wol); ++ ++int at803x_ack_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_read(phydev, AT803X_INTR_STATUS); ++ ++ return (err < 0) ? err : 0; ++} ++EXPORT_SYMBOL_GPL(at803x_ack_interrupt); ++ ++int at803x_config_intr(struct phy_device *phydev) ++{ ++ int err; ++ int value; ++ ++ value = phy_read(phydev, AT803X_INTR_ENABLE); ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { ++ /* Clear any pending interrupts */ ++ err = at803x_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ value |= AT803X_INTR_ENABLE_AUTONEG_ERR; ++ value |= AT803X_INTR_ENABLE_SPEED_CHANGED; ++ value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED; ++ value |= AT803X_INTR_ENABLE_LINK_FAIL; ++ value |= AT803X_INTR_ENABLE_LINK_SUCCESS; ++ ++ err = phy_write(phydev, AT803X_INTR_ENABLE, value); ++ } else { ++ err = phy_write(phydev, AT803X_INTR_ENABLE, 0); ++ if (err) ++ return err; ++ ++ /* Clear any pending interrupts */ ++ err = at803x_ack_interrupt(phydev); ++ } ++ ++ return err; ++} ++EXPORT_SYMBOL_GPL(at803x_config_intr); ++ ++irqreturn_t at803x_handle_interrupt(struct phy_device *phydev) ++{ ++ int irq_status, int_enabled; ++ ++ irq_status = phy_read(phydev, AT803X_INTR_STATUS); ++ if (irq_status < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ /* Read the current enabled interrupts */ ++ int_enabled = phy_read(phydev, AT803X_INTR_ENABLE); ++ if (int_enabled < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ /* See if this was one of our enabled interrupts */ ++ if (!(irq_status & int_enabled)) ++ return IRQ_NONE; ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++EXPORT_SYMBOL_GPL(at803x_handle_interrupt); ++ ++int at803x_read_specific_status(struct phy_device *phydev, ++ struct at803x_ss_mask ss_mask) ++{ ++ int ss; ++ ++ /* Read the AT8035 PHY-Specific Status register, which indicates the ++ * speed and duplex that the PHY is actually using, irrespective of ++ * whether we are in autoneg mode or not. ++ */ ++ ss = phy_read(phydev, AT803X_SPECIFIC_STATUS); ++ if (ss < 0) ++ return ss; ++ ++ if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) { ++ int sfc, speed; ++ ++ sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL); ++ if (sfc < 0) ++ return sfc; ++ ++ speed = ss & ss_mask.speed_mask; ++ speed >>= ss_mask.speed_shift; ++ ++ switch (speed) { ++ case AT803X_SS_SPEED_10: ++ phydev->speed = SPEED_10; ++ break; ++ case AT803X_SS_SPEED_100: ++ phydev->speed = SPEED_100; ++ break; ++ case AT803X_SS_SPEED_1000: ++ phydev->speed = SPEED_1000; ++ break; ++ case QCA808X_SS_SPEED_2500: ++ phydev->speed = SPEED_2500; ++ break; ++ } ++ if (ss & AT803X_SS_DUPLEX) ++ phydev->duplex = DUPLEX_FULL; ++ else ++ phydev->duplex = DUPLEX_HALF; ++ ++ if (ss & AT803X_SS_MDIX) ++ phydev->mdix = ETH_TP_MDI_X; ++ else ++ phydev->mdix = ETH_TP_MDI; ++ ++ switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) { ++ case AT803X_SFC_MANUAL_MDI: ++ phydev->mdix_ctrl = ETH_TP_MDI; ++ break; ++ case AT803X_SFC_MANUAL_MDIX: ++ phydev->mdix_ctrl = ETH_TP_MDI_X; ++ break; ++ case AT803X_SFC_AUTOMATIC_CROSSOVER: ++ phydev->mdix_ctrl = ETH_TP_MDI_AUTO; ++ break; ++ } ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(at803x_read_specific_status); ++ ++int at803x_config_mdix(struct phy_device *phydev, u8 ctrl) ++{ ++ u16 val; ++ ++ switch (ctrl) { ++ case ETH_TP_MDI: ++ val = AT803X_SFC_MANUAL_MDI; ++ break; ++ case ETH_TP_MDI_X: ++ val = AT803X_SFC_MANUAL_MDIX; ++ break; ++ case ETH_TP_MDI_AUTO: ++ val = AT803X_SFC_AUTOMATIC_CROSSOVER; ++ break; ++ default: ++ return 0; ++ } ++ ++ return phy_modify_changed(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL, ++ AT803X_SFC_MDI_CROSSOVER_MODE_M, ++ FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val)); ++} ++EXPORT_SYMBOL_GPL(at803x_config_mdix); ++ ++int at803x_prepare_config_aneg(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = at803x_config_mdix(phydev, phydev->mdix_ctrl); ++ if (ret < 0) ++ return ret; ++ ++ /* Changes of the midx bits are disruptive to the normal operation; ++ * therefore any changes to these registers must be followed by a ++ * software reset to take effect. ++ */ ++ if (ret == 1) { ++ ret = genphy_soft_reset(phydev); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(at803x_prepare_config_aneg); ++ ++static int at803x_get_downshift(struct phy_device *phydev, u8 *d) ++{ ++ int val; ++ ++ val = phy_read(phydev, AT803X_SMART_SPEED); ++ if (val < 0) ++ return val; ++ ++ if (val & AT803X_SMART_SPEED_ENABLE) ++ *d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2; ++ else ++ *d = DOWNSHIFT_DEV_DISABLE; ++ ++ return 0; ++} ++ ++static int at803x_set_downshift(struct phy_device *phydev, u8 cnt) ++{ ++ u16 mask, set; ++ int ret; ++ ++ switch (cnt) { ++ case DOWNSHIFT_DEV_DEFAULT_COUNT: ++ cnt = AT803X_DEFAULT_DOWNSHIFT; ++ fallthrough; ++ case AT803X_MIN_DOWNSHIFT ... AT803X_MAX_DOWNSHIFT: ++ set = AT803X_SMART_SPEED_ENABLE | ++ AT803X_SMART_SPEED_BYPASS_TIMER | ++ FIELD_PREP(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, cnt - 2); ++ mask = AT803X_SMART_SPEED_RETRY_LIMIT_MASK; ++ break; ++ case DOWNSHIFT_DEV_DISABLE: ++ set = 0; ++ mask = AT803X_SMART_SPEED_ENABLE | ++ AT803X_SMART_SPEED_BYPASS_TIMER; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set); ++ ++ /* After changing the smart speed settings, we need to perform a ++ * software reset, use phy_init_hw() to make sure we set the ++ * reapply any values which might got lost during software reset. ++ */ ++ if (ret == 1) ++ ret = phy_init_hw(phydev); ++ ++ return ret; ++} ++ ++int at803x_get_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return at803x_get_downshift(phydev, data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++EXPORT_SYMBOL_GPL(at803x_get_tunable); ++ ++int at803x_set_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, const void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return at803x_set_downshift(phydev, *(const u8 *)data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++EXPORT_SYMBOL_GPL(at803x_set_tunable); ++ ++int at803x_cdt_fault_length(int dt) ++{ ++ /* According to the datasheet the distance to the fault is ++ * DELTA_TIME * 0.824 meters. ++ * ++ * The author suspect the correct formula is: ++ * ++ * fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2 ++ * ++ * where c is the speed of light, VF is the velocity factor of ++ * the twisted pair cable, 125MHz the counter frequency and ++ * we need to divide by 2 because the hardware will measure the ++ * round trip time to the fault and back to the PHY. ++ * ++ * With a VF of 0.69 we get the factor 0.824 mentioned in the ++ * datasheet. ++ */ ++ return (dt * 824) / 10; ++} ++EXPORT_SYMBOL_GPL(at803x_cdt_fault_length); ++ ++int at803x_cdt_start(struct phy_device *phydev, u32 cdt_start) ++{ ++ return phy_write(phydev, AT803X_CDT, cdt_start); ++} ++EXPORT_SYMBOL_GPL(at803x_cdt_start); ++ ++int at803x_cdt_wait_for_completion(struct phy_device *phydev, ++ u32 cdt_en) ++{ ++ int val, ret; ++ ++ /* One test run takes about 25ms */ ++ ret = phy_read_poll_timeout(phydev, AT803X_CDT, val, ++ !(val & cdt_en), ++ 30000, 100000, true); ++ ++ return ret < 0 ? ret : 0; ++} ++EXPORT_SYMBOL_GPL(at803x_cdt_wait_for_completion); +--- a/drivers/net/phy/qcom/qcom.h ++++ b/drivers/net/phy/qcom/qcom.h +@@ -1,5 +1,63 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + ++#define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10 ++#define AT803X_SFC_ASSERT_CRS BIT(11) ++#define AT803X_SFC_FORCE_LINK BIT(10) ++#define AT803X_SFC_MDI_CROSSOVER_MODE_M GENMASK(6, 5) ++#define AT803X_SFC_AUTOMATIC_CROSSOVER 0x3 ++#define AT803X_SFC_MANUAL_MDIX 0x1 ++#define AT803X_SFC_MANUAL_MDI 0x0 ++#define AT803X_SFC_SQE_TEST BIT(2) ++#define AT803X_SFC_POLARITY_REVERSAL BIT(1) ++#define AT803X_SFC_DISABLE_JABBER BIT(0) ++ ++#define AT803X_SPECIFIC_STATUS 0x11 ++#define AT803X_SS_SPEED_MASK GENMASK(15, 14) ++#define AT803X_SS_SPEED_1000 2 ++#define AT803X_SS_SPEED_100 1 ++#define AT803X_SS_SPEED_10 0 ++#define AT803X_SS_DUPLEX BIT(13) ++#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11) ++#define AT803X_SS_MDIX BIT(6) ++ ++#define QCA808X_SS_SPEED_MASK GENMASK(9, 7) ++#define QCA808X_SS_SPEED_2500 4 ++ ++#define AT803X_INTR_ENABLE 0x12 ++#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15) ++#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14) ++#define AT803X_INTR_ENABLE_DUPLEX_CHANGED BIT(13) ++#define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12) ++#define AT803X_INTR_ENABLE_LINK_FAIL BIT(11) ++#define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10) ++#define AT803X_INTR_ENABLE_LINK_FAIL_BX BIT(8) ++#define AT803X_INTR_ENABLE_LINK_SUCCESS_BX BIT(7) ++#define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5) ++#define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1) ++#define AT803X_INTR_ENABLE_WOL BIT(0) ++ ++#define AT803X_INTR_STATUS 0x13 ++ ++#define AT803X_SMART_SPEED 0x14 ++#define AT803X_SMART_SPEED_ENABLE BIT(5) ++#define AT803X_SMART_SPEED_RETRY_LIMIT_MASK GENMASK(4, 2) ++#define AT803X_SMART_SPEED_BYPASS_TIMER BIT(1) ++ ++#define AT803X_CDT 0x16 ++#define AT803X_CDT_MDI_PAIR_MASK GENMASK(9, 8) ++#define AT803X_CDT_ENABLE_TEST BIT(0) ++#define AT803X_CDT_STATUS 0x1c ++#define AT803X_CDT_STATUS_STAT_NORMAL 0 ++#define AT803X_CDT_STATUS_STAT_SHORT 1 ++#define AT803X_CDT_STATUS_STAT_OPEN 2 ++#define AT803X_CDT_STATUS_STAT_FAIL 3 ++#define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8) ++#define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0) ++ ++#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C ++#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B ++#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A ++ + #define AT803X_DEBUG_ADDR 0x1D + #define AT803X_DEBUG_DATA 0x1E + +@@ -16,6 +74,10 @@ + #define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13) + #define AT803X_DEBUG_HIB_CTRL_PS_HIB_EN BIT(15) + ++#define AT803X_DEFAULT_DOWNSHIFT 5 ++#define AT803X_MIN_DOWNSHIFT 2 ++#define AT803X_MAX_DOWNSHIFT 9 ++ + enum stat_access_type { + PHY, + MMD +@@ -28,7 +90,31 @@ struct at803x_hw_stat { + enum stat_access_type access_type; + }; + ++struct at803x_ss_mask { ++ u16 speed_mask; ++ u8 speed_shift; ++}; ++ + int at803x_debug_reg_read(struct phy_device *phydev, u16 reg); + int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, + u16 clear, u16 set); + int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data); ++int at803x_set_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol); ++void at803x_get_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol); ++int at803x_ack_interrupt(struct phy_device *phydev); ++int at803x_config_intr(struct phy_device *phydev); ++irqreturn_t at803x_handle_interrupt(struct phy_device *phydev); ++int at803x_read_specific_status(struct phy_device *phydev, ++ struct at803x_ss_mask ss_mask); ++int at803x_config_mdix(struct phy_device *phydev, u8 ctrl); ++int at803x_prepare_config_aneg(struct phy_device *phydev); ++int at803x_get_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, void *data); ++int at803x_set_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, const void *data); ++int at803x_cdt_fault_length(int dt); ++int at803x_cdt_start(struct phy_device *phydev, u32 cdt_start); ++int at803x_cdt_wait_for_completion(struct phy_device *phydev, ++ u32 cdt_en); diff --git a/lede/target/linux/generic/backport-6.1/713-v6.9-05-net-phy-qcom-detach-qca808x-PHY-driver-from-at803x.patch b/lede/target/linux/generic/backport-6.1/713-v6.9-05-net-phy-qcom-detach-qca808x-PHY-driver-from-at803x.patch new file mode 100644 index 0000000000..597dcea4c0 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/713-v6.9-05-net-phy-qcom-detach-qca808x-PHY-driver-from-at803x.patch @@ -0,0 +1,1936 @@ +From c89414adf2ec7cd9e7080c419aa5847f1db1009c Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 29 Jan 2024 15:15:23 +0100 +Subject: [PATCH 5/5] net: phy: qcom: detach qca808x PHY driver from at803x + +Almost all the QCA8081 PHY driver OPs are specific and only some of them +use the generic at803x. + +To make the at803x code slimmer, move all the specific qca808x regs and +functions to a dedicated PHY driver. + +Probe function and priv struct is reworked to allocate and use only the +qca808x specific data. Unused data from at803x PHY driver are dropped +from at803x priv struct. + +Also a new Kconfig is introduced QCA808X_PHY, to compile the newly +introduced PHY driver for QCA8081 PHY. + +As the Kconfig name starts with Qualcomm the same order is kept. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240129141600.2592-6-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/qcom/Kconfig | 6 + + drivers/net/phy/qcom/Makefile | 1 + + drivers/net/phy/qcom/at803x.c | 897 +------------------------------ + drivers/net/phy/qcom/qca808x.c | 934 +++++++++++++++++++++++++++++++++ + 4 files changed, 942 insertions(+), 896 deletions(-) + create mode 100644 drivers/net/phy/qcom/qca808x.c + +--- a/drivers/net/phy/qcom/Kconfig ++++ b/drivers/net/phy/qcom/Kconfig +@@ -14,3 +14,9 @@ config QCA83XX_PHY + select QCOM_NET_PHYLIB + help + Currently supports the internal QCA8337(Internal qca8k PHY) model ++ ++config QCA808X_PHY ++ tristate "Qualcomm QCA808x PHYs" ++ select QCOM_NET_PHYLIB ++ help ++ Currently supports the QCA8081 model +--- a/drivers/net/phy/qcom/Makefile ++++ b/drivers/net/phy/qcom/Makefile +@@ -2,3 +2,4 @@ + obj-$(CONFIG_QCOM_NET_PHYLIB) += qcom-phy-lib.o + obj-$(CONFIG_AT803X_PHY) += at803x.o + obj-$(CONFIG_QCA83XX_PHY) += qca83xx.o ++obj-$(CONFIG_QCA808X_PHY) += qca808x.o +--- a/drivers/net/phy/qcom/at803x.c ++++ b/drivers/net/phy/qcom/at803x.c +@@ -96,8 +96,6 @@ + #define ATH8035_PHY_ID 0x004dd072 + #define AT8030_PHY_ID_MASK 0xffffffef + +-#define QCA8081_PHY_ID 0x004dd101 +- + #define QCA9561_PHY_ID 0x004dd042 + + #define AT803X_PAGE_FIBER 0 +@@ -110,201 +108,7 @@ + /* disable hibernation mode */ + #define AT803X_DISABLE_HIBERNATION_MODE BIT(2) + +-/* ADC threshold */ +-#define QCA808X_PHY_DEBUG_ADC_THRESHOLD 0x2c80 +-#define QCA808X_ADC_THRESHOLD_MASK GENMASK(7, 0) +-#define QCA808X_ADC_THRESHOLD_80MV 0 +-#define QCA808X_ADC_THRESHOLD_100MV 0xf0 +-#define QCA808X_ADC_THRESHOLD_200MV 0x0f +-#define QCA808X_ADC_THRESHOLD_300MV 0xff +- +-/* CLD control */ +-#define QCA808X_PHY_MMD3_ADDR_CLD_CTRL7 0x8007 +-#define QCA808X_8023AZ_AFE_CTRL_MASK GENMASK(8, 4) +-#define QCA808X_8023AZ_AFE_EN 0x90 +- +-/* AZ control */ +-#define QCA808X_PHY_MMD3_AZ_TRAINING_CTRL 0x8008 +-#define QCA808X_MMD3_AZ_TRAINING_VAL 0x1c32 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB 0x8014 +-#define QCA808X_MSE_THRESHOLD_20DB_VALUE 0x529 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB 0x800E +-#define QCA808X_MSE_THRESHOLD_17DB_VALUE 0x341 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB 0x801E +-#define QCA808X_MSE_THRESHOLD_27DB_VALUE 0x419 +- +-#define QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB 0x8020 +-#define QCA808X_MSE_THRESHOLD_28DB_VALUE 0x341 +- +-#define QCA808X_PHY_MMD7_TOP_OPTION1 0x901c +-#define QCA808X_TOP_OPTION1_DATA 0x0 +- +-#define QCA808X_PHY_MMD3_DEBUG_1 0xa100 +-#define QCA808X_MMD3_DEBUG_1_VALUE 0x9203 +-#define QCA808X_PHY_MMD3_DEBUG_2 0xa101 +-#define QCA808X_MMD3_DEBUG_2_VALUE 0x48ad +-#define QCA808X_PHY_MMD3_DEBUG_3 0xa103 +-#define QCA808X_MMD3_DEBUG_3_VALUE 0x1698 +-#define QCA808X_PHY_MMD3_DEBUG_4 0xa105 +-#define QCA808X_MMD3_DEBUG_4_VALUE 0x8001 +-#define QCA808X_PHY_MMD3_DEBUG_5 0xa106 +-#define QCA808X_MMD3_DEBUG_5_VALUE 0x1111 +-#define QCA808X_PHY_MMD3_DEBUG_6 0xa011 +-#define QCA808X_MMD3_DEBUG_6_VALUE 0x5f85 +- +-/* master/slave seed config */ +-#define QCA808X_PHY_DEBUG_LOCAL_SEED 9 +-#define QCA808X_MASTER_SLAVE_SEED_ENABLE BIT(1) +-#define QCA808X_MASTER_SLAVE_SEED_CFG GENMASK(12, 2) +-#define QCA808X_MASTER_SLAVE_SEED_RANGE 0x32 +- +-/* Hibernation yields lower power consumpiton in contrast with normal operation mode. +- * when the copper cable is unplugged, the PHY enters into hibernation mode in about 10s. +- */ +-#define QCA808X_DBG_AN_TEST 0xb +-#define QCA808X_HIBERNATION_EN BIT(15) +- +-#define QCA808X_CDT_ENABLE_TEST BIT(15) +-#define QCA808X_CDT_INTER_CHECK_DIS BIT(13) +-#define QCA808X_CDT_STATUS BIT(11) +-#define QCA808X_CDT_LENGTH_UNIT BIT(10) +- +-#define QCA808X_MMD3_CDT_STATUS 0x8064 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 +-#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) +-#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) +- +-#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) +-#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) +-#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) +-#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) +- +-#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) +-#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) +-#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) +-#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) +-#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) +- +-#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) +-#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) +-#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) +-#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) +- +-/* NORMAL are MDI with type set to 0 */ +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI1) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI1) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI2) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI2) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI3) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI3) +- +-/* Added for reference of existence but should be handled by wait_for_completion already */ +-#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) +- +-#define QCA808X_MMD7_LED_GLOBAL 0x8073 +-#define QCA808X_LED_BLINK_1 GENMASK(11, 6) +-#define QCA808X_LED_BLINK_2 GENMASK(5, 0) +-/* Values are the same for both BLINK_1 and BLINK_2 */ +-#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3) +-#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0) +-#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1) +-#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2) +-#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3) +-#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4) +-#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5) +-#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6) +-#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7) +-#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0) +-#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0) +-#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1) +-#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2) +-#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3) +-#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4) +-#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5) +-#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6) +-#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7) +- +-#define QCA808X_MMD7_LED2_CTRL 0x8074 +-#define QCA808X_MMD7_LED2_FORCE_CTRL 0x8075 +-#define QCA808X_MMD7_LED1_CTRL 0x8076 +-#define QCA808X_MMD7_LED1_FORCE_CTRL 0x8077 +-#define QCA808X_MMD7_LED0_CTRL 0x8078 +-#define QCA808X_MMD7_LED_CTRL(x) (0x8078 - ((x) * 2)) +- +-/* LED hw control pattern is the same for every LED */ +-#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) +-#define QCA808X_LED_SPEED2500_ON BIT(15) +-#define QCA808X_LED_SPEED2500_BLINK BIT(14) +-/* Follow blink trigger even if duplex or speed condition doesn't match */ +-#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) +-#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) +-#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) +-#define QCA808X_LED_TX_BLINK BIT(10) +-#define QCA808X_LED_RX_BLINK BIT(9) +-#define QCA808X_LED_TX_ON_10MS BIT(8) +-#define QCA808X_LED_RX_ON_10MS BIT(7) +-#define QCA808X_LED_SPEED1000_ON BIT(6) +-#define QCA808X_LED_SPEED100_ON BIT(5) +-#define QCA808X_LED_SPEED10_ON BIT(4) +-#define QCA808X_LED_COLLISION_BLINK BIT(3) +-#define QCA808X_LED_SPEED1000_BLINK BIT(2) +-#define QCA808X_LED_SPEED100_BLINK BIT(1) +-#define QCA808X_LED_SPEED10_BLINK BIT(0) +- +-#define QCA808X_MMD7_LED0_FORCE_CTRL 0x8079 +-#define QCA808X_MMD7_LED_FORCE_CTRL(x) (0x8079 - ((x) * 2)) +- +-/* LED force ctrl is the same for every LED +- * No documentation exist for this, not even internal one +- * with NDA as QCOM gives only info about configuring +- * hw control pattern rules and doesn't indicate any way +- * to force the LED to specific mode. +- * These define comes from reverse and testing and maybe +- * lack of some info or some info are not entirely correct. +- * For the basic LED control and hw control these finding +- * are enough to support LED control in all the required APIs. +- * +- * On doing some comparison with implementation with qca807x, +- * it was found that it's 1:1 equal to it and confirms all the +- * reverse done. It was also found further specification with the +- * force mode and the blink modes. +- */ +-#define QCA808X_LED_FORCE_EN BIT(15) +-#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13) +-#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3) +-#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2) +-#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1) +-#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0) +- +-#define QCA808X_MMD7_LED_POLARITY_CTRL 0x901a +-/* QSDK sets by default 0x46 to this reg that sets BIT 6 for +- * LED to active high. It's not clear what BIT 3 and BIT 4 does. +- */ +-#define QCA808X_LED_ACTIVE_HIGH BIT(6) +- +-/* QCA808X 1G chip type */ +-#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d +-#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) +- +-#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 +-#define QCA8081_PHY_FIFO_RSTN BIT(11) +- +-MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); ++MODULE_DESCRIPTION("Qualcomm Atheros AR803x PHY driver"); + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); + +@@ -318,7 +122,6 @@ struct at803x_priv { + bool is_1000basex; + struct regulator_dev *vddio_rdev; + struct regulator_dev *vddh_rdev; +- int led_polarity_mode; + }; + + struct at803x_context { +@@ -519,9 +322,6 @@ static int at803x_probe(struct phy_devic + if (!priv) + return -ENOMEM; + +- /* Init LED polarity mode to -1 */ +- priv->led_polarity_mode = -1; +- + phydev->priv = priv; + + ret = at803x_parse_dt(phydev); +@@ -1216,672 +1016,6 @@ static int at8035_probe(struct phy_devic + return at8035_parse_dt(phydev); + } + +-static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) +-{ +- int ret; +- +- /* Enable fast retrain */ +- ret = genphy_c45_fast_retrain(phydev, true); +- if (ret) +- return ret; +- +- phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1, +- QCA808X_TOP_OPTION1_DATA); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB, +- QCA808X_MSE_THRESHOLD_20DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB, +- QCA808X_MSE_THRESHOLD_17DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB, +- QCA808X_MSE_THRESHOLD_27DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB, +- QCA808X_MSE_THRESHOLD_28DB_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1, +- QCA808X_MMD3_DEBUG_1_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4, +- QCA808X_MMD3_DEBUG_4_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5, +- QCA808X_MMD3_DEBUG_5_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3, +- QCA808X_MMD3_DEBUG_3_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6, +- QCA808X_MMD3_DEBUG_6_VALUE); +- phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2, +- QCA808X_MMD3_DEBUG_2_VALUE); +- +- return 0; +-} +- +-static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) +-{ +- u16 seed_value; +- +- if (!enable) +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); +- +- seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, +- FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | +- QCA808X_MASTER_SLAVE_SEED_ENABLE); +-} +- +-static bool qca808x_is_prefer_master(struct phy_device *phydev) +-{ +- return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || +- (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); +-} +- +-static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) +-{ +- return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); +-} +- +-static int qca808x_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- /* Active adc&vga on 802.3az for the link 1000M and 100M */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, +- QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); +- if (ret) +- return ret; +- +- /* Adjust the threshold on 802.3az for the link 1000M */ +- ret = phy_write_mmd(phydev, MDIO_MMD_PCS, +- QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, +- QCA808X_MMD3_AZ_TRAINING_VAL); +- if (ret) +- return ret; +- +- if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { +- /* Config the fast retrain for the link 2500M */ +- ret = qca808x_phy_fast_retrain_config(phydev); +- if (ret) +- return ret; +- +- ret = genphy_read_master_slave(phydev); +- if (ret < 0) +- return ret; +- +- if (!qca808x_is_prefer_master(phydev)) { +- /* Enable seed and configure lower ramdom seed to make phy +- * linked as slave mode. +- */ +- ret = qca808x_phy_ms_seed_enable(phydev, true); +- if (ret) +- return ret; +- } +- } +- +- /* Configure adc threshold as 100mv for the link 10M */ +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, +- QCA808X_ADC_THRESHOLD_MASK, +- QCA808X_ADC_THRESHOLD_100MV); +-} +- +-static int qca808x_read_status(struct phy_device *phydev) +-{ +- struct at803x_ss_mask ss_mask = { 0 }; +- int ret; +- +- ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); +- if (ret < 0) +- return ret; +- +- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising, +- ret & MDIO_AN_10GBT_STAT_LP2_5G); +- +- ret = genphy_read_status(phydev); +- if (ret) +- return ret; +- +- /* qca8081 takes the different bits for speed value from at803x */ +- ss_mask.speed_mask = QCA808X_SS_SPEED_MASK; +- ss_mask.speed_shift = __bf_shf(QCA808X_SS_SPEED_MASK); +- ret = at803x_read_specific_status(phydev, ss_mask); +- if (ret < 0) +- return ret; +- +- if (phydev->link) { +- if (phydev->speed == SPEED_2500) +- phydev->interface = PHY_INTERFACE_MODE_2500BASEX; +- else +- phydev->interface = PHY_INTERFACE_MODE_SGMII; +- } else { +- /* generate seed as a lower random value to make PHY linked as SLAVE easily, +- * except for master/slave configuration fault detected or the master mode +- * preferred. +- * +- * the reason for not putting this code into the function link_change_notify is +- * the corner case where the link partner is also the qca8081 PHY and the seed +- * value is configured as the same value, the link can't be up and no link change +- * occurs. +- */ +- if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { +- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || +- qca808x_is_prefer_master(phydev)) { +- qca808x_phy_ms_seed_enable(phydev, false); +- } else { +- qca808x_phy_ms_seed_enable(phydev, true); +- } +- } +- } +- +- return 0; +-} +- +-static int qca808x_soft_reset(struct phy_device *phydev) +-{ +- int ret; +- +- ret = genphy_soft_reset(phydev); +- if (ret < 0) +- return ret; +- +- if (qca808x_has_fast_retrain_or_slave_seed(phydev)) +- ret = qca808x_phy_ms_seed_enable(phydev, true); +- +- return ret; +-} +- +-static bool qca808x_cdt_fault_length_valid(int cdt_code) +-{ +- switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: +- return true; +- default: +- return false; +- } +-} +- +-static int qca808x_cable_test_result_trans(int cdt_code) +-{ +- switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_NORMAL: +- return ETHTOOL_A_CABLE_RESULT_CODE_OK; +- case QCA808X_CDT_STATUS_STAT_SAME_SHORT: +- return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; +- case QCA808X_CDT_STATUS_STAT_SAME_OPEN: +- return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: +- return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; +- case QCA808X_CDT_STATUS_STAT_FAIL: +- default: +- return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; +- } +-} +- +-static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, +- int result) +-{ +- int val; +- u32 cdt_length_reg = 0; +- +- switch (pair) { +- case ETHTOOL_A_CABLE_PAIR_A: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A; +- break; +- case ETHTOOL_A_CABLE_PAIR_B: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B; +- break; +- case ETHTOOL_A_CABLE_PAIR_C: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C; +- break; +- case ETHTOOL_A_CABLE_PAIR_D: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D; +- break; +- default: +- return -EINVAL; +- } +- +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg); +- if (val < 0) +- return val; +- +- if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); +- else +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); +- +- return at803x_cdt_fault_length(val); +-} +- +-static int qca808x_cable_test_start(struct phy_device *phydev) +-{ +- int ret; +- +- /* perform CDT with the following configs: +- * 1. disable hibernation. +- * 2. force PHY working in MDI mode. +- * 3. for PHY working in 1000BaseT. +- * 4. configure the threshold. +- */ +- +- ret = at803x_debug_reg_mask(phydev, QCA808X_DBG_AN_TEST, QCA808X_HIBERNATION_EN, 0); +- if (ret < 0) +- return ret; +- +- ret = at803x_config_mdix(phydev, ETH_TP_MDI); +- if (ret < 0) +- return ret; +- +- /* Force 1000base-T needs to configure PMA/PMD and MII_BMCR */ +- phydev->duplex = DUPLEX_FULL; +- phydev->speed = SPEED_1000; +- ret = genphy_c45_pma_setup_forced(phydev); +- if (ret < 0) +- return ret; +- +- ret = genphy_setup_forced(phydev); +- if (ret < 0) +- return ret; +- +- /* configure the thresholds for open, short, pair ok test */ +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8074, 0xc040); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8076, 0xc040); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8077, 0xa060); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8078, 0xc050); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807a, 0xc060); +- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807e, 0xb060); +- +- return 0; +-} +- +-static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, +- u16 status) +-{ +- int length, result; +- u16 pair_code; +- +- switch (pair) { +- case ETHTOOL_A_CABLE_PAIR_A: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_B: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_C: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_D: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); +- break; +- default: +- return -EINVAL; +- } +- +- result = qca808x_cable_test_result_trans(pair_code); +- ethnl_cable_test_result(phydev, pair, result); +- +- if (qca808x_cdt_fault_length_valid(pair_code)) { +- length = qca808x_cdt_fault_length(phydev, pair, result); +- ethnl_cable_test_fault_length(phydev, pair, length); +- } +- +- return 0; +-} +- +-static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) +-{ +- int ret, val; +- +- *finished = false; +- +- val = QCA808X_CDT_ENABLE_TEST | +- QCA808X_CDT_LENGTH_UNIT; +- ret = at803x_cdt_start(phydev, val); +- if (ret) +- return ret; +- +- ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); +- if (ret) +- return ret; +- +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS); +- if (val < 0) +- return val; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); +- if (ret) +- return ret; +- +- *finished = true; +- +- return 0; +-} +- +-static int qca808x_get_features(struct phy_device *phydev) +-{ +- int ret; +- +- ret = genphy_c45_pma_read_abilities(phydev); +- if (ret) +- return ret; +- +- /* The autoneg ability is not existed in bit3 of MMD7.1, +- * but it is supported by qca808x PHY, so we add it here +- * manually. +- */ +- linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); +- +- /* As for the qca8081 1G version chip, the 2500baseT ability is also +- * existed in the bit0 of MMD1.21, we need to remove it manually if +- * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. +- */ +- ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); +- if (ret < 0) +- return ret; +- +- if (QCA808X_PHY_CHIP_TYPE_1G & ret) +- linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); +- +- return 0; +-} +- +-static int qca808x_config_aneg(struct phy_device *phydev) +-{ +- int phy_ctrl = 0; +- int ret; +- +- ret = at803x_prepare_config_aneg(phydev); +- if (ret) +- return ret; +- +- /* The reg MII_BMCR also needs to be configured for force mode, the +- * genphy_config_aneg is also needed. +- */ +- if (phydev->autoneg == AUTONEG_DISABLE) +- genphy_c45_pma_setup_forced(phydev); +- +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) +- phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; +- +- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, +- MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); +- if (ret < 0) +- return ret; +- +- return __genphy_config_aneg(phydev, ret); +-} +- +-static void qca808x_link_change_notify(struct phy_device *phydev) +-{ +- /* Assert interface sgmii fifo on link down, deassert it on link up, +- * the interface device address is always phy address added by 1. +- */ +- mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, +- MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, +- QCA8081_PHY_FIFO_RSTN, +- phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); +-} +- +-static int qca808x_led_parse_netdev(struct phy_device *phydev, unsigned long rules, +- u16 *offload_trigger) +-{ +- /* Parsing specific to netdev trigger */ +- if (test_bit(TRIGGER_NETDEV_TX, &rules)) +- *offload_trigger |= QCA808X_LED_TX_BLINK; +- if (test_bit(TRIGGER_NETDEV_RX, &rules)) +- *offload_trigger |= QCA808X_LED_RX_BLINK; +- if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED10_ON; +- if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED100_ON; +- if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED1000_ON; +- if (test_bit(TRIGGER_NETDEV_LINK_2500, &rules)) +- *offload_trigger |= QCA808X_LED_SPEED2500_ON; +- if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) +- *offload_trigger |= QCA808X_LED_HALF_DUPLEX_ON; +- if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) +- *offload_trigger |= QCA808X_LED_FULL_DUPLEX_ON; +- +- if (rules && !*offload_trigger) +- return -EOPNOTSUPP; +- +- /* Enable BLINK_CHECK_BYPASS by default to make the LED +- * blink even with duplex or speed mode not enabled. +- */ +- *offload_trigger |= QCA808X_LED_BLINK_CHECK_BYPASS; +- +- return 0; +-} +- +-static int qca808x_led_hw_control_enable(struct phy_device *phydev, u8 index) +-{ +- u16 reg; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN); +-} +- +-static int qca808x_led_hw_is_supported(struct phy_device *phydev, u8 index, +- unsigned long rules) +-{ +- u16 offload_trigger = 0; +- +- if (index > 2) +- return -EINVAL; +- +- return qca808x_led_parse_netdev(phydev, rules, &offload_trigger); +-} +- +-static int qca808x_led_hw_control_set(struct phy_device *phydev, u8 index, +- unsigned long rules) +-{ +- u16 reg, offload_trigger = 0; +- int ret; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_CTRL(index); +- +- ret = qca808x_led_parse_netdev(phydev, rules, &offload_trigger); +- if (ret) +- return ret; +- +- ret = qca808x_led_hw_control_enable(phydev, index); +- if (ret) +- return ret; +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_PATTERN_MASK, +- offload_trigger); +-} +- +-static bool qca808x_led_hw_control_status(struct phy_device *phydev, u8 index) +-{ +- u16 reg; +- int val; +- +- if (index > 2) +- return false; +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); +- +- return !(val & QCA808X_LED_FORCE_EN); +-} +- +-static int qca808x_led_hw_control_get(struct phy_device *phydev, u8 index, +- unsigned long *rules) +-{ +- u16 reg; +- int val; +- +- if (index > 2) +- return -EINVAL; +- +- /* Check if we have hw control enabled */ +- if (qca808x_led_hw_control_status(phydev, index)) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_CTRL(index); +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); +- if (val & QCA808X_LED_TX_BLINK) +- set_bit(TRIGGER_NETDEV_TX, rules); +- if (val & QCA808X_LED_RX_BLINK) +- set_bit(TRIGGER_NETDEV_RX, rules); +- if (val & QCA808X_LED_SPEED10_ON) +- set_bit(TRIGGER_NETDEV_LINK_10, rules); +- if (val & QCA808X_LED_SPEED100_ON) +- set_bit(TRIGGER_NETDEV_LINK_100, rules); +- if (val & QCA808X_LED_SPEED1000_ON) +- set_bit(TRIGGER_NETDEV_LINK_1000, rules); +- if (val & QCA808X_LED_SPEED2500_ON) +- set_bit(TRIGGER_NETDEV_LINK_2500, rules); +- if (val & QCA808X_LED_HALF_DUPLEX_ON) +- set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); +- if (val & QCA808X_LED_FULL_DUPLEX_ON) +- set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); +- +- return 0; +-} +- +-static int qca808x_led_hw_control_reset(struct phy_device *phydev, u8 index) +-{ +- u16 reg; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_CTRL(index); +- +- return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_PATTERN_MASK); +-} +- +-static int qca808x_led_brightness_set(struct phy_device *phydev, +- u8 index, enum led_brightness value) +-{ +- u16 reg; +- int ret; +- +- if (index > 2) +- return -EINVAL; +- +- if (!value) { +- ret = qca808x_led_hw_control_reset(phydev, index); +- if (ret) +- return ret; +- } +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, +- QCA808X_LED_FORCE_EN | value ? QCA808X_LED_FORCE_ON : +- QCA808X_LED_FORCE_OFF); +-} +- +-static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, +- unsigned long *delay_on, +- unsigned long *delay_off) +-{ +- int ret; +- u16 reg; +- +- if (index > 2) +- return -EINVAL; +- +- reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- /* Set blink to 50% off, 50% on at 4Hz by default */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL, +- QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK, +- QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50); +- if (ret) +- return ret; +- +- /* We use BLINK_1 for normal blinking */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1); +- if (ret) +- return ret; +- +- /* We set blink to 4Hz, aka 250ms */ +- *delay_on = 250 / 2; +- *delay_off = 250 / 2; +- +- return 0; +-} +- +-static int qca808x_led_polarity_set(struct phy_device *phydev, int index, +- unsigned long modes) +-{ +- struct at803x_priv *priv = phydev->priv; +- bool active_low = false; +- u32 mode; +- +- for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { +- switch (mode) { +- case PHY_LED_ACTIVE_LOW: +- active_low = true; +- break; +- default: +- return -EINVAL; +- } +- } +- +- /* PHY polarity is global and can't be set per LED. +- * To detect this, check if last requested polarity mode +- * match the new one. +- */ +- if (priv->led_polarity_mode >= 0 && +- priv->led_polarity_mode != active_low) { +- phydev_err(phydev, "PHY polarity is global. Mismatched polarity on different LED\n"); +- return -EINVAL; +- } +- +- /* Save the last PHY polarity mode */ +- priv->led_polarity_mode = active_low; +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, +- QCA808X_MMD7_LED_POLARITY_CTRL, +- QCA808X_LED_ACTIVE_HIGH, +- active_low ? 0 : QCA808X_LED_ACTIVE_HIGH); +-} +- + static struct phy_driver at803x_driver[] = { + { + /* Qualcomm Atheros AR8035 */ +@@ -1989,34 +1123,6 @@ static struct phy_driver at803x_driver[] + .read_status = at803x_read_status, + .soft_reset = genphy_soft_reset, + .config_aneg = at803x_config_aneg, +-}, { +- /* Qualcomm QCA8081 */ +- PHY_ID_MATCH_EXACT(QCA8081_PHY_ID), +- .name = "Qualcomm QCA8081", +- .flags = PHY_POLL_CABLE_TEST, +- .probe = at803x_probe, +- .config_intr = at803x_config_intr, +- .handle_interrupt = at803x_handle_interrupt, +- .get_tunable = at803x_get_tunable, +- .set_tunable = at803x_set_tunable, +- .set_wol = at803x_set_wol, +- .get_wol = at803x_get_wol, +- .get_features = qca808x_get_features, +- .config_aneg = qca808x_config_aneg, +- .suspend = genphy_suspend, +- .resume = genphy_resume, +- .read_status = qca808x_read_status, +- .config_init = qca808x_config_init, +- .soft_reset = qca808x_soft_reset, +- .cable_test_start = qca808x_cable_test_start, +- .cable_test_get_status = qca808x_cable_test_get_status, +- .link_change_notify = qca808x_link_change_notify, +- .led_brightness_set = qca808x_led_brightness_set, +- .led_blink_set = qca808x_led_blink_set, +- .led_hw_is_supported = qca808x_led_hw_is_supported, +- .led_hw_control_set = qca808x_led_hw_control_set, +- .led_hw_control_get = qca808x_led_hw_control_get, +- .led_polarity_set = qca808x_led_polarity_set, + }, }; + + module_phy_driver(at803x_driver); +@@ -2028,7 +1134,6 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) }, + { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) }, + { PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) }, +- { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) }, + { } + }; + +--- /dev/null ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -0,0 +1,934 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++ ++#include ++#include ++#include ++ ++#include "qcom.h" ++ ++/* ADC threshold */ ++#define QCA808X_PHY_DEBUG_ADC_THRESHOLD 0x2c80 ++#define QCA808X_ADC_THRESHOLD_MASK GENMASK(7, 0) ++#define QCA808X_ADC_THRESHOLD_80MV 0 ++#define QCA808X_ADC_THRESHOLD_100MV 0xf0 ++#define QCA808X_ADC_THRESHOLD_200MV 0x0f ++#define QCA808X_ADC_THRESHOLD_300MV 0xff ++ ++/* CLD control */ ++#define QCA808X_PHY_MMD3_ADDR_CLD_CTRL7 0x8007 ++#define QCA808X_8023AZ_AFE_CTRL_MASK GENMASK(8, 4) ++#define QCA808X_8023AZ_AFE_EN 0x90 ++ ++/* AZ control */ ++#define QCA808X_PHY_MMD3_AZ_TRAINING_CTRL 0x8008 ++#define QCA808X_MMD3_AZ_TRAINING_VAL 0x1c32 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB 0x8014 ++#define QCA808X_MSE_THRESHOLD_20DB_VALUE 0x529 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB 0x800E ++#define QCA808X_MSE_THRESHOLD_17DB_VALUE 0x341 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB 0x801E ++#define QCA808X_MSE_THRESHOLD_27DB_VALUE 0x419 ++ ++#define QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB 0x8020 ++#define QCA808X_MSE_THRESHOLD_28DB_VALUE 0x341 ++ ++#define QCA808X_PHY_MMD7_TOP_OPTION1 0x901c ++#define QCA808X_TOP_OPTION1_DATA 0x0 ++ ++#define QCA808X_PHY_MMD3_DEBUG_1 0xa100 ++#define QCA808X_MMD3_DEBUG_1_VALUE 0x9203 ++#define QCA808X_PHY_MMD3_DEBUG_2 0xa101 ++#define QCA808X_MMD3_DEBUG_2_VALUE 0x48ad ++#define QCA808X_PHY_MMD3_DEBUG_3 0xa103 ++#define QCA808X_MMD3_DEBUG_3_VALUE 0x1698 ++#define QCA808X_PHY_MMD3_DEBUG_4 0xa105 ++#define QCA808X_MMD3_DEBUG_4_VALUE 0x8001 ++#define QCA808X_PHY_MMD3_DEBUG_5 0xa106 ++#define QCA808X_MMD3_DEBUG_5_VALUE 0x1111 ++#define QCA808X_PHY_MMD3_DEBUG_6 0xa011 ++#define QCA808X_MMD3_DEBUG_6_VALUE 0x5f85 ++ ++/* master/slave seed config */ ++#define QCA808X_PHY_DEBUG_LOCAL_SEED 9 ++#define QCA808X_MASTER_SLAVE_SEED_ENABLE BIT(1) ++#define QCA808X_MASTER_SLAVE_SEED_CFG GENMASK(12, 2) ++#define QCA808X_MASTER_SLAVE_SEED_RANGE 0x32 ++ ++/* Hibernation yields lower power consumpiton in contrast with normal operation mode. ++ * when the copper cable is unplugged, the PHY enters into hibernation mode in about 10s. ++ */ ++#define QCA808X_DBG_AN_TEST 0xb ++#define QCA808X_HIBERNATION_EN BIT(15) ++ ++#define QCA808X_CDT_ENABLE_TEST BIT(15) ++#define QCA808X_CDT_INTER_CHECK_DIS BIT(13) ++#define QCA808X_CDT_STATUS BIT(11) ++#define QCA808X_CDT_LENGTH_UNIT BIT(10) ++ ++#define QCA808X_MMD3_CDT_STATUS 0x8064 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 ++#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) ++#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) ++ ++#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) ++#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) ++#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) ++#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) ++ ++#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) ++#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) ++#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) ++#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) ++#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) ++ ++#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) ++#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) ++ ++/* NORMAL are MDI with type set to 0 */ ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++ ++/* Added for reference of existence but should be handled by wait_for_completion already */ ++#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) ++ ++#define QCA808X_MMD7_LED_GLOBAL 0x8073 ++#define QCA808X_LED_BLINK_1 GENMASK(11, 6) ++#define QCA808X_LED_BLINK_2 GENMASK(5, 0) ++/* Values are the same for both BLINK_1 and BLINK_2 */ ++#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3) ++#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0) ++#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1) ++#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2) ++#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3) ++#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4) ++#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5) ++#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6) ++#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7) ++#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0) ++#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0) ++#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1) ++#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2) ++#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3) ++#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4) ++#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5) ++#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6) ++#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7) ++ ++#define QCA808X_MMD7_LED2_CTRL 0x8074 ++#define QCA808X_MMD7_LED2_FORCE_CTRL 0x8075 ++#define QCA808X_MMD7_LED1_CTRL 0x8076 ++#define QCA808X_MMD7_LED1_FORCE_CTRL 0x8077 ++#define QCA808X_MMD7_LED0_CTRL 0x8078 ++#define QCA808X_MMD7_LED_CTRL(x) (0x8078 - ((x) * 2)) ++ ++/* LED hw control pattern is the same for every LED */ ++#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) ++#define QCA808X_LED_SPEED2500_ON BIT(15) ++#define QCA808X_LED_SPEED2500_BLINK BIT(14) ++/* Follow blink trigger even if duplex or speed condition doesn't match */ ++#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) ++#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) ++#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) ++#define QCA808X_LED_TX_BLINK BIT(10) ++#define QCA808X_LED_RX_BLINK BIT(9) ++#define QCA808X_LED_TX_ON_10MS BIT(8) ++#define QCA808X_LED_RX_ON_10MS BIT(7) ++#define QCA808X_LED_SPEED1000_ON BIT(6) ++#define QCA808X_LED_SPEED100_ON BIT(5) ++#define QCA808X_LED_SPEED10_ON BIT(4) ++#define QCA808X_LED_COLLISION_BLINK BIT(3) ++#define QCA808X_LED_SPEED1000_BLINK BIT(2) ++#define QCA808X_LED_SPEED100_BLINK BIT(1) ++#define QCA808X_LED_SPEED10_BLINK BIT(0) ++ ++#define QCA808X_MMD7_LED0_FORCE_CTRL 0x8079 ++#define QCA808X_MMD7_LED_FORCE_CTRL(x) (0x8079 - ((x) * 2)) ++ ++/* LED force ctrl is the same for every LED ++ * No documentation exist for this, not even internal one ++ * with NDA as QCOM gives only info about configuring ++ * hw control pattern rules and doesn't indicate any way ++ * to force the LED to specific mode. ++ * These define comes from reverse and testing and maybe ++ * lack of some info or some info are not entirely correct. ++ * For the basic LED control and hw control these finding ++ * are enough to support LED control in all the required APIs. ++ * ++ * On doing some comparison with implementation with qca807x, ++ * it was found that it's 1:1 equal to it and confirms all the ++ * reverse done. It was also found further specification with the ++ * force mode and the blink modes. ++ */ ++#define QCA808X_LED_FORCE_EN BIT(15) ++#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13) ++#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3) ++#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2) ++#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1) ++#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0) ++ ++#define QCA808X_MMD7_LED_POLARITY_CTRL 0x901a ++/* QSDK sets by default 0x46 to this reg that sets BIT 6 for ++ * LED to active high. It's not clear what BIT 3 and BIT 4 does. ++ */ ++#define QCA808X_LED_ACTIVE_HIGH BIT(6) ++ ++/* QCA808X 1G chip type */ ++#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d ++#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) ++ ++#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 ++#define QCA8081_PHY_FIFO_RSTN BIT(11) ++ ++#define QCA8081_PHY_ID 0x004dd101 ++ ++MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); ++MODULE_AUTHOR("Matus Ujhelyi"); ++MODULE_LICENSE("GPL"); ++ ++struct qca808x_priv { ++ int led_polarity_mode; ++}; ++ ++static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Enable fast retrain */ ++ ret = genphy_c45_fast_retrain(phydev, true); ++ if (ret) ++ return ret; ++ ++ phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1, ++ QCA808X_TOP_OPTION1_DATA); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB, ++ QCA808X_MSE_THRESHOLD_20DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB, ++ QCA808X_MSE_THRESHOLD_17DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB, ++ QCA808X_MSE_THRESHOLD_27DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB, ++ QCA808X_MSE_THRESHOLD_28DB_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1, ++ QCA808X_MMD3_DEBUG_1_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4, ++ QCA808X_MMD3_DEBUG_4_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5, ++ QCA808X_MMD3_DEBUG_5_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3, ++ QCA808X_MMD3_DEBUG_3_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6, ++ QCA808X_MMD3_DEBUG_6_VALUE); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2, ++ QCA808X_MMD3_DEBUG_2_VALUE); ++ ++ return 0; ++} ++ ++static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) ++{ ++ u16 seed_value; ++ ++ if (!enable) ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, ++ QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); ++ ++ seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, ++ QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, ++ FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | ++ QCA808X_MASTER_SLAVE_SEED_ENABLE); ++} ++ ++static bool qca808x_is_prefer_master(struct phy_device *phydev) ++{ ++ return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || ++ (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); ++} ++ ++static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) ++{ ++ return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++} ++ ++static int qca808x_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct qca808x_priv *priv; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ /* Init LED polarity mode to -1 */ ++ priv->led_polarity_mode = -1; ++ ++ phydev->priv = priv; ++ ++ return 0; ++} ++ ++static int qca808x_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Active adc&vga on 802.3az for the link 1000M and 100M */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, ++ QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); ++ if (ret) ++ return ret; ++ ++ /* Adjust the threshold on 802.3az for the link 1000M */ ++ ret = phy_write_mmd(phydev, MDIO_MMD_PCS, ++ QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, ++ QCA808X_MMD3_AZ_TRAINING_VAL); ++ if (ret) ++ return ret; ++ ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ /* Config the fast retrain for the link 2500M */ ++ ret = qca808x_phy_fast_retrain_config(phydev); ++ if (ret) ++ return ret; ++ ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (!qca808x_is_prefer_master(phydev)) { ++ /* Enable seed and configure lower ramdom seed to make phy ++ * linked as slave mode. ++ */ ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ /* Configure adc threshold as 100mv for the link 10M */ ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, ++ QCA808X_ADC_THRESHOLD_MASK, ++ QCA808X_ADC_THRESHOLD_100MV); ++} ++ ++static int qca808x_read_status(struct phy_device *phydev) ++{ ++ struct at803x_ss_mask ss_mask = { 0 }; ++ int ret; ++ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); ++ if (ret < 0) ++ return ret; ++ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising, ++ ret & MDIO_AN_10GBT_STAT_LP2_5G); ++ ++ ret = genphy_read_status(phydev); ++ if (ret) ++ return ret; ++ ++ /* qca8081 takes the different bits for speed value from at803x */ ++ ss_mask.speed_mask = QCA808X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(QCA808X_SS_SPEED_MASK); ++ ret = at803x_read_specific_status(phydev, ss_mask); ++ if (ret < 0) ++ return ret; ++ ++ if (phydev->link) { ++ if (phydev->speed == SPEED_2500) ++ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; ++ else ++ phydev->interface = PHY_INTERFACE_MODE_SGMII; ++ } else { ++ /* generate seed as a lower random value to make PHY linked as SLAVE easily, ++ * except for master/slave configuration fault detected or the master mode ++ * preferred. ++ * ++ * the reason for not putting this code into the function link_change_notify is ++ * the corner case where the link partner is also the qca8081 PHY and the seed ++ * value is configured as the same value, the link can't be up and no link change ++ * occurs. ++ */ ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || ++ qca808x_is_prefer_master(phydev)) { ++ qca808x_phy_ms_seed_enable(phydev, false); ++ } else { ++ qca808x_phy_ms_seed_enable(phydev, true); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static int qca808x_soft_reset(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = genphy_soft_reset(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ ++ return ret; ++} ++ ++static bool qca808x_cdt_fault_length_valid(int cdt_code) ++{ ++ switch (cdt_code) { ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static int qca808x_cable_test_result_trans(int cdt_code) ++{ ++ switch (cdt_code) { ++ case QCA808X_CDT_STATUS_STAT_NORMAL: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OK; ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; ++ case QCA808X_CDT_STATUS_STAT_FAIL: ++ default: ++ return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; ++ } ++} ++ ++static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, ++ int result) ++{ ++ int val; ++ u32 cdt_length_reg = 0; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg); ++ if (val < 0) ++ return val; ++ ++ if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); ++ else ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); ++ ++ return at803x_cdt_fault_length(val); ++} ++ ++static int qca808x_cable_test_start(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* perform CDT with the following configs: ++ * 1. disable hibernation. ++ * 2. force PHY working in MDI mode. ++ * 3. for PHY working in 1000BaseT. ++ * 4. configure the threshold. ++ */ ++ ++ ret = at803x_debug_reg_mask(phydev, QCA808X_DBG_AN_TEST, QCA808X_HIBERNATION_EN, 0); ++ if (ret < 0) ++ return ret; ++ ++ ret = at803x_config_mdix(phydev, ETH_TP_MDI); ++ if (ret < 0) ++ return ret; ++ ++ /* Force 1000base-T needs to configure PMA/PMD and MII_BMCR */ ++ phydev->duplex = DUPLEX_FULL; ++ phydev->speed = SPEED_1000; ++ ret = genphy_c45_pma_setup_forced(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = genphy_setup_forced(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* configure the thresholds for open, short, pair ok test */ ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8074, 0xc040); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8076, 0xc040); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8077, 0xa060); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8078, 0xc050); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807a, 0xc060); ++ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807e, 0xb060); ++ ++ return 0; ++} ++ ++static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, ++ u16 status) ++{ ++ int length, result; ++ u16 pair_code; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ result = qca808x_cable_test_result_trans(pair_code); ++ ethnl_cable_test_result(phydev, pair, result); ++ ++ if (qca808x_cdt_fault_length_valid(pair_code)) { ++ length = qca808x_cdt_fault_length(phydev, pair, result); ++ ethnl_cable_test_fault_length(phydev, pair, length); ++ } ++ ++ return 0; ++} ++ ++static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) ++{ ++ int ret, val; ++ ++ *finished = false; ++ ++ val = QCA808X_CDT_ENABLE_TEST | ++ QCA808X_CDT_LENGTH_UNIT; ++ ret = at803x_cdt_start(phydev, val); ++ if (ret) ++ return ret; ++ ++ ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); ++ if (ret) ++ return ret; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS); ++ if (val < 0) ++ return val; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); ++ if (ret) ++ return ret; ++ ++ *finished = true; ++ ++ return 0; ++} ++ ++static int qca808x_get_features(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = genphy_c45_pma_read_abilities(phydev); ++ if (ret) ++ return ret; ++ ++ /* The autoneg ability is not existed in bit3 of MMD7.1, ++ * but it is supported by qca808x PHY, so we add it here ++ * manually. ++ */ ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); ++ ++ /* As for the qca8081 1G version chip, the 2500baseT ability is also ++ * existed in the bit0 of MMD1.21, we need to remove it manually if ++ * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. ++ */ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); ++ if (ret < 0) ++ return ret; ++ ++ if (QCA808X_PHY_CHIP_TYPE_1G & ret) ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++ ++ return 0; ++} ++ ++static int qca808x_config_aneg(struct phy_device *phydev) ++{ ++ int phy_ctrl = 0; ++ int ret; ++ ++ ret = at803x_prepare_config_aneg(phydev); ++ if (ret) ++ return ret; ++ ++ /* The reg MII_BMCR also needs to be configured for force mode, the ++ * genphy_config_aneg is also needed. ++ */ ++ if (phydev->autoneg == AUTONEG_DISABLE) ++ genphy_c45_pma_setup_forced(phydev); ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) ++ phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; ++ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, ++ MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); ++ if (ret < 0) ++ return ret; ++ ++ return __genphy_config_aneg(phydev, ret); ++} ++ ++static void qca808x_link_change_notify(struct phy_device *phydev) ++{ ++ /* Assert interface sgmii fifo on link down, deassert it on link up, ++ * the interface device address is always phy address added by 1. ++ */ ++ mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, ++ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, ++ QCA8081_PHY_FIFO_RSTN, ++ phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); ++} ++ ++static int qca808x_led_parse_netdev(struct phy_device *phydev, unsigned long rules, ++ u16 *offload_trigger) ++{ ++ /* Parsing specific to netdev trigger */ ++ if (test_bit(TRIGGER_NETDEV_TX, &rules)) ++ *offload_trigger |= QCA808X_LED_TX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_RX, &rules)) ++ *offload_trigger |= QCA808X_LED_RX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED10_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED100_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED1000_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_2500, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED2500_ON; ++ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_HALF_DUPLEX_ON; ++ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_FULL_DUPLEX_ON; ++ ++ if (rules && !*offload_trigger) ++ return -EOPNOTSUPP; ++ ++ /* Enable BLINK_CHECK_BYPASS by default to make the LED ++ * blink even with duplex or speed mode not enabled. ++ */ ++ *offload_trigger |= QCA808X_LED_BLINK_CHECK_BYPASS; ++ ++ return 0; ++} ++ ++static int qca808x_led_hw_control_enable(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN); ++} ++ ++static int qca808x_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 offload_trigger = 0; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ return qca808x_led_parse_netdev(phydev, rules, &offload_trigger); ++} ++ ++static int qca808x_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 reg, offload_trigger = 0; ++ int ret; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ ret = qca808x_led_parse_netdev(phydev, rules, &offload_trigger); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_led_hw_control_enable(phydev, index); ++ if (ret) ++ return ret; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_PATTERN_MASK, ++ offload_trigger); ++} ++ ++static bool qca808x_led_hw_control_status(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ int val; ++ ++ if (index > 2) ++ return false; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ ++ return !(val & QCA808X_LED_FORCE_EN); ++} ++ ++static int qca808x_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ u16 reg; ++ int val; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ /* Check if we have hw control enabled */ ++ if (qca808x_led_hw_control_status(phydev, index)) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ if (val & QCA808X_LED_TX_BLINK) ++ set_bit(TRIGGER_NETDEV_TX, rules); ++ if (val & QCA808X_LED_RX_BLINK) ++ set_bit(TRIGGER_NETDEV_RX, rules); ++ if (val & QCA808X_LED_SPEED10_ON) ++ set_bit(TRIGGER_NETDEV_LINK_10, rules); ++ if (val & QCA808X_LED_SPEED100_ON) ++ set_bit(TRIGGER_NETDEV_LINK_100, rules); ++ if (val & QCA808X_LED_SPEED1000_ON) ++ set_bit(TRIGGER_NETDEV_LINK_1000, rules); ++ if (val & QCA808X_LED_SPEED2500_ON) ++ set_bit(TRIGGER_NETDEV_LINK_2500, rules); ++ if (val & QCA808X_LED_HALF_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); ++ if (val & QCA808X_LED_FULL_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); ++ ++ return 0; ++} ++ ++static int qca808x_led_hw_control_reset(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_CTRL(index); ++ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_PATTERN_MASK); ++} ++ ++static int qca808x_led_brightness_set(struct phy_device *phydev, ++ u8 index, enum led_brightness value) ++{ ++ u16 reg; ++ int ret; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ if (!value) { ++ ret = qca808x_led_hw_control_reset(phydev, index); ++ if (ret) ++ return ret; ++ } ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | value ? QCA808X_LED_FORCE_ON : ++ QCA808X_LED_FORCE_OFF); ++} ++ ++static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ int ret; ++ u16 reg; ++ ++ if (index > 2) ++ return -EINVAL; ++ ++ reg = QCA808X_MMD7_LED_FORCE_CTRL(index); ++ ++ /* Set blink to 50% off, 50% on at 4Hz by default */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL, ++ QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK, ++ QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50); ++ if (ret) ++ return ret; ++ ++ /* We use BLINK_1 for normal blinking */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1); ++ if (ret) ++ return ret; ++ ++ /* We set blink to 4Hz, aka 250ms */ ++ *delay_on = 250 / 2; ++ *delay_off = 250 / 2; ++ ++ return 0; ++} ++ ++static int qca808x_led_polarity_set(struct phy_device *phydev, int index, ++ unsigned long modes) ++{ ++ struct qca808x_priv *priv = phydev->priv; ++ bool active_low = false; ++ u32 mode; ++ ++ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { ++ switch (mode) { ++ case PHY_LED_ACTIVE_LOW: ++ active_low = true; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ /* PHY polarity is global and can't be set per LED. ++ * To detect this, check if last requested polarity mode ++ * match the new one. ++ */ ++ if (priv->led_polarity_mode >= 0 && ++ priv->led_polarity_mode != active_low) { ++ phydev_err(phydev, "PHY polarity is global. Mismatched polarity on different LED\n"); ++ return -EINVAL; ++ } ++ ++ /* Save the last PHY polarity mode */ ++ priv->led_polarity_mode = active_low; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, ++ QCA808X_MMD7_LED_POLARITY_CTRL, ++ QCA808X_LED_ACTIVE_HIGH, ++ active_low ? 0 : QCA808X_LED_ACTIVE_HIGH); ++} ++ ++static struct phy_driver qca808x_driver[] = { ++{ ++ /* Qualcomm QCA8081 */ ++ PHY_ID_MATCH_EXACT(QCA8081_PHY_ID), ++ .name = "Qualcomm QCA8081", ++ .flags = PHY_POLL_CABLE_TEST, ++ .probe = qca808x_probe, ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .get_tunable = at803x_get_tunable, ++ .set_tunable = at803x_set_tunable, ++ .set_wol = at803x_set_wol, ++ .get_wol = at803x_get_wol, ++ .get_features = qca808x_get_features, ++ .config_aneg = qca808x_config_aneg, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .read_status = qca808x_read_status, ++ .config_init = qca808x_config_init, ++ .soft_reset = qca808x_soft_reset, ++ .cable_test_start = qca808x_cable_test_start, ++ .cable_test_get_status = qca808x_cable_test_get_status, ++ .link_change_notify = qca808x_link_change_notify, ++ .led_brightness_set = qca808x_led_brightness_set, ++ .led_blink_set = qca808x_led_blink_set, ++ .led_hw_is_supported = qca808x_led_hw_is_supported, ++ .led_hw_control_set = qca808x_led_hw_control_set, ++ .led_hw_control_get = qca808x_led_hw_control_get, ++ .led_polarity_set = qca808x_led_polarity_set, ++}, }; ++ ++module_phy_driver(qca808x_driver); ++ ++static struct mdio_device_id __maybe_unused qca808x_tbl[] = { ++ { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, qca808x_tbl); diff --git a/lede/target/linux/generic/backport-6.1/723-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch b/lede/target/linux/generic/backport-6.1/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch similarity index 100% rename from lede/target/linux/generic/backport-6.1/723-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch rename to lede/target/linux/generic/backport-6.1/714-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch diff --git a/lede/target/linux/generic/backport-6.1/714-v6.8-01-net-phy-make-addr-type-u8-in-phy_package_shared-stru.patch b/lede/target/linux/generic/backport-6.1/714-v6.8-01-net-phy-make-addr-type-u8-in-phy_package_shared-stru.patch new file mode 100644 index 0000000000..6decc3430b --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/714-v6.8-01-net-phy-make-addr-type-u8-in-phy_package_shared-stru.patch @@ -0,0 +1,28 @@ +From ebb30ccbbdbd6fae5177b676da4f4ac92bb4f635 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 15 Dec 2023 14:15:31 +0100 +Subject: [PATCH 1/4] net: phy: make addr type u8 in phy_package_shared struct + +Switch addr type in phy_package_shared struct to u8. + +The value is already checked to be non negative and to be less than +PHY_MAX_ADDR, hence u8 is better suited than using int. + +Signed-off-by: Christian Marangi +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + include/linux/phy.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -330,7 +330,7 @@ struct mdio_bus_stats { + * phy_package_leave(). + */ + struct phy_package_shared { +- int addr; ++ u8 addr; + refcount_t refcnt; + unsigned long flags; + size_t priv_size; diff --git a/lede/target/linux/generic/backport-6.1/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch b/lede/target/linux/generic/backport-6.1/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch new file mode 100644 index 0000000000..0cf01df3d3 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch @@ -0,0 +1,341 @@ +From 9eea577eb1155fe4a183bc5e7bf269b0b2e7a6ba Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 15 Dec 2023 14:15:32 +0100 +Subject: [PATCH 2/4] net: phy: extend PHY package API to support multiple + global address + +Current API for PHY package are limited to single address to configure +global settings for the PHY package. + +It was found that some PHY package (for example the qca807x, a PHY +package that is shipped with a bundle of 5 PHY) requires multiple PHY +address to configure global settings. An example scenario is a PHY that +have a dedicated PHY for PSGMII/serdes calibrarion and have a specific +PHY in the package where the global PHY mode is set and affects every +other PHY in the package. + +Change the API in the following way: +- Change phy_package_join() to take the base addr of the PHY package + instead of the global PHY addr. +- Make __/phy_package_write/read() require an additional arg that + select what global PHY address to use by passing the offset from the + base addr passed on phy_package_join(). + +Each user of this API is updated to follow this new implementation +following a pattern where an enum is defined to declare the offset of the +addr. + +We also drop the check if shared is defined as any user of the +phy_package_read/write is expected to use phy_package_join first. Misuse +of this will correctly trigger a kernel panic for NULL pointer +exception. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/bcm54140.c | 16 ++++++-- + drivers/net/phy/mscc/mscc.h | 5 +++ + drivers/net/phy/mscc/mscc_main.c | 4 +- + drivers/net/phy/phy_device.c | 35 +++++++++-------- + include/linux/phy.h | 64 +++++++++++++++++++++----------- + 5 files changed, 80 insertions(+), 44 deletions(-) + +--- a/drivers/net/phy/bcm54140.c ++++ b/drivers/net/phy/bcm54140.c +@@ -128,6 +128,10 @@ + #define BCM54140_DEFAULT_DOWNSHIFT 5 + #define BCM54140_MAX_DOWNSHIFT 9 + ++enum bcm54140_global_phy { ++ BCM54140_BASE_ADDR = 0, ++}; ++ + struct bcm54140_priv { + int port; + int base_addr; +@@ -429,11 +433,13 @@ static int bcm54140_base_read_rdb(struct + int ret; + + phy_lock_mdio_bus(phydev); +- ret = __phy_package_write(phydev, MII_BCM54XX_RDB_ADDR, rdb); ++ ret = __phy_package_write(phydev, BCM54140_BASE_ADDR, ++ MII_BCM54XX_RDB_ADDR, rdb); + if (ret < 0) + goto out; + +- ret = __phy_package_read(phydev, MII_BCM54XX_RDB_DATA); ++ ret = __phy_package_read(phydev, BCM54140_BASE_ADDR, ++ MII_BCM54XX_RDB_DATA); + + out: + phy_unlock_mdio_bus(phydev); +@@ -446,11 +452,13 @@ static int bcm54140_base_write_rdb(struc + int ret; + + phy_lock_mdio_bus(phydev); +- ret = __phy_package_write(phydev, MII_BCM54XX_RDB_ADDR, rdb); ++ ret = __phy_package_write(phydev, BCM54140_BASE_ADDR, ++ MII_BCM54XX_RDB_ADDR, rdb); + if (ret < 0) + goto out; + +- ret = __phy_package_write(phydev, MII_BCM54XX_RDB_DATA, val); ++ ret = __phy_package_write(phydev, BCM54140_BASE_ADDR, ++ MII_BCM54XX_RDB_DATA, val); + + out: + phy_unlock_mdio_bus(phydev); +--- a/drivers/net/phy/mscc/mscc.h ++++ b/drivers/net/phy/mscc/mscc.h +@@ -414,6 +414,11 @@ struct vsc8531_private { + * gpio_lock: used for PHC operations. Common for all PHYs as the load/save GPIO + * is shared. + */ ++ ++enum vsc85xx_global_phy { ++ VSC88XX_BASE_ADDR = 0, ++}; ++ + struct vsc85xx_shared_private { + struct mutex gpio_lock; + }; +--- a/drivers/net/phy/mscc/mscc_main.c ++++ b/drivers/net/phy/mscc/mscc_main.c +@@ -700,7 +700,7 @@ int phy_base_write(struct phy_device *ph + dump_stack(); + } + +- return __phy_package_write(phydev, regnum, val); ++ return __phy_package_write(phydev, VSC88XX_BASE_ADDR, regnum, val); + } + + /* phydev->bus->mdio_lock should be locked when using this function */ +@@ -711,7 +711,7 @@ int phy_base_read(struct phy_device *phy + dump_stack(); + } + +- return __phy_package_read(phydev, regnum); ++ return __phy_package_read(phydev, VSC88XX_BASE_ADDR, regnum); + } + + u32 vsc85xx_csr_read(struct phy_device *phydev, +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1602,20 +1602,22 @@ EXPORT_SYMBOL_GPL(phy_driver_is_genphy_1 + /** + * phy_package_join - join a common PHY group + * @phydev: target phy_device struct +- * @addr: cookie and PHY address for global register access ++ * @base_addr: cookie and base PHY address of PHY package for offset ++ * calculation of global register access + * @priv_size: if non-zero allocate this amount of bytes for private data + * + * This joins a PHY group and provides a shared storage for all phydevs in + * this group. This is intended to be used for packages which contain + * more than one PHY, for example a quad PHY transceiver. + * +- * The addr parameter serves as a cookie which has to have the same value +- * for all members of one group and as a PHY address to access generic +- * registers of a PHY package. Usually, one of the PHY addresses of the +- * different PHYs in the package provides access to these global registers. ++ * The base_addr parameter serves as cookie which has to have the same values ++ * for all members of one group and as the base PHY address of the PHY package ++ * for offset calculation to access generic registers of a PHY package. ++ * Usually, one of the PHY addresses of the different PHYs in the package ++ * provides access to these global registers. + * The address which is given here, will be used in the phy_package_read() +- * and phy_package_write() convenience functions. If your PHY doesn't have +- * global registers you can just pick any of the PHY addresses. ++ * and phy_package_write() convenience functions as base and added to the ++ * passed offset in those functions. + * + * This will set the shared pointer of the phydev to the shared storage. + * If this is the first call for a this cookie the shared storage will be +@@ -1625,17 +1627,17 @@ EXPORT_SYMBOL_GPL(phy_driver_is_genphy_1 + * Returns < 1 on error, 0 on success. Esp. calling phy_package_join() + * with the same cookie but a different priv_size is an error. + */ +-int phy_package_join(struct phy_device *phydev, int addr, size_t priv_size) ++int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size) + { + struct mii_bus *bus = phydev->mdio.bus; + struct phy_package_shared *shared; + int ret; + +- if (addr < 0 || addr >= PHY_MAX_ADDR) ++ if (base_addr < 0 || base_addr >= PHY_MAX_ADDR) + return -EINVAL; + + mutex_lock(&bus->shared_lock); +- shared = bus->shared[addr]; ++ shared = bus->shared[base_addr]; + if (!shared) { + ret = -ENOMEM; + shared = kzalloc(sizeof(*shared), GFP_KERNEL); +@@ -1647,9 +1649,9 @@ int phy_package_join(struct phy_device * + goto err_free; + shared->priv_size = priv_size; + } +- shared->addr = addr; ++ shared->base_addr = base_addr; + refcount_set(&shared->refcnt, 1); +- bus->shared[addr] = shared; ++ bus->shared[base_addr] = shared; + } else { + ret = -EINVAL; + if (priv_size && priv_size != shared->priv_size) +@@ -1687,7 +1689,7 @@ void phy_package_leave(struct phy_device + return; + + if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) { +- bus->shared[shared->addr] = NULL; ++ bus->shared[shared->base_addr] = NULL; + mutex_unlock(&bus->shared_lock); + kfree(shared->priv); + kfree(shared); +@@ -1706,7 +1708,8 @@ static void devm_phy_package_leave(struc + * devm_phy_package_join - resource managed phy_package_join() + * @dev: device that is registering this PHY package + * @phydev: target phy_device struct +- * @addr: cookie and PHY address for global register access ++ * @base_addr: cookie and base PHY address of PHY package for offset ++ * calculation of global register access + * @priv_size: if non-zero allocate this amount of bytes for private data + * + * Managed phy_package_join(). Shared storage fetched by this function, +@@ -1714,7 +1717,7 @@ static void devm_phy_package_leave(struc + * phy_package_join() for more information. + */ + int devm_phy_package_join(struct device *dev, struct phy_device *phydev, +- int addr, size_t priv_size) ++ int base_addr, size_t priv_size) + { + struct phy_device **ptr; + int ret; +@@ -1724,7 +1727,7 @@ int devm_phy_package_join(struct device + if (!ptr) + return -ENOMEM; + +- ret = phy_package_join(phydev, addr, priv_size); ++ ret = phy_package_join(phydev, base_addr, priv_size); + + if (!ret) { + *ptr = phydev; +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -319,7 +319,8 @@ struct mdio_bus_stats { + + /** + * struct phy_package_shared - Shared information in PHY packages +- * @addr: Common PHY address used to combine PHYs in one package ++ * @base_addr: Base PHY address of PHY package used to combine PHYs ++ * in one package and for offset calculation of phy_package_read/write + * @refcnt: Number of PHYs connected to this shared data + * @flags: Initialization of PHY package + * @priv_size: Size of the shared private data @priv +@@ -330,7 +331,7 @@ struct mdio_bus_stats { + * phy_package_leave(). + */ + struct phy_package_shared { +- u8 addr; ++ u8 base_addr; + refcount_t refcnt; + unsigned long flags; + size_t priv_size; +@@ -1763,10 +1764,10 @@ int phy_ethtool_get_link_ksettings(struc + int phy_ethtool_set_link_ksettings(struct net_device *ndev, + const struct ethtool_link_ksettings *cmd); + int phy_ethtool_nway_reset(struct net_device *ndev); +-int phy_package_join(struct phy_device *phydev, int addr, size_t priv_size); ++int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size); + void phy_package_leave(struct phy_device *phydev); + int devm_phy_package_join(struct device *dev, struct phy_device *phydev, +- int addr, size_t priv_size); ++ int base_addr, size_t priv_size); + + #if IS_ENABLED(CONFIG_PHYLIB) + int __init mdio_bus_init(void); +@@ -1778,46 +1779,65 @@ int phy_ethtool_get_sset_count(struct ph + int phy_ethtool_get_stats(struct phy_device *phydev, + struct ethtool_stats *stats, u64 *data); + +-static inline int phy_package_read(struct phy_device *phydev, u32 regnum) ++static inline int phy_package_address(struct phy_device *phydev, ++ unsigned int addr_offset) + { + struct phy_package_shared *shared = phydev->shared; ++ u8 base_addr = shared->base_addr; + +- if (!shared) ++ if (addr_offset >= PHY_MAX_ADDR - base_addr) + return -EIO; + +- return mdiobus_read(phydev->mdio.bus, shared->addr, regnum); ++ /* we know that addr will be in the range 0..31 and thus the ++ * implicit cast to a signed int is not a problem. ++ */ ++ return base_addr + addr_offset; + } + +-static inline int __phy_package_read(struct phy_device *phydev, u32 regnum) ++static inline int phy_package_read(struct phy_device *phydev, ++ unsigned int addr_offset, u32 regnum) + { +- struct phy_package_shared *shared = phydev->shared; ++ int addr = phy_package_address(phydev, addr_offset); + +- if (!shared) +- return -EIO; ++ if (addr < 0) ++ return addr; ++ ++ return mdiobus_read(phydev->mdio.bus, addr, regnum); ++} ++ ++static inline int __phy_package_read(struct phy_device *phydev, ++ unsigned int addr_offset, u32 regnum) ++{ ++ int addr = phy_package_address(phydev, addr_offset); ++ ++ if (addr < 0) ++ return addr; + +- return __mdiobus_read(phydev->mdio.bus, shared->addr, regnum); ++ return __mdiobus_read(phydev->mdio.bus, addr, regnum); + } + + static inline int phy_package_write(struct phy_device *phydev, +- u32 regnum, u16 val) ++ unsigned int addr_offset, u32 regnum, ++ u16 val) + { +- struct phy_package_shared *shared = phydev->shared; ++ int addr = phy_package_address(phydev, addr_offset); + +- if (!shared) +- return -EIO; ++ if (addr < 0) ++ return addr; + +- return mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val); ++ return mdiobus_write(phydev->mdio.bus, addr, regnum, val); + } + + static inline int __phy_package_write(struct phy_device *phydev, +- u32 regnum, u16 val) ++ unsigned int addr_offset, u32 regnum, ++ u16 val) + { +- struct phy_package_shared *shared = phydev->shared; ++ int addr = phy_package_address(phydev, addr_offset); + +- if (!shared) +- return -EIO; ++ if (addr < 0) ++ return addr; + +- return __mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val); ++ return __mdiobus_write(phydev->mdio.bus, addr, regnum, val); + } + + static inline bool __phy_package_set_once(struct phy_device *phydev, diff --git a/lede/target/linux/generic/backport-6.1/714-v6.8-03-net-phy-restructure-__phy_write-read_mmd-to-helper-a.patch b/lede/target/linux/generic/backport-6.1/714-v6.8-03-net-phy-restructure-__phy_write-read_mmd-to-helper-a.patch new file mode 100644 index 0000000000..4a17d46453 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/714-v6.8-03-net-phy-restructure-__phy_write-read_mmd-to-helper-a.patch @@ -0,0 +1,116 @@ +From 028672bd1d73cf65249a420c1de75e8d2acd2f6a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 15 Dec 2023 14:15:33 +0100 +Subject: [PATCH 3/4] net: phy: restructure __phy_write/read_mmd to helper and + phydev user + +Restructure phy_write_mmd and phy_read_mmd to implement generic helper +for direct mdiobus access for mmd and use these helper for phydev user. + +This is needed in preparation of PHY package API that requires generic +access to the mdiobus and are deatched from phydev struct but instead +access them based on PHY package base_addr and offsets. + +Signed-off-by: Christian Marangi +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy-core.c | 64 ++++++++++++++++++-------------------- + 1 file changed, 30 insertions(+), 34 deletions(-) + +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -528,6 +528,28 @@ static void mmd_phy_indirect(struct mii_ + devad | MII_MMD_CTRL_NOINCR); + } + ++static int mmd_phy_read(struct mii_bus *bus, int phy_addr, bool is_c45, ++ int devad, u32 regnum) ++{ ++ if (is_c45) ++ return __mdiobus_c45_read(bus, phy_addr, devad, regnum); ++ ++ mmd_phy_indirect(bus, phy_addr, devad, regnum); ++ /* Read the content of the MMD's selected register */ ++ return __mdiobus_read(bus, phy_addr, MII_MMD_DATA); ++} ++ ++static int mmd_phy_write(struct mii_bus *bus, int phy_addr, bool is_c45, ++ int devad, u32 regnum, u16 val) ++{ ++ if (is_c45) ++ return __mdiobus_c45_write(bus, phy_addr, devad, regnum, val); ++ ++ mmd_phy_indirect(bus, phy_addr, devad, regnum); ++ /* Write the data into MMD's selected register */ ++ return __mdiobus_write(bus, phy_addr, MII_MMD_DATA, val); ++} ++ + /** + * __phy_read_mmd - Convenience function for reading a register + * from an MMD on a given PHY. +@@ -539,26 +561,14 @@ static void mmd_phy_indirect(struct mii_ + */ + int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) + { +- int val; +- + if (regnum > (u16)~0 || devad > 32) + return -EINVAL; + +- if (phydev->drv && phydev->drv->read_mmd) { +- val = phydev->drv->read_mmd(phydev, devad, regnum); +- } else if (phydev->is_c45) { +- val = __mdiobus_c45_read(phydev->mdio.bus, phydev->mdio.addr, +- devad, regnum); +- } else { +- struct mii_bus *bus = phydev->mdio.bus; +- int phy_addr = phydev->mdio.addr; +- +- mmd_phy_indirect(bus, phy_addr, devad, regnum); +- +- /* Read the content of the MMD's selected register */ +- val = __mdiobus_read(bus, phy_addr, MII_MMD_DATA); +- } +- return val; ++ if (phydev->drv && phydev->drv->read_mmd) ++ return phydev->drv->read_mmd(phydev, devad, regnum); ++ ++ return mmd_phy_read(phydev->mdio.bus, phydev->mdio.addr, ++ phydev->is_c45, devad, regnum); + } + EXPORT_SYMBOL(__phy_read_mmd); + +@@ -595,28 +605,14 @@ EXPORT_SYMBOL(phy_read_mmd); + */ + int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) + { +- int ret; +- + if (regnum > (u16)~0 || devad > 32) + return -EINVAL; + +- if (phydev->drv && phydev->drv->write_mmd) { +- ret = phydev->drv->write_mmd(phydev, devad, regnum, val); +- } else if (phydev->is_c45) { +- ret = __mdiobus_c45_write(phydev->mdio.bus, phydev->mdio.addr, +- devad, regnum, val); +- } else { +- struct mii_bus *bus = phydev->mdio.bus; +- int phy_addr = phydev->mdio.addr; ++ if (phydev->drv && phydev->drv->write_mmd) ++ return phydev->drv->write_mmd(phydev, devad, regnum, val); + +- mmd_phy_indirect(bus, phy_addr, devad, regnum); +- +- /* Write the data into MMD's selected register */ +- __mdiobus_write(bus, phy_addr, MII_MMD_DATA, val); +- +- ret = 0; +- } +- return ret; ++ return mmd_phy_write(phydev->mdio.bus, phydev->mdio.addr, ++ phydev->is_c45, devad, regnum, val); + } + EXPORT_SYMBOL(__phy_write_mmd); + diff --git a/lede/target/linux/generic/backport-6.1/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch b/lede/target/linux/generic/backport-6.1/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch new file mode 100644 index 0000000000..a628a37929 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch @@ -0,0 +1,196 @@ +From d63710fc0f1a501fd75a7025e3070a96ffa1645f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 15 Dec 2023 14:15:34 +0100 +Subject: [PATCH 4/4] net: phy: add support for PHY package MMD read/write + +Some PHY in PHY package may require to read/write MMD regs to correctly +configure the PHY package. + +Add support for these additional required function in both lock and no +lock variant. + +It's assumed that the entire PHY package is either C22 or C45. We use +C22 or C45 way of writing/reading to mmd regs based on the passed phydev +whether it's C22 or C45. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy-core.c | 140 +++++++++++++++++++++++++++++++++++++ + include/linux/phy.h | 16 +++++ + 2 files changed, 156 insertions(+) + +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -639,6 +639,146 @@ int phy_write_mmd(struct phy_device *phy + EXPORT_SYMBOL(phy_write_mmd); + + /** ++ * __phy_package_read_mmd - read MMD reg relative to PHY package base addr ++ * @phydev: The phy_device struct ++ * @addr_offset: The offset to be added to PHY package base_addr ++ * @devad: The MMD to read from ++ * @regnum: The register on the MMD to read ++ * ++ * Convenience helper for reading a register of an MMD on a given PHY ++ * using the PHY package base address. The base address is added to ++ * the addr_offset value. ++ * ++ * Same calling rules as for __phy_read(); ++ * ++ * NOTE: It's assumed that the entire PHY package is either C22 or C45. ++ */ ++int __phy_package_read_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum) ++{ ++ int addr = phy_package_address(phydev, addr_offset); ++ ++ if (addr < 0) ++ return addr; ++ ++ if (regnum > (u16)~0 || devad > 32) ++ return -EINVAL; ++ ++ return mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad, ++ regnum); ++} ++EXPORT_SYMBOL(__phy_package_read_mmd); ++ ++/** ++ * phy_package_read_mmd - read MMD reg relative to PHY package base addr ++ * @phydev: The phy_device struct ++ * @addr_offset: The offset to be added to PHY package base_addr ++ * @devad: The MMD to read from ++ * @regnum: The register on the MMD to read ++ * ++ * Convenience helper for reading a register of an MMD on a given PHY ++ * using the PHY package base address. The base address is added to ++ * the addr_offset value. ++ * ++ * Same calling rules as for phy_read(); ++ * ++ * NOTE: It's assumed that the entire PHY package is either C22 or C45. ++ */ ++int phy_package_read_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum) ++{ ++ int addr = phy_package_address(phydev, addr_offset); ++ int val; ++ ++ if (addr < 0) ++ return addr; ++ ++ if (regnum > (u16)~0 || devad > 32) ++ return -EINVAL; ++ ++ phy_lock_mdio_bus(phydev); ++ val = mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad, ++ regnum); ++ phy_unlock_mdio_bus(phydev); ++ ++ return val; ++} ++EXPORT_SYMBOL(phy_package_read_mmd); ++ ++/** ++ * __phy_package_write_mmd - write MMD reg relative to PHY package base addr ++ * @phydev: The phy_device struct ++ * @addr_offset: The offset to be added to PHY package base_addr ++ * @devad: The MMD to write to ++ * @regnum: The register on the MMD to write ++ * @val: value to write to @regnum ++ * ++ * Convenience helper for writing a register of an MMD on a given PHY ++ * using the PHY package base address. The base address is added to ++ * the addr_offset value. ++ * ++ * Same calling rules as for __phy_write(); ++ * ++ * NOTE: It's assumed that the entire PHY package is either C22 or C45. ++ */ ++int __phy_package_write_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum, u16 val) ++{ ++ int addr = phy_package_address(phydev, addr_offset); ++ ++ if (addr < 0) ++ return addr; ++ ++ if (regnum > (u16)~0 || devad > 32) ++ return -EINVAL; ++ ++ return mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad, ++ regnum, val); ++} ++EXPORT_SYMBOL(__phy_package_write_mmd); ++ ++/** ++ * phy_package_write_mmd - write MMD reg relative to PHY package base addr ++ * @phydev: The phy_device struct ++ * @addr_offset: The offset to be added to PHY package base_addr ++ * @devad: The MMD to write to ++ * @regnum: The register on the MMD to write ++ * @val: value to write to @regnum ++ * ++ * Convenience helper for writing a register of an MMD on a given PHY ++ * using the PHY package base address. The base address is added to ++ * the addr_offset value. ++ * ++ * Same calling rules as for phy_write(); ++ * ++ * NOTE: It's assumed that the entire PHY package is either C22 or C45. ++ */ ++int phy_package_write_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum, u16 val) ++{ ++ int addr = phy_package_address(phydev, addr_offset); ++ int ret; ++ ++ if (addr < 0) ++ return addr; ++ ++ if (regnum > (u16)~0 || devad > 32) ++ return -EINVAL; ++ ++ phy_lock_mdio_bus(phydev); ++ ret = mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad, ++ regnum, val); ++ phy_unlock_mdio_bus(phydev); ++ ++ return ret; ++} ++EXPORT_SYMBOL(phy_package_write_mmd); ++ ++/** + * phy_modify_changed - Function for modifying a PHY register + * @phydev: the phy_device struct + * @regnum: register number to modify +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -1840,6 +1840,22 @@ static inline int __phy_package_write(st + return __mdiobus_write(phydev->mdio.bus, addr, regnum, val); + } + ++int __phy_package_read_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum); ++ ++int phy_package_read_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum); ++ ++int __phy_package_write_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum, u16 val); ++ ++int phy_package_write_mmd(struct phy_device *phydev, ++ unsigned int addr_offset, int devad, ++ u32 regnum, u16 val); ++ + static inline bool __phy_package_set_once(struct phy_device *phydev, + unsigned int b) + { diff --git a/lede/target/linux/generic/backport-6.1/715-01-v6.2-net-fman-memac-Add-serdes-support.patch b/lede/target/linux/generic/backport-6.1/715-01-v6.2-net-fman-memac-Add-serdes-support.patch new file mode 100644 index 0000000000..2886123f2d --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-01-v6.2-net-fman-memac-Add-serdes-support.patch @@ -0,0 +1,103 @@ +From affa013f494486079c3c5ad2d00cebc41a3d7445 Mon Sep 17 00:00:00 2001 +From: Sean Anderson +Date: Mon, 17 Oct 2022 16:22:36 -0400 +Subject: [PATCH 01/21] net: fman: memac: Add serdes support + +This adds support for using a serdes which has to be configured. This is +primarly in preparation for phylink conversion, which will then change the +serdes mode dynamically. + +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +--- + .../net/ethernet/freescale/fman/fman_memac.c | 49 ++++++++++++++++++- + 1 file changed, 47 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/freescale/fman/fman_memac.c ++++ b/drivers/net/ethernet/freescale/fman/fman_memac.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + + /* PCS registers */ +@@ -324,6 +325,7 @@ struct fman_mac { + void *fm; + struct fman_rev_info fm_rev_info; + bool basex_if; ++ struct phy *serdes; + struct phy_device *pcsphy; + bool allmulti_enabled; + }; +@@ -1203,17 +1205,56 @@ int memac_initialization(struct mac_devi + } + } + ++ memac->serdes = devm_of_phy_get(mac_dev->dev, mac_node, "serdes"); ++ err = PTR_ERR(memac->serdes); ++ if (err == -ENODEV || err == -ENOSYS) { ++ dev_dbg(mac_dev->dev, "could not get (optional) serdes\n"); ++ memac->serdes = NULL; ++ } else if (IS_ERR(memac->serdes)) { ++ dev_err_probe(mac_dev->dev, err, "could not get serdes\n"); ++ goto _return_fm_mac_free; ++ } else { ++ err = phy_init(memac->serdes); ++ if (err) { ++ dev_err_probe(mac_dev->dev, err, ++ "could not initialize serdes\n"); ++ goto _return_fm_mac_free; ++ } ++ ++ err = phy_power_on(memac->serdes); ++ if (err) { ++ dev_err_probe(mac_dev->dev, err, ++ "could not power on serdes\n"); ++ goto _return_phy_exit; ++ } ++ ++ if (memac->phy_if == PHY_INTERFACE_MODE_SGMII || ++ memac->phy_if == PHY_INTERFACE_MODE_1000BASEX || ++ memac->phy_if == PHY_INTERFACE_MODE_2500BASEX || ++ memac->phy_if == PHY_INTERFACE_MODE_QSGMII || ++ memac->phy_if == PHY_INTERFACE_MODE_XGMII) { ++ err = phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET, ++ memac->phy_if); ++ if (err) { ++ dev_err_probe(mac_dev->dev, err, ++ "could not set serdes mode to %s\n", ++ phy_modes(memac->phy_if)); ++ goto _return_phy_power_off; ++ } ++ } ++ } ++ + if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) { + struct phy_device *phy; + + err = of_phy_register_fixed_link(mac_node); + if (err) +- goto _return_fm_mac_free; ++ goto _return_phy_power_off; + + fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL); + if (!fixed_link) { + err = -ENOMEM; +- goto _return_fm_mac_free; ++ goto _return_phy_power_off; + } + + mac_dev->phy_node = of_node_get(mac_node); +@@ -1242,6 +1283,10 @@ int memac_initialization(struct mac_devi + + goto _return; + ++_return_phy_power_off: ++ phy_power_off(memac->serdes); ++_return_phy_exit: ++ phy_exit(memac->serdes); + _return_fixed_link_free: + kfree(fixed_link); + _return_fm_mac_free: diff --git a/lede/target/linux/generic/backport-6.1/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch b/lede/target/linux/generic/backport-6.1/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch new file mode 100644 index 0000000000..873debc080 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-02-v6.2-net-fman-memac-Use-lynx-pcs-driver.patch @@ -0,0 +1,384 @@ +From fe60e7154d3a35af975c5e6570d6ec31aab9a731 Mon Sep 17 00:00:00 2001 +From: Sean Anderson +Date: Mon, 17 Oct 2022 16:22:37 -0400 +Subject: [PATCH 02/21] net: fman: memac: Use lynx pcs driver + +Although not stated in the datasheet, as far as I can tell PCS for mEMACs +is a "Lynx." By reusing the existing driver, we can remove the PCS +management code from the memac driver. This requires calling some PCS +functions manually which phylink would usually do for us, but we will let +it do that soon. + +One problem is that we don't actually have a PCS for QSGMII. We pretend +that each mEMAC's MDIO bus has four QSGMII PCSs, but this is not the case. +Only the "base" mEMAC's MDIO bus has the four QSGMII PCSs. This is not an +issue yet, because we never get the PCS state. However, it will be once the +conversion to phylink is complete, since the links will appear to never +come up. To get around this, we allow specifying multiple PCSs in pcsphy. +This breaks backwards compatibility with old device trees, but only for +QSGMII. IMO this is the only reasonable way to figure out what the actual +QSGMII PCS is. + +Additionally, we now also support a separate XFI PCS. This can allow the +SerDes driver to set different addresses for the SGMII and XFI PCSs so they +can be accessed at the same time. + +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/freescale/fman/Kconfig | 3 + + .../net/ethernet/freescale/fman/fman_memac.c | 258 +++++++----------- + 2 files changed, 105 insertions(+), 156 deletions(-) + +--- a/drivers/net/ethernet/freescale/fman/Kconfig ++++ b/drivers/net/ethernet/freescale/fman/Kconfig +@@ -4,6 +4,9 @@ config FSL_FMAN + depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST + select GENERIC_ALLOCATOR + select PHYLIB ++ select PHYLINK ++ select PCS ++ select PCS_LYNX + select CRC32 + default n + help +--- a/drivers/net/ethernet/freescale/fman/fman_memac.c ++++ b/drivers/net/ethernet/freescale/fman/fman_memac.c +@@ -11,43 +11,12 @@ + + #include + #include ++#include + #include + #include + #include + #include + +-/* PCS registers */ +-#define MDIO_SGMII_CR 0x00 +-#define MDIO_SGMII_DEV_ABIL_SGMII 0x04 +-#define MDIO_SGMII_LINK_TMR_L 0x12 +-#define MDIO_SGMII_LINK_TMR_H 0x13 +-#define MDIO_SGMII_IF_MODE 0x14 +- +-/* SGMII Control defines */ +-#define SGMII_CR_AN_EN 0x1000 +-#define SGMII_CR_RESTART_AN 0x0200 +-#define SGMII_CR_FD 0x0100 +-#define SGMII_CR_SPEED_SEL1_1G 0x0040 +-#define SGMII_CR_DEF_VAL (SGMII_CR_AN_EN | SGMII_CR_FD | \ +- SGMII_CR_SPEED_SEL1_1G) +- +-/* SGMII Device Ability for SGMII defines */ +-#define MDIO_SGMII_DEV_ABIL_SGMII_MODE 0x4001 +-#define MDIO_SGMII_DEV_ABIL_BASEX_MODE 0x01A0 +- +-/* Link timer define */ +-#define LINK_TMR_L 0xa120 +-#define LINK_TMR_H 0x0007 +-#define LINK_TMR_L_BASEX 0xaf08 +-#define LINK_TMR_H_BASEX 0x002f +- +-/* SGMII IF Mode defines */ +-#define IF_MODE_USE_SGMII_AN 0x0002 +-#define IF_MODE_SGMII_EN 0x0001 +-#define IF_MODE_SGMII_SPEED_100M 0x0004 +-#define IF_MODE_SGMII_SPEED_1G 0x0008 +-#define IF_MODE_SGMII_DUPLEX_HALF 0x0010 +- + /* Num of additional exact match MAC adr regs */ + #define MEMAC_NUM_OF_PADDRS 7 + +@@ -326,7 +295,9 @@ struct fman_mac { + struct fman_rev_info fm_rev_info; + bool basex_if; + struct phy *serdes; +- struct phy_device *pcsphy; ++ struct phylink_pcs *sgmii_pcs; ++ struct phylink_pcs *qsgmii_pcs; ++ struct phylink_pcs *xfi_pcs; + bool allmulti_enabled; + }; + +@@ -487,91 +458,22 @@ static u32 get_mac_addr_hash_code(u64 et + return xor_val; + } + +-static void setup_sgmii_internal_phy(struct fman_mac *memac, +- struct fixed_phy_status *fixed_link) +-{ +- u16 tmp_reg16; +- +- if (WARN_ON(!memac->pcsphy)) +- return; +- +- /* SGMII mode */ +- tmp_reg16 = IF_MODE_SGMII_EN; +- if (!fixed_link) +- /* AN enable */ +- tmp_reg16 |= IF_MODE_USE_SGMII_AN; +- else { +- switch (fixed_link->speed) { +- case 10: +- /* For 10M: IF_MODE[SPEED_10M] = 0 */ +- break; +- case 100: +- tmp_reg16 |= IF_MODE_SGMII_SPEED_100M; +- break; +- case 1000: +- default: +- tmp_reg16 |= IF_MODE_SGMII_SPEED_1G; +- break; +- } +- if (!fixed_link->duplex) +- tmp_reg16 |= IF_MODE_SGMII_DUPLEX_HALF; +- } +- phy_write(memac->pcsphy, MDIO_SGMII_IF_MODE, tmp_reg16); +- +- /* Device ability according to SGMII specification */ +- tmp_reg16 = MDIO_SGMII_DEV_ABIL_SGMII_MODE; +- phy_write(memac->pcsphy, MDIO_SGMII_DEV_ABIL_SGMII, tmp_reg16); +- +- /* Adjust link timer for SGMII - +- * According to Cisco SGMII specification the timer should be 1.6 ms. +- * The link_timer register is configured in units of the clock. +- * - When running as 1G SGMII, Serdes clock is 125 MHz, so +- * unit = 1 / (125*10^6 Hz) = 8 ns. +- * 1.6 ms in units of 8 ns = 1.6ms / 8ns = 2*10^5 = 0x30d40 +- * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so +- * unit = 1 / (312.5*10^6 Hz) = 3.2 ns. +- * 1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5*10^5 = 0x7a120. +- * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII, +- * we always set up here a value of 2.5 SGMII. +- */ +- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_H, LINK_TMR_H); +- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_L, LINK_TMR_L); +- +- if (!fixed_link) +- /* Restart AN */ +- tmp_reg16 = SGMII_CR_DEF_VAL | SGMII_CR_RESTART_AN; ++static void setup_sgmii_internal(struct fman_mac *memac, ++ struct phylink_pcs *pcs, ++ struct fixed_phy_status *fixed_link) ++{ ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); ++ phy_interface_t iface = memac->basex_if ? PHY_INTERFACE_MODE_1000BASEX : ++ PHY_INTERFACE_MODE_SGMII; ++ unsigned int mode = fixed_link ? MLO_AN_FIXED : MLO_AN_INBAND; ++ ++ linkmode_set_pause(advertising, true, true); ++ pcs->ops->pcs_config(pcs, mode, iface, advertising, true); ++ if (fixed_link) ++ pcs->ops->pcs_link_up(pcs, mode, iface, fixed_link->speed, ++ fixed_link->duplex); + else +- /* AN disabled */ +- tmp_reg16 = SGMII_CR_DEF_VAL & ~SGMII_CR_AN_EN; +- phy_write(memac->pcsphy, 0x0, tmp_reg16); +-} +- +-static void setup_sgmii_internal_phy_base_x(struct fman_mac *memac) +-{ +- u16 tmp_reg16; +- +- /* AN Device capability */ +- tmp_reg16 = MDIO_SGMII_DEV_ABIL_BASEX_MODE; +- phy_write(memac->pcsphy, MDIO_SGMII_DEV_ABIL_SGMII, tmp_reg16); +- +- /* Adjust link timer for SGMII - +- * For Serdes 1000BaseX auto-negotiation the timer should be 10 ms. +- * The link_timer register is configured in units of the clock. +- * - When running as 1G SGMII, Serdes clock is 125 MHz, so +- * unit = 1 / (125*10^6 Hz) = 8 ns. +- * 10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0 +- * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so +- * unit = 1 / (312.5*10^6 Hz) = 3.2 ns. +- * 10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08. +- * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII, +- * we always set up here a value of 2.5 SGMII. +- */ +- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_H, LINK_TMR_H_BASEX); +- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_L, LINK_TMR_L_BASEX); +- +- /* Restart AN */ +- tmp_reg16 = SGMII_CR_DEF_VAL | SGMII_CR_RESTART_AN; +- phy_write(memac->pcsphy, 0x0, tmp_reg16); ++ pcs->ops->pcs_an_restart(pcs); + } + + static int check_init_parameters(struct fman_mac *memac) +@@ -983,7 +885,6 @@ static int memac_set_exception(struct fm + static int memac_init(struct fman_mac *memac) + { + struct memac_cfg *memac_drv_param; +- u8 i; + enet_addr_t eth_addr; + bool slow_10g_if = false; + struct fixed_phy_status *fixed_link = NULL; +@@ -1036,32 +937,10 @@ static int memac_init(struct fman_mac *m + iowrite32be(reg32, &memac->regs->command_config); + } + +- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII) { +- /* Configure internal SGMII PHY */ +- if (memac->basex_if) +- setup_sgmii_internal_phy_base_x(memac); +- else +- setup_sgmii_internal_phy(memac, fixed_link); +- } else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII) { +- /* Configure 4 internal SGMII PHYs */ +- for (i = 0; i < 4; i++) { +- u8 qsmgii_phy_addr, phy_addr; +- /* QSGMII PHY address occupies 3 upper bits of 5-bit +- * phy_address; the lower 2 bits are used to extend +- * register address space and access each one of 4 +- * ports inside QSGMII. +- */ +- phy_addr = memac->pcsphy->mdio.addr; +- qsmgii_phy_addr = (u8)((phy_addr << 2) | i); +- memac->pcsphy->mdio.addr = qsmgii_phy_addr; +- if (memac->basex_if) +- setup_sgmii_internal_phy_base_x(memac); +- else +- setup_sgmii_internal_phy(memac, fixed_link); +- +- memac->pcsphy->mdio.addr = phy_addr; +- } +- } ++ if (memac->phy_if == PHY_INTERFACE_MODE_SGMII) ++ setup_sgmii_internal(memac, memac->sgmii_pcs, fixed_link); ++ else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII) ++ setup_sgmii_internal(memac, memac->qsgmii_pcs, fixed_link); + + /* Max Frame Length */ + err = fman_set_mac_max_frame(memac->fm, memac->mac_id, +@@ -1097,12 +976,25 @@ static int memac_init(struct fman_mac *m + return 0; + } + ++static void pcs_put(struct phylink_pcs *pcs) ++{ ++ struct mdio_device *mdiodev; ++ ++ if (IS_ERR_OR_NULL(pcs)) ++ return; ++ ++ mdiodev = lynx_get_mdio_device(pcs); ++ lynx_pcs_destroy(pcs); ++ mdio_device_free(mdiodev); ++} ++ + static int memac_free(struct fman_mac *memac) + { + free_init_resources(memac); + +- if (memac->pcsphy) +- put_device(&memac->pcsphy->mdio.dev); ++ pcs_put(memac->sgmii_pcs); ++ pcs_put(memac->qsgmii_pcs); ++ pcs_put(memac->xfi_pcs); + + kfree(memac->memac_drv_param); + kfree(memac); +@@ -1153,12 +1045,31 @@ static struct fman_mac *memac_config(str + return memac; + } + ++static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node, ++ int index) ++{ ++ struct device_node *node; ++ struct mdio_device *mdiodev = NULL; ++ struct phylink_pcs *pcs; ++ ++ node = of_parse_phandle(mac_node, "pcsphy-handle", index); ++ if (node && of_device_is_available(node)) ++ mdiodev = of_mdio_find_device(node); ++ of_node_put(node); ++ ++ if (!mdiodev) ++ return ERR_PTR(-EPROBE_DEFER); ++ ++ pcs = lynx_pcs_create(mdiodev); ++ return pcs; ++} ++ + int memac_initialization(struct mac_device *mac_dev, + struct device_node *mac_node, + struct fman_mac_params *params) + { + int err; +- struct device_node *phy_node; ++ struct phylink_pcs *pcs; + struct fixed_phy_status *fixed_link; + struct fman_mac *memac; + +@@ -1188,23 +1099,58 @@ int memac_initialization(struct mac_devi + memac = mac_dev->fman_mac; + memac->memac_drv_param->max_frame_length = fman_get_max_frm(); + memac->memac_drv_param->reset_on_init = true; +- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII || +- memac->phy_if == PHY_INTERFACE_MODE_QSGMII) { +- phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0); +- if (!phy_node) { +- pr_err("PCS PHY node is not available\n"); +- err = -EINVAL; ++ ++ err = of_property_match_string(mac_node, "pcs-handle-names", "xfi"); ++ if (err >= 0) { ++ memac->xfi_pcs = memac_pcs_create(mac_node, err); ++ if (IS_ERR(memac->xfi_pcs)) { ++ err = PTR_ERR(memac->xfi_pcs); ++ dev_err_probe(mac_dev->dev, err, "missing xfi pcs\n"); + goto _return_fm_mac_free; + } ++ } else if (err != -EINVAL && err != -ENODATA) { ++ goto _return_fm_mac_free; ++ } + +- memac->pcsphy = of_phy_find_device(phy_node); +- if (!memac->pcsphy) { +- pr_err("of_phy_find_device (PCS PHY) failed\n"); +- err = -EINVAL; ++ err = of_property_match_string(mac_node, "pcs-handle-names", "qsgmii"); ++ if (err >= 0) { ++ memac->qsgmii_pcs = memac_pcs_create(mac_node, err); ++ if (IS_ERR(memac->qsgmii_pcs)) { ++ err = PTR_ERR(memac->qsgmii_pcs); ++ dev_err_probe(mac_dev->dev, err, ++ "missing qsgmii pcs\n"); + goto _return_fm_mac_free; + } ++ } else if (err != -EINVAL && err != -ENODATA) { ++ goto _return_fm_mac_free; ++ } ++ ++ /* For compatibility, if pcs-handle-names is missing, we assume this ++ * phy is the first one in pcsphy-handle ++ */ ++ err = of_property_match_string(mac_node, "pcs-handle-names", "sgmii"); ++ if (err == -EINVAL || err == -ENODATA) ++ pcs = memac_pcs_create(mac_node, 0); ++ else if (err < 0) ++ goto _return_fm_mac_free; ++ else ++ pcs = memac_pcs_create(mac_node, err); ++ ++ if (!pcs) { ++ dev_err(mac_dev->dev, "missing pcs\n"); ++ err = -ENOENT; ++ goto _return_fm_mac_free; + } + ++ /* If err is set here, it means that pcs-handle-names was missing above ++ * (and therefore that xfi_pcs cannot be set). If we are defaulting to ++ * XGMII, assume this is for XFI. Otherwise, assume it is for SGMII. ++ */ ++ if (err && mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) ++ memac->xfi_pcs = pcs; ++ else ++ memac->sgmii_pcs = pcs; ++ + memac->serdes = devm_of_phy_get(mac_dev->dev, mac_node, "serdes"); + err = PTR_ERR(memac->serdes); + if (err == -ENODEV || err == -ENOSYS) { diff --git a/lede/target/linux/generic/backport-6.1/715-03-v6.2-net-dpaa-Convert-to-phylink.patch b/lede/target/linux/generic/backport-6.1/715-03-v6.2-net-dpaa-Convert-to-phylink.patch new file mode 100644 index 0000000000..63b651bb2d --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-03-v6.2-net-dpaa-Convert-to-phylink.patch @@ -0,0 +1,2451 @@ +From 38e50fc3d43882a43115b4f1ca3eb88255163c5b Mon Sep 17 00:00:00 2001 +From: Sean Anderson +Date: Mon, 17 Oct 2022 16:22:38 -0400 +Subject: [PATCH 03/21] net: dpaa: Convert to phylink + +This converts DPAA to phylink. All macs are converted. This should work +with no device tree modifications (including those made in this series), +except for QSGMII (as noted previously). + +The mEMAC configuration is one of the tricker areas. I have tried to +capture all the restrictions across the various models. Most of the time, +we assume that if the serdes supports a mode or the phy-interface-mode +specifies it, then we support it. The only place we can't do this is +(RG)MII, since there's no serdes. In that case, we rely on a (new) +devicetree property. There are also several cases where half-duplex is +broken. Unfortunately, only a single compatible is used for the MAC, so we +have to use the board compatible instead. + +The 10GEC conversion is very straightforward, since it only supports XAUI. +There is generally nothing to configure. + +The dTSEC conversion is broadly similar to mEMAC, but is simpler because we +don't support configuring the SerDes (though this can be easily added) and +we don't have multiple PCSs. From what I can tell, there's nothing +different in the driver or documentation between SGMII and 1000BASE-X +except for the advertising. Similarly, I couldn't find anything about +2500BASE-X. In both cases, I treat them like SGMII. These modes aren't used +by any in-tree boards. Similarly, despite being mentioned in the driver, I +couldn't find any documented SoCs which supported QSGMII. I have left it +unimplemented for now. + +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/freescale/dpaa/Kconfig | 4 +- + .../net/ethernet/freescale/dpaa/dpaa_eth.c | 89 +-- + .../ethernet/freescale/dpaa/dpaa_ethtool.c | 90 +-- + drivers/net/ethernet/freescale/fman/Kconfig | 1 - + .../net/ethernet/freescale/fman/fman_dtsec.c | 458 +++++++-------- + .../net/ethernet/freescale/fman/fman_mac.h | 10 - + .../net/ethernet/freescale/fman/fman_memac.c | 547 +++++++++--------- + .../net/ethernet/freescale/fman/fman_tgec.c | 131 ++--- + drivers/net/ethernet/freescale/fman/mac.c | 168 +----- + drivers/net/ethernet/freescale/fman/mac.h | 23 +- + 10 files changed, 612 insertions(+), 909 deletions(-) + +--- a/drivers/net/ethernet/freescale/dpaa/Kconfig ++++ b/drivers/net/ethernet/freescale/dpaa/Kconfig +@@ -2,8 +2,8 @@ + menuconfig FSL_DPAA_ETH + tristate "DPAA Ethernet" + depends on FSL_DPAA && FSL_FMAN +- select PHYLIB +- select FIXED_PHY ++ select PHYLINK ++ select PCS_LYNX + help + Data Path Acceleration Architecture Ethernet driver, + supporting the Freescale QorIQ chips. +--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c ++++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +@@ -264,8 +264,19 @@ static int dpaa_netdev_init(struct net_d + net_dev->needed_headroom = priv->tx_headroom; + net_dev->watchdog_timeo = msecs_to_jiffies(tx_timeout); + +- mac_dev->net_dev = net_dev; ++ /* The rest of the config is filled in by the mac device already */ ++ mac_dev->phylink_config.dev = &net_dev->dev; ++ mac_dev->phylink_config.type = PHYLINK_NETDEV; + mac_dev->update_speed = dpaa_eth_cgr_set_speed; ++ mac_dev->phylink = phylink_create(&mac_dev->phylink_config, ++ dev_fwnode(mac_dev->dev), ++ mac_dev->phy_if, ++ mac_dev->phylink_ops); ++ if (IS_ERR(mac_dev->phylink)) { ++ err = PTR_ERR(mac_dev->phylink); ++ dev_err_probe(dev, err, "Could not create phylink\n"); ++ return err; ++ } + + /* start without the RUNNING flag, phylib controls it later */ + netif_carrier_off(net_dev); +@@ -273,6 +284,7 @@ static int dpaa_netdev_init(struct net_d + err = register_netdev(net_dev); + if (err < 0) { + dev_err(dev, "register_netdev() = %d\n", err); ++ phylink_destroy(mac_dev->phylink); + return err; + } + +@@ -295,8 +307,7 @@ static int dpaa_stop(struct net_device * + */ + msleep(200); + +- if (mac_dev->phy_dev) +- phy_stop(mac_dev->phy_dev); ++ phylink_stop(mac_dev->phylink); + mac_dev->disable(mac_dev->fman_mac); + + for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) { +@@ -305,8 +316,7 @@ static int dpaa_stop(struct net_device * + err = error; + } + +- if (net_dev->phydev) +- phy_disconnect(net_dev->phydev); ++ phylink_disconnect_phy(mac_dev->phylink); + net_dev->phydev = NULL; + + msleep(200); +@@ -834,10 +844,10 @@ static int dpaa_eth_cgr_init(struct dpaa + + /* Set different thresholds based on the configured MAC speed. + * This may turn suboptimal if the MAC is reconfigured at another +- * speed, so MACs must call dpaa_eth_cgr_set_speed in their adjust_link ++ * speed, so MACs must call dpaa_eth_cgr_set_speed in their link_up + * callback. + */ +- if (priv->mac_dev->if_support & SUPPORTED_10000baseT_Full) ++ if (priv->mac_dev->phylink_config.mac_capabilities & MAC_10000FD) + cs_th = DPAA_CS_THRESHOLD_10G; + else + cs_th = DPAA_CS_THRESHOLD_1G; +@@ -866,7 +876,7 @@ out_error: + + static void dpaa_eth_cgr_set_speed(struct mac_device *mac_dev, int speed) + { +- struct net_device *net_dev = mac_dev->net_dev; ++ struct net_device *net_dev = to_net_dev(mac_dev->phylink_config.dev); + struct dpaa_priv *priv = netdev_priv(net_dev); + struct qm_mcc_initcgr opts = { }; + u32 cs_th; +@@ -2905,58 +2915,6 @@ static void dpaa_eth_napi_disable(struct + } + } + +-static void dpaa_adjust_link(struct net_device *net_dev) +-{ +- struct mac_device *mac_dev; +- struct dpaa_priv *priv; +- +- priv = netdev_priv(net_dev); +- mac_dev = priv->mac_dev; +- mac_dev->adjust_link(mac_dev); +-} +- +-/* The Aquantia PHYs are capable of performing rate adaptation */ +-#define PHY_VEND_AQUANTIA 0x03a1b400 +-#define PHY_VEND_AQUANTIA2 0x31c31c00 +- +-static int dpaa_phy_init(struct net_device *net_dev) +-{ +- __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; +- struct mac_device *mac_dev; +- struct phy_device *phy_dev; +- struct dpaa_priv *priv; +- u32 phy_vendor; +- +- priv = netdev_priv(net_dev); +- mac_dev = priv->mac_dev; +- +- phy_dev = of_phy_connect(net_dev, mac_dev->phy_node, +- &dpaa_adjust_link, 0, +- mac_dev->phy_if); +- if (!phy_dev) { +- netif_err(priv, ifup, net_dev, "init_phy() failed\n"); +- return -ENODEV; +- } +- +- phy_vendor = phy_dev->drv->phy_id & GENMASK(31, 10); +- /* Unless the PHY is capable of rate adaptation */ +- if (mac_dev->phy_if != PHY_INTERFACE_MODE_XGMII || +- (phy_vendor != PHY_VEND_AQUANTIA && +- phy_vendor != PHY_VEND_AQUANTIA2)) { +- /* remove any features not supported by the controller */ +- ethtool_convert_legacy_u32_to_link_mode(mask, +- mac_dev->if_support); +- linkmode_and(phy_dev->supported, phy_dev->supported, mask); +- } +- +- phy_support_asym_pause(phy_dev); +- +- mac_dev->phy_dev = phy_dev; +- net_dev->phydev = phy_dev; +- +- return 0; +-} +- + static int dpaa_open(struct net_device *net_dev) + { + struct mac_device *mac_dev; +@@ -2967,7 +2925,8 @@ static int dpaa_open(struct net_device * + mac_dev = priv->mac_dev; + dpaa_eth_napi_enable(priv); + +- err = dpaa_phy_init(net_dev); ++ err = phylink_of_phy_connect(mac_dev->phylink, ++ mac_dev->dev->of_node, 0); + if (err) + goto phy_init_failed; + +@@ -2982,7 +2941,7 @@ static int dpaa_open(struct net_device * + netif_err(priv, ifup, net_dev, "mac_dev->enable() = %d\n", err); + goto mac_start_failed; + } +- phy_start(priv->mac_dev->phy_dev); ++ phylink_start(mac_dev->phylink); + + netif_tx_start_all_queues(net_dev); + +@@ -2991,6 +2950,7 @@ static int dpaa_open(struct net_device * + mac_start_failed: + for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) + fman_port_disable(mac_dev->port[i]); ++ phylink_disconnect_phy(mac_dev->phylink); + + phy_init_failed: + dpaa_eth_napi_disable(priv); +@@ -3146,10 +3106,12 @@ static int dpaa_ts_ioctl(struct net_devi + static int dpaa_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd) + { + int ret = -EINVAL; ++ struct dpaa_priv *priv = netdev_priv(net_dev); + + if (cmd == SIOCGMIIREG) { + if (net_dev->phydev) +- return phy_mii_ioctl(net_dev->phydev, rq, cmd); ++ return phylink_mii_ioctl(priv->mac_dev->phylink, rq, ++ cmd); + } + + if (cmd == SIOCSHWTSTAMP) +@@ -3552,6 +3514,7 @@ static int dpaa_remove(struct platform_d + + dev_set_drvdata(dev, NULL); + unregister_netdev(net_dev); ++ phylink_destroy(priv->mac_dev->phylink); + + err = dpaa_fq_free(dev, &priv->dpaa_fq_list); + +--- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c ++++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c +@@ -54,27 +54,19 @@ static char dpaa_stats_global[][ETH_GSTR + static int dpaa_get_link_ksettings(struct net_device *net_dev, + struct ethtool_link_ksettings *cmd) + { +- if (!net_dev->phydev) +- return 0; ++ struct dpaa_priv *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; + +- phy_ethtool_ksettings_get(net_dev->phydev, cmd); +- +- return 0; ++ return phylink_ethtool_ksettings_get(mac_dev->phylink, cmd); + } + + static int dpaa_set_link_ksettings(struct net_device *net_dev, + const struct ethtool_link_ksettings *cmd) + { +- int err; +- +- if (!net_dev->phydev) +- return -ENODEV; ++ struct dpaa_priv *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; + +- err = phy_ethtool_ksettings_set(net_dev->phydev, cmd); +- if (err < 0) +- netdev_err(net_dev, "phy_ethtool_ksettings_set() = %d\n", err); +- +- return err; ++ return phylink_ethtool_ksettings_set(mac_dev->phylink, cmd); + } + + static void dpaa_get_drvinfo(struct net_device *net_dev, +@@ -99,80 +91,28 @@ static void dpaa_set_msglevel(struct net + + static int dpaa_nway_reset(struct net_device *net_dev) + { +- int err; +- +- if (!net_dev->phydev) +- return -ENODEV; ++ struct dpaa_priv *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; + +- err = 0; +- if (net_dev->phydev->autoneg) { +- err = phy_start_aneg(net_dev->phydev); +- if (err < 0) +- netdev_err(net_dev, "phy_start_aneg() = %d\n", +- err); +- } +- +- return err; ++ return phylink_ethtool_nway_reset(mac_dev->phylink); + } + + static void dpaa_get_pauseparam(struct net_device *net_dev, + struct ethtool_pauseparam *epause) + { +- struct mac_device *mac_dev; +- struct dpaa_priv *priv; +- +- priv = netdev_priv(net_dev); +- mac_dev = priv->mac_dev; +- +- if (!net_dev->phydev) +- return; ++ struct dpaa_priv *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; + +- epause->autoneg = mac_dev->autoneg_pause; +- epause->rx_pause = mac_dev->rx_pause_active; +- epause->tx_pause = mac_dev->tx_pause_active; ++ phylink_ethtool_get_pauseparam(mac_dev->phylink, epause); + } + + static int dpaa_set_pauseparam(struct net_device *net_dev, + struct ethtool_pauseparam *epause) + { +- struct mac_device *mac_dev; +- struct phy_device *phydev; +- bool rx_pause, tx_pause; +- struct dpaa_priv *priv; +- int err; +- +- priv = netdev_priv(net_dev); +- mac_dev = priv->mac_dev; +- +- phydev = net_dev->phydev; +- if (!phydev) { +- netdev_err(net_dev, "phy device not initialized\n"); +- return -ENODEV; +- } +- +- if (!phy_validate_pause(phydev, epause)) +- return -EINVAL; +- +- /* The MAC should know how to handle PAUSE frame autonegotiation before +- * adjust_link is triggered by a forced renegotiation of sym/asym PAUSE +- * settings. +- */ +- mac_dev->autoneg_pause = !!epause->autoneg; +- mac_dev->rx_pause_req = !!epause->rx_pause; +- mac_dev->tx_pause_req = !!epause->tx_pause; +- +- /* Determine the sym/asym advertised PAUSE capabilities from the desired +- * rx/tx pause settings. +- */ +- +- phy_set_asym_pause(phydev, epause->rx_pause, epause->tx_pause); +- +- fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); +- err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); +- if (err < 0) +- netdev_err(net_dev, "set_mac_active_pause() = %d\n", err); ++ struct dpaa_priv *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; + +- return err; ++ return phylink_ethtool_set_pauseparam(mac_dev->phylink, epause); + } + + static int dpaa_get_sset_count(struct net_device *net_dev, int type) +--- a/drivers/net/ethernet/freescale/fman/Kconfig ++++ b/drivers/net/ethernet/freescale/fman/Kconfig +@@ -3,7 +3,6 @@ config FSL_FMAN + tristate "FMan support" + depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST + select GENERIC_ALLOCATOR +- select PHYLIB + select PHYLINK + select PCS + select PCS_LYNX +--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c ++++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + /* TBI register addresses */ + #define MII_TBICON 0x11 +@@ -29,9 +30,6 @@ + #define TBICON_CLK_SELECT 0x0020 /* Clock select */ + #define TBICON_MI_MODE 0x0010 /* GMII mode (TBI if not set) */ + +-#define TBIANA_SGMII 0x4001 +-#define TBIANA_1000X 0x01a0 +- + /* Interrupt Mask Register (IMASK) */ + #define DTSEC_IMASK_BREN 0x80000000 + #define DTSEC_IMASK_RXCEN 0x40000000 +@@ -92,9 +90,10 @@ + + #define DTSEC_ECNTRL_GMIIM 0x00000040 + #define DTSEC_ECNTRL_TBIM 0x00000020 +-#define DTSEC_ECNTRL_SGMIIM 0x00000002 + #define DTSEC_ECNTRL_RPM 0x00000010 + #define DTSEC_ECNTRL_R100M 0x00000008 ++#define DTSEC_ECNTRL_RMM 0x00000004 ++#define DTSEC_ECNTRL_SGMIIM 0x00000002 + #define DTSEC_ECNTRL_QSGMIIM 0x00000001 + + #define TCTRL_TTSE 0x00000040 +@@ -318,7 +317,8 @@ struct fman_mac { + void *fm; + struct fman_rev_info fm_rev_info; + bool basex_if; +- struct phy_device *tbiphy; ++ struct mdio_device *tbidev; ++ struct phylink_pcs pcs; + }; + + static void set_dflts(struct dtsec_cfg *cfg) +@@ -356,56 +356,14 @@ static int init(struct dtsec_regs __iome + phy_interface_t iface, u16 iface_speed, u64 addr, + u32 exception_mask, u8 tbi_addr) + { +- bool is_rgmii, is_sgmii, is_qsgmii; + enet_addr_t eth_addr; +- u32 tmp; ++ u32 tmp = 0; + int i; + + /* Soft reset */ + iowrite32be(MACCFG1_SOFT_RESET, ®s->maccfg1); + iowrite32be(0, ®s->maccfg1); + +- /* dtsec_id2 */ +- tmp = ioread32be(®s->tsec_id2); +- +- /* check RGMII support */ +- if (iface == PHY_INTERFACE_MODE_RGMII || +- iface == PHY_INTERFACE_MODE_RGMII_ID || +- iface == PHY_INTERFACE_MODE_RGMII_RXID || +- iface == PHY_INTERFACE_MODE_RGMII_TXID || +- iface == PHY_INTERFACE_MODE_RMII) +- if (tmp & DTSEC_ID2_INT_REDUCED_OFF) +- return -EINVAL; +- +- if (iface == PHY_INTERFACE_MODE_SGMII || +- iface == PHY_INTERFACE_MODE_MII) +- if (tmp & DTSEC_ID2_INT_REDUCED_OFF) +- return -EINVAL; +- +- is_rgmii = iface == PHY_INTERFACE_MODE_RGMII || +- iface == PHY_INTERFACE_MODE_RGMII_ID || +- iface == PHY_INTERFACE_MODE_RGMII_RXID || +- iface == PHY_INTERFACE_MODE_RGMII_TXID; +- is_sgmii = iface == PHY_INTERFACE_MODE_SGMII; +- is_qsgmii = iface == PHY_INTERFACE_MODE_QSGMII; +- +- tmp = 0; +- if (is_rgmii || iface == PHY_INTERFACE_MODE_GMII) +- tmp |= DTSEC_ECNTRL_GMIIM; +- if (is_sgmii) +- tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM); +- if (is_qsgmii) +- tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM | +- DTSEC_ECNTRL_QSGMIIM); +- if (is_rgmii) +- tmp |= DTSEC_ECNTRL_RPM; +- if (iface_speed == SPEED_100) +- tmp |= DTSEC_ECNTRL_R100M; +- +- iowrite32be(tmp, ®s->ecntrl); +- +- tmp = 0; +- + if (cfg->tx_pause_time) + tmp |= cfg->tx_pause_time; + if (cfg->tx_pause_time_extd) +@@ -446,17 +404,10 @@ static int init(struct dtsec_regs __iome + + tmp = 0; + +- if (iface_speed < SPEED_1000) +- tmp |= MACCFG2_NIBBLE_MODE; +- else if (iface_speed == SPEED_1000) +- tmp |= MACCFG2_BYTE_MODE; +- + tmp |= (cfg->preamble_len << MACCFG2_PREAMBLE_LENGTH_SHIFT) & + MACCFG2_PREAMBLE_LENGTH_MASK; + if (cfg->tx_pad_crc) + tmp |= MACCFG2_PAD_CRC_EN; +- /* Full Duplex */ +- tmp |= MACCFG2_FULL_DUPLEX; + iowrite32be(tmp, ®s->maccfg2); + + tmp = (((cfg->non_back_to_back_ipg1 << +@@ -525,10 +476,6 @@ static void set_bucket(struct dtsec_regs + + static int check_init_parameters(struct fman_mac *dtsec) + { +- if (dtsec->max_speed >= SPEED_10000) { +- pr_err("1G MAC driver supports 1G or lower speeds\n"); +- return -EINVAL; +- } + if ((dtsec->dtsec_drv_param)->rx_prepend > + MAX_PACKET_ALIGNMENT) { + pr_err("packetAlignmentPadding can't be > than %d\n", +@@ -630,22 +577,10 @@ static int get_exception_flag(enum fman_ + return bit_mask; + } + +-static bool is_init_done(struct dtsec_cfg *dtsec_drv_params) +-{ +- /* Checks if dTSEC driver parameters were initialized */ +- if (!dtsec_drv_params) +- return true; +- +- return false; +-} +- + static u16 dtsec_get_max_frame_length(struct fman_mac *dtsec) + { + struct dtsec_regs __iomem *regs = dtsec->regs; + +- if (is_init_done(dtsec->dtsec_drv_param)) +- return 0; +- + return (u16)ioread32be(®s->maxfrm); + } + +@@ -682,6 +617,7 @@ static void dtsec_isr(void *handle) + dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_COL_RET_LMT); + if (event & DTSEC_IMASK_XFUNEN) { + /* FM_TX_LOCKUP_ERRATA_DTSEC6 Errata workaround */ ++ /* FIXME: This races with the rest of the driver! */ + if (dtsec->fm_rev_info.major == 2) { + u32 tpkt1, tmp_reg1, tpkt2, tmp_reg2, i; + /* a. Write 0x00E0_0C00 to DTSEC_ID +@@ -814,6 +750,43 @@ static void free_init_resources(struct f + dtsec->unicast_addr_hash = NULL; + } + ++static struct fman_mac *pcs_to_dtsec(struct phylink_pcs *pcs) ++{ ++ return container_of(pcs, struct fman_mac, pcs); ++} ++ ++static void dtsec_pcs_get_state(struct phylink_pcs *pcs, ++ struct phylink_link_state *state) ++{ ++ struct fman_mac *dtsec = pcs_to_dtsec(pcs); ++ ++ phylink_mii_c22_pcs_get_state(dtsec->tbidev, state); ++} ++ ++static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++ phy_interface_t interface, ++ const unsigned long *advertising, ++ bool permit_pause_to_mac) ++{ ++ struct fman_mac *dtsec = pcs_to_dtsec(pcs); ++ ++ return phylink_mii_c22_pcs_config(dtsec->tbidev, mode, interface, ++ advertising); ++} ++ ++static void dtsec_pcs_an_restart(struct phylink_pcs *pcs) ++{ ++ struct fman_mac *dtsec = pcs_to_dtsec(pcs); ++ ++ phylink_mii_c22_pcs_an_restart(dtsec->tbidev); ++} ++ ++static const struct phylink_pcs_ops dtsec_pcs_ops = { ++ .pcs_get_state = dtsec_pcs_get_state, ++ .pcs_config = dtsec_pcs_config, ++ .pcs_an_restart = dtsec_pcs_an_restart, ++}; ++ + static void graceful_start(struct fman_mac *dtsec) + { + struct dtsec_regs __iomem *regs = dtsec->regs; +@@ -854,36 +827,11 @@ static void graceful_stop(struct fman_ma + + static int dtsec_enable(struct fman_mac *dtsec) + { +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 tmp; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- /* Enable */ +- tmp = ioread32be(®s->maccfg1); +- tmp |= MACCFG1_RX_EN | MACCFG1_TX_EN; +- iowrite32be(tmp, ®s->maccfg1); +- +- /* Graceful start - clear the graceful Rx/Tx stop bit */ +- graceful_start(dtsec); +- + return 0; + } + + static void dtsec_disable(struct fman_mac *dtsec) + { +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 tmp; +- +- WARN_ON_ONCE(!is_init_done(dtsec->dtsec_drv_param)); +- +- /* Graceful stop - Assert the graceful Rx/Tx stop bit */ +- graceful_stop(dtsec); +- +- tmp = ioread32be(®s->maccfg1); +- tmp &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); +- iowrite32be(tmp, ®s->maccfg1); + } + + static int dtsec_set_tx_pause_frames(struct fman_mac *dtsec, +@@ -894,11 +842,6 @@ static int dtsec_set_tx_pause_frames(str + struct dtsec_regs __iomem *regs = dtsec->regs; + u32 ptv = 0; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- graceful_stop(dtsec); +- + if (pause_time) { + /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 Errata workaround */ + if (dtsec->fm_rev_info.major == 2 && pause_time <= 320) { +@@ -919,8 +862,6 @@ static int dtsec_set_tx_pause_frames(str + iowrite32be(ioread32be(®s->maccfg1) & ~MACCFG1_TX_FLOW, + ®s->maccfg1); + +- graceful_start(dtsec); +- + return 0; + } + +@@ -929,11 +870,6 @@ static int dtsec_accept_rx_pause_frames( + struct dtsec_regs __iomem *regs = dtsec->regs; + u32 tmp; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- graceful_stop(dtsec); +- + tmp = ioread32be(®s->maccfg1); + if (en) + tmp |= MACCFG1_RX_FLOW; +@@ -941,17 +877,125 @@ static int dtsec_accept_rx_pause_frames( + tmp &= ~MACCFG1_RX_FLOW; + iowrite32be(tmp, ®s->maccfg1); + ++ return 0; ++} ++ ++static struct phylink_pcs *dtsec_select_pcs(struct phylink_config *config, ++ phy_interface_t iface) ++{ ++ struct fman_mac *dtsec = fman_config_to_mac(config)->fman_mac; ++ ++ switch (iface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ return &dtsec->pcs; ++ default: ++ return NULL; ++ } ++} ++ ++static void dtsec_mac_config(struct phylink_config *config, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ struct mac_device *mac_dev = fman_config_to_mac(config); ++ struct dtsec_regs __iomem *regs = mac_dev->fman_mac->regs; ++ u32 tmp; ++ ++ switch (state->interface) { ++ case PHY_INTERFACE_MODE_RMII: ++ tmp = DTSEC_ECNTRL_RMM; ++ break; ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ tmp = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM; ++ break; ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ tmp = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM; ++ break; ++ default: ++ dev_warn(mac_dev->dev, "cannot configure dTSEC for %s\n", ++ phy_modes(state->interface)); ++ return; ++ } ++ ++ iowrite32be(tmp, ®s->ecntrl); ++} ++ ++static void dtsec_link_up(struct phylink_config *config, struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, bool tx_pause, bool rx_pause) ++{ ++ struct mac_device *mac_dev = fman_config_to_mac(config); ++ struct fman_mac *dtsec = mac_dev->fman_mac; ++ struct dtsec_regs __iomem *regs = dtsec->regs; ++ u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE : ++ FSL_FM_PAUSE_TIME_DISABLE; ++ u32 tmp; ++ ++ dtsec_set_tx_pause_frames(dtsec, 0, pause_time, 0); ++ dtsec_accept_rx_pause_frames(dtsec, rx_pause); ++ ++ tmp = ioread32be(®s->ecntrl); ++ if (speed == SPEED_100) ++ tmp |= DTSEC_ECNTRL_R100M; ++ else ++ tmp &= ~DTSEC_ECNTRL_R100M; ++ iowrite32be(tmp, ®s->ecntrl); ++ ++ tmp = ioread32be(®s->maccfg2); ++ tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE | MACCFG2_FULL_DUPLEX); ++ if (speed >= SPEED_1000) ++ tmp |= MACCFG2_BYTE_MODE; ++ else ++ tmp |= MACCFG2_NIBBLE_MODE; ++ ++ if (duplex == DUPLEX_FULL) ++ tmp |= MACCFG2_FULL_DUPLEX; ++ ++ iowrite32be(tmp, ®s->maccfg2); ++ ++ mac_dev->update_speed(mac_dev, speed); ++ ++ /* Enable */ ++ tmp = ioread32be(®s->maccfg1); ++ tmp |= MACCFG1_RX_EN | MACCFG1_TX_EN; ++ iowrite32be(tmp, ®s->maccfg1); ++ ++ /* Graceful start - clear the graceful Rx/Tx stop bit */ + graceful_start(dtsec); ++} + +- return 0; ++static void dtsec_link_down(struct phylink_config *config, unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct fman_mac *dtsec = fman_config_to_mac(config)->fman_mac; ++ struct dtsec_regs __iomem *regs = dtsec->regs; ++ u32 tmp; ++ ++ /* Graceful stop - Assert the graceful Rx/Tx stop bit */ ++ graceful_stop(dtsec); ++ ++ tmp = ioread32be(®s->maccfg1); ++ tmp &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); ++ iowrite32be(tmp, ®s->maccfg1); + } + ++static const struct phylink_mac_ops dtsec_mac_ops = { ++ .validate = phylink_generic_validate, ++ .mac_select_pcs = dtsec_select_pcs, ++ .mac_config = dtsec_mac_config, ++ .mac_link_up = dtsec_link_up, ++ .mac_link_down = dtsec_link_down, ++}; ++ + static int dtsec_modify_mac_address(struct fman_mac *dtsec, + const enet_addr_t *enet_addr) + { +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + graceful_stop(dtsec); + + /* Initialize MAC Station Address registers (1 & 2) +@@ -975,9 +1019,6 @@ static int dtsec_add_hash_mac_address(st + u32 crc = 0xFFFFFFFF; + bool mcast, ghtx; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + addr = ENET_ADDR_TO_UINT64(*eth_addr); + + ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? true : false); +@@ -1037,9 +1078,6 @@ static int dtsec_set_allmulti(struct fma + u32 tmp; + struct dtsec_regs __iomem *regs = dtsec->regs; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + tmp = ioread32be(®s->rctrl); + if (enable) + tmp |= RCTRL_MPROM; +@@ -1056,9 +1094,6 @@ static int dtsec_set_tstamp(struct fman_ + struct dtsec_regs __iomem *regs = dtsec->regs; + u32 rctrl, tctrl; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + rctrl = ioread32be(®s->rctrl); + tctrl = ioread32be(®s->tctrl); + +@@ -1087,9 +1122,6 @@ static int dtsec_del_hash_mac_address(st + u32 crc = 0xFFFFFFFF; + bool mcast, ghtx; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + addr = ENET_ADDR_TO_UINT64(*eth_addr); + + ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? true : false); +@@ -1153,9 +1185,6 @@ static int dtsec_set_promiscuous(struct + struct dtsec_regs __iomem *regs = dtsec->regs; + u32 tmp; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + /* Set unicast promiscuous */ + tmp = ioread32be(®s->rctrl); + if (new_val) +@@ -1177,90 +1206,12 @@ static int dtsec_set_promiscuous(struct + return 0; + } + +-static int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed) +-{ +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 tmp; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- graceful_stop(dtsec); +- +- tmp = ioread32be(®s->maccfg2); +- +- /* Full Duplex */ +- tmp |= MACCFG2_FULL_DUPLEX; +- +- tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE); +- if (speed < SPEED_1000) +- tmp |= MACCFG2_NIBBLE_MODE; +- else if (speed == SPEED_1000) +- tmp |= MACCFG2_BYTE_MODE; +- iowrite32be(tmp, ®s->maccfg2); +- +- tmp = ioread32be(®s->ecntrl); +- if (speed == SPEED_100) +- tmp |= DTSEC_ECNTRL_R100M; +- else +- tmp &= ~DTSEC_ECNTRL_R100M; +- iowrite32be(tmp, ®s->ecntrl); +- +- graceful_start(dtsec); +- +- return 0; +-} +- +-static int dtsec_restart_autoneg(struct fman_mac *dtsec) +-{ +- u16 tmp_reg16; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- tmp_reg16 = phy_read(dtsec->tbiphy, MII_BMCR); +- +- tmp_reg16 &= ~(BMCR_SPEED100 | BMCR_SPEED1000); +- tmp_reg16 |= (BMCR_ANENABLE | BMCR_ANRESTART | +- BMCR_FULLDPLX | BMCR_SPEED1000); +- +- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); +- +- return 0; +-} +- +-static void adjust_link_dtsec(struct mac_device *mac_dev) +-{ +- struct phy_device *phy_dev = mac_dev->phy_dev; +- struct fman_mac *fman_mac; +- bool rx_pause, tx_pause; +- int err; +- +- fman_mac = mac_dev->fman_mac; +- if (!phy_dev->link) { +- dtsec_restart_autoneg(fman_mac); +- +- return; +- } +- +- dtsec_adjust_link(fman_mac, phy_dev->speed); +- mac_dev->update_speed(mac_dev, phy_dev->speed); +- fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); +- err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); +- if (err < 0) +- dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n", +- err); +-} +- + static int dtsec_set_exception(struct fman_mac *dtsec, + enum fman_mac_exceptions exception, bool enable) + { + struct dtsec_regs __iomem *regs = dtsec->regs; + u32 bit_mask = 0; + +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + if (exception != FM_MAC_EX_1G_1588_TS_RX_ERR) { + bit_mask = get_exception_flag(exception); + if (bit_mask) { +@@ -1310,12 +1261,9 @@ static int dtsec_init(struct fman_mac *d + { + struct dtsec_regs __iomem *regs = dtsec->regs; + struct dtsec_cfg *dtsec_drv_param; +- u16 max_frm_ln; ++ u16 max_frm_ln, tbicon; + int err; + +- if (is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- + if (DEFAULT_RESET_ON_INIT && + (fman_reset_mac(dtsec->fm, dtsec->mac_id) != 0)) { + pr_err("Can't reset MAC!\n"); +@@ -1330,38 +1278,19 @@ static int dtsec_init(struct fman_mac *d + + err = init(dtsec->regs, dtsec_drv_param, dtsec->phy_if, + dtsec->max_speed, dtsec->addr, dtsec->exceptions, +- dtsec->tbiphy->mdio.addr); ++ dtsec->tbidev->addr); + if (err) { + free_init_resources(dtsec); + pr_err("DTSEC version doesn't support this i/f mode\n"); + return err; + } + +- if (dtsec->phy_if == PHY_INTERFACE_MODE_SGMII) { +- u16 tmp_reg16; +- +- /* Configure the TBI PHY Control Register */ +- tmp_reg16 = TBICON_CLK_SELECT | TBICON_SOFT_RESET; +- phy_write(dtsec->tbiphy, MII_TBICON, tmp_reg16); +- +- tmp_reg16 = TBICON_CLK_SELECT; +- phy_write(dtsec->tbiphy, MII_TBICON, tmp_reg16); +- +- tmp_reg16 = (BMCR_RESET | BMCR_ANENABLE | +- BMCR_FULLDPLX | BMCR_SPEED1000); +- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); +- +- if (dtsec->basex_if) +- tmp_reg16 = TBIANA_1000X; +- else +- tmp_reg16 = TBIANA_SGMII; +- phy_write(dtsec->tbiphy, MII_ADVERTISE, tmp_reg16); ++ /* Configure the TBI PHY Control Register */ ++ tbicon = TBICON_CLK_SELECT | TBICON_SOFT_RESET; ++ mdiodev_write(dtsec->tbidev, MII_TBICON, tbicon); + +- tmp_reg16 = (BMCR_ANENABLE | BMCR_ANRESTART | +- BMCR_FULLDPLX | BMCR_SPEED1000); +- +- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); +- } ++ tbicon = TBICON_CLK_SELECT; ++ mdiodev_write(dtsec->tbidev, MII_TBICON, tbicon); + + /* Max Frame Length */ + max_frm_ln = (u16)ioread32be(®s->maxfrm); +@@ -1406,6 +1335,8 @@ static int dtsec_free(struct fman_mac *d + + kfree(dtsec->dtsec_drv_param); + dtsec->dtsec_drv_param = NULL; ++ if (!IS_ERR_OR_NULL(dtsec->tbidev)) ++ put_device(&dtsec->tbidev->dev); + kfree(dtsec); + + return 0; +@@ -1434,7 +1365,6 @@ static struct fman_mac *dtsec_config(str + + dtsec->regs = mac_dev->vaddr; + dtsec->addr = ENET_ADDR_TO_UINT64(mac_dev->addr); +- dtsec->max_speed = params->max_speed; + dtsec->phy_if = mac_dev->phy_if; + dtsec->mac_id = params->mac_id; + dtsec->exceptions = (DTSEC_IMASK_BREN | +@@ -1457,7 +1387,6 @@ static struct fman_mac *dtsec_config(str + dtsec->en_tsu_err_exception = dtsec->dtsec_drv_param->ptp_exception_en; + + dtsec->fm = params->fm; +- dtsec->basex_if = params->basex_if; + + /* Save FMan revision */ + fman_get_revision(dtsec->fm, &dtsec->fm_rev_info); +@@ -1476,18 +1405,18 @@ int dtsec_initialization(struct mac_devi + int err; + struct fman_mac *dtsec; + struct device_node *phy_node; ++ unsigned long capabilities; ++ unsigned long *supported; + ++ mac_dev->phylink_ops = &dtsec_mac_ops; + mac_dev->set_promisc = dtsec_set_promiscuous; + mac_dev->change_addr = dtsec_modify_mac_address; + mac_dev->add_hash_mac_addr = dtsec_add_hash_mac_address; + mac_dev->remove_hash_mac_addr = dtsec_del_hash_mac_address; +- mac_dev->set_tx_pause = dtsec_set_tx_pause_frames; +- mac_dev->set_rx_pause = dtsec_accept_rx_pause_frames; + mac_dev->set_exception = dtsec_set_exception; + mac_dev->set_allmulti = dtsec_set_allmulti; + mac_dev->set_tstamp = dtsec_set_tstamp; + mac_dev->set_multi = fman_set_multi; +- mac_dev->adjust_link = adjust_link_dtsec; + mac_dev->enable = dtsec_enable; + mac_dev->disable = dtsec_disable; + +@@ -1502,19 +1431,56 @@ int dtsec_initialization(struct mac_devi + dtsec->dtsec_drv_param->tx_pad_crc = true; + + phy_node = of_parse_phandle(mac_node, "tbi-handle", 0); +- if (!phy_node) { +- pr_err("TBI PHY node is not available\n"); ++ if (!phy_node || of_device_is_available(phy_node)) { ++ of_node_put(phy_node); + err = -EINVAL; ++ dev_err_probe(mac_dev->dev, err, ++ "TBI PCS node is not available\n"); + goto _return_fm_mac_free; + } + +- dtsec->tbiphy = of_phy_find_device(phy_node); +- if (!dtsec->tbiphy) { +- pr_err("of_phy_find_device (TBI PHY) failed\n"); +- err = -EINVAL; ++ dtsec->tbidev = of_mdio_find_device(phy_node); ++ of_node_put(phy_node); ++ if (!dtsec->tbidev) { ++ err = -EPROBE_DEFER; ++ dev_err_probe(mac_dev->dev, err, ++ "could not find mdiodev for PCS\n"); + goto _return_fm_mac_free; + } +- put_device(&dtsec->tbiphy->mdio.dev); ++ dtsec->pcs.ops = &dtsec_pcs_ops; ++ dtsec->pcs.poll = true; ++ ++ supported = mac_dev->phylink_config.supported_interfaces; ++ ++ /* FIXME: Can we use DTSEC_ID2_INT_FULL_OFF to determine if these are ++ * supported? If not, we can determine support via the phy if SerDes ++ * support is added. ++ */ ++ if (mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII || ++ mac_dev->phy_if == PHY_INTERFACE_MODE_1000BASEX) { ++ __set_bit(PHY_INTERFACE_MODE_SGMII, supported); ++ __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported); ++ } else if (mac_dev->phy_if == PHY_INTERFACE_MODE_2500BASEX) { ++ __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); ++ } ++ ++ if (!(ioread32be(&dtsec->regs->tsec_id2) & DTSEC_ID2_INT_REDUCED_OFF)) { ++ phy_interface_set_rgmii(supported); ++ ++ /* DTSEC_ID2_INT_REDUCED_OFF indicates that the dTSEC supports ++ * RMII and RGMII. However, the only SoCs which support RMII ++ * are the P1017 and P1023. Avoid advertising this mode on ++ * other SoCs. This is a bit of a moot point, since there's no ++ * in-tree support for ethernet on these platforms... ++ */ ++ if (of_machine_is_compatible("fsl,P1023") || ++ of_machine_is_compatible("fsl,P1023RDB")) ++ __set_bit(PHY_INTERFACE_MODE_RMII, supported); ++ } ++ ++ capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE; ++ capabilities |= MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD; ++ mac_dev->phylink_config.mac_capabilities = capabilities; + + err = dtsec_init(dtsec); + if (err < 0) +--- a/drivers/net/ethernet/freescale/fman/fman_mac.h ++++ b/drivers/net/ethernet/freescale/fman/fman_mac.h +@@ -170,20 +170,10 @@ struct fman_mac_params { + * 0 - FM_MAX_NUM_OF_10G_MACS + */ + u8 mac_id; +- /* Note that the speed should indicate the maximum rate that +- * this MAC should support rather than the actual speed; +- */ +- u16 max_speed; + /* A handle to the FM object this port related to */ + void *fm; + fman_mac_exception_cb *event_cb; /* MDIO Events Callback Routine */ + fman_mac_exception_cb *exception_cb;/* Exception Callback Routine */ +- /* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC +- * and phy or backplane; Note: 1000BaseX auto-negotiation relates only +- * to interface between MAC and phy/backplane, SGMII phy can still +- * synchronize with far-end phy at 10Mbps, 100Mbps or 1000Mbps +- */ +- bool basex_if; + }; + + struct eth_hash_t { +--- a/drivers/net/ethernet/freescale/fman/fman_memac.c ++++ b/drivers/net/ethernet/freescale/fman/fman_memac.c +@@ -278,9 +278,6 @@ struct fman_mac { + struct memac_regs __iomem *regs; + /* MAC address of device */ + u64 addr; +- /* Ethernet physical interface */ +- phy_interface_t phy_if; +- u16 max_speed; + struct mac_device *dev_id; /* device cookie used by the exception cbs */ + fman_mac_exception_cb *exception_cb; + fman_mac_exception_cb *event_cb; +@@ -293,12 +290,12 @@ struct fman_mac { + struct memac_cfg *memac_drv_param; + void *fm; + struct fman_rev_info fm_rev_info; +- bool basex_if; + struct phy *serdes; + struct phylink_pcs *sgmii_pcs; + struct phylink_pcs *qsgmii_pcs; + struct phylink_pcs *xfi_pcs; + bool allmulti_enabled; ++ bool rgmii_no_half_duplex; + }; + + static void add_addr_in_paddr(struct memac_regs __iomem *regs, const u8 *adr, +@@ -356,7 +353,6 @@ static void set_exception(struct memac_r + } + + static int init(struct memac_regs __iomem *regs, struct memac_cfg *cfg, +- phy_interface_t phy_if, u16 speed, bool slow_10g_if, + u32 exceptions) + { + u32 tmp; +@@ -384,41 +380,6 @@ static int init(struct memac_regs __iome + iowrite32be((u32)cfg->pause_quanta, ®s->pause_quanta[0]); + iowrite32be((u32)0, ®s->pause_thresh[0]); + +- /* IF_MODE */ +- tmp = 0; +- switch (phy_if) { +- case PHY_INTERFACE_MODE_XGMII: +- tmp |= IF_MODE_10G; +- break; +- case PHY_INTERFACE_MODE_MII: +- tmp |= IF_MODE_MII; +- break; +- default: +- tmp |= IF_MODE_GMII; +- if (phy_if == PHY_INTERFACE_MODE_RGMII || +- phy_if == PHY_INTERFACE_MODE_RGMII_ID || +- phy_if == PHY_INTERFACE_MODE_RGMII_RXID || +- phy_if == PHY_INTERFACE_MODE_RGMII_TXID) +- tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO; +- } +- iowrite32be(tmp, ®s->if_mode); +- +- /* TX_FIFO_SECTIONS */ +- tmp = 0; +- if (phy_if == PHY_INTERFACE_MODE_XGMII) { +- if (slow_10g_if) { +- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G | +- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G); +- } else { +- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_10G | +- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G); +- } +- } else { +- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_1G | +- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G); +- } +- iowrite32be(tmp, ®s->tx_fifo_sections); +- + /* clear all pending events and set-up interrupts */ + iowrite32be(0xffffffff, ®s->ievent); + set_exception(regs, exceptions, true); +@@ -458,24 +419,6 @@ static u32 get_mac_addr_hash_code(u64 et + return xor_val; + } + +-static void setup_sgmii_internal(struct fman_mac *memac, +- struct phylink_pcs *pcs, +- struct fixed_phy_status *fixed_link) +-{ +- __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); +- phy_interface_t iface = memac->basex_if ? PHY_INTERFACE_MODE_1000BASEX : +- PHY_INTERFACE_MODE_SGMII; +- unsigned int mode = fixed_link ? MLO_AN_FIXED : MLO_AN_INBAND; +- +- linkmode_set_pause(advertising, true, true); +- pcs->ops->pcs_config(pcs, mode, iface, advertising, true); +- if (fixed_link) +- pcs->ops->pcs_link_up(pcs, mode, iface, fixed_link->speed, +- fixed_link->duplex); +- else +- pcs->ops->pcs_an_restart(pcs); +-} +- + static int check_init_parameters(struct fman_mac *memac) + { + if (!memac->exception_cb) { +@@ -581,41 +524,31 @@ static void free_init_resources(struct f + memac->unicast_addr_hash = NULL; + } + +-static bool is_init_done(struct memac_cfg *memac_drv_params) +-{ +- /* Checks if mEMAC driver parameters were initialized */ +- if (!memac_drv_params) +- return true; +- +- return false; +-} +- + static int memac_enable(struct fman_mac *memac) + { +- struct memac_regs __iomem *regs = memac->regs; +- u32 tmp; ++ int ret; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; ++ ret = phy_init(memac->serdes); ++ if (ret) { ++ dev_err(memac->dev_id->dev, ++ "could not initialize serdes: %pe\n", ERR_PTR(ret)); ++ return ret; ++ } + +- tmp = ioread32be(®s->command_config); +- tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; +- iowrite32be(tmp, ®s->command_config); ++ ret = phy_power_on(memac->serdes); ++ if (ret) { ++ dev_err(memac->dev_id->dev, ++ "could not power on serdes: %pe\n", ERR_PTR(ret)); ++ phy_exit(memac->serdes); ++ } + +- return 0; ++ return ret; + } + + static void memac_disable(struct fman_mac *memac) +- + { +- struct memac_regs __iomem *regs = memac->regs; +- u32 tmp; +- +- WARN_ON_ONCE(!is_init_done(memac->memac_drv_param)); +- +- tmp = ioread32be(®s->command_config); +- tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); +- iowrite32be(tmp, ®s->command_config); ++ phy_power_off(memac->serdes); ++ phy_exit(memac->serdes); + } + + static int memac_set_promiscuous(struct fman_mac *memac, bool new_val) +@@ -623,9 +556,6 @@ static int memac_set_promiscuous(struct + struct memac_regs __iomem *regs = memac->regs; + u32 tmp; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + tmp = ioread32be(®s->command_config); + if (new_val) + tmp |= CMD_CFG_PROMIS_EN; +@@ -637,73 +567,12 @@ static int memac_set_promiscuous(struct + return 0; + } + +-static int memac_adjust_link(struct fman_mac *memac, u16 speed) +-{ +- struct memac_regs __iomem *regs = memac->regs; +- u32 tmp; +- +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- tmp = ioread32be(®s->if_mode); +- +- /* Set full duplex */ +- tmp &= ~IF_MODE_HD; +- +- if (phy_interface_mode_is_rgmii(memac->phy_if)) { +- /* Configure RGMII in manual mode */ +- tmp &= ~IF_MODE_RGMII_AUTO; +- tmp &= ~IF_MODE_RGMII_SP_MASK; +- /* Full duplex */ +- tmp |= IF_MODE_RGMII_FD; +- +- switch (speed) { +- case SPEED_1000: +- tmp |= IF_MODE_RGMII_1000; +- break; +- case SPEED_100: +- tmp |= IF_MODE_RGMII_100; +- break; +- case SPEED_10: +- tmp |= IF_MODE_RGMII_10; +- break; +- default: +- break; +- } +- } +- +- iowrite32be(tmp, ®s->if_mode); +- +- return 0; +-} +- +-static void adjust_link_memac(struct mac_device *mac_dev) +-{ +- struct phy_device *phy_dev = mac_dev->phy_dev; +- struct fman_mac *fman_mac; +- bool rx_pause, tx_pause; +- int err; +- +- fman_mac = mac_dev->fman_mac; +- memac_adjust_link(fman_mac, phy_dev->speed); +- mac_dev->update_speed(mac_dev, phy_dev->speed); +- +- fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); +- err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); +- if (err < 0) +- dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n", +- err); +-} +- + static int memac_set_tx_pause_frames(struct fman_mac *memac, u8 priority, + u16 pause_time, u16 thresh_time) + { + struct memac_regs __iomem *regs = memac->regs; + u32 tmp; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + tmp = ioread32be(®s->tx_fifo_sections); + + GET_TX_EMPTY_DEFAULT_VALUE(tmp); +@@ -738,9 +607,6 @@ static int memac_accept_rx_pause_frames( + struct memac_regs __iomem *regs = memac->regs; + u32 tmp; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + tmp = ioread32be(®s->command_config); + if (en) + tmp &= ~CMD_CFG_PAUSE_IGNORE; +@@ -752,12 +618,175 @@ static int memac_accept_rx_pause_frames( + return 0; + } + ++static void memac_validate(struct phylink_config *config, ++ unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; ++ unsigned long caps = config->mac_capabilities; ++ ++ if (phy_interface_mode_is_rgmii(state->interface) && ++ memac->rgmii_no_half_duplex) ++ caps &= ~(MAC_10HD | MAC_100HD); ++ ++ phylink_validate_mask_caps(supported, state, caps); ++} ++ ++/** ++ * memac_if_mode() - Convert an interface mode into an IF_MODE config ++ * @interface: A phy interface mode ++ * ++ * Return: A configuration word, suitable for programming into the lower bits ++ * of %IF_MODE. ++ */ ++static u32 memac_if_mode(phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_MII: ++ return IF_MODE_MII; ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ return IF_MODE_GMII | IF_MODE_RGMII; ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_QSGMII: ++ return IF_MODE_GMII; ++ case PHY_INTERFACE_MODE_10GBASER: ++ return IF_MODE_10G; ++ default: ++ WARN_ON_ONCE(1); ++ return 0; ++ } ++} ++ ++static struct phylink_pcs *memac_select_pcs(struct phylink_config *config, ++ phy_interface_t iface) ++{ ++ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; ++ ++ switch (iface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ return memac->sgmii_pcs; ++ case PHY_INTERFACE_MODE_QSGMII: ++ return memac->qsgmii_pcs; ++ case PHY_INTERFACE_MODE_10GBASER: ++ return memac->xfi_pcs; ++ default: ++ return NULL; ++ } ++} ++ ++static int memac_prepare(struct phylink_config *config, unsigned int mode, ++ phy_interface_t iface) ++{ ++ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; ++ ++ switch (iface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ return phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET, ++ iface); ++ default: ++ return 0; ++ } ++} ++ ++static void memac_mac_config(struct phylink_config *config, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ struct mac_device *mac_dev = fman_config_to_mac(config); ++ struct memac_regs __iomem *regs = mac_dev->fman_mac->regs; ++ u32 tmp = ioread32be(®s->if_mode); ++ ++ tmp &= ~(IF_MODE_MASK | IF_MODE_RGMII); ++ tmp |= memac_if_mode(state->interface); ++ if (phylink_autoneg_inband(mode)) ++ tmp |= IF_MODE_RGMII_AUTO; ++ iowrite32be(tmp, ®s->if_mode); ++} ++ ++static void memac_link_up(struct phylink_config *config, struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, bool tx_pause, bool rx_pause) ++{ ++ struct mac_device *mac_dev = fman_config_to_mac(config); ++ struct fman_mac *memac = mac_dev->fman_mac; ++ struct memac_regs __iomem *regs = memac->regs; ++ u32 tmp = memac_if_mode(interface); ++ u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE : ++ FSL_FM_PAUSE_TIME_DISABLE; ++ ++ memac_set_tx_pause_frames(memac, 0, pause_time, 0); ++ memac_accept_rx_pause_frames(memac, rx_pause); ++ ++ if (duplex == DUPLEX_HALF) ++ tmp |= IF_MODE_HD; ++ ++ switch (speed) { ++ case SPEED_1000: ++ tmp |= IF_MODE_RGMII_1000; ++ break; ++ case SPEED_100: ++ tmp |= IF_MODE_RGMII_100; ++ break; ++ case SPEED_10: ++ tmp |= IF_MODE_RGMII_10; ++ break; ++ } ++ iowrite32be(tmp, ®s->if_mode); ++ ++ /* TODO: EEE? */ ++ ++ if (speed == SPEED_10000) { ++ if (memac->fm_rev_info.major == 6 && ++ memac->fm_rev_info.minor == 4) ++ tmp = TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G; ++ else ++ tmp = TX_FIFO_SECTIONS_TX_AVAIL_10G; ++ tmp |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G; ++ } else { ++ tmp = TX_FIFO_SECTIONS_TX_AVAIL_1G | ++ TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G; ++ } ++ iowrite32be(tmp, ®s->tx_fifo_sections); ++ ++ mac_dev->update_speed(mac_dev, speed); ++ ++ tmp = ioread32be(®s->command_config); ++ tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++static void memac_link_down(struct phylink_config *config, unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct fman_mac *memac = fman_config_to_mac(config)->fman_mac; ++ struct memac_regs __iomem *regs = memac->regs; ++ u32 tmp; ++ ++ /* TODO: graceful */ ++ tmp = ioread32be(®s->command_config); ++ tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++static const struct phylink_mac_ops memac_mac_ops = { ++ .validate = memac_validate, ++ .mac_select_pcs = memac_select_pcs, ++ .mac_prepare = memac_prepare, ++ .mac_config = memac_mac_config, ++ .mac_link_up = memac_link_up, ++ .mac_link_down = memac_link_down, ++}; ++ + static int memac_modify_mac_address(struct fman_mac *memac, + const enet_addr_t *enet_addr) + { +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + add_addr_in_paddr(memac->regs, (const u8 *)(*enet_addr), 0); + + return 0; +@@ -771,9 +800,6 @@ static int memac_add_hash_mac_address(st + u32 hash; + u64 addr; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + addr = ENET_ADDR_TO_UINT64(*eth_addr); + + if (!(addr & GROUP_ADDRESS)) { +@@ -802,9 +828,6 @@ static int memac_set_allmulti(struct fma + u32 entry; + struct memac_regs __iomem *regs = memac->regs; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + if (enable) { + for (entry = 0; entry < HASH_TABLE_SIZE; entry++) + iowrite32be(entry | HASH_CTRL_MCAST_EN, +@@ -834,9 +857,6 @@ static int memac_del_hash_mac_address(st + u32 hash; + u64 addr; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + addr = ENET_ADDR_TO_UINT64(*eth_addr); + + hash = get_mac_addr_hash_code(addr) & HASH_CTRL_ADDR_MASK; +@@ -864,9 +884,6 @@ static int memac_set_exception(struct fm + { + u32 bit_mask = 0; + +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + bit_mask = get_exception_flag(exception); + if (bit_mask) { + if (enable) +@@ -886,23 +903,15 @@ static int memac_init(struct fman_mac *m + { + struct memac_cfg *memac_drv_param; + enet_addr_t eth_addr; +- bool slow_10g_if = false; +- struct fixed_phy_status *fixed_link = NULL; + int err; + u32 reg32 = 0; + +- if (is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- + err = check_init_parameters(memac); + if (err) + return err; + + memac_drv_param = memac->memac_drv_param; + +- if (memac->fm_rev_info.major == 6 && memac->fm_rev_info.minor == 4) +- slow_10g_if = true; +- + /* First, reset the MAC if desired. */ + if (memac_drv_param->reset_on_init) { + err = reset(memac->regs); +@@ -918,10 +927,7 @@ static int memac_init(struct fman_mac *m + add_addr_in_paddr(memac->regs, (const u8 *)eth_addr, 0); + } + +- fixed_link = memac_drv_param->fixed_link; +- +- init(memac->regs, memac->memac_drv_param, memac->phy_if, +- memac->max_speed, slow_10g_if, memac->exceptions); ++ init(memac->regs, memac->memac_drv_param, memac->exceptions); + + /* FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 errata workaround + * Exists only in FMan 6.0 and 6.3. +@@ -937,11 +943,6 @@ static int memac_init(struct fman_mac *m + iowrite32be(reg32, &memac->regs->command_config); + } + +- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII) +- setup_sgmii_internal(memac, memac->sgmii_pcs, fixed_link); +- else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII) +- setup_sgmii_internal(memac, memac->qsgmii_pcs, fixed_link); +- + /* Max Frame Length */ + err = fman_set_mac_max_frame(memac->fm, memac->mac_id, + memac_drv_param->max_frame_length); +@@ -970,9 +971,6 @@ static int memac_init(struct fman_mac *m + fman_register_intr(memac->fm, FMAN_MOD_MAC, memac->mac_id, + FMAN_INTR_TYPE_NORMAL, memac_exception, memac); + +- kfree(memac_drv_param); +- memac->memac_drv_param = NULL; +- + return 0; + } + +@@ -995,7 +993,6 @@ static int memac_free(struct fman_mac *m + pcs_put(memac->sgmii_pcs); + pcs_put(memac->qsgmii_pcs); + pcs_put(memac->xfi_pcs); +- + kfree(memac->memac_drv_param); + kfree(memac); + +@@ -1028,8 +1025,6 @@ static struct fman_mac *memac_config(str + memac->addr = ENET_ADDR_TO_UINT64(mac_dev->addr); + + memac->regs = mac_dev->vaddr; +- memac->max_speed = params->max_speed; +- memac->phy_if = mac_dev->phy_if; + memac->mac_id = params->mac_id; + memac->exceptions = (MEMAC_IMASK_TSECC_ER | MEMAC_IMASK_TECC_ER | + MEMAC_IMASK_RECC_ER | MEMAC_IMASK_MGI); +@@ -1037,7 +1032,6 @@ static struct fman_mac *memac_config(str + memac->event_cb = params->event_cb; + memac->dev_id = mac_dev; + memac->fm = params->fm; +- memac->basex_if = params->basex_if; + + /* Save FMan revision */ + fman_get_revision(memac->fm, &memac->fm_rev_info); +@@ -1064,37 +1058,44 @@ static struct phylink_pcs *memac_pcs_cre + return pcs; + } + ++static bool memac_supports(struct mac_device *mac_dev, phy_interface_t iface) ++{ ++ /* If there's no serdes device, assume that it's been configured for ++ * whatever the default interface mode is. ++ */ ++ if (!mac_dev->fman_mac->serdes) ++ return mac_dev->phy_if == iface; ++ /* Otherwise, ask the serdes */ ++ return !phy_validate(mac_dev->fman_mac->serdes, PHY_MODE_ETHERNET, ++ iface, NULL); ++} ++ + int memac_initialization(struct mac_device *mac_dev, + struct device_node *mac_node, + struct fman_mac_params *params) + { + int err; ++ struct device_node *fixed; + struct phylink_pcs *pcs; +- struct fixed_phy_status *fixed_link; + struct fman_mac *memac; ++ unsigned long capabilities; ++ unsigned long *supported; + ++ mac_dev->phylink_ops = &memac_mac_ops; + mac_dev->set_promisc = memac_set_promiscuous; + mac_dev->change_addr = memac_modify_mac_address; + mac_dev->add_hash_mac_addr = memac_add_hash_mac_address; + mac_dev->remove_hash_mac_addr = memac_del_hash_mac_address; +- mac_dev->set_tx_pause = memac_set_tx_pause_frames; +- mac_dev->set_rx_pause = memac_accept_rx_pause_frames; + mac_dev->set_exception = memac_set_exception; + mac_dev->set_allmulti = memac_set_allmulti; + mac_dev->set_tstamp = memac_set_tstamp; + mac_dev->set_multi = fman_set_multi; +- mac_dev->adjust_link = adjust_link_memac; + mac_dev->enable = memac_enable; + mac_dev->disable = memac_disable; + +- if (params->max_speed == SPEED_10000) +- mac_dev->phy_if = PHY_INTERFACE_MODE_XGMII; +- + mac_dev->fman_mac = memac_config(mac_dev, params); +- if (!mac_dev->fman_mac) { +- err = -EINVAL; +- goto _return; +- } ++ if (!mac_dev->fman_mac) ++ return -EINVAL; + + memac = mac_dev->fman_mac; + memac->memac_drv_param->max_frame_length = fman_get_max_frm(); +@@ -1136,9 +1137,9 @@ int memac_initialization(struct mac_devi + else + pcs = memac_pcs_create(mac_node, err); + +- if (!pcs) { +- dev_err(mac_dev->dev, "missing pcs\n"); +- err = -ENOENT; ++ if (IS_ERR(pcs)) { ++ err = PTR_ERR(pcs); ++ dev_err_probe(mac_dev->dev, err, "missing pcs\n"); + goto _return_fm_mac_free; + } + +@@ -1159,84 +1160,100 @@ int memac_initialization(struct mac_devi + } else if (IS_ERR(memac->serdes)) { + dev_err_probe(mac_dev->dev, err, "could not get serdes\n"); + goto _return_fm_mac_free; +- } else { +- err = phy_init(memac->serdes); +- if (err) { +- dev_err_probe(mac_dev->dev, err, +- "could not initialize serdes\n"); +- goto _return_fm_mac_free; +- } +- +- err = phy_power_on(memac->serdes); +- if (err) { +- dev_err_probe(mac_dev->dev, err, +- "could not power on serdes\n"); +- goto _return_phy_exit; +- } +- +- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII || +- memac->phy_if == PHY_INTERFACE_MODE_1000BASEX || +- memac->phy_if == PHY_INTERFACE_MODE_2500BASEX || +- memac->phy_if == PHY_INTERFACE_MODE_QSGMII || +- memac->phy_if == PHY_INTERFACE_MODE_XGMII) { +- err = phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET, +- memac->phy_if); +- if (err) { +- dev_err_probe(mac_dev->dev, err, +- "could not set serdes mode to %s\n", +- phy_modes(memac->phy_if)); +- goto _return_phy_power_off; +- } +- } + } + +- if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) { +- struct phy_device *phy; +- +- err = of_phy_register_fixed_link(mac_node); +- if (err) +- goto _return_phy_power_off; +- +- fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL); +- if (!fixed_link) { +- err = -ENOMEM; +- goto _return_phy_power_off; +- } ++ /* The internal connection to the serdes is XGMII, but this isn't ++ * really correct for the phy mode (which is the external connection). ++ * However, this is how all older device trees say that they want ++ * 10GBASE-R (aka XFI), so just convert it for them. ++ */ ++ if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) ++ mac_dev->phy_if = PHY_INTERFACE_MODE_10GBASER; + +- mac_dev->phy_node = of_node_get(mac_node); +- phy = of_phy_find_device(mac_dev->phy_node); +- if (!phy) { +- err = -EINVAL; +- of_node_put(mac_dev->phy_node); +- goto _return_fixed_link_free; +- } ++ /* TODO: The following interface modes are supported by (some) hardware ++ * but not by this driver: ++ * - 1000BASE-KX ++ * - 10GBASE-KR ++ * - XAUI/HiGig ++ */ ++ supported = mac_dev->phylink_config.supported_interfaces; + +- fixed_link->link = phy->link; +- fixed_link->speed = phy->speed; +- fixed_link->duplex = phy->duplex; +- fixed_link->pause = phy->pause; +- fixed_link->asym_pause = phy->asym_pause; ++ /* Note that half duplex is only supported on 10/100M interfaces. */ + +- put_device(&phy->mdio.dev); +- memac->memac_drv_param->fixed_link = fixed_link; ++ if (memac->sgmii_pcs && ++ (memac_supports(mac_dev, PHY_INTERFACE_MODE_SGMII) || ++ memac_supports(mac_dev, PHY_INTERFACE_MODE_1000BASEX))) { ++ __set_bit(PHY_INTERFACE_MODE_SGMII, supported); ++ __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported); ++ } ++ ++ if (memac->sgmii_pcs && ++ memac_supports(mac_dev, PHY_INTERFACE_MODE_2500BASEX)) ++ __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); ++ ++ if (memac->qsgmii_pcs && ++ memac_supports(mac_dev, PHY_INTERFACE_MODE_QSGMII)) ++ __set_bit(PHY_INTERFACE_MODE_QSGMII, supported); ++ else if (mac_dev->phy_if == PHY_INTERFACE_MODE_QSGMII) ++ dev_warn(mac_dev->dev, "no QSGMII pcs specified\n"); ++ ++ if (memac->xfi_pcs && ++ memac_supports(mac_dev, PHY_INTERFACE_MODE_10GBASER)) { ++ __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); ++ } else { ++ /* From what I can tell, no 10g macs support RGMII. */ ++ phy_interface_set_rgmii(supported); ++ __set_bit(PHY_INTERFACE_MODE_MII, supported); + } + ++ capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10 | MAC_100; ++ capabilities |= MAC_1000FD | MAC_2500FD | MAC_10000FD; ++ ++ /* These SoCs don't support half duplex at all; there's no different ++ * FMan version or compatible, so we just have to check the machine ++ * compatible instead ++ */ ++ if (of_machine_is_compatible("fsl,ls1043a") || ++ of_machine_is_compatible("fsl,ls1046a") || ++ of_machine_is_compatible("fsl,B4QDS")) ++ capabilities &= ~(MAC_10HD | MAC_100HD); ++ ++ mac_dev->phylink_config.mac_capabilities = capabilities; ++ ++ /* The T2080 and T4240 don't support half duplex RGMII. There is no ++ * other way to identify these SoCs, so just use the machine ++ * compatible. ++ */ ++ if (of_machine_is_compatible("fsl,T2080QDS") || ++ of_machine_is_compatible("fsl,T2080RDB") || ++ of_machine_is_compatible("fsl,T2081QDS") || ++ of_machine_is_compatible("fsl,T4240QDS") || ++ of_machine_is_compatible("fsl,T4240RDB")) ++ memac->rgmii_no_half_duplex = true; ++ ++ /* Most boards should use MLO_AN_INBAND, but existing boards don't have ++ * a managed property. Default to MLO_AN_INBAND if nothing else is ++ * specified. We need to be careful and not enable this if we have a ++ * fixed link or if we are using MII or RGMII, since those ++ * configurations modes don't use in-band autonegotiation. ++ */ ++ fixed = of_get_child_by_name(mac_node, "fixed-link"); ++ if (!fixed && !of_property_read_bool(mac_node, "fixed-link") && ++ !of_property_read_bool(mac_node, "managed") && ++ mac_dev->phy_if != PHY_INTERFACE_MODE_MII && ++ !phy_interface_mode_is_rgmii(mac_dev->phy_if)) ++ mac_dev->phylink_config.ovr_an_inband = true; ++ of_node_put(fixed); ++ + err = memac_init(mac_dev->fman_mac); + if (err < 0) +- goto _return_fixed_link_free; ++ goto _return_fm_mac_free; + + dev_info(mac_dev->dev, "FMan MEMAC\n"); + +- goto _return; ++ return 0; + +-_return_phy_power_off: +- phy_power_off(memac->serdes); +-_return_phy_exit: +- phy_exit(memac->serdes); +-_return_fixed_link_free: +- kfree(fixed_link); + _return_fm_mac_free: + memac_free(mac_dev->fman_mac); +-_return: + return err; + } +--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c ++++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + + /* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */ + #define TGEC_TX_IPG_LENGTH_MASK 0x000003ff +@@ -243,10 +244,6 @@ static int init(struct tgec_regs __iomem + + static int check_init_parameters(struct fman_mac *tgec) + { +- if (tgec->max_speed < SPEED_10000) { +- pr_err("10G MAC driver only support 10G speed\n"); +- return -EINVAL; +- } + if (!tgec->exception_cb) { + pr_err("uninitialized exception_cb\n"); + return -EINVAL; +@@ -384,40 +381,13 @@ static void free_init_resources(struct f + tgec->unicast_addr_hash = NULL; + } + +-static bool is_init_done(struct tgec_cfg *cfg) +-{ +- /* Checks if tGEC driver parameters were initialized */ +- if (!cfg) +- return true; +- +- return false; +-} +- + static int tgec_enable(struct fman_mac *tgec) + { +- struct tgec_regs __iomem *regs = tgec->regs; +- u32 tmp; +- +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- +- tmp = ioread32be(®s->command_config); +- tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; +- iowrite32be(tmp, ®s->command_config); +- + return 0; + } + + static void tgec_disable(struct fman_mac *tgec) + { +- struct tgec_regs __iomem *regs = tgec->regs; +- u32 tmp; +- +- WARN_ON_ONCE(!is_init_done(tgec->cfg)); +- +- tmp = ioread32be(®s->command_config); +- tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); +- iowrite32be(tmp, ®s->command_config); + } + + static int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val) +@@ -425,9 +395,6 @@ static int tgec_set_promiscuous(struct f + struct tgec_regs __iomem *regs = tgec->regs; + u32 tmp; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + tmp = ioread32be(®s->command_config); + if (new_val) + tmp |= CMD_CFG_PROMIS_EN; +@@ -444,9 +411,6 @@ static int tgec_set_tx_pause_frames(stru + { + struct tgec_regs __iomem *regs = tgec->regs; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + iowrite32be((u32)pause_time, ®s->pause_quant); + + return 0; +@@ -457,9 +421,6 @@ static int tgec_accept_rx_pause_frames(s + struct tgec_regs __iomem *regs = tgec->regs; + u32 tmp; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + tmp = ioread32be(®s->command_config); + if (!en) + tmp |= CMD_CFG_PAUSE_IGNORE; +@@ -470,12 +431,53 @@ static int tgec_accept_rx_pause_frames(s + return 0; + } + ++static void tgec_mac_config(struct phylink_config *config, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++} ++ ++static void tgec_link_up(struct phylink_config *config, struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, bool tx_pause, bool rx_pause) ++{ ++ struct mac_device *mac_dev = fman_config_to_mac(config); ++ struct fman_mac *tgec = mac_dev->fman_mac; ++ struct tgec_regs __iomem *regs = tgec->regs; ++ u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE : ++ FSL_FM_PAUSE_TIME_DISABLE; ++ u32 tmp; ++ ++ tgec_set_tx_pause_frames(tgec, 0, pause_time, 0); ++ tgec_accept_rx_pause_frames(tgec, rx_pause); ++ mac_dev->update_speed(mac_dev, speed); ++ ++ tmp = ioread32be(®s->command_config); ++ tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN; ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++static void tgec_link_down(struct phylink_config *config, unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct fman_mac *tgec = fman_config_to_mac(config)->fman_mac; ++ struct tgec_regs __iomem *regs = tgec->regs; ++ u32 tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN); ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++static const struct phylink_mac_ops tgec_mac_ops = { ++ .validate = phylink_generic_validate, ++ .mac_config = tgec_mac_config, ++ .mac_link_up = tgec_link_up, ++ .mac_link_down = tgec_link_down, ++}; ++ + static int tgec_modify_mac_address(struct fman_mac *tgec, + const enet_addr_t *p_enet_addr) + { +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + tgec->addr = ENET_ADDR_TO_UINT64(*p_enet_addr); + set_mac_address(tgec->regs, (const u8 *)(*p_enet_addr)); + +@@ -490,9 +492,6 @@ static int tgec_add_hash_mac_address(str + u32 crc = 0xFFFFFFFF, hash; + u64 addr; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + addr = ENET_ADDR_TO_UINT64(*eth_addr); + + if (!(addr & GROUP_ADDRESS)) { +@@ -525,9 +524,6 @@ static int tgec_set_allmulti(struct fman + u32 entry; + struct tgec_regs __iomem *regs = tgec->regs; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + if (enable) { + for (entry = 0; entry < TGEC_HASH_TABLE_SIZE; entry++) + iowrite32be(entry | TGEC_HASH_MCAST_EN, +@@ -548,9 +544,6 @@ static int tgec_set_tstamp(struct fman_m + struct tgec_regs __iomem *regs = tgec->regs; + u32 tmp; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + tmp = ioread32be(®s->command_config); + + if (enable) +@@ -572,9 +565,6 @@ static int tgec_del_hash_mac_address(str + u32 crc = 0xFFFFFFFF, hash; + u64 addr; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + addr = ((*(u64 *)eth_addr) >> 16); + + /* CRC calculation */ +@@ -601,22 +591,12 @@ static int tgec_del_hash_mac_address(str + return 0; + } + +-static void tgec_adjust_link(struct mac_device *mac_dev) +-{ +- struct phy_device *phy_dev = mac_dev->phy_dev; +- +- mac_dev->update_speed(mac_dev, phy_dev->speed); +-} +- + static int tgec_set_exception(struct fman_mac *tgec, + enum fman_mac_exceptions exception, bool enable) + { + struct tgec_regs __iomem *regs = tgec->regs; + u32 bit_mask = 0; + +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- + bit_mask = get_exception_flag(exception); + if (bit_mask) { + if (enable) +@@ -641,9 +621,6 @@ static int tgec_init(struct fman_mac *tg + enet_addr_t eth_addr; + int err; + +- if (is_init_done(tgec->cfg)) +- return -EINVAL; +- + if (DEFAULT_RESET_ON_INIT && + (fman_reset_mac(tgec->fm, tgec->mac_id) != 0)) { + pr_err("Can't reset MAC!\n"); +@@ -753,7 +730,6 @@ static struct fman_mac *tgec_config(stru + + tgec->regs = mac_dev->vaddr; + tgec->addr = ENET_ADDR_TO_UINT64(mac_dev->addr); +- tgec->max_speed = params->max_speed; + tgec->mac_id = params->mac_id; + tgec->exceptions = (TGEC_IMASK_MDIO_SCAN_EVENT | + TGEC_IMASK_REM_FAULT | +@@ -788,17 +764,15 @@ int tgec_initialization(struct mac_devic + int err; + struct fman_mac *tgec; + ++ mac_dev->phylink_ops = &tgec_mac_ops; + mac_dev->set_promisc = tgec_set_promiscuous; + mac_dev->change_addr = tgec_modify_mac_address; + mac_dev->add_hash_mac_addr = tgec_add_hash_mac_address; + mac_dev->remove_hash_mac_addr = tgec_del_hash_mac_address; +- mac_dev->set_tx_pause = tgec_set_tx_pause_frames; +- mac_dev->set_rx_pause = tgec_accept_rx_pause_frames; + mac_dev->set_exception = tgec_set_exception; + mac_dev->set_allmulti = tgec_set_allmulti; + mac_dev->set_tstamp = tgec_set_tstamp; + mac_dev->set_multi = fman_set_multi; +- mac_dev->adjust_link = tgec_adjust_link; + mac_dev->enable = tgec_enable; + mac_dev->disable = tgec_disable; + +@@ -808,6 +782,19 @@ int tgec_initialization(struct mac_devic + goto _return; + } + ++ /* The internal connection to the serdes is XGMII, but this isn't ++ * really correct for the phy mode (which is the external connection). ++ * However, this is how all older device trees say that they want ++ * XAUI, so just convert it for them. ++ */ ++ if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) ++ mac_dev->phy_if = PHY_INTERFACE_MODE_XAUI; ++ ++ __set_bit(PHY_INTERFACE_MODE_XAUI, ++ mac_dev->phylink_config.supported_interfaces); ++ mac_dev->phylink_config.mac_capabilities = ++ MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10000FD; ++ + tgec = mac_dev->fman_mac; + tgec->cfg->max_frame_length = fman_get_max_frm(); + err = tgec_init(tgec); +--- a/drivers/net/ethernet/freescale/fman/mac.c ++++ b/drivers/net/ethernet/freescale/fman/mac.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -93,130 +94,8 @@ int fman_set_multi(struct net_device *ne + return 0; + } + +-/** +- * fman_set_mac_active_pause +- * @mac_dev: A pointer to the MAC device +- * @rx: Pause frame setting for RX +- * @tx: Pause frame setting for TX +- * +- * Set the MAC RX/TX PAUSE frames settings +- * +- * Avoid redundant calls to FMD, if the MAC driver already contains the desired +- * active PAUSE settings. Otherwise, the new active settings should be reflected +- * in FMan. +- * +- * Return: 0 on success; Error code otherwise. +- */ +-int fman_set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx) +-{ +- struct fman_mac *fman_mac = mac_dev->fman_mac; +- int err = 0; +- +- if (rx != mac_dev->rx_pause_active) { +- err = mac_dev->set_rx_pause(fman_mac, rx); +- if (likely(err == 0)) +- mac_dev->rx_pause_active = rx; +- } +- +- if (tx != mac_dev->tx_pause_active) { +- u16 pause_time = (tx ? FSL_FM_PAUSE_TIME_ENABLE : +- FSL_FM_PAUSE_TIME_DISABLE); +- +- err = mac_dev->set_tx_pause(fman_mac, 0, pause_time, 0); +- +- if (likely(err == 0)) +- mac_dev->tx_pause_active = tx; +- } +- +- return err; +-} +-EXPORT_SYMBOL(fman_set_mac_active_pause); +- +-/** +- * fman_get_pause_cfg +- * @mac_dev: A pointer to the MAC device +- * @rx_pause: Return value for RX setting +- * @tx_pause: Return value for TX setting +- * +- * Determine the MAC RX/TX PAUSE frames settings based on PHY +- * autonegotiation or values set by eththool. +- * +- * Return: Pointer to FMan device. +- */ +-void fman_get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause, +- bool *tx_pause) +-{ +- struct phy_device *phy_dev = mac_dev->phy_dev; +- u16 lcl_adv, rmt_adv; +- u8 flowctrl; +- +- *rx_pause = *tx_pause = false; +- +- if (!phy_dev->duplex) +- return; +- +- /* If PAUSE autonegotiation is disabled, the TX/RX PAUSE settings +- * are those set by ethtool. +- */ +- if (!mac_dev->autoneg_pause) { +- *rx_pause = mac_dev->rx_pause_req; +- *tx_pause = mac_dev->tx_pause_req; +- return; +- } +- +- /* Else if PAUSE autonegotiation is enabled, the TX/RX PAUSE +- * settings depend on the result of the link negotiation. +- */ +- +- /* get local capabilities */ +- lcl_adv = linkmode_adv_to_lcl_adv_t(phy_dev->advertising); +- +- /* get link partner capabilities */ +- rmt_adv = 0; +- if (phy_dev->pause) +- rmt_adv |= LPA_PAUSE_CAP; +- if (phy_dev->asym_pause) +- rmt_adv |= LPA_PAUSE_ASYM; +- +- /* Calculate TX/RX settings based on local and peer advertised +- * symmetric/asymmetric PAUSE capabilities. +- */ +- flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); +- if (flowctrl & FLOW_CTRL_RX) +- *rx_pause = true; +- if (flowctrl & FLOW_CTRL_TX) +- *tx_pause = true; +-} +-EXPORT_SYMBOL(fman_get_pause_cfg); +- +-#define DTSEC_SUPPORTED \ +- (SUPPORTED_10baseT_Half \ +- | SUPPORTED_10baseT_Full \ +- | SUPPORTED_100baseT_Half \ +- | SUPPORTED_100baseT_Full \ +- | SUPPORTED_Autoneg \ +- | SUPPORTED_Pause \ +- | SUPPORTED_Asym_Pause \ +- | SUPPORTED_FIBRE \ +- | SUPPORTED_MII) +- + static DEFINE_MUTEX(eth_lock); + +-static const u16 phy2speed[] = { +- [PHY_INTERFACE_MODE_MII] = SPEED_100, +- [PHY_INTERFACE_MODE_GMII] = SPEED_1000, +- [PHY_INTERFACE_MODE_SGMII] = SPEED_1000, +- [PHY_INTERFACE_MODE_TBI] = SPEED_1000, +- [PHY_INTERFACE_MODE_RMII] = SPEED_100, +- [PHY_INTERFACE_MODE_RGMII] = SPEED_1000, +- [PHY_INTERFACE_MODE_RGMII_ID] = SPEED_1000, +- [PHY_INTERFACE_MODE_RGMII_RXID] = SPEED_1000, +- [PHY_INTERFACE_MODE_RGMII_TXID] = SPEED_1000, +- [PHY_INTERFACE_MODE_RTBI] = SPEED_1000, +- [PHY_INTERFACE_MODE_QSGMII] = SPEED_1000, +- [PHY_INTERFACE_MODE_XGMII] = SPEED_10000 +-}; +- + static struct platform_device *dpaa_eth_add_device(int fman_id, + struct mac_device *mac_dev) + { +@@ -263,8 +142,8 @@ no_mem: + } + + static const struct of_device_id mac_match[] = { +- { .compatible = "fsl,fman-dtsec", .data = dtsec_initialization }, +- { .compatible = "fsl,fman-xgec", .data = tgec_initialization }, ++ { .compatible = "fsl,fman-dtsec", .data = dtsec_initialization }, ++ { .compatible = "fsl,fman-xgec", .data = tgec_initialization }, + { .compatible = "fsl,fman-memac", .data = memac_initialization }, + {} + }; +@@ -295,6 +174,7 @@ static int mac_probe(struct platform_dev + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; ++ platform_set_drvdata(_of_dev, mac_dev); + + /* Save private information */ + mac_dev->priv = priv; +@@ -424,57 +304,21 @@ static int mac_probe(struct platform_dev + } + mac_dev->phy_if = phy_if; + +- priv->speed = phy2speed[mac_dev->phy_if]; +- params.max_speed = priv->speed; +- mac_dev->if_support = DTSEC_SUPPORTED; +- /* We don't support half-duplex in SGMII mode */ +- if (mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII) +- mac_dev->if_support &= ~(SUPPORTED_10baseT_Half | +- SUPPORTED_100baseT_Half); +- +- /* Gigabit support (no half-duplex) */ +- if (params.max_speed == 1000) +- mac_dev->if_support |= SUPPORTED_1000baseT_Full; +- +- /* The 10G interface only supports one mode */ +- if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII) +- mac_dev->if_support = SUPPORTED_10000baseT_Full; +- +- /* Get the rest of the PHY information */ +- mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0); +- +- params.basex_if = false; + params.mac_id = priv->cell_index; + params.fm = (void *)priv->fman; + params.exception_cb = mac_exception; + params.event_cb = mac_exception; + + err = init(mac_dev, mac_node, ¶ms); +- if (err < 0) { +- dev_err(dev, "mac_dev->init() = %d\n", err); +- of_node_put(mac_dev->phy_node); +- return err; +- } +- +- /* pause frame autonegotiation enabled */ +- mac_dev->autoneg_pause = true; +- +- /* By intializing the values to false, force FMD to enable PAUSE frames +- * on RX and TX +- */ +- mac_dev->rx_pause_req = true; +- mac_dev->tx_pause_req = true; +- mac_dev->rx_pause_active = false; +- mac_dev->tx_pause_active = false; +- err = fman_set_mac_active_pause(mac_dev, true, true); + if (err < 0) +- dev_err(dev, "fman_set_mac_active_pause() = %d\n", err); ++ return err; + + if (!is_zero_ether_addr(mac_dev->addr)) + dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr); + + priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev); + if (IS_ERR(priv->eth_dev)) { ++ err = PTR_ERR(priv->eth_dev); + dev_err(dev, "failed to add Ethernet platform device for MAC %d\n", + priv->cell_index); + priv->eth_dev = NULL; +--- a/drivers/net/ethernet/freescale/fman/mac.h ++++ b/drivers/net/ethernet/freescale/fman/mac.h +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + + #include "fman_port.h" +@@ -24,32 +25,22 @@ struct mac_device { + struct resource *res; + u8 addr[ETH_ALEN]; + struct fman_port *port[2]; +- u32 if_support; +- struct phy_device *phy_dev; ++ struct phylink *phylink; ++ struct phylink_config phylink_config; + phy_interface_t phy_if; +- struct device_node *phy_node; +- struct net_device *net_dev; + +- bool autoneg_pause; +- bool rx_pause_req; +- bool tx_pause_req; +- bool rx_pause_active; +- bool tx_pause_active; + bool promisc; + bool allmulti; + ++ const struct phylink_mac_ops *phylink_ops; + int (*enable)(struct fman_mac *mac_dev); + void (*disable)(struct fman_mac *mac_dev); +- void (*adjust_link)(struct mac_device *mac_dev); + int (*set_promisc)(struct fman_mac *mac_dev, bool enable); + int (*change_addr)(struct fman_mac *mac_dev, const enet_addr_t *enet_addr); + int (*set_allmulti)(struct fman_mac *mac_dev, bool enable); + int (*set_tstamp)(struct fman_mac *mac_dev, bool enable); + int (*set_multi)(struct net_device *net_dev, + struct mac_device *mac_dev); +- int (*set_rx_pause)(struct fman_mac *mac_dev, bool en); +- int (*set_tx_pause)(struct fman_mac *mac_dev, u8 priority, +- u16 pause_time, u16 thresh_time); + int (*set_exception)(struct fman_mac *mac_dev, + enum fman_mac_exceptions exception, bool enable); + int (*add_hash_mac_addr)(struct fman_mac *mac_dev, +@@ -63,6 +54,12 @@ struct mac_device { + struct mac_priv_s *priv; + }; + ++static inline struct mac_device ++*fman_config_to_mac(struct phylink_config *config) ++{ ++ return container_of(config, struct mac_device, phylink_config); ++} ++ + struct dpaa_eth_data { + struct mac_device *mac_dev; + int mac_hw_id; diff --git a/lede/target/linux/generic/backport-6.1/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch b/lede/target/linux/generic/backport-6.1/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch new file mode 100644 index 0000000000..06c348b1cd --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-04-v6.2-net-phylink-provide-phylink_validate_mask_caps-helpe.patch @@ -0,0 +1,93 @@ +From bf4de031052fe7c5309e8956c342d4e5ce79038e Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Mon, 17 Oct 2022 16:22:35 -0400 +Subject: [PATCH 04/21] net: phylink: provide phylink_validate_mask_caps() + helper + +Provide a helper that restricts the link modes according to the +phylink capabilities. + +Signed-off-by: Russell King (Oracle) +[rebased on net-next/master and added documentation] +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +--- + drivers/net/phy/phylink.c | 41 +++++++++++++++++++++++++++------------ + include/linux/phylink.h | 3 +++ + 2 files changed, 32 insertions(+), 12 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -564,31 +564,48 @@ unsigned long phylink_get_capabilities(p + EXPORT_SYMBOL_GPL(phylink_get_capabilities); + + /** +- * phylink_generic_validate() - generic validate() callback implementation +- * @config: a pointer to a &struct phylink_config. ++ * phylink_validate_mask_caps() - Restrict link modes based on caps + * @supported: ethtool bitmask for supported link modes. +- * @state: a pointer to a &struct phylink_link_state. ++ * @state: an (optional) pointer to a &struct phylink_link_state. ++ * @mac_capabilities: bitmask of MAC capabilities + * +- * Generic implementation of the validate() callback that MAC drivers can +- * use when they pass the range of supported interfaces and MAC capabilities. +- * This makes use of phylink_get_linkmodes(). ++ * Calculate the supported link modes based on @mac_capabilities, and restrict ++ * @supported and @state based on that. Use this function if your capabiliies ++ * aren't constant, such as if they vary depending on the interface. + */ +-void phylink_generic_validate(struct phylink_config *config, +- unsigned long *supported, +- struct phylink_link_state *state) ++void phylink_validate_mask_caps(unsigned long *supported, ++ struct phylink_link_state *state, ++ unsigned long mac_capabilities) + { + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + unsigned long caps; + + phylink_set_port_modes(mask); + phylink_set(mask, Autoneg); +- caps = phylink_get_capabilities(state->interface, +- config->mac_capabilities, ++ caps = phylink_get_capabilities(state->interface, mac_capabilities, + state->rate_matching); + phylink_caps_to_linkmodes(mask, caps); + + linkmode_and(supported, supported, mask); +- linkmode_and(state->advertising, state->advertising, mask); ++ if (state) ++ linkmode_and(state->advertising, state->advertising, mask); ++} ++EXPORT_SYMBOL_GPL(phylink_validate_mask_caps); ++ ++/** ++ * phylink_generic_validate() - generic validate() callback implementation ++ * @config: a pointer to a &struct phylink_config. ++ * @supported: ethtool bitmask for supported link modes. ++ * @state: a pointer to a &struct phylink_link_state. ++ * ++ * Generic implementation of the validate() callback that MAC drivers can ++ * use when they pass the range of supported interfaces and MAC capabilities. ++ */ ++void phylink_generic_validate(struct phylink_config *config, ++ unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ phylink_validate_mask_caps(supported, state, config->mac_capabilities); + } + EXPORT_SYMBOL_GPL(phylink_generic_validate); + +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -558,6 +558,9 @@ void phylink_caps_to_linkmodes(unsigned + unsigned long phylink_get_capabilities(phy_interface_t interface, + unsigned long mac_capabilities, + int rate_matching); ++void phylink_validate_mask_caps(unsigned long *supported, ++ struct phylink_link_state *state, ++ unsigned long caps); + void phylink_generic_validate(struct phylink_config *config, + unsigned long *supported, + struct phylink_link_state *state); diff --git a/lede/target/linux/generic/backport-6.1/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch b/lede/target/linux/generic/backport-6.1/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch new file mode 100644 index 0000000000..e3a1dda688 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-05-v6.2-phylink-require-valid-state-argument-to-phylink_vali.patch @@ -0,0 +1,39 @@ +From 2bf7e4a68c42eed909f3c29582e1fb85cb157e35 Mon Sep 17 00:00:00 2001 +From: Jakub Kicinski +Date: Tue, 25 Oct 2022 11:51:26 -0700 +Subject: [PATCH 05/21] phylink: require valid state argument to + phylink_validate_mask_caps() + +state is deferenced earlier in the function, the NULL check +is pointless. Since we don't have any crash reports presumably +it's safe to assume state is not NULL. + +Fixes: f392a1846489 ("net: phylink: provide phylink_validate_mask_caps() helper") +Reviewed-by: Sean Anderson +Link: https://lore.kernel.org/r/20221025185126.1720553-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -566,7 +566,7 @@ EXPORT_SYMBOL_GPL(phylink_get_capabiliti + /** + * phylink_validate_mask_caps() - Restrict link modes based on caps + * @supported: ethtool bitmask for supported link modes. +- * @state: an (optional) pointer to a &struct phylink_link_state. ++ * @state: pointer to a &struct phylink_link_state. + * @mac_capabilities: bitmask of MAC capabilities + * + * Calculate the supported link modes based on @mac_capabilities, and restrict +@@ -587,8 +587,7 @@ void phylink_validate_mask_caps(unsigned + phylink_caps_to_linkmodes(mask, caps); + + linkmode_and(supported, supported, mask); +- if (state) +- linkmode_and(state->advertising, state->advertising, mask); ++ linkmode_and(state->advertising, state->advertising, mask); + } + EXPORT_SYMBOL_GPL(phylink_validate_mask_caps); + diff --git a/lede/target/linux/generic/backport-6.1/700-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch b/lede/target/linux/generic/backport-6.1/715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch similarity index 87% rename from lede/target/linux/generic/backport-6.1/700-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch rename to lede/target/linux/generic/backport-6.1/715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch index 81c14a0557..c217ed87b5 100644 --- a/lede/target/linux/generic/backport-6.1/700-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch +++ b/lede/target/linux/generic/backport-6.1/715-06-v6.2-net-phylink-add-phylink_get_link_timer_ns-helper.patch @@ -1,7 +1,7 @@ -From 9c5a170677c3c8facc83e931a57f4c99c0511ae0 Mon Sep 17 00:00:00 2001 +From f8fc363bf0c023e4736a0328174b4a24b44ab23a Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 27 Oct 2022 14:10:37 +0100 -Subject: [PATCH] net: phylink: add phylink_get_link_timer_ns() helper +Subject: [PATCH 06/21] net: phylink: add phylink_get_link_timer_ns() helper Add a helper to convert the PHY interface mode to the required link timer setting as stated by the appropriate standard. Inappropriate @@ -15,7 +15,7 @@ Signed-off-by: Jakub Kicinski --- a/include/linux/phylink.h +++ b/include/linux/phylink.h -@@ -614,6 +614,30 @@ int phylink_speed_up(struct phylink *pl) +@@ -617,6 +617,30 @@ int phylink_speed_up(struct phylink *pl) void phylink_set_port_modes(unsigned long *bits); diff --git a/lede/target/linux/generic/backport-6.1/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch b/lede/target/linux/generic/backport-6.1/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch new file mode 100644 index 0000000000..31fde5f18e --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-07-v6.2-net-remove-explicit-phylink_generic_validate-referen.patch @@ -0,0 +1,250 @@ +From b45b773a96b0e9e8d51e5d005485f4e376d6ce9a Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 4 Nov 2022 17:13:01 +0000 +Subject: [PATCH 07/21] net: remove explicit phylink_generic_validate() + references + +Virtually all conventional network drivers are now converted to use +phylink_generic_validate() - only DSA drivers and fman_memac remain, +so lets remove the necessity for network drivers to explicitly set +this member, and default to phylink_generic_validate() when unset. +This is possible as .validate must currently be set. + +Any remaining instances that have not been addressed by this patch can +be fixed up later. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/E1or0FZ-001tRa-DI@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/altera/altera_tse_main.c | 1 - + drivers/net/ethernet/atheros/ag71xx.c | 1 - + drivers/net/ethernet/cadence/macb_main.c | 1 - + drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 1 - + drivers/net/ethernet/freescale/enetc/enetc_pf.c | 1 - + drivers/net/ethernet/freescale/fman/fman_dtsec.c | 1 - + drivers/net/ethernet/freescale/fman/fman_tgec.c | 1 - + drivers/net/ethernet/marvell/mvneta.c | 1 - + drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 1 - + drivers/net/ethernet/marvell/prestera/prestera_main.c | 1 - + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 - + drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c | 1 - + drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c | 1 - + drivers/net/ethernet/mscc/ocelot_net.c | 1 - + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 1 - + drivers/net/ethernet/ti/am65-cpsw-nuss.c | 1 - + drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 1 - + drivers/net/phy/phylink.c | 5 ++++- + drivers/net/usb/asix_devices.c | 1 - + include/linux/phylink.h | 5 +++++ + 20 files changed, 9 insertions(+), 19 deletions(-) + +--- a/drivers/net/ethernet/altera/altera_tse_main.c ++++ b/drivers/net/ethernet/altera/altera_tse_main.c +@@ -1096,7 +1096,6 @@ static struct phylink_pcs *alt_tse_selec + } + + static const struct phylink_mac_ops alt_tse_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_an_restart = alt_tse_mac_an_restart, + .mac_config = alt_tse_mac_config, + .mac_link_down = alt_tse_mac_link_down, +--- a/drivers/net/ethernet/atheros/ag71xx.c ++++ b/drivers/net/ethernet/atheros/ag71xx.c +@@ -1086,7 +1086,6 @@ static void ag71xx_mac_link_up(struct ph + } + + static const struct phylink_mac_ops ag71xx_phylink_mac_ops = { +- .validate = phylink_generic_validate, + .mac_config = ag71xx_mac_config, + .mac_link_down = ag71xx_mac_link_down, + .mac_link_up = ag71xx_mac_link_up, +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -752,7 +752,6 @@ static struct phylink_pcs *macb_mac_sele + } + + static const struct phylink_mac_ops macb_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = macb_mac_select_pcs, + .mac_config = macb_mac_config, + .mac_link_down = macb_mac_link_down, +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c +@@ -235,7 +235,6 @@ static void dpaa2_mac_link_down(struct p + } + + static const struct phylink_mac_ops dpaa2_mac_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = dpaa2_mac_select_pcs, + .mac_config = dpaa2_mac_config, + .mac_link_up = dpaa2_mac_link_up, +--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c +@@ -1111,7 +1111,6 @@ static void enetc_pl_mac_link_down(struc + } + + static const struct phylink_mac_ops enetc_mac_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = enetc_pl_mac_select_pcs, + .mac_config = enetc_pl_mac_config, + .mac_link_up = enetc_pl_mac_link_up, +--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c ++++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +@@ -986,7 +986,6 @@ static void dtsec_link_down(struct phyli + } + + static const struct phylink_mac_ops dtsec_mac_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = dtsec_select_pcs, + .mac_config = dtsec_mac_config, + .mac_link_up = dtsec_link_up, +--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c ++++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c +@@ -469,7 +469,6 @@ static void tgec_link_down(struct phylin + } + + static const struct phylink_mac_ops tgec_mac_ops = { +- .validate = phylink_generic_validate, + .mac_config = tgec_mac_config, + .mac_link_up = tgec_link_up, + .mac_link_down = tgec_link_down, +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -4228,7 +4228,6 @@ static void mvneta_mac_link_up(struct ph + } + + static const struct phylink_mac_ops mvneta_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = mvneta_mac_select_pcs, + .mac_prepare = mvneta_mac_prepare, + .mac_config = mvneta_mac_config, +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +@@ -6633,7 +6633,6 @@ static void mvpp2_mac_link_down(struct p + } + + static const struct phylink_mac_ops mvpp2_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = mvpp2_select_pcs, + .mac_prepare = mvpp2_mac_prepare, + .mac_config = mvpp2_mac_config, +--- a/drivers/net/ethernet/marvell/prestera/prestera_main.c ++++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c +@@ -360,7 +360,6 @@ static void prestera_pcs_an_restart(stru + } + + static const struct phylink_mac_ops prestera_mac_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = prestera_mac_select_pcs, + .mac_config = prestera_mac_config, + .mac_link_down = prestera_mac_link_down, +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -653,7 +653,6 @@ static void mtk_mac_link_up(struct phyli + } + + static const struct phylink_mac_ops mtk_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = mtk_mac_select_pcs, + .mac_pcs_get_state = mtk_mac_pcs_get_state, + .mac_config = mtk_mac_config, +--- a/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c ++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c +@@ -125,7 +125,6 @@ static void lan966x_pcs_aneg_restart(str + } + + const struct phylink_mac_ops lan966x_phylink_mac_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = lan966x_phylink_mac_select, + .mac_config = lan966x_phylink_mac_config, + .mac_prepare = lan966x_phylink_mac_prepare, +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c +@@ -138,7 +138,6 @@ const struct phylink_pcs_ops sparx5_phyl + }; + + const struct phylink_mac_ops sparx5_phylink_mac_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = sparx5_phylink_mac_select_pcs, + .mac_config = sparx5_phylink_mac_config, + .mac_link_down = sparx5_phylink_mac_link_down, +--- a/drivers/net/ethernet/mscc/ocelot_net.c ++++ b/drivers/net/ethernet/mscc/ocelot_net.c +@@ -1737,7 +1737,6 @@ static void vsc7514_phylink_mac_link_up( + } + + static const struct phylink_mac_ops ocelot_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_config = vsc7514_phylink_mac_config, + .mac_link_down = vsc7514_phylink_mac_link_down, + .mac_link_up = vsc7514_phylink_mac_link_up, +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -1090,7 +1090,6 @@ static void stmmac_mac_link_up(struct ph + } + + static const struct phylink_mac_ops stmmac_phylink_mac_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = stmmac_mac_select_pcs, + .mac_config = stmmac_mac_config, + .mac_link_down = stmmac_mac_link_down, +--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c ++++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c +@@ -1493,7 +1493,6 @@ static void am65_cpsw_nuss_mac_link_up(s + } + + static const struct phylink_mac_ops am65_cpsw_phylink_mac_ops = { +- .validate = phylink_generic_validate, + .mac_config = am65_cpsw_nuss_mac_config, + .mac_link_down = am65_cpsw_nuss_mac_link_down, + .mac_link_up = am65_cpsw_nuss_mac_link_up, +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -1736,7 +1736,6 @@ static void axienet_mac_link_up(struct p + } + + static const struct phylink_mac_ops axienet_phylink_ops = { +- .validate = phylink_generic_validate, + .mac_select_pcs = axienet_mac_select_pcs, + .mac_config = axienet_mac_config, + .mac_link_down = axienet_mac_link_down, +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -651,7 +651,10 @@ static int phylink_validate_mac_and_pcs( + } + + /* Then validate the link parameters with the MAC */ +- pl->mac_ops->validate(pl->config, supported, state); ++ if (pl->mac_ops->validate) ++ pl->mac_ops->validate(pl->config, supported, state); ++ else ++ phylink_generic_validate(pl->config, supported, state); + + return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; + } +--- a/drivers/net/usb/asix_devices.c ++++ b/drivers/net/usb/asix_devices.c +@@ -787,7 +787,6 @@ static void ax88772_mac_link_up(struct p + } + + static const struct phylink_mac_ops ax88772_phylink_mac_ops = { +- .validate = phylink_generic_validate, + .mac_config = ax88772_mac_config, + .mac_link_down = ax88772_mac_link_down, + .mac_link_up = ax88772_mac_link_up, +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -207,6 +207,11 @@ struct phylink_mac_ops { + * + * If the @state->interface mode is not supported, then the @supported + * mask must be cleared. ++ * ++ * This member is optional; if not set, the generic validator will be ++ * used making use of @config->mac_capabilities and ++ * @config->supported_interfaces to determine which link modes are ++ * supported. + */ + void validate(struct phylink_config *config, unsigned long *supported, + struct phylink_link_state *state); diff --git a/lede/target/linux/generic/backport-6.1/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch b/lede/target/linux/generic/backport-6.1/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch new file mode 100644 index 0000000000..37d82b2cd7 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-08-net-sfp-make-sfp_bus_find_fwnode-take-a-const-fwnode.patch @@ -0,0 +1,48 @@ +From a90ac762d345890b40d88a1385a34a2449c2d75e Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Mar 2023 09:23:42 +0000 +Subject: [PATCH] net: sfp: make sfp_bus_find_fwnode() take a const fwnode + +sfp_bus_find_fwnode() does not write to the fwnode, so let's make it +const. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/sfp-bus.c | 2 +- + include/linux/sfp.h | 5 +++-- + 2 files changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/sfp-bus.c ++++ b/drivers/net/phy/sfp-bus.c +@@ -603,7 +603,7 @@ static void sfp_upstream_clear(struct sf + * - %-ENOMEM if we failed to allocate the bus. + * - an error from the upstream's connect_phy() method. + */ +-struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode) ++struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode) + { + struct fwnode_reference_args ref; + struct sfp_bus *bus; +--- a/include/linux/sfp.h ++++ b/include/linux/sfp.h +@@ -548,7 +548,7 @@ int sfp_get_module_eeprom_by_page(struct + void sfp_upstream_start(struct sfp_bus *bus); + void sfp_upstream_stop(struct sfp_bus *bus); + void sfp_bus_put(struct sfp_bus *bus); +-struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode); ++struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode); + int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream, + const struct sfp_upstream_ops *ops); + void sfp_bus_del_upstream(struct sfp_bus *bus); +@@ -610,7 +610,8 @@ static inline void sfp_bus_put(struct sf + { + } + +-static inline struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode) ++static inline struct sfp_bus * ++sfp_bus_find_fwnode(const struct fwnode_handle *fwnode) + { + return NULL; + } diff --git a/lede/target/linux/generic/backport-6.1/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch b/lede/target/linux/generic/backport-6.1/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch new file mode 100644 index 0000000000..290cb8d161 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-09-v6.4-net-pcs-lynx-don-t-print-an_enabled-in-pcs_get_state.patch @@ -0,0 +1,31 @@ +From ecec0ebbc6381a5a375f1cf10c4858f24e91e2ef Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 15 Mar 2023 14:46:49 +0000 +Subject: [PATCH] net: pcs: lynx: don't print an_enabled in pcs_get_state() + +an_enabled will be going away, and in any case, pcs_get_state() should +not be updating this member. Remove the print. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Steen Hegelund +Signed-off-by: David S. Miller +--- + drivers/net/pcs/pcs-lynx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/pcs/pcs-lynx.c ++++ b/drivers/net/pcs/pcs-lynx.c +@@ -115,11 +115,11 @@ static void lynx_pcs_get_state(struct ph + } + + dev_dbg(&lynx->mdio->dev, +- "mode=%s/%s/%s link=%u an_enabled=%u an_complete=%u\n", ++ "mode=%s/%s/%s link=%u an_complete=%u\n", + phy_modes(state->interface), + phy_speed_to_str(state->speed), + phy_duplex_to_str(state->duplex), +- state->link, state->an_enabled, state->an_complete); ++ state->link, state->an_complete); + } + + static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode, diff --git a/lede/target/linux/generic/backport-6.1/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch b/lede/target/linux/generic/backport-6.1/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch new file mode 100644 index 0000000000..38ea265476 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-10-v6.4-net-dpaa2-mac-use-Autoneg-bit-rather-than-an_enabled.patch @@ -0,0 +1,32 @@ +From 99d0f3a1095f4c938b1665025c29411edafe8a01 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 21 Mar 2023 15:58:44 +0000 +Subject: [PATCH] net: dpaa2-mac: use Autoneg bit rather than an_enabled + +The Autoneg bit in the advertising bitmap and state->an_enabled are +always identical. Thus, we will be removing state->an_enabled. + +Use the Autoneg bit in the advertising bitmap to indicate whether +autonegotiation should be used, rather than using the an_enabled +member which will be going away. This means we use the same condition +as phylink_mii_c22_pcs_config(). + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Simon Horman +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c +@@ -158,7 +158,8 @@ static void dpaa2_mac_config(struct phyl + struct dpmac_link_state *dpmac_state = &mac->state; + int err; + +- if (state->an_enabled) ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ state->advertising)) + dpmac_state->options |= DPMAC_LINK_OPT_AUTONEG; + else + dpmac_state->options &= ~DPMAC_LINK_OPT_AUTONEG; diff --git a/lede/target/linux/generic/backport-6.1/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch b/lede/target/linux/generic/backport-6.1/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch new file mode 100644 index 0000000000..cb9c411cfb --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-11-v6.4-net-phylink-support-validated-pause-and-autoneg-in-f.patch @@ -0,0 +1,64 @@ +From 471c40bde606ec0b1ce8c616f7998739c7a783a6 Mon Sep 17 00:00:00 2001 +From: Ivan Bornyakov +Date: Fri, 10 Feb 2023 18:46:27 +0300 +Subject: [PATCH 10/21] net: phylink: support validated pause and autoneg in + fixed-link + +In fixed-link setup phylink_parse_fixedlink() unconditionally sets +Pause, Asym_Pause and Autoneg bits to "supported" bitmap, while MAC may +not support these. + +This leads to ethtool reporting: + + > Supported pause frame use: Symmetric Receive-only + > Supports auto-negotiation: Yes + +regardless of what is actually supported. + +Instead of unconditionally set Pause, Asym_Pause and Autoneg it is +sensible to set them according to validated "supported" bitmap, i.e. the +result of phylink_validate(). + +Signed-off-by: Ivan Bornyakov +Signed-off-by: David S. Miller +--- + drivers/net/phy/phylink.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -709,6 +709,7 @@ static int phylink_parse_fixedlink(struc + struct fwnode_handle *fwnode) + { + struct fwnode_handle *fixed_node; ++ bool pause, asym_pause, autoneg; + const struct phy_setting *s; + struct gpio_desc *desc; + u32 speed; +@@ -781,13 +782,23 @@ static int phylink_parse_fixedlink(struc + linkmode_copy(pl->link_config.advertising, pl->supported); + phylink_validate(pl, pl->supported, &pl->link_config); + ++ pause = phylink_test(pl->supported, Pause); ++ asym_pause = phylink_test(pl->supported, Asym_Pause); ++ autoneg = phylink_test(pl->supported, Autoneg); + s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex, + pl->supported, true); + linkmode_zero(pl->supported); + phylink_set(pl->supported, MII); +- phylink_set(pl->supported, Pause); +- phylink_set(pl->supported, Asym_Pause); +- phylink_set(pl->supported, Autoneg); ++ ++ if (pause) ++ phylink_set(pl->supported, Pause); ++ ++ if (asym_pause) ++ phylink_set(pl->supported, Asym_Pause); ++ ++ if (autoneg) ++ phylink_set(pl->supported, Autoneg); ++ + if (s) { + __set_bit(s->bit, pl->supported); + __set_bit(s->bit, pl->link_config.lp_advertising); diff --git a/lede/target/linux/generic/backport-6.1/715-12-v6.4-net-phylink-remove-an_enabled.patch b/lede/target/linux/generic/backport-6.1/715-12-v6.4-net-phylink-remove-an_enabled.patch new file mode 100644 index 0000000000..03b4f9d0c4 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-12-v6.4-net-phylink-remove-an_enabled.patch @@ -0,0 +1,177 @@ +From 7211ffd70941933a7825a56cf480f07ee81c321c Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 21 Mar 2023 15:58:54 +0000 +Subject: [PATCH 11/21] net: phylink: remove an_enabled + +The Autoneg bit in the advertising bitmap and state->an_enabled are +always identical. state->an_enabled is now no longer used by any +drivers, so lets kill this duplication. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Simon Horman +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 37 +++++++++++++++++-------------------- + include/linux/phylink.h | 2 -- + 2 files changed, 17 insertions(+), 22 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -841,7 +841,6 @@ static int phylink_parse_mode(struct phy + phylink_set(pl->supported, Autoneg); + phylink_set(pl->supported, Asym_Pause); + phylink_set(pl->supported, Pause); +- pl->link_config.an_enabled = true; + pl->cfg_link_an_mode = MLO_AN_INBAND; + + switch (pl->link_config.interface) { +@@ -944,9 +943,6 @@ static int phylink_parse_mode(struct phy + "failed to validate link configuration for in-band status\n"); + return -EINVAL; + } +- +- /* Check if MAC/PCS also supports Autoneg. */ +- pl->link_config.an_enabled = phylink_test(pl->supported, Autoneg); + } + + return 0; +@@ -956,7 +952,8 @@ static void phylink_apply_manual_flow(st + struct phylink_link_state *state) + { + /* If autoneg is disabled, pause AN is also disabled */ +- if (!state->an_enabled) ++ if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ state->advertising)) + state->pause &= ~MLO_PAUSE_AN; + + /* Manual configuration of pause modes */ +@@ -996,21 +993,22 @@ static void phylink_mac_config(struct ph + const struct phylink_link_state *state) + { + phylink_dbg(pl, +- "%s: mode=%s/%s/%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n", ++ "%s: mode=%s/%s/%s/%s/%s adv=%*pb pause=%02x link=%u\n", + __func__, phylink_an_mode_str(pl->cur_link_an_mode), + phy_modes(state->interface), + phy_speed_to_str(state->speed), + phy_duplex_to_str(state->duplex), + phy_rate_matching_to_str(state->rate_matching), + __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising, +- state->pause, state->link, state->an_enabled); ++ state->pause, state->link); + + pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, state); + } + + static void phylink_mac_pcs_an_restart(struct phylink *pl) + { +- if (pl->link_config.an_enabled && ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ pl->link_config.advertising) && + phy_interface_mode_is_8023z(pl->link_config.interface) && + phylink_autoneg_inband(pl->cur_link_an_mode)) { + if (pl->pcs) +@@ -1137,9 +1135,9 @@ static void phylink_mac_pcs_get_state(st + linkmode_copy(state->advertising, pl->link_config.advertising); + linkmode_zero(state->lp_advertising); + state->interface = pl->link_config.interface; +- state->an_enabled = pl->link_config.an_enabled; + state->rate_matching = pl->link_config.rate_matching; +- if (state->an_enabled) { ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ state->advertising)) { + state->speed = SPEED_UNKNOWN; + state->duplex = DUPLEX_UNKNOWN; + state->pause = MLO_PAUSE_NONE; +@@ -1531,7 +1529,6 @@ struct phylink *phylink_create(struct ph + pl->link_config.pause = MLO_PAUSE_AN; + pl->link_config.speed = SPEED_UNKNOWN; + pl->link_config.duplex = DUPLEX_UNKNOWN; +- pl->link_config.an_enabled = true; + pl->mac_ops = mac_ops; + __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); + timer_setup(&pl->link_poll, phylink_fixed_poll, 0); +@@ -2155,8 +2152,9 @@ static void phylink_get_ksettings(const + kset->base.speed = state->speed; + kset->base.duplex = state->duplex; + } +- kset->base.autoneg = state->an_enabled ? AUTONEG_ENABLE : +- AUTONEG_DISABLE; ++ kset->base.autoneg = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ state->advertising) ? ++ AUTONEG_ENABLE : AUTONEG_DISABLE; + } + + /** +@@ -2303,9 +2301,8 @@ int phylink_ethtool_ksettings_set(struct + /* We have ruled out the case with a PHY attached, and the + * fixed-link cases. All that is left are in-band links. + */ +- config.an_enabled = kset->base.autoneg == AUTONEG_ENABLE; + linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, config.advertising, +- config.an_enabled); ++ kset->base.autoneg == AUTONEG_ENABLE); + + /* If this link is with an SFP, ensure that changes to advertised modes + * also cause the associated interface to be selected such that the +@@ -2339,13 +2336,14 @@ int phylink_ethtool_ksettings_set(struct + } + + /* If autonegotiation is enabled, we must have an advertisement */ +- if (config.an_enabled && phylink_is_empty_linkmode(config.advertising)) ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ config.advertising) && ++ phylink_is_empty_linkmode(config.advertising)) + return -EINVAL; + + mutex_lock(&pl->state_mutex); + pl->link_config.speed = config.speed; + pl->link_config.duplex = config.duplex; +- pl->link_config.an_enabled = config.an_enabled; + + if (pl->link_config.interface != config.interface) { + /* The interface changed, e.g. 1000base-X <-> 2500base-X */ +@@ -2951,7 +2949,6 @@ static int phylink_sfp_config_phy(struct + config.speed = SPEED_UNKNOWN; + config.duplex = DUPLEX_UNKNOWN; + config.pause = MLO_PAUSE_AN; +- config.an_enabled = pl->link_config.an_enabled; + + /* Ignore errors if we're expecting a PHY to attach later */ + ret = phylink_validate(pl, support, &config); +@@ -3020,7 +3017,6 @@ static int phylink_sfp_config_optical(st + config.speed = SPEED_UNKNOWN; + config.duplex = DUPLEX_UNKNOWN; + config.pause = MLO_PAUSE_AN; +- config.an_enabled = true; + + /* For all the interfaces that are supported, reduce the sfp_support + * mask to only those link modes that can be supported. +@@ -3354,7 +3350,8 @@ void phylink_mii_c22_pcs_decode_state(st + /* If there is no link or autonegotiation is disabled, the LP advertisement + * data is not meaningful, so don't go any further. + */ +- if (!state->link || !state->an_enabled) ++ if (!state->link || !linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ state->advertising)) + return; + + switch (state->interface) { +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -93,7 +93,6 @@ static inline bool phylink_autoneg_inban + * the medium link mode (@speed and @duplex) and the speed/duplex of the phy + * interface mode (@interface) are different. + * @link: true if the link is up. +- * @an_enabled: true if autonegotiation is enabled/desired. + * @an_complete: true if autonegotiation has completed. + */ + struct phylink_link_state { +@@ -105,7 +104,6 @@ struct phylink_link_state { + int pause; + int rate_matching; + unsigned int link:1; +- unsigned int an_enabled:1; + unsigned int an_complete:1; + }; + diff --git a/lede/target/linux/generic/backport-6.1/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch b/lede/target/linux/generic/backport-6.1/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch new file mode 100644 index 0000000000..c06a367b8b --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-13-v6.5-net-phylink-constify-fwnode-arguments.patch @@ -0,0 +1,88 @@ +From a3555d1f5c208f0a63eafee77381f68d304a0512 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 12 May 2023 17:58:37 +0100 +Subject: [PATCH 12/21] net: phylink: constify fwnode arguments + +Both phylink_create() and phylink_fwnode_phy_connect() do not modify +the fwnode argument that they are passed, so lets constify these. + +Reviewed-by: Simon Horman +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/phylink.c | 11 ++++++----- + include/linux/phylink.h | 9 +++++---- + 2 files changed, 11 insertions(+), 9 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -706,7 +706,7 @@ static int phylink_validate(struct phyli + } + + static int phylink_parse_fixedlink(struct phylink *pl, +- struct fwnode_handle *fwnode) ++ const struct fwnode_handle *fwnode) + { + struct fwnode_handle *fixed_node; + bool pause, asym_pause, autoneg; +@@ -817,7 +817,8 @@ static int phylink_parse_fixedlink(struc + return 0; + } + +-static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode) ++static int phylink_parse_mode(struct phylink *pl, ++ const struct fwnode_handle *fwnode) + { + struct fwnode_handle *dn; + const char *managed; +@@ -1440,7 +1441,7 @@ static void phylink_fixed_poll(struct ti + static const struct sfp_upstream_ops sfp_phylink_ops; + + static int phylink_register_sfp(struct phylink *pl, +- struct fwnode_handle *fwnode) ++ const struct fwnode_handle *fwnode) + { + struct sfp_bus *bus; + int ret; +@@ -1479,7 +1480,7 @@ static int phylink_register_sfp(struct p + * must use IS_ERR() to check for errors from this function. + */ + struct phylink *phylink_create(struct phylink_config *config, +- struct fwnode_handle *fwnode, ++ const struct fwnode_handle *fwnode, + phy_interface_t iface, + const struct phylink_mac_ops *mac_ops) + { +@@ -1809,7 +1810,7 @@ EXPORT_SYMBOL_GPL(phylink_of_phy_connect + * Returns 0 on success or a negative errno. + */ + int phylink_fwnode_phy_connect(struct phylink *pl, +- struct fwnode_handle *fwnode, ++ const struct fwnode_handle *fwnode, + u32 flags) + { + struct fwnode_handle *phy_fwnode; +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -568,16 +568,17 @@ void phylink_generic_validate(struct phy + unsigned long *supported, + struct phylink_link_state *state); + +-struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *, +- phy_interface_t iface, +- const struct phylink_mac_ops *mac_ops); ++struct phylink *phylink_create(struct phylink_config *, ++ const struct fwnode_handle *, ++ phy_interface_t, ++ const struct phylink_mac_ops *); + void phylink_destroy(struct phylink *); + bool phylink_expects_phy(struct phylink *pl); + + int phylink_connect_phy(struct phylink *, struct phy_device *); + int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags); + int phylink_fwnode_phy_connect(struct phylink *pl, +- struct fwnode_handle *fwnode, ++ const struct fwnode_handle *fwnode, + u32 flags); + void phylink_disconnect_phy(struct phylink *); + diff --git a/lede/target/linux/generic/backport-6.1/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch b/lede/target/linux/generic/backport-6.1/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch new file mode 100644 index 0000000000..2649634dc7 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-14-v6.3-net-phy-constify-fwnode_get_phy_node-fwnode-argument.patch @@ -0,0 +1,38 @@ +From 4a0faa02d419a6728abef0f1d8a32d8c35ef95e6 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Mar 2023 09:23:53 +0000 +Subject: [PATCH] net: phy: constify fwnode_get_phy_node() fwnode argument + +fwnode_get_phy_node() does not motify the fwnode structure, so make +the argument const, + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy_device.c | 2 +- + include/linux/phy.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -3003,7 +3003,7 @@ EXPORT_SYMBOL_GPL(device_phy_find_device + * and "phy-device" are not supported in ACPI. DT supports all the three + * named references to the phy node. + */ +-struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode) ++struct fwnode_handle *fwnode_get_phy_node(const struct fwnode_handle *fwnode) + { + struct fwnode_handle *phy_node; + +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -1473,7 +1473,7 @@ int fwnode_get_phy_id(struct fwnode_hand + struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode); + struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode); + struct phy_device *device_phy_find_device(struct device *dev); +-struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode); ++struct fwnode_handle *fwnode_get_phy_node(const struct fwnode_handle *fwnode); + struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45); + int phy_device_register(struct phy_device *phy); + void phy_device_free(struct phy_device *phydev); diff --git a/lede/target/linux/generic/backport-6.1/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch b/lede/target/linux/generic/backport-6.1/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch new file mode 100644 index 0000000000..5eba18b026 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-15-v6.4-net-phylink-fix-ksettings_set-ethtool-call.patch @@ -0,0 +1,44 @@ +From cc73de0411f7d3cdd157564a78f7a39058420ff8 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Sat, 13 May 2023 22:03:45 +0100 +Subject: [PATCH 13/21] net: phylink: fix ksettings_set() ethtool call + +While testing a Fiberstore SFP-10G-T module (which uses 10GBASE-R with +rate adaption) in a Clearfog platform (which can't do that) it was +found that the PHYs advertisement was not limited according to the +hosts capabilities when using ethtool to change it. + +Fix this by ensuring that we mask the advertisement with the computed +support mask as the very first thing we do. + +Fixes: cbc1bb1e4689 ("net: phylink: simplify phy case for ksettings_set method") +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/phylink.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -2226,6 +2226,10 @@ int phylink_ethtool_ksettings_set(struct + + ASSERT_RTNL(); + ++ /* Mask out unsupported advertisements */ ++ linkmode_and(config.advertising, kset->link_modes.advertising, ++ pl->supported); ++ + if (pl->phydev) { + /* We can rely on phylib for this update; we also do not need + * to update the pl->link_config settings: +@@ -2250,10 +2254,6 @@ int phylink_ethtool_ksettings_set(struct + + config = pl->link_config; + +- /* Mask out unsupported advertisements */ +- linkmode_and(config.advertising, kset->link_modes.advertising, +- pl->supported); +- + /* FIXME: should we reject autoneg if phy/mac does not support it? */ + switch (kset->base.autoneg) { + case AUTONEG_DISABLE: diff --git a/lede/target/linux/generic/backport-6.1/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch b/lede/target/linux/generic/backport-6.1/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch new file mode 100644 index 0000000000..f9670539fc --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-16-v6.5-net-sfp-add-support-for-setting-signalling-rate.patch @@ -0,0 +1,149 @@ +From 0100d1c5789018ba77bf2f4fab3bd91ecece7b3b Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 17 May 2023 11:38:12 +0100 +Subject: [PATCH 14/21] net: sfp: add support for setting signalling rate + +Add support to the SFP layer to allow phylink to set the signalling +rate for a SFP module. The rate given will be in units of kilo-baud +(1000 baud). + +Reviewed-by: Simon Horman +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 24 ++++++++++++++++++++++++ + drivers/net/phy/sfp-bus.c | 20 ++++++++++++++++++++ + drivers/net/phy/sfp.c | 5 +++++ + drivers/net/phy/sfp.h | 1 + + include/linux/sfp.h | 6 ++++++ + 5 files changed, 56 insertions(+) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -156,6 +156,23 @@ static const char *phylink_an_mode_str(u + return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown"; + } + ++static unsigned int phylink_interface_signal_rate(phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: /* 1.25Mbd */ ++ return 1250; ++ case PHY_INTERFACE_MODE_2500BASEX: /* 3.125Mbd */ ++ return 3125; ++ case PHY_INTERFACE_MODE_5GBASER: /* 5.15625Mbd */ ++ return 5156; ++ case PHY_INTERFACE_MODE_10GBASER: /* 10.3125Mbd */ ++ return 10313; ++ default: ++ return 0; ++ } ++} ++ + /** + * phylink_interface_max_speed() - get the maximum speed of a phy interface + * @interface: phy interface mode defined by &typedef phy_interface_t +@@ -1024,6 +1041,7 @@ static void phylink_major_config(struct + { + struct phylink_pcs *pcs = NULL; + bool pcs_changed = false; ++ unsigned int rate_kbd; + int err; + + phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); +@@ -1083,6 +1101,12 @@ static void phylink_major_config(struct + ERR_PTR(err)); + } + ++ if (pl->sfp_bus) { ++ rate_kbd = phylink_interface_signal_rate(state->interface); ++ if (rate_kbd) ++ sfp_upstream_set_signal_rate(pl->sfp_bus, rate_kbd); ++ } ++ + phylink_pcs_poll_start(pl); + } + +--- a/drivers/net/phy/sfp-bus.c ++++ b/drivers/net/phy/sfp-bus.c +@@ -586,6 +586,26 @@ static void sfp_upstream_clear(struct sf + } + + /** ++ * sfp_upstream_set_signal_rate() - set data signalling rate ++ * @bus: a pointer to the &struct sfp_bus structure for the sfp module ++ * @rate_kbd: signalling rate in units of 1000 baud ++ * ++ * Configure the rate select settings on the SFP module for the signalling ++ * rate (not the same as the data rate). ++ * ++ * Locks that may be held: ++ * Phylink's state_mutex ++ * rtnl lock ++ * SFP's sm_mutex ++ */ ++void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd) ++{ ++ if (bus->registered) ++ bus->socket_ops->set_signal_rate(bus->sfp, rate_kbd); ++} ++EXPORT_SYMBOL_GPL(sfp_upstream_set_signal_rate); ++ ++/** + * sfp_bus_find_fwnode() - parse and locate the SFP bus from fwnode + * @fwnode: firmware node for the parent device (MAC or PHY) + * +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -2473,6 +2473,10 @@ static void sfp_stop(struct sfp *sfp) + sfp_sm_event(sfp, SFP_E_DEV_DOWN); + } + ++static void sfp_set_signal_rate(struct sfp *sfp, unsigned int rate_kbd) ++{ ++} ++ + static int sfp_module_info(struct sfp *sfp, struct ethtool_modinfo *modinfo) + { + /* locking... and check module is present */ +@@ -2551,6 +2555,7 @@ static const struct sfp_socket_ops sfp_m + .detach = sfp_detach, + .start = sfp_start, + .stop = sfp_stop, ++ .set_signal_rate = sfp_set_signal_rate, + .module_info = sfp_module_info, + .module_eeprom = sfp_module_eeprom, + .module_eeprom_by_page = sfp_module_eeprom_by_page, +--- a/drivers/net/phy/sfp.h ++++ b/drivers/net/phy/sfp.h +@@ -19,6 +19,7 @@ struct sfp_socket_ops { + void (*detach)(struct sfp *sfp); + void (*start)(struct sfp *sfp); + void (*stop)(struct sfp *sfp); ++ void (*set_signal_rate)(struct sfp *sfp, unsigned int rate_kbd); + int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo); + int (*module_eeprom)(struct sfp *sfp, struct ethtool_eeprom *ee, + u8 *data); +--- a/include/linux/sfp.h ++++ b/include/linux/sfp.h +@@ -547,6 +547,7 @@ int sfp_get_module_eeprom_by_page(struct + struct netlink_ext_ack *extack); + void sfp_upstream_start(struct sfp_bus *bus); + void sfp_upstream_stop(struct sfp_bus *bus); ++void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd); + void sfp_bus_put(struct sfp_bus *bus); + struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode); + int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream, +@@ -606,6 +607,11 @@ static inline void sfp_upstream_stop(str + { + } + ++static inline void sfp_upstream_set_signal_rate(struct sfp_bus *bus, ++ unsigned int rate_kbd) ++{ ++} ++ + static inline void sfp_bus_put(struct sfp_bus *bus) + { + } diff --git a/lede/target/linux/generic/backport-6.1/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch b/lede/target/linux/generic/backport-6.1/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch new file mode 100644 index 0000000000..8a694c86da --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-17-v6.5-net-phy-add-helpers-for-comparing-phy-IDs.patch @@ -0,0 +1,147 @@ +From b84acdb07222a701bfc6403b374249c86f97d18d Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Fri, 19 May 2023 14:03:59 +0100 +Subject: [PATCH 15/21] net: phy: add helpers for comparing phy IDs + +There are several places which open code comparing PHY IDs. Provide a +couple of helpers to assist with this, using a slightly simpler test +than the original: + +- phy_id_compare() compares two arbitary PHY IDs and a mask of the + significant bits in the ID. +- phydev_id_compare() compares the bound phydev with the specified + PHY ID, using the bound driver's mask. + +Signed-off-by: Russell King +Reviewed-by: Simon Horman +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/micrel.c | 6 +++--- + drivers/net/phy/phy_device.c | 16 +++++++--------- + drivers/net/phy/phylink.c | 4 ++-- + include/linux/phy.h | 28 ++++++++++++++++++++++++++++ + 4 files changed, 40 insertions(+), 14 deletions(-) + +--- a/drivers/net/phy/micrel.c ++++ b/drivers/net/phy/micrel.c +@@ -620,7 +620,7 @@ static int ksz8051_ksz8795_match_phy_dev + { + int ret; + +- if ((phydev->phy_id & MICREL_PHY_ID_MASK) != PHY_ID_KSZ8051) ++ if (!phy_id_compare(phydev->phy_id, PHY_ID_KSZ8051, MICREL_PHY_ID_MASK)) + return 0; + + ret = phy_read(phydev, MII_BMSR); +@@ -1455,7 +1455,7 @@ static int ksz9x31_cable_test_fault_leng + * + * distance to fault = (VCT_DATA - 22) * 4 / cable propagation velocity + */ +- if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_KSZ9131) ++ if (phydev_id_compare(phydev, PHY_ID_KSZ9131)) + dt = clamp(dt - 22, 0, 255); + + return (dt * 400) / 10; +@@ -1887,7 +1887,7 @@ static __always_inline int ksz886x_cable + */ + dt = FIELD_GET(data_mask, status); + +- if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_LAN8814) ++ if (phydev_id_compare(phydev, PHY_ID_LAN8814)) + return ((dt - 22) * 800) / 10; + else + return (dt * 400) / 10; +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -422,8 +422,7 @@ int phy_unregister_fixup(const char *bus + fixup = list_entry(pos, struct phy_fixup, list); + + if ((!strcmp(fixup->bus_id, bus_id)) && +- ((fixup->phy_uid & phy_uid_mask) == +- (phy_uid & phy_uid_mask))) { ++ phy_id_compare(fixup->phy_uid, phy_uid, phy_uid_mask)) { + list_del(&fixup->list); + kfree(fixup); + ret = 0; +@@ -459,8 +458,8 @@ static int phy_needs_fixup(struct phy_de + if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0) + return 0; + +- if ((fixup->phy_uid & fixup->phy_uid_mask) != +- (phydev->phy_id & fixup->phy_uid_mask)) ++ if (!phy_id_compare(phydev->phy_id, fixup->phy_uid, ++ fixup->phy_uid_mask)) + if (fixup->phy_uid != PHY_ANY_UID) + return 0; + +@@ -507,15 +506,14 @@ static int phy_bus_match(struct device * + if (phydev->c45_ids.device_ids[i] == 0xffffffff) + continue; + +- if ((phydrv->phy_id & phydrv->phy_id_mask) == +- (phydev->c45_ids.device_ids[i] & +- phydrv->phy_id_mask)) ++ if (phy_id_compare(phydev->c45_ids.device_ids[i], ++ phydrv->phy_id, phydrv->phy_id_mask)) + return 1; + } + return 0; + } else { +- return (phydrv->phy_id & phydrv->phy_id_mask) == +- (phydev->phy_id & phydrv->phy_id_mask); ++ return phy_id_compare(phydev->phy_id, phydrv->phy_id, ++ phydrv->phy_id_mask); + } + } + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -3151,8 +3151,8 @@ static void phylink_sfp_link_up(void *up + */ + static bool phylink_phy_no_inband(struct phy_device *phy) + { +- return phy->is_c45 && +- (phy->c45_ids.device_ids[1] & 0xfffffff0) == 0xae025150; ++ return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1], ++ 0xae025150, 0xfffffff0); + } + + static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -993,6 +993,34 @@ struct phy_driver { + #define PHY_ID_MATCH_MODEL(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 4) + #define PHY_ID_MATCH_VENDOR(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 10) + ++/** ++ * phy_id_compare - compare @id1 with @id2 taking account of @mask ++ * @id1: first PHY ID ++ * @id2: second PHY ID ++ * @mask: the PHY ID mask, set bits are significant in matching ++ * ++ * Return true if the bits from @id1 and @id2 specified by @mask match. ++ * This uses an equivalent test to (@id & @mask) == (@phy_id & @mask). ++ */ ++static inline bool phy_id_compare(u32 id1, u32 id2, u32 mask) ++{ ++ return !((id1 ^ id2) & mask); ++} ++ ++/** ++ * phydev_id_compare - compare @id with the PHY's Clause 22 ID ++ * @phydev: the PHY device ++ * @id: the PHY ID to be matched ++ * ++ * Compare the @phydev clause 22 ID with the provided @id and return true or ++ * false depending whether it matches, using the bound driver mask. The ++ * @phydev must be bound to a driver. ++ */ ++static inline bool phydev_id_compare(struct phy_device *phydev, u32 id) ++{ ++ return phy_id_compare(id, phydev->phy_id, phydev->drv->phy_id_mask); ++} ++ + /* A Structure for boards to register fixups with the PHY Lib */ + struct phy_fixup { + struct list_head list; diff --git a/lede/target/linux/generic/backport-6.1/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch b/lede/target/linux/generic/backport-6.1/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch new file mode 100644 index 0000000000..5970355a6c --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-18-v6.5-net-phylink-require-supported_interfaces-to-be-fille.patch @@ -0,0 +1,71 @@ +From 441e1e44301fc5762a06737f8ec04bf1ce3fb039 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Sat, 20 May 2023 11:41:42 +0100 +Subject: [PATCH 16/21] net: phylink: require supported_interfaces to be filled + +We have been requiring the supported_interfaces bitmap to be filled in +by MAC drivers that have a mac_select_pcs() method. Now that all MAC +drivers fill in the supported_interfaces bitmap, it is time to enforce +this. We have already required supported_interfaces to be set in order +for optical SFPs to be configured in commit f81fa96d8a6c ("net: phylink: +use phy_interface_t bitmaps for optical modules"). + +Refuse phylink creation if supported_interfaces is empty, and remove +code to deal with cases where this mask is empty. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1q0K1u-006EIP-ET@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 26 +++++++++++--------------- + 1 file changed, 11 insertions(+), 15 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -710,14 +710,11 @@ static int phylink_validate(struct phyli + { + const unsigned long *interfaces = pl->config->supported_interfaces; + +- if (!phy_interface_empty(interfaces)) { +- if (state->interface == PHY_INTERFACE_MODE_NA) +- return phylink_validate_mask(pl, supported, state, +- interfaces); ++ if (state->interface == PHY_INTERFACE_MODE_NA) ++ return phylink_validate_mask(pl, supported, state, interfaces); + +- if (!test_bit(state->interface, interfaces)) +- return -EINVAL; +- } ++ if (!test_bit(state->interface, interfaces)) ++ return -EINVAL; + + return phylink_validate_mac_and_pcs(pl, supported, state); + } +@@ -1512,19 +1509,18 @@ struct phylink *phylink_create(struct ph + struct phylink *pl; + int ret; + +- if (mac_ops->mac_select_pcs && +- mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) != +- ERR_PTR(-EOPNOTSUPP)) +- using_mac_select_pcs = true; +- + /* Validate the supplied configuration */ +- if (using_mac_select_pcs && +- phy_interface_empty(config->supported_interfaces)) { ++ if (phy_interface_empty(config->supported_interfaces)) { + dev_err(config->dev, +- "phylink: error: empty supported_interfaces but mac_select_pcs() method present\n"); ++ "phylink: error: empty supported_interfaces\n"); + return ERR_PTR(-EINVAL); + } + ++ if (mac_ops->mac_select_pcs && ++ mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) != ++ ERR_PTR(-EOPNOTSUPP)) ++ using_mac_select_pcs = true; ++ + pl = kzalloc(sizeof(*pl), GFP_KERNEL); + if (!pl) + return ERR_PTR(-ENOMEM); diff --git a/lede/target/linux/generic/backport-6.1/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch b/lede/target/linux/generic/backport-6.1/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch new file mode 100644 index 0000000000..3a26b4b600 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-19-v6.5-net-phylink-remove-duplicated-linkmode-pause-resolut.patch @@ -0,0 +1,64 @@ +From 4b624a39f2ab523ca6a6ad9448fab1deb7b101e2 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 23 May 2023 11:15:53 +0100 +Subject: [PATCH 17/21] net: phylink: remove duplicated linkmode pause + resolution + +Phylink had two chunks of code virtually the same for resolving the +negotiated pause modes. Factor this down to one function. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 15 ++++----------- + 1 file changed, 4 insertions(+), 11 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -976,11 +976,10 @@ static void phylink_apply_manual_flow(st + state->pause = pl->link_config.pause; + } + +-static void phylink_resolve_flow(struct phylink_link_state *state) ++static void phylink_resolve_an_pause(struct phylink_link_state *state) + { + bool tx_pause, rx_pause; + +- state->pause = MLO_PAUSE_NONE; + if (state->duplex == DUPLEX_FULL) { + linkmode_resolve_pause(state->advertising, + state->lp_advertising, +@@ -1192,7 +1191,8 @@ static void phylink_get_fixed_state(stru + else if (pl->link_gpio) + state->link = !!gpiod_get_value_cansleep(pl->link_gpio); + +- phylink_resolve_flow(state); ++ state->pause = MLO_PAUSE_NONE; ++ phylink_resolve_an_pause(state); + } + + static void phylink_mac_initial_config(struct phylink *pl, bool force_restart) +@@ -3215,7 +3215,6 @@ static const struct sfp_upstream_ops sfp + static void phylink_decode_c37_word(struct phylink_link_state *state, + uint16_t config_reg, int speed) + { +- bool tx_pause, rx_pause; + int fd_bit; + + if (speed == SPEED_2500) +@@ -3234,13 +3233,7 @@ static void phylink_decode_c37_word(stru + state->link = false; + } + +- linkmode_resolve_pause(state->advertising, state->lp_advertising, +- &tx_pause, &rx_pause); +- +- if (tx_pause) +- state->pause |= MLO_PAUSE_TX; +- if (rx_pause) +- state->pause |= MLO_PAUSE_RX; ++ phylink_resolve_an_pause(state); + } + + static void phylink_decode_sgmii_word(struct phylink_link_state *state, diff --git a/lede/target/linux/generic/backport-6.1/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch b/lede/target/linux/generic/backport-6.1/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch new file mode 100644 index 0000000000..2b2634f80c --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-20-v6.5-net-phylink-add-function-to-resolve-clause-73-negoti.patch @@ -0,0 +1,76 @@ +From aa8b6bd2b1f235b262bd27f317a0516f196c2c6a Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 23 May 2023 11:15:58 +0100 +Subject: [PATCH 18/21] net: phylink: add function to resolve clause 73 + negotiation + +Add a function to resolve clause 73 negotiation according to the +priority resolution function described in clause 73.3.6. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 39 +++++++++++++++++++++++++++++++++++++++ + include/linux/phylink.h | 2 ++ + 2 files changed, 41 insertions(+) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -3212,6 +3212,45 @@ static const struct sfp_upstream_ops sfp + + /* Helpers for MAC drivers */ + ++static struct { ++ int bit; ++ int speed; ++} phylink_c73_priority_resolution[] = { ++ { ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, SPEED_100000 }, ++ { ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, SPEED_100000 }, ++ /* 100GBASE-KP4 and 100GBASE-CR10 not supported */ ++ { ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, SPEED_40000 }, ++ { ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, SPEED_40000 }, ++ { ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, SPEED_10000 }, ++ { ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, SPEED_10000 }, ++ /* 5GBASE-KR not supported */ ++ { ETHTOOL_LINK_MODE_2500baseX_Full_BIT, SPEED_2500 }, ++ { ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, SPEED_1000 }, ++}; ++ ++void phylink_resolve_c73(struct phylink_link_state *state) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(phylink_c73_priority_resolution); i++) { ++ int bit = phylink_c73_priority_resolution[i].bit; ++ if (linkmode_test_bit(bit, state->advertising) && ++ linkmode_test_bit(bit, state->lp_advertising)) ++ break; ++ } ++ ++ if (i < ARRAY_SIZE(phylink_c73_priority_resolution)) { ++ state->speed = phylink_c73_priority_resolution[i].speed; ++ state->duplex = DUPLEX_FULL; ++ } else { ++ /* negotiation failure */ ++ state->link = false; ++ } ++ ++ phylink_resolve_an_pause(state); ++} ++EXPORT_SYMBOL_GPL(phylink_resolve_c73); ++ + static void phylink_decode_c37_word(struct phylink_link_state *state, + uint16_t config_reg, int speed) + { +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -656,6 +656,8 @@ int phylink_mii_c22_pcs_config(struct md + const unsigned long *advertising); + void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs); + ++void phylink_resolve_c73(struct phylink_link_state *state); ++ + void phylink_mii_c45_pcs_get_state(struct mdio_device *pcs, + struct phylink_link_state *state); + diff --git a/lede/target/linux/generic/backport-6.1/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch b/lede/target/linux/generic/backport-6.1/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch new file mode 100644 index 0000000000..eea99a5d78 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-21-v6.5-net-phylink-provide-phylink_pcs_config-and-phylink_p.patch @@ -0,0 +1,100 @@ +From 796d709363135a6bd6a8ccc07b509c939e5b855f Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 23 May 2023 16:31:50 +0100 +Subject: [PATCH 19/21] net: phylink: provide phylink_pcs_config() and + phylink_pcs_link_up() + +Add two helper functions for calling PCS methods. phylink_pcs_config() +allows us to handle PCS configuration specifics in one location, rather +than the two call sites. phylink_pcs_link_up() gives us consistency. + +Signed-off-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/E1q1TzK-007Exd-Rs@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 53 ++++++++++++++++++++++++--------------- + 1 file changed, 33 insertions(+), 20 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -991,6 +991,25 @@ static void phylink_resolve_an_pause(str + } + } + ++static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++ const struct phylink_link_state *state, ++ bool permit_pause_to_mac) ++{ ++ if (!pcs) ++ return 0; ++ ++ return pcs->ops->pcs_config(pcs, mode, state->interface, ++ state->advertising, permit_pause_to_mac); ++} ++ ++static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, ++ phy_interface_t interface, int speed, ++ int duplex) ++{ ++ if (pcs && pcs->ops->pcs_link_up) ++ pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex); ++} ++ + static void phylink_pcs_poll_stop(struct phylink *pl) + { + if (pl->cfg_link_an_mode == MLO_AN_INBAND) +@@ -1074,18 +1093,15 @@ static void phylink_major_config(struct + + phylink_mac_config(pl, state); + +- if (pl->pcs) { +- err = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, +- state->interface, +- state->advertising, +- !!(pl->link_config.pause & +- MLO_PAUSE_AN)); +- if (err < 0) +- phylink_err(pl, "pcs_config failed: %pe\n", +- ERR_PTR(err)); +- if (err > 0) +- restart = true; +- } ++ err = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, state, ++ !!(pl->link_config.pause & ++ MLO_PAUSE_AN)); ++ if (err < 0) ++ phylink_err(pl, "pcs_config failed: %pe\n", ++ ERR_PTR(err)); ++ else if (err > 0) ++ restart = true; ++ + if (restart) + phylink_mac_pcs_an_restart(pl); + +@@ -1136,11 +1152,9 @@ static int phylink_change_inband_advert( + * restart negotiation if the pcs_config() helper indicates that + * the programmed advertisement has changed. + */ +- ret = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, +- pl->link_config.interface, +- pl->link_config.advertising, +- !!(pl->link_config.pause & +- MLO_PAUSE_AN)); ++ ret = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, ++ &pl->link_config, ++ !!(pl->link_config.pause & MLO_PAUSE_AN)); + if (ret < 0) + return ret; + +@@ -1272,9 +1286,8 @@ static void phylink_link_up(struct phyli + + pl->cur_interface = link_state.interface; + +- if (pl->pcs && pl->pcs->ops->pcs_link_up) +- pl->pcs->ops->pcs_link_up(pl->pcs, pl->cur_link_an_mode, +- pl->cur_interface, speed, duplex); ++ phylink_pcs_link_up(pl->pcs, pl->cur_link_an_mode, pl->cur_interface, ++ speed, duplex); + + pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode, + pl->cur_interface, speed, duplex, diff --git a/lede/target/linux/generic/backport-6.1/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch b/lede/target/linux/generic/backport-6.1/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch new file mode 100644 index 0000000000..2f7f7a5737 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-23-v6.4-net-phylink-actually-fix-ksettings_set-ethtool-call.patch @@ -0,0 +1,55 @@ +From 11933aa76865621d8e82553c8f3bc07796a5aaa2 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 1 Jun 2023 10:12:06 +0100 +Subject: [PATCH 20/21] net: phylink: actually fix ksettings_set() ethtool call + +Raju Lakkaraju reported that the below commit caused a regression +with Lan743x drivers and a 2.5G SFP. Sadly, this is because the commit +was utterly wrong. Let's fix this properly by not moving the +linkmode_and(), but instead copying the link ksettings and then +modifying the advertising mask before passing the modified link +ksettings to phylib. + +Fixes: df0acdc59b09 ("net: phylink: fix ksettings_set() ethtool call") +Signed-off-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/E1q4eLm-00Ayxk-GZ@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -2259,11 +2259,13 @@ int phylink_ethtool_ksettings_set(struct + + ASSERT_RTNL(); + +- /* Mask out unsupported advertisements */ +- linkmode_and(config.advertising, kset->link_modes.advertising, +- pl->supported); +- + if (pl->phydev) { ++ struct ethtool_link_ksettings phy_kset = *kset; ++ ++ linkmode_and(phy_kset.link_modes.advertising, ++ phy_kset.link_modes.advertising, ++ pl->supported); ++ + /* We can rely on phylib for this update; we also do not need + * to update the pl->link_config settings: + * - the configuration returned via ksettings_get() will come +@@ -2282,10 +2284,13 @@ int phylink_ethtool_ksettings_set(struct + * the presence of a PHY, this should not be changed as that + * should be determined from the media side advertisement. + */ +- return phy_ethtool_ksettings_set(pl->phydev, kset); ++ return phy_ethtool_ksettings_set(pl->phydev, &phy_kset); + } + + config = pl->link_config; ++ /* Mask out unsupported advertisements */ ++ linkmode_and(config.advertising, kset->link_modes.advertising, ++ pl->supported); + + /* FIXME: should we reject autoneg if phy/mac does not support it? */ + switch (kset->base.autoneg) { diff --git a/lede/target/linux/generic/backport-6.1/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch b/lede/target/linux/generic/backport-6.1/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch new file mode 100644 index 0000000000..e1a8539aae --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-24-v6.5-net-phylink-add-PCS-negotiation-mode.patch @@ -0,0 +1,324 @@ +From 79b07c3e9c4a2272927be8848c26b372516e1958 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 16 Jun 2023 13:06:22 +0100 +Subject: [PATCH 21/21] net: phylink: add PCS negotiation mode + +PCS have to work out whether they should enable PCS negotiation by +looking at the "mode" and "interface" arguments, and the Autoneg bit +in the advertising mask. + +This leads to some complex logic, so lets pull that out into phylink +and instead pass a "neg_mode" argument to the PCS configuration and +link up methods, instead of the "mode" argument. + +In order to transition drivers, add a "neg_mode" flag to the phylink +PCS structure to PCS can indicate whether they want to be passed the +neg_mode or the old mode argument. + +Signed-off-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/E1qA8De-00EaFA-Ht@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 45 +++++++++++++---- + include/linux/phylink.h | 104 +++++++++++++++++++++++++++++++++++--- + 2 files changed, 132 insertions(+), 17 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -71,6 +71,7 @@ struct phylink { + struct mutex state_mutex; + struct phylink_link_state phy_state; + struct work_struct resolve; ++ unsigned int pcs_neg_mode; + + bool mac_link_dropped; + bool using_mac_select_pcs; +@@ -991,23 +992,23 @@ static void phylink_resolve_an_pause(str + } + } + +-static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, + const struct phylink_link_state *state, + bool permit_pause_to_mac) + { + if (!pcs) + return 0; + +- return pcs->ops->pcs_config(pcs, mode, state->interface, ++ return pcs->ops->pcs_config(pcs, neg_mode, state->interface, + state->advertising, permit_pause_to_mac); + } + +-static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, ++static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, int speed, + int duplex) + { + if (pcs && pcs->ops->pcs_link_up) +- pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex); ++ pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex); + } + + static void phylink_pcs_poll_stop(struct phylink *pl) +@@ -1057,10 +1058,15 @@ static void phylink_major_config(struct + struct phylink_pcs *pcs = NULL; + bool pcs_changed = false; + unsigned int rate_kbd; ++ unsigned int neg_mode; + int err; + + phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); + ++ pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode, ++ state->interface, ++ state->advertising); ++ + if (pl->using_mac_select_pcs) { + pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); + if (IS_ERR(pcs)) { +@@ -1093,9 +1099,12 @@ static void phylink_major_config(struct + + phylink_mac_config(pl, state); + +- err = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, state, +- !!(pl->link_config.pause & +- MLO_PAUSE_AN)); ++ neg_mode = pl->cur_link_an_mode; ++ if (pl->pcs && pl->pcs->neg_mode) ++ neg_mode = pl->pcs_neg_mode; ++ ++ err = phylink_pcs_config(pl->pcs, neg_mode, state, ++ !!(pl->link_config.pause & MLO_PAUSE_AN)); + if (err < 0) + phylink_err(pl, "pcs_config failed: %pe\n", + ERR_PTR(err)); +@@ -1130,6 +1139,7 @@ static void phylink_major_config(struct + */ + static int phylink_change_inband_advert(struct phylink *pl) + { ++ unsigned int neg_mode; + int ret; + + if (test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) +@@ -1148,12 +1158,20 @@ static int phylink_change_inband_advert( + __ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising, + pl->link_config.pause); + ++ /* Recompute the PCS neg mode */ ++ pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode, ++ pl->link_config.interface, ++ pl->link_config.advertising); ++ ++ neg_mode = pl->cur_link_an_mode; ++ if (pl->pcs->neg_mode) ++ neg_mode = pl->pcs_neg_mode; ++ + /* Modern PCS-based method; update the advert at the PCS, and + * restart negotiation if the pcs_config() helper indicates that + * the programmed advertisement has changed. + */ +- ret = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, +- &pl->link_config, ++ ret = phylink_pcs_config(pl->pcs, neg_mode, &pl->link_config, + !!(pl->link_config.pause & MLO_PAUSE_AN)); + if (ret < 0) + return ret; +@@ -1256,6 +1274,7 @@ static void phylink_link_up(struct phyli + struct phylink_link_state link_state) + { + struct net_device *ndev = pl->netdev; ++ unsigned int neg_mode; + int speed, duplex; + bool rx_pause; + +@@ -1286,8 +1305,12 @@ static void phylink_link_up(struct phyli + + pl->cur_interface = link_state.interface; + +- phylink_pcs_link_up(pl->pcs, pl->cur_link_an_mode, pl->cur_interface, +- speed, duplex); ++ neg_mode = pl->cur_link_an_mode; ++ if (pl->pcs && pl->pcs->neg_mode) ++ neg_mode = pl->pcs_neg_mode; ++ ++ phylink_pcs_link_up(pl->pcs, neg_mode, pl->cur_interface, speed, ++ duplex); + + pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode, + pl->cur_interface, speed, duplex, +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -21,6 +21,24 @@ enum { + MLO_AN_FIXED, /* Fixed-link mode */ + MLO_AN_INBAND, /* In-band protocol */ + ++ /* PCS "negotiation" mode. ++ * PHYLINK_PCS_NEG_NONE - protocol has no inband capability ++ * PHYLINK_PCS_NEG_OUTBAND - some out of band or fixed link setting ++ * PHYLINK_PCS_NEG_INBAND_DISABLED - inband mode disabled, e.g. ++ * 1000base-X with autoneg off ++ * PHYLINK_PCS_NEG_INBAND_ENABLED - inband mode enabled ++ * Additionally, this can be tested using bitmasks: ++ * PHYLINK_PCS_NEG_INBAND - inband mode selected ++ * PHYLINK_PCS_NEG_ENABLED - negotiation mode enabled ++ */ ++ PHYLINK_PCS_NEG_NONE = 0, ++ PHYLINK_PCS_NEG_ENABLED = BIT(4), ++ PHYLINK_PCS_NEG_OUTBAND = BIT(5), ++ PHYLINK_PCS_NEG_INBAND = BIT(6), ++ PHYLINK_PCS_NEG_INBAND_DISABLED = PHYLINK_PCS_NEG_INBAND, ++ PHYLINK_PCS_NEG_INBAND_ENABLED = PHYLINK_PCS_NEG_INBAND | ++ PHYLINK_PCS_NEG_ENABLED, ++ + /* MAC_SYM_PAUSE and MAC_ASYM_PAUSE are used when configuring our + * autonegotiation advertisement. They correspond to the PAUSE and + * ASM_DIR bits defined by 802.3, respectively. +@@ -80,6 +98,70 @@ static inline bool phylink_autoneg_inban + } + + /** ++ * phylink_pcs_neg_mode() - helper to determine PCS inband mode ++ * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. ++ * @interface: interface mode to be used ++ * @advertising: adertisement ethtool link mode mask ++ * ++ * Determines the negotiation mode to be used by the PCS, and returns ++ * one of: ++ * %PHYLINK_PCS_NEG_NONE: interface mode does not support inband ++ * %PHYLINK_PCS_NEG_OUTBAND: an out of band mode (e.g. reading the PHY) ++ * will be used. ++ * %PHYLINK_PCS_NEG_INBAND_DISABLED: inband mode selected but autoneg disabled ++ * %PHYLINK_PCS_NEG_INBAND_ENABLED: inband mode selected and autoneg enabled ++ * ++ * Note: this is for cases where the PCS itself is involved in negotiation ++ * (e.g. Clause 37, SGMII and similar) not Clause 73. ++ */ ++static inline unsigned int phylink_pcs_neg_mode(unsigned int mode, ++ phy_interface_t interface, ++ const unsigned long *advertising) ++{ ++ unsigned int neg_mode; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_QUSGMII: ++ case PHY_INTERFACE_MODE_USXGMII: ++ /* These protocols are designed for use with a PHY which ++ * communicates its negotiation result back to the MAC via ++ * inband communication. Note: there exist PHYs that run ++ * with SGMII but do not send the inband data. ++ */ ++ if (!phylink_autoneg_inband(mode)) ++ neg_mode = PHYLINK_PCS_NEG_OUTBAND; ++ else ++ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; ++ break; ++ ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ /* 1000base-X is designed for use media-side for Fibre ++ * connections, and thus the Autoneg bit needs to be ++ * taken into account. We also do this for 2500base-X ++ * as well, but drivers may not support this, so may ++ * need to override this. ++ */ ++ if (!phylink_autoneg_inband(mode)) ++ neg_mode = PHYLINK_PCS_NEG_OUTBAND; ++ else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ advertising)) ++ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; ++ else ++ neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED; ++ break; ++ ++ default: ++ neg_mode = PHYLINK_PCS_NEG_NONE; ++ break; ++ } ++ ++ return neg_mode; ++} ++ ++/** + * struct phylink_link_state - link state structure + * @advertising: ethtool bitmask containing advertised link modes + * @lp_advertising: ethtool bitmask containing link partner advertised link +@@ -436,6 +518,7 @@ struct phylink_pcs_ops; + /** + * struct phylink_pcs - PHYLINK PCS instance + * @ops: a pointer to the &struct phylink_pcs_ops structure ++ * @neg_mode: provide PCS neg mode via "mode" argument + * @poll: poll the PCS for link changes + * + * This structure is designed to be embedded within the PCS private data, +@@ -443,6 +526,7 @@ struct phylink_pcs_ops; + */ + struct phylink_pcs { + const struct phylink_pcs_ops *ops; ++ bool neg_mode; + bool poll; + }; + +@@ -460,12 +544,12 @@ struct phylink_pcs_ops { + const struct phylink_link_state *state); + void (*pcs_get_state)(struct phylink_pcs *pcs, + struct phylink_link_state *state); +- int (*pcs_config)(struct phylink_pcs *pcs, unsigned int mode, ++ int (*pcs_config)(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac); + void (*pcs_an_restart)(struct phylink_pcs *pcs); +- void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int mode, ++ void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, int speed, int duplex); + }; + +@@ -508,7 +592,7 @@ void pcs_get_state(struct phylink_pcs *p + /** + * pcs_config() - Configure the PCS mode and advertisement + * @pcs: a pointer to a &struct phylink_pcs. +- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. ++ * @neg_mode: link negotiation mode (see below) + * @interface: interface mode to be used + * @advertising: adertisement ethtool link mode mask + * @permit_pause_to_mac: permit forwarding pause resolution to MAC +@@ -526,8 +610,12 @@ void pcs_get_state(struct phylink_pcs *p + * For 1000BASE-X, the advertisement should be programmed into the PCS. + * + * For most 10GBASE-R, there is no advertisement. ++ * ++ * The %neg_mode argument should be tested via the phylink_mode_*() family of ++ * functions, or for PCS that set pcs->neg_mode true, should be tested ++ * against the %PHYLINK_PCS_NEG_* definitions. + */ +-int pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++int pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, const unsigned long *advertising, + bool permit_pause_to_mac); + +@@ -543,7 +631,7 @@ void pcs_an_restart(struct phylink_pcs * + /** + * pcs_link_up() - program the PCS for the resolved link configuration + * @pcs: a pointer to a &struct phylink_pcs. +- * @mode: link autonegotiation mode ++ * @neg_mode: link negotiation mode (see below) + * @interface: link &typedef phy_interface_t mode + * @speed: link speed + * @duplex: link duplex +@@ -552,8 +640,12 @@ void pcs_an_restart(struct phylink_pcs * + * the resolved link parameters. For example, a PCS operating in SGMII + * mode without in-band AN needs to be manually configured for the link + * and duplex setting. Otherwise, this should be a no-op. ++ * ++ * The %mode argument should be tested via the phylink_mode_*() family of ++ * functions, or for PCS that set pcs->neg_mode true, should be tested ++ * against the %PHYLINK_PCS_NEG_* definitions. + */ +-void pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, ++void pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, int speed, int duplex); + #endif + diff --git a/lede/target/linux/generic/backport-6.1/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch b/lede/target/linux/generic/backport-6.1/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch new file mode 100644 index 0000000000..473e9d5836 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-25-v6.5-net-phylink-convert-phylink_mii_c22_pcs_config-to-ne.patch @@ -0,0 +1,45 @@ +From cdb08aa0473730315dbc088d5394e59622314034 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 16 Jun 2023 13:06:27 +0100 +Subject: [PATCH 1/2] net: phylink: convert phylink_mii_c22_pcs_config() to + neg_mode + +Use phylink_pcs_neg_mode() for phylink_mii_c22_pcs_config(). This +results in no functional change. + +Signed-off-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/E1qA8Dj-00EaFG-Mt@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -3558,6 +3558,7 @@ int phylink_mii_c22_pcs_config(struct md + phy_interface_t interface, + const unsigned long *advertising) + { ++ unsigned int neg_mode; + bool changed = 0; + u16 bmcr; + int ret, adv; +@@ -3571,15 +3572,13 @@ int phylink_mii_c22_pcs_config(struct md + changed = ret; + } + +- /* Ensure ISOLATE bit is disabled */ +- if (mode == MLO_AN_INBAND && +- (interface == PHY_INTERFACE_MODE_SGMII || +- interface == PHY_INTERFACE_MODE_QSGMII || +- linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising))) ++ neg_mode = phylink_pcs_neg_mode(mode, interface, advertising); ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) + bmcr = BMCR_ANENABLE; + else + bmcr = 0; + ++ /* Configure the inband state. Ensure ISOLATE bit is disabled */ + ret = mdiodev_modify(pcs, MII_BMCR, BMCR_ANENABLE | BMCR_ISOLATE, bmcr); + if (ret < 0) + return ret; diff --git a/lede/target/linux/generic/backport-6.1/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch b/lede/target/linux/generic/backport-6.1/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch new file mode 100644 index 0000000000..5572850e95 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-26-v6.5-net-phylink-pass-neg_mode-into-phylink_mii_c22_pcs_c.patch @@ -0,0 +1,187 @@ +From febf2aaf05641f3258cc30e072aff65cffc7c82c Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 16 Jun 2023 13:06:32 +0100 +Subject: [PATCH 2/2] net: phylink: pass neg_mode into + phylink_mii_c22_pcs_config() + +Convert fman_dtsec, xilinx_axienet and pcs-lynx to pass the neg_mode +into phylink_mii_c22_pcs_config(). Where appropriate, drivers are +updated to have neg_mode passed into their pcs_config() and +pcs_link_up() functions. For other drivers, we just hoist the call +to phylink_pcs_neg_mode() to their pcs_config() method out of +phylink_mii_c22_pcs_config(). + +Signed-off-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/E1qA8Do-00EaFM-Ra@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + .../net/ethernet/freescale/fman/fman_dtsec.c | 7 ++++--- + .../net/ethernet/xilinx/xilinx_axienet_main.c | 6 ++++-- + drivers/net/pcs/pcs-lynx.c | 18 ++++++++++++------ + drivers/net/phy/phylink.c | 9 ++++----- + include/linux/phylink.h | 5 +++-- + 5 files changed, 27 insertions(+), 18 deletions(-) + +--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c ++++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +@@ -763,15 +763,15 @@ static void dtsec_pcs_get_state(struct p + phylink_mii_c22_pcs_get_state(dtsec->tbidev, state); + } + +-static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) + { + struct fman_mac *dtsec = pcs_to_dtsec(pcs); + +- return phylink_mii_c22_pcs_config(dtsec->tbidev, mode, interface, +- advertising); ++ return phylink_mii_c22_pcs_config(dtsec->tbidev, interface, ++ advertising, neg_mode); + } + + static void dtsec_pcs_an_restart(struct phylink_pcs *pcs) +@@ -1447,6 +1447,7 @@ int dtsec_initialization(struct mac_devi + goto _return_fm_mac_free; + } + dtsec->pcs.ops = &dtsec_pcs_ops; ++ dtsec->pcs.neg_mode = true; + dtsec->pcs.poll = true; + + supported = mac_dev->phylink_config.supported_interfaces; +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -1631,7 +1631,7 @@ static void axienet_pcs_an_restart(struc + phylink_mii_c22_pcs_an_restart(pcs_phy); + } + +-static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) +@@ -1653,7 +1653,8 @@ static int axienet_pcs_config(struct phy + } + } + +- ret = phylink_mii_c22_pcs_config(pcs_phy, mode, interface, advertising); ++ ret = phylink_mii_c22_pcs_config(pcs_phy, interface, advertising, ++ neg_mode); + if (ret < 0) + netdev_warn(ndev, "Failed to configure PCS: %d\n", ret); + +@@ -2129,6 +2130,7 @@ static int axienet_probe(struct platform + } + of_node_put(np); + lp->pcs.ops = &axienet_pcs_ops; ++ lp->pcs.neg_mode = true; + lp->pcs.poll = true; + } + +--- a/drivers/net/pcs/pcs-lynx.c ++++ b/drivers/net/pcs/pcs-lynx.c +@@ -122,9 +122,10 @@ static void lynx_pcs_get_state(struct ph + state->link, state->an_complete); + } + +-static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode, ++static int lynx_pcs_config_giga(struct mdio_device *pcs, + phy_interface_t interface, +- const unsigned long *advertising) ++ const unsigned long *advertising, ++ unsigned int neg_mode) + { + u32 link_timer; + u16 if_mode; +@@ -137,8 +138,9 @@ static int lynx_pcs_config_giga(struct m + + if_mode = 0; + } else { ++ /* SGMII and QSGMII */ + if_mode = IF_MODE_SGMII_EN; +- if (mode == MLO_AN_INBAND) { ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { + if_mode |= IF_MODE_USE_SGMII_AN; + + /* Adjust link timer for SGMII */ +@@ -154,7 +156,8 @@ static int lynx_pcs_config_giga(struct m + if (err) + return err; + +- return phylink_mii_c22_pcs_config(pcs, mode, interface, advertising); ++ return phylink_mii_c22_pcs_config(pcs, interface, advertising, ++ neg_mode); + } + + static int lynx_pcs_config_usxgmii(struct mdio_device *pcs, unsigned int mode, +@@ -181,13 +184,16 @@ static int lynx_pcs_config(struct phylin + bool permit) + { + struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs); ++ unsigned int neg_mode; ++ ++ neg_mode = phylink_pcs_neg_mode(mode, ifmode, advertising); + + switch (ifmode) { + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: +- return lynx_pcs_config_giga(lynx->mdio, mode, ifmode, +- advertising); ++ return lynx_pcs_config_giga(lynx->mdio, ifmode, advertising, ++ neg_mode); + case PHY_INTERFACE_MODE_2500BASEX: + if (phylink_autoneg_inband(mode)) { + dev_err(&lynx->mdio->dev, +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -3545,20 +3545,20 @@ EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_en + /** + * phylink_mii_c22_pcs_config() - configure clause 22 PCS + * @pcs: a pointer to a &struct mdio_device. +- * @mode: link autonegotiation mode + * @interface: the PHY interface mode being configured + * @advertising: the ethtool advertisement mask ++ * @neg_mode: PCS negotiation mode + * + * Configure a Clause 22 PCS PHY with the appropriate negotiation + * parameters for the @mode, @interface and @advertising parameters. + * Returns negative error number on failure, zero if the advertisement + * has not changed, or positive if there is a change. + */ +-int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode, ++int phylink_mii_c22_pcs_config(struct mdio_device *pcs, + phy_interface_t interface, +- const unsigned long *advertising) ++ const unsigned long *advertising, ++ unsigned int neg_mode) + { +- unsigned int neg_mode; + bool changed = 0; + u16 bmcr; + int ret, adv; +@@ -3572,7 +3572,6 @@ int phylink_mii_c22_pcs_config(struct md + changed = ret; + } + +- neg_mode = phylink_pcs_neg_mode(mode, interface, advertising); + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) + bmcr = BMCR_ANENABLE; + else +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -743,9 +743,10 @@ void phylink_mii_c22_pcs_get_state(struc + struct phylink_link_state *state); + int phylink_mii_c22_pcs_encode_advertisement(phy_interface_t interface, + const unsigned long *advertising); +-int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode, ++int phylink_mii_c22_pcs_config(struct mdio_device *pcs, + phy_interface_t interface, +- const unsigned long *advertising); ++ const unsigned long *advertising, ++ unsigned int neg_mode); + void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs); + + void phylink_resolve_c73(struct phylink_link_state *state); diff --git a/lede/target/linux/generic/backport-6.1/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch b/lede/target/linux/generic/backport-6.1/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch new file mode 100644 index 0000000000..5e0128766c --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-27-v6.5-net-pcs-lynxi-update-PCS-driver-to-use-neg_mode.patch @@ -0,0 +1,101 @@ +From 3b2de56a146f34e3f70a84cc3a1897064e445d16 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 16 Jun 2023 13:06:43 +0100 +Subject: [PATCH] net: pcs: lynxi: update PCS driver to use neg_mode + +Update the Lynxi PCS driver to use neg_mode rather than the mode +argument. This ensures that the link_up() method will always program +the speed and duplex when negotiation is disabled. + +Signed-off-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/E1qA8Dz-00EaFY-5A@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/pcs/pcs-mtk-lynxi.c | 39 ++++++++++++++------------------- + 1 file changed, 16 insertions(+), 23 deletions(-) + +--- a/drivers/net/pcs/pcs-mtk-lynxi.c ++++ b/drivers/net/pcs/pcs-mtk-lynxi.c +@@ -102,13 +102,13 @@ static void mtk_pcs_lynxi_get_state(stru + FIELD_GET(SGMII_LPA, adv)); + } + +-static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode, ++static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) + { + struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); +- bool mode_changed = false, changed, use_an; ++ bool mode_changed = false, changed; + unsigned int rgc3, sgm_mode, bmcr; + int advertise, link_timer; + +@@ -121,30 +121,22 @@ static int mtk_pcs_lynxi_config(struct p + * we assume that fixes it's speed at bitrate = line rate (in + * other words, 1000Mbps or 2500Mbps). + */ +- if (interface == PHY_INTERFACE_MODE_SGMII) { ++ if (interface == PHY_INTERFACE_MODE_SGMII) + sgm_mode = SGMII_IF_MODE_SGMII; +- if (phylink_autoneg_inband(mode)) { +- sgm_mode |= SGMII_REMOTE_FAULT_DIS | +- SGMII_SPEED_DUPLEX_AN; +- use_an = true; +- } else { +- use_an = false; +- } +- } else if (phylink_autoneg_inband(mode)) { +- /* 1000base-X or 2500base-X autoneg */ +- sgm_mode = SGMII_REMOTE_FAULT_DIS; +- use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, +- advertising); +- } else { ++ else + /* 1000base-X or 2500base-X without autoneg */ + sgm_mode = 0; +- use_an = false; +- } + +- if (use_an) ++ if (neg_mode & PHYLINK_PCS_NEG_INBAND) ++ sgm_mode |= SGMII_REMOTE_FAULT_DIS; ++ ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { ++ if (interface == PHY_INTERFACE_MODE_SGMII) ++ sgm_mode |= SGMII_SPEED_DUPLEX_AN; + bmcr = BMCR_ANENABLE; +- else ++ } else { + bmcr = 0; ++ } + + if (mpcs->interface != interface) { + link_timer = phylink_get_link_timer_ns(interface); +@@ -216,14 +208,15 @@ static void mtk_pcs_lynxi_restart_an(str + regmap_set_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, BMCR_ANRESTART); + } + +-static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, unsigned int mode, ++static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, ++ unsigned int neg_mode, + phy_interface_t interface, int speed, + int duplex) + { + struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); + unsigned int sgm_mode; + +- if (!phylink_autoneg_inband(mode)) { ++ if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) { + /* Force the speed and duplex setting */ + if (speed == SPEED_10) + sgm_mode = SGMII_SPEED_10; +@@ -286,6 +279,7 @@ struct phylink_pcs *mtk_pcs_lynxi_create + mpcs->regmap = regmap; + mpcs->flags = flags; + mpcs->pcs.ops = &mtk_pcs_lynxi_ops; ++ mpcs->pcs.neg_mode = true; + mpcs->pcs.poll = true; + mpcs->interface = PHY_INTERFACE_MODE_NA; + diff --git a/lede/target/linux/generic/backport-6.1/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch b/lede/target/linux/generic/backport-6.1/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch new file mode 100644 index 0000000000..3dd22d2916 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-28-v6.4-net-pcs-xpcs-use-Autoneg-bit-rather-than-an_enabled.patch @@ -0,0 +1,55 @@ +From 459fd2f11204c962e3153020f4f56748e0e10afb Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 21 Mar 2023 15:58:49 +0000 +Subject: [PATCH] net: pcs: xpcs: use Autoneg bit rather than an_enabled + +The Autoneg bit in the advertising bitmap and state->an_enabled are +always identical. Thus, we will be removing state->an_enabled. + +Use the Autoneg bit in the advertising bitmap to indicate whether +autonegotiation should be used, rather than using the an_enabled +member which will be going away. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Simon Horman +Signed-off-by: Jakub Kicinski +--- + drivers/net/pcs/pcs-xpcs.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/net/pcs/pcs-xpcs.c ++++ b/drivers/net/pcs/pcs-xpcs.c +@@ -931,6 +931,7 @@ static int xpcs_get_state_c73(struct dw_ + struct phylink_link_state *state, + const struct xpcs_compat *compat) + { ++ bool an_enabled; + int ret; + + /* Link needs to be read first ... */ +@@ -948,11 +949,13 @@ static int xpcs_get_state_c73(struct dw_ + return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND, NULL); + } + +- if (state->an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) { ++ an_enabled = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ state->advertising); ++ if (an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) { + state->an_complete = true; + xpcs_read_lpa_c73(xpcs, state); + xpcs_resolve_lpa_c73(xpcs, state); +- } else if (state->an_enabled) { ++ } else if (an_enabled) { + state->link = 0; + } else if (state->link) { + xpcs_resolve_pma(xpcs, state); +@@ -1007,7 +1010,8 @@ static int xpcs_get_state_c37_1000basex( + { + int lpa, bmsr; + +- if (state->an_enabled) { ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ state->advertising)) { + /* Reset link state */ + state->link = false; + diff --git a/lede/target/linux/generic/backport-6.1/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch b/lede/target/linux/generic/backport-6.1/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch new file mode 100644 index 0000000000..7cae8515fa --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-29-v6.4-net-pcs-xpcs-fix-incorrect-number-of-interfaces.patch @@ -0,0 +1,30 @@ +From 43fb622d91a9f408322735d2f736495c1009f575 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 9 May 2023 12:50:04 +0100 +Subject: [PATCH] net: pcs: xpcs: fix incorrect number of interfaces + +In synopsys_xpcs_compat[], the DW_XPCS_2500BASEX entry was setting +the number of interfaces using the xpcs_2500basex_features array +rather than xpcs_2500basex_interfaces. This causes us to overflow +the array of interfaces. Fix this. + +Fixes: f27abde3042a ("net: pcs: add 2500BASEX support for Intel mGbE controller") +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Reviewed-by: Leon Romanovsky +Signed-off-by: David S. Miller +--- + drivers/net/pcs/pcs-xpcs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/pcs/pcs-xpcs.c ++++ b/drivers/net/pcs/pcs-xpcs.c +@@ -1211,7 +1211,7 @@ static const struct xpcs_compat synopsys + [DW_XPCS_2500BASEX] = { + .supported = xpcs_2500basex_features, + .interface = xpcs_2500basex_interfaces, +- .num_interfaces = ARRAY_SIZE(xpcs_2500basex_features), ++ .num_interfaces = ARRAY_SIZE(xpcs_2500basex_interfaces), + .an_mode = DW_2500BASEX, + }, + }; diff --git a/lede/target/linux/generic/backport-6.1/715-v6.9-01-net-phy-qcom-qca808x-fix-logic-error-in-LED-brightne.patch b/lede/target/linux/generic/backport-6.1/715-v6.9-01-net-phy-qcom-qca808x-fix-logic-error-in-LED-brightne.patch new file mode 100644 index 0000000000..0a7b5358f1 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-v6.9-01-net-phy-qcom-qca808x-fix-logic-error-in-LED-brightne.patch @@ -0,0 +1,36 @@ +From f2ec98566775dd4341ec1dcf93aa5859c60de826 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 1 Feb 2024 14:46:00 +0100 +Subject: [PATCH 1/2] net: phy: qcom: qca808x: fix logic error in LED + brightness set + +In switching to using phy_modify_mmd and a more short version of the +LED ON/OFF condition in later revision, it was made a logic error where + +value ? QCA808X_LED_FORCE_ON : QCA808X_LED_FORCE_OFF is always true as +value is always OR with QCA808X_LED_FORCE_EN due to missing () +resulting in the testing condition being QCA808X_LED_FORCE_EN | value. + +Add the () to apply the correct condition and restore correct +functionality of the brightness ON/OFF. + +Fixes: 7196062b64ee ("net: phy: at803x: add LED support for qca808x") +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca808x.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -820,8 +820,8 @@ static int qca808x_led_brightness_set(st + + return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, + QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, +- QCA808X_LED_FORCE_EN | value ? QCA808X_LED_FORCE_ON : +- QCA808X_LED_FORCE_OFF); ++ QCA808X_LED_FORCE_EN | (value ? QCA808X_LED_FORCE_ON : ++ QCA808X_LED_FORCE_OFF)); + } + + static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, diff --git a/lede/target/linux/generic/backport-6.1/715-v6.9-02-net-phy-qcom-qca808x-default-to-LED-active-High-if-n.patch b/lede/target/linux/generic/backport-6.1/715-v6.9-02-net-phy-qcom-qca808x-default-to-LED-active-High-if-n.patch new file mode 100644 index 0000000000..e32ed7f777 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/715-v6.9-02-net-phy-qcom-qca808x-default-to-LED-active-High-if-n.patch @@ -0,0 +1,41 @@ +From f203c8c77c7616c099647636f4c67d59a45fe8a2 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 1 Feb 2024 14:46:01 +0100 +Subject: [PATCH 2/2] net: phy: qcom: qca808x: default to LED active High if + not set + +qca808x PHY provide support for the led_polarity_set OP to configure +and apply the active-low property but on PHY reset, the Active High bit +is not set resulting in the LED driven as active-low. + +To fix this, check if active-low is not set in DT and enable Active High +polarity by default to restore correct funcionality of the LED. + +Fixes: 7196062b64ee ("net: phy: at803x: add LED support for qca808x") +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca808x.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -290,8 +290,18 @@ static int qca808x_probe(struct phy_devi + + static int qca808x_config_init(struct phy_device *phydev) + { ++ struct qca808x_priv *priv = phydev->priv; + int ret; + ++ /* Default to LED Active High if active-low not in DT */ ++ if (priv->led_polarity_mode == -1) { ++ ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, ++ QCA808X_MMD7_LED_POLARITY_CTRL, ++ QCA808X_LED_ACTIVE_HIGH); ++ if (ret) ++ return ret; ++ } ++ + /* Active adc&vga on 802.3az for the link 1000M and 100M */ + ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, + QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); diff --git a/lede/target/linux/generic/backport-6.1/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch b/lede/target/linux/generic/backport-6.1/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch new file mode 100644 index 0000000000..b355031aa5 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/716-v6.9-02-net-phy-add-support-for-scanning-PHY-in-PHY-packages.patch @@ -0,0 +1,211 @@ +From 385ef48f468696d6d172eb367656a3466fa0408d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 6 Feb 2024 18:31:05 +0100 +Subject: [PATCH 02/10] net: phy: add support for scanning PHY in PHY packages + nodes + +Add support for scanning PHY in PHY package nodes. PHY packages nodes +are just container for actual PHY on the MDIO bus. + +Their PHY address defined in the PHY package node are absolute and +reflect the address on the MDIO bus. + +mdio_bus.c and of_mdio.c is updated to now support and parse also +PHY package subnode by checking if the node name match +"ethernet-phy-package". + +As PHY package reg is mandatory and each PHY in the PHY package must +have a reg, every invalid PHY Package node is ignored and will be +skipped by the autoscan fallback. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/mdio/of_mdio.c | 79 +++++++++++++++++++++++++++----------- + drivers/net/phy/mdio_bus.c | 44 +++++++++++++++++---- + 2 files changed, 92 insertions(+), 31 deletions(-) + +--- a/drivers/net/mdio/of_mdio.c ++++ b/drivers/net/mdio/of_mdio.c +@@ -138,6 +138,53 @@ bool of_mdiobus_child_is_phy(struct devi + } + EXPORT_SYMBOL(of_mdiobus_child_is_phy); + ++static int __of_mdiobus_parse_phys(struct mii_bus *mdio, struct device_node *np, ++ bool *scanphys) ++{ ++ struct device_node *child; ++ int addr, rc = 0; ++ ++ /* Loop over the child nodes and register a phy_device for each phy */ ++ for_each_available_child_of_node(np, child) { ++ if (of_node_name_eq(child, "ethernet-phy-package")) { ++ /* Ignore invalid ethernet-phy-package node */ ++ if (!of_find_property(child, "reg", NULL)) ++ continue; ++ ++ rc = __of_mdiobus_parse_phys(mdio, child, NULL); ++ if (rc && rc != -ENODEV) ++ goto exit; ++ ++ continue; ++ } ++ ++ addr = of_mdio_parse_addr(&mdio->dev, child); ++ if (addr < 0) { ++ /* Skip scanning for invalid ethernet-phy-package node */ ++ if (scanphys) ++ *scanphys = true; ++ continue; ++ } ++ ++ if (of_mdiobus_child_is_phy(child)) ++ rc = of_mdiobus_register_phy(mdio, child, addr); ++ else ++ rc = of_mdiobus_register_device(mdio, child, addr); ++ ++ if (rc == -ENODEV) ++ dev_err(&mdio->dev, ++ "MDIO device at address %d is missing.\n", ++ addr); ++ else if (rc) ++ goto exit; ++ } ++ ++ return 0; ++exit: ++ of_node_put(child); ++ return rc; ++} ++ + /** + * __of_mdiobus_register - Register mii_bus and create PHYs from the device tree + * @mdio: pointer to mii_bus structure +@@ -179,33 +226,18 @@ int __of_mdiobus_register(struct mii_bus + return rc; + + /* Loop over the child nodes and register a phy_device for each phy */ +- for_each_available_child_of_node(np, child) { +- addr = of_mdio_parse_addr(&mdio->dev, child); +- if (addr < 0) { +- scanphys = true; +- continue; +- } +- +- if (of_mdiobus_child_is_phy(child)) +- rc = of_mdiobus_register_phy(mdio, child, addr); +- else +- rc = of_mdiobus_register_device(mdio, child, addr); +- +- if (rc == -ENODEV) +- dev_err(&mdio->dev, +- "MDIO device at address %d is missing.\n", +- addr); +- else if (rc) +- goto unregister; +- } ++ rc = __of_mdiobus_parse_phys(mdio, np, &scanphys); ++ if (rc) ++ goto unregister; + + if (!scanphys) + return 0; + + /* auto scan for PHYs with empty reg property */ + for_each_available_child_of_node(np, child) { +- /* Skip PHYs with reg property set */ +- if (of_find_property(child, "reg", NULL)) ++ /* Skip PHYs with reg property set or ethernet-phy-package node */ ++ if (of_find_property(child, "reg", NULL) || ++ of_node_name_eq(child, "ethernet-phy-package")) + continue; + + for (addr = 0; addr < PHY_MAX_ADDR; addr++) { +@@ -226,15 +258,16 @@ int __of_mdiobus_register(struct mii_bus + if (!rc) + break; + if (rc != -ENODEV) +- goto unregister; ++ goto put_unregister; + } + } + } + + return 0; + +-unregister: ++put_unregister: + of_node_put(child); ++unregister: + mdiobus_unregister(mdio); + return rc; + } +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -448,19 +448,34 @@ EXPORT_SYMBOL(of_mdio_find_bus); + * found, set the of_node pointer for the mdio device. This allows + * auto-probed phy devices to be supplied with information passed in + * via DT. ++ * If a PHY package is found, PHY is searched also there. + */ +-static void of_mdiobus_link_mdiodev(struct mii_bus *bus, +- struct mdio_device *mdiodev) ++static int of_mdiobus_find_phy(struct device *dev, struct mdio_device *mdiodev, ++ struct device_node *np) + { +- struct device *dev = &mdiodev->dev; + struct device_node *child; + +- if (dev->of_node || !bus->dev.of_node) +- return; +- +- for_each_available_child_of_node(bus->dev.of_node, child) { ++ for_each_available_child_of_node(np, child) { + int addr; + ++ if (of_node_name_eq(child, "ethernet-phy-package")) { ++ /* Validate PHY package reg presence */ ++ if (!of_find_property(child, "reg", NULL)) { ++ of_node_put(child); ++ return -EINVAL; ++ } ++ ++ if (!of_mdiobus_find_phy(dev, mdiodev, child)) { ++ /* The refcount for the PHY package will be ++ * incremented later when PHY join the Package. ++ */ ++ of_node_put(child); ++ return 0; ++ } ++ ++ continue; ++ } ++ + addr = of_mdio_parse_addr(dev, child); + if (addr < 0) + continue; +@@ -470,9 +485,22 @@ static void of_mdiobus_link_mdiodev(stru + /* The refcount on "child" is passed to the mdio + * device. Do _not_ use of_node_put(child) here. + */ +- return; ++ return 0; + } + } ++ ++ return -ENODEV; ++} ++ ++static void of_mdiobus_link_mdiodev(struct mii_bus *bus, ++ struct mdio_device *mdiodev) ++{ ++ struct device *dev = &mdiodev->dev; ++ ++ if (dev->of_node || !bus->dev.of_node) ++ return; ++ ++ of_mdiobus_find_phy(dev, mdiodev, bus->dev.of_node); + } + #else /* !IS_ENABLED(CONFIG_OF_MDIO) */ + static inline void of_mdiobus_link_mdiodev(struct mii_bus *mdio, diff --git a/lede/target/linux/generic/backport-6.1/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch b/lede/target/linux/generic/backport-6.1/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch new file mode 100644 index 0000000000..3c7bf6c132 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch @@ -0,0 +1,185 @@ +From 471e8fd3afcef5a9f9089f0bd21965ad9ba35c91 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 6 Feb 2024 18:31:06 +0100 +Subject: [PATCH 03/10] net: phy: add devm/of_phy_package_join helper + +Add devm/of_phy_package_join helper to join PHYs in a PHY package. These +are variant of the manual phy_package_join with the difference that +these will use DT nodes to derive the base_addr instead of manually +passing an hardcoded value. + +An additional value is added in phy_package_shared, "np" to reference +the PHY package node pointer in specific PHY driver probe_once and +config_init_once functions to make use of additional specific properties +defined in the PHY package node in DT. + +The np value is filled only with of_phy_package_join if a valid PHY +package node is found. A valid PHY package node must have the node name +set to "ethernet-phy-package". + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy_device.c | 96 ++++++++++++++++++++++++++++++++++++ + include/linux/phy.h | 6 +++ + 2 files changed, 102 insertions(+) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1648,6 +1648,7 @@ int phy_package_join(struct phy_device * + shared->priv_size = priv_size; + } + shared->base_addr = base_addr; ++ shared->np = NULL; + refcount_set(&shared->refcnt, 1); + bus->shared[base_addr] = shared; + } else { +@@ -1671,6 +1672,63 @@ err_unlock: + EXPORT_SYMBOL_GPL(phy_package_join); + + /** ++ * of_phy_package_join - join a common PHY group in PHY package ++ * @phydev: target phy_device struct ++ * @priv_size: if non-zero allocate this amount of bytes for private data ++ * ++ * This is a variant of phy_package_join for PHY package defined in DT. ++ * ++ * The parent node of the @phydev is checked as a valid PHY package node ++ * structure (by matching the node name "ethernet-phy-package") and the ++ * base_addr for the PHY package is passed to phy_package_join. ++ * ++ * With this configuration the shared struct will also have the np value ++ * filled to use additional DT defined properties in PHY specific ++ * probe_once and config_init_once PHY package OPs. ++ * ++ * Returns < 0 on error, 0 on success. Esp. calling phy_package_join() ++ * with the same cookie but a different priv_size is an error. Or a parent ++ * node is not detected or is not valid or doesn't match the expected node ++ * name for PHY package. ++ */ ++int of_phy_package_join(struct phy_device *phydev, size_t priv_size) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ struct device_node *package_node; ++ u32 base_addr; ++ int ret; ++ ++ if (!node) ++ return -EINVAL; ++ ++ package_node = of_get_parent(node); ++ if (!package_node) ++ return -EINVAL; ++ ++ if (!of_node_name_eq(package_node, "ethernet-phy-package")) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (of_property_read_u32(package_node, "reg", &base_addr)) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ ret = phy_package_join(phydev, base_addr, priv_size); ++ if (ret) ++ goto exit; ++ ++ phydev->shared->np = package_node; ++ ++ return 0; ++exit: ++ of_node_put(package_node); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(of_phy_package_join); ++ ++/** + * phy_package_leave - leave a common PHY group + * @phydev: target phy_device struct + * +@@ -1686,6 +1744,10 @@ void phy_package_leave(struct phy_device + if (!shared) + return; + ++ /* Decrease the node refcount on leave if present */ ++ if (shared->np) ++ of_node_put(shared->np); ++ + if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) { + bus->shared[shared->base_addr] = NULL; + mutex_unlock(&bus->shared_lock); +@@ -1739,6 +1801,40 @@ int devm_phy_package_join(struct device + EXPORT_SYMBOL_GPL(devm_phy_package_join); + + /** ++ * devm_of_phy_package_join - resource managed of_phy_package_join() ++ * @dev: device that is registering this PHY package ++ * @phydev: target phy_device struct ++ * @priv_size: if non-zero allocate this amount of bytes for private data ++ * ++ * Managed of_phy_package_join(). Shared storage fetched by this function, ++ * phy_package_leave() is automatically called on driver detach. See ++ * of_phy_package_join() for more information. ++ */ ++int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev, ++ size_t priv_size) ++{ ++ struct phy_device **ptr; ++ int ret; ++ ++ ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr), ++ GFP_KERNEL); ++ if (!ptr) ++ return -ENOMEM; ++ ++ ret = of_phy_package_join(phydev, priv_size); ++ ++ if (!ret) { ++ *ptr = phydev; ++ devres_add(dev, ptr); ++ } else { ++ devres_free(ptr); ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(devm_of_phy_package_join); ++ ++/** + * phy_detach - detach a PHY device from its network device + * @phydev: target phy_device struct + * +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -321,6 +321,7 @@ struct mdio_bus_stats { + * struct phy_package_shared - Shared information in PHY packages + * @base_addr: Base PHY address of PHY package used to combine PHYs + * in one package and for offset calculation of phy_package_read/write ++ * @np: Pointer to the Device Node if PHY package defined in DT + * @refcnt: Number of PHYs connected to this shared data + * @flags: Initialization of PHY package + * @priv_size: Size of the shared private data @priv +@@ -332,6 +333,8 @@ struct mdio_bus_stats { + */ + struct phy_package_shared { + u8 base_addr; ++ /* With PHY package defined in DT this points to the PHY package node */ ++ struct device_node *np; + refcount_t refcnt; + unsigned long flags; + size_t priv_size; +@@ -1793,9 +1796,12 @@ int phy_ethtool_set_link_ksettings(struc + const struct ethtool_link_ksettings *cmd); + int phy_ethtool_nway_reset(struct net_device *ndev); + int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size); ++int of_phy_package_join(struct phy_device *phydev, size_t priv_size); + void phy_package_leave(struct phy_device *phydev); + int devm_phy_package_join(struct device *dev, struct phy_device *phydev, + int base_addr, size_t priv_size); ++int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev, ++ size_t priv_size); + + #if IS_ENABLED(CONFIG_PHYLIB) + int __init mdio_bus_init(void); diff --git a/lede/target/linux/generic/backport-6.1/716-v6.9-04-net-phy-qcom-move-more-function-to-shared-library.patch b/lede/target/linux/generic/backport-6.1/716-v6.9-04-net-phy-qcom-move-more-function-to-shared-library.patch new file mode 100644 index 0000000000..e935725630 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/716-v6.9-04-net-phy-qcom-move-more-function-to-shared-library.patch @@ -0,0 +1,583 @@ +From 737eb75a815f9c08dcbb6631db57f4f4b0540a5b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 6 Feb 2024 18:31:07 +0100 +Subject: [PATCH 04/10] net: phy: qcom: move more function to shared library + +Move more function to shared library in preparation for introduction of +new PHY Family qca807x that will make use of both functions from at803x +and qca808x as it's a transition PHY with some implementation of at803x +and some from the new qca808x. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/at803x.c | 35 ----- + drivers/net/phy/qcom/qca808x.c | 205 ---------------------------- + drivers/net/phy/qcom/qcom-phy-lib.c | 193 ++++++++++++++++++++++++++ + drivers/net/phy/qcom/qcom.h | 51 +++++++ + 4 files changed, 244 insertions(+), 240 deletions(-) + +--- a/drivers/net/phy/qcom/at803x.c ++++ b/drivers/net/phy/qcom/at803x.c +@@ -504,41 +504,6 @@ static void at803x_link_change_notify(st + } + } + +-static int at803x_read_status(struct phy_device *phydev) +-{ +- struct at803x_ss_mask ss_mask = { 0 }; +- int err, old_link = phydev->link; +- +- /* Update the link, but return if there was an error */ +- err = genphy_update_link(phydev); +- if (err) +- return err; +- +- /* why bother the PHY if nothing can have changed */ +- if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) +- return 0; +- +- phydev->speed = SPEED_UNKNOWN; +- phydev->duplex = DUPLEX_UNKNOWN; +- phydev->pause = 0; +- phydev->asym_pause = 0; +- +- err = genphy_read_lpa(phydev); +- if (err < 0) +- return err; +- +- ss_mask.speed_mask = AT803X_SS_SPEED_MASK; +- ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK); +- err = at803x_read_specific_status(phydev, ss_mask); +- if (err < 0) +- return err; +- +- if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) +- phy_resolve_aneg_pause(phydev); +- +- return 0; +-} +- + static int at803x_config_aneg(struct phy_device *phydev) + { + struct at803x_priv *priv = phydev->priv; +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -2,7 +2,6 @@ + + #include + #include +-#include + + #include "qcom.h" + +@@ -63,55 +62,6 @@ + #define QCA808X_DBG_AN_TEST 0xb + #define QCA808X_HIBERNATION_EN BIT(15) + +-#define QCA808X_CDT_ENABLE_TEST BIT(15) +-#define QCA808X_CDT_INTER_CHECK_DIS BIT(13) +-#define QCA808X_CDT_STATUS BIT(11) +-#define QCA808X_CDT_LENGTH_UNIT BIT(10) +- +-#define QCA808X_MMD3_CDT_STATUS 0x8064 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 +-#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 +-#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) +-#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) +- +-#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) +-#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) +-#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) +-#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) +- +-#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) +-#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) +-#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) +-#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) +-#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) +- +-#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) +-#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) +-#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) +-#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) +- +-/* NORMAL are MDI with type set to 0 */ +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI1) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI1) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI2) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI2) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ +- QCA808X_CDT_STATUS_STAT_MDI3) +-#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ +- QCA808X_CDT_STATUS_STAT_MDI3) +- +-/* Added for reference of existence but should be handled by wait_for_completion already */ +-#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) +- + #define QCA808X_MMD7_LED_GLOBAL 0x8073 + #define QCA808X_LED_BLINK_1 GENMASK(11, 6) + #define QCA808X_LED_BLINK_2 GENMASK(5, 0) +@@ -406,86 +356,6 @@ static int qca808x_soft_reset(struct phy + return ret; + } + +-static bool qca808x_cdt_fault_length_valid(int cdt_code) +-{ +- switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: +- return true; +- default: +- return false; +- } +-} +- +-static int qca808x_cable_test_result_trans(int cdt_code) +-{ +- switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_NORMAL: +- return ETHTOOL_A_CABLE_RESULT_CODE_OK; +- case QCA808X_CDT_STATUS_STAT_SAME_SHORT: +- return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; +- case QCA808X_CDT_STATUS_STAT_SAME_OPEN: +- return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: +- case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: +- return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; +- case QCA808X_CDT_STATUS_STAT_FAIL: +- default: +- return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; +- } +-} +- +-static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, +- int result) +-{ +- int val; +- u32 cdt_length_reg = 0; +- +- switch (pair) { +- case ETHTOOL_A_CABLE_PAIR_A: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A; +- break; +- case ETHTOOL_A_CABLE_PAIR_B: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B; +- break; +- case ETHTOOL_A_CABLE_PAIR_C: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C; +- break; +- case ETHTOOL_A_CABLE_PAIR_D: +- cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D; +- break; +- default: +- return -EINVAL; +- } +- +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg); +- if (val < 0) +- return val; +- +- if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); +- else +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); +- +- return at803x_cdt_fault_length(val); +-} +- + static int qca808x_cable_test_start(struct phy_device *phydev) + { + int ret; +@@ -526,81 +396,6 @@ static int qca808x_cable_test_start(stru + + return 0; + } +- +-static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, +- u16 status) +-{ +- int length, result; +- u16 pair_code; +- +- switch (pair) { +- case ETHTOOL_A_CABLE_PAIR_A: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_B: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_C: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); +- break; +- case ETHTOOL_A_CABLE_PAIR_D: +- pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); +- break; +- default: +- return -EINVAL; +- } +- +- result = qca808x_cable_test_result_trans(pair_code); +- ethnl_cable_test_result(phydev, pair, result); +- +- if (qca808x_cdt_fault_length_valid(pair_code)) { +- length = qca808x_cdt_fault_length(phydev, pair, result); +- ethnl_cable_test_fault_length(phydev, pair, length); +- } +- +- return 0; +-} +- +-static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) +-{ +- int ret, val; +- +- *finished = false; +- +- val = QCA808X_CDT_ENABLE_TEST | +- QCA808X_CDT_LENGTH_UNIT; +- ret = at803x_cdt_start(phydev, val); +- if (ret) +- return ret; +- +- ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); +- if (ret) +- return ret; +- +- val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS); +- if (val < 0) +- return val; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); +- if (ret) +- return ret; +- +- ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); +- if (ret) +- return ret; +- +- *finished = true; +- +- return 0; +-} + + static int qca808x_get_features(struct phy_device *phydev) + { +--- a/drivers/net/phy/qcom/qcom-phy-lib.c ++++ b/drivers/net/phy/qcom/qcom-phy-lib.c +@@ -5,6 +5,7 @@ + + #include + #include ++#include + + #include "qcom.h" + +@@ -311,6 +312,42 @@ int at803x_prepare_config_aneg(struct ph + } + EXPORT_SYMBOL_GPL(at803x_prepare_config_aneg); + ++int at803x_read_status(struct phy_device *phydev) ++{ ++ struct at803x_ss_mask ss_mask = { 0 }; ++ int err, old_link = phydev->link; ++ ++ /* Update the link, but return if there was an error */ ++ err = genphy_update_link(phydev); ++ if (err) ++ return err; ++ ++ /* why bother the PHY if nothing can have changed */ ++ if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) ++ return 0; ++ ++ phydev->speed = SPEED_UNKNOWN; ++ phydev->duplex = DUPLEX_UNKNOWN; ++ phydev->pause = 0; ++ phydev->asym_pause = 0; ++ ++ err = genphy_read_lpa(phydev); ++ if (err < 0) ++ return err; ++ ++ ss_mask.speed_mask = AT803X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK); ++ err = at803x_read_specific_status(phydev, ss_mask); ++ if (err < 0) ++ return err; ++ ++ if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) ++ phy_resolve_aneg_pause(phydev); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(at803x_read_status); ++ + static int at803x_get_downshift(struct phy_device *phydev, u8 *d) + { + int val; +@@ -427,3 +464,159 @@ int at803x_cdt_wait_for_completion(struc + return ret < 0 ? ret : 0; + } + EXPORT_SYMBOL_GPL(at803x_cdt_wait_for_completion); ++ ++static bool qca808x_cdt_fault_length_valid(int cdt_code) ++{ ++ switch (cdt_code) { ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static int qca808x_cable_test_result_trans(int cdt_code) ++{ ++ switch (cdt_code) { ++ case QCA808X_CDT_STATUS_STAT_NORMAL: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OK; ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; ++ case QCA808X_CDT_STATUS_STAT_FAIL: ++ default: ++ return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; ++ } ++} ++ ++static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, ++ int result) ++{ ++ int val; ++ u32 cdt_length_reg = 0; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C; ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg); ++ if (val < 0) ++ return val; ++ ++ if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); ++ else ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); ++ ++ return at803x_cdt_fault_length(val); ++} ++ ++static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, ++ u16 status) ++{ ++ int length, result; ++ u16 pair_code; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ result = qca808x_cable_test_result_trans(pair_code); ++ ethnl_cable_test_result(phydev, pair, result); ++ ++ if (qca808x_cdt_fault_length_valid(pair_code)) { ++ length = qca808x_cdt_fault_length(phydev, pair, result); ++ ethnl_cable_test_fault_length(phydev, pair, length); ++ } ++ ++ return 0; ++} ++ ++int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) ++{ ++ int ret, val; ++ ++ *finished = false; ++ ++ val = QCA808X_CDT_ENABLE_TEST | ++ QCA808X_CDT_LENGTH_UNIT; ++ ret = at803x_cdt_start(phydev, val); ++ if (ret) ++ return ret; ++ ++ ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); ++ if (ret) ++ return ret; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS); ++ if (val < 0) ++ return val; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); ++ if (ret) ++ return ret; ++ ++ *finished = true; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(qca808x_cable_test_get_status); +--- a/drivers/net/phy/qcom/qcom.h ++++ b/drivers/net/phy/qcom/qcom.h +@@ -54,6 +54,55 @@ + #define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8) + #define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0) + ++#define QCA808X_CDT_ENABLE_TEST BIT(15) ++#define QCA808X_CDT_INTER_CHECK_DIS BIT(13) ++#define QCA808X_CDT_STATUS BIT(11) ++#define QCA808X_CDT_LENGTH_UNIT BIT(10) ++ ++#define QCA808X_MMD3_CDT_STATUS 0x8064 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 ++#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 ++#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) ++#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) ++ ++#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) ++#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) ++#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) ++#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) ++ ++#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) ++#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) ++#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) ++#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) ++#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) ++ ++#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) ++#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) ++ ++/* NORMAL are MDI with type set to 0 */ ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++ ++/* Added for reference of existence but should be handled by wait_for_completion already */ ++#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) ++ + #define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C + #define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B + #define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A +@@ -110,6 +159,7 @@ int at803x_read_specific_status(struct p + struct at803x_ss_mask ss_mask); + int at803x_config_mdix(struct phy_device *phydev, u8 ctrl); + int at803x_prepare_config_aneg(struct phy_device *phydev); ++int at803x_read_status(struct phy_device *phydev); + int at803x_get_tunable(struct phy_device *phydev, + struct ethtool_tunable *tuna, void *data); + int at803x_set_tunable(struct phy_device *phydev, +@@ -118,3 +168,4 @@ int at803x_cdt_fault_length(int dt); + int at803x_cdt_start(struct phy_device *phydev, u32 cdt_start); + int at803x_cdt_wait_for_completion(struct phy_device *phydev, + u32 cdt_en); ++int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished); diff --git a/lede/target/linux/generic/backport-6.1/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch b/lede/target/linux/generic/backport-6.1/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch new file mode 100644 index 0000000000..acaa4a644e --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch @@ -0,0 +1,100 @@ +From 9b1d5e055508393561e26bd1720f4c2639b03b1a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 6 Feb 2024 18:31:09 +0100 +Subject: [PATCH 06/10] net: phy: provide whether link has changed in + c37_read_status + +Some PHY driver might require additional regs call after +genphy_c37_read_status() is called. + +Expand genphy_c37_read_status to provide a bool wheather the link has +changed or not to permit PHY driver to skip additional regs call if +nothing has changed. + +Every user of genphy_c37_read_status() is updated with the new +additional bool. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/broadcom.c | 3 ++- + drivers/net/phy/phy_device.c | 11 +++++++++-- + drivers/net/phy/qcom/at803x.c | 3 ++- + include/linux/phy.h | 2 +- + 4 files changed, 14 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/broadcom.c ++++ b/drivers/net/phy/broadcom.c +@@ -609,10 +609,11 @@ static int bcm54616s_config_aneg(struct + static int bcm54616s_read_status(struct phy_device *phydev) + { + struct bcm54616s_phy_priv *priv = phydev->priv; ++ bool changed; + int err; + + if (priv->mode_1000bx_en) +- err = genphy_c37_read_status(phydev); ++ err = genphy_c37_read_status(phydev, &changed); + else + err = genphy_read_status(phydev); + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -2549,12 +2549,15 @@ EXPORT_SYMBOL(genphy_read_status); + /** + * genphy_c37_read_status - check the link status and update current link state + * @phydev: target phy_device struct ++ * @changed: pointer where to store if link changed + * + * Description: Check the link, then figure out the current state + * by comparing what we advertise with what the link partner + * advertises. This function is for Clause 37 1000Base-X mode. ++ * ++ * If link has changed, @changed is set to true, false otherwise. + */ +-int genphy_c37_read_status(struct phy_device *phydev) ++int genphy_c37_read_status(struct phy_device *phydev, bool *changed) + { + int lpa, err, old_link = phydev->link; + +@@ -2564,9 +2567,13 @@ int genphy_c37_read_status(struct phy_de + return err; + + /* why bother the PHY if nothing can have changed */ +- if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) ++ if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) { ++ *changed = false; + return 0; ++ } + ++ /* Signal link has changed */ ++ *changed = true; + phydev->duplex = DUPLEX_UNKNOWN; + phydev->pause = 0; + phydev->asym_pause = 0; +--- a/drivers/net/phy/qcom/at803x.c ++++ b/drivers/net/phy/qcom/at803x.c +@@ -912,9 +912,10 @@ static int at8031_config_intr(struct phy + static int at8031_read_status(struct phy_device *phydev) + { + struct at803x_priv *priv = phydev->priv; ++ bool changed; + + if (priv->is_1000basex) +- return genphy_c37_read_status(phydev); ++ return genphy_c37_read_status(phydev, &changed); + + return at803x_read_status(phydev); + } +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -1688,7 +1688,7 @@ int genphy_write_mmd_unsupported(struct + + /* Clause 37 */ + int genphy_c37_config_aneg(struct phy_device *phydev); +-int genphy_c37_read_status(struct phy_device *phydev); ++int genphy_c37_read_status(struct phy_device *phydev, bool *changed); + + /* Clause 45 PHY */ + int genphy_c45_restart_aneg(struct phy_device *phydev); diff --git a/lede/target/linux/generic/backport-6.1/716-v6.9-07-net-phy-qcom-add-support-for-QCA807x-PHY-Family.patch b/lede/target/linux/generic/backport-6.1/716-v6.9-07-net-phy-qcom-add-support-for-QCA807x-PHY-Family.patch new file mode 100644 index 0000000000..bbf0f76d68 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/716-v6.9-07-net-phy-qcom-add-support-for-QCA807x-PHY-Family.patch @@ -0,0 +1,668 @@ +From d1cb613efbd3cd7d0c000167816beb3f248f5eb8 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 6 Feb 2024 18:31:10 +0100 +Subject: [PATCH 07/10] net: phy: qcom: add support for QCA807x PHY Family + +This adds driver for the Qualcomm QCA8072 and QCA8075 PHY-s. + +They are 2 or 5 port IEEE 802.3 clause 22 compliant 10BASE-Te, +100BASE-TX and 1000BASE-T PHY-s. + +They feature 2 SerDes, one for PSGMII or QSGMII connection with +MAC, while second one is SGMII for connection to MAC or fiber. + +Both models have a combo port that supports 1000BASE-X and +100BASE-FX fiber. + +PHY package can be configured in 3 mode following this table: + + First Serdes mode Second Serdes mode +Option 1 PSGMII for copper Disabled + ports 0-4 +Option 2 PSGMII for copper 1000BASE-X / 100BASE-FX + ports 0-4 +Option 3 QSGMII for copper SGMII for + ports 0-3 copper port 4 + +Each PHY inside of QCA807x series has 4 digitally controlled +output only pins that natively drive LED-s. +But some vendors used these to driver generic LED-s controlled +by userspace, so lets enable registering each PHY as GPIO +controller and add driver for it. + +These are commonly used in Qualcomm IPQ40xx, IPQ60xx and IPQ807x +boards. + +Co-developed-by: Christian Marangi +Signed-off-by: Robert Marko +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/Kconfig | 8 + + drivers/net/phy/qcom/Makefile | 1 + + drivers/net/phy/qcom/qca807x.c | 597 +++++++++++++++++++++++++++++++++ + 3 files changed, 606 insertions(+) + create mode 100644 drivers/net/phy/qcom/qca807x.c + +--- a/drivers/net/phy/qcom/Kconfig ++++ b/drivers/net/phy/qcom/Kconfig +@@ -20,3 +20,11 @@ config QCA808X_PHY + select QCOM_NET_PHYLIB + help + Currently supports the QCA8081 model ++ ++config QCA807X_PHY ++ tristate "Qualcomm QCA807x PHYs" ++ select QCOM_NET_PHYLIB ++ depends on OF_MDIO ++ help ++ Currently supports the Qualcomm QCA8072, QCA8075 and the PSGMII ++ control PHY. +--- a/drivers/net/phy/qcom/Makefile ++++ b/drivers/net/phy/qcom/Makefile +@@ -3,3 +3,4 @@ obj-$(CONFIG_QCOM_NET_PHYLIB) += qcom-ph + obj-$(CONFIG_AT803X_PHY) += at803x.o + obj-$(CONFIG_QCA83XX_PHY) += qca83xx.o + obj-$(CONFIG_QCA808X_PHY) += qca808x.o ++obj-$(CONFIG_QCA807X_PHY) += qca807x.o +--- /dev/null ++++ b/drivers/net/phy/qcom/qca807x.c +@@ -0,0 +1,597 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (c) 2023 Sartura Ltd. ++ * ++ * Author: Robert Marko ++ * Christian Marangi ++ * ++ * Qualcomm QCA8072 and QCA8075 PHY driver ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "qcom.h" ++ ++#define QCA807X_CHIP_CONFIGURATION 0x1f ++#define QCA807X_BT_BX_REG_SEL BIT(15) ++#define QCA807X_BT_BX_REG_SEL_FIBER 0 ++#define QCA807X_BT_BX_REG_SEL_COPPER 1 ++#define QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK GENMASK(3, 0) ++#define QCA807X_CHIP_CONFIGURATION_MODE_QSGMII_SGMII 4 ++#define QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_FIBER 3 ++#define QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_ALL_COPPER 0 ++ ++#define QCA807X_MEDIA_SELECT_STATUS 0x1a ++#define QCA807X_MEDIA_DETECTED_COPPER BIT(5) ++#define QCA807X_MEDIA_DETECTED_1000_BASE_X BIT(4) ++#define QCA807X_MEDIA_DETECTED_100_BASE_FX BIT(3) ++ ++#define QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION 0x807e ++#define QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION_EN BIT(0) ++ ++#define QCA807X_MMD7_1000BASE_T_POWER_SAVE_PER_CABLE_LENGTH 0x801a ++#define QCA807X_CONTROL_DAC_MASK GENMASK(2, 0) ++/* List of tweaks enabled by this bit: ++ * - With both FULL amplitude and FULL bias current: bias current ++ * is set to half. ++ * - With only DSP amplitude: bias current is set to half and ++ * is set to 1/4 with cable < 10m. ++ * - With DSP bias current (included both DSP amplitude and ++ * DSP bias current): bias current is half the detected current ++ * with cable < 10m. ++ */ ++#define QCA807X_CONTROL_DAC_BIAS_CURRENT_TWEAK BIT(2) ++#define QCA807X_CONTROL_DAC_DSP_BIAS_CURRENT BIT(1) ++#define QCA807X_CONTROL_DAC_DSP_AMPLITUDE BIT(0) ++ ++#define QCA807X_MMD7_LED_100N_1 0x8074 ++#define QCA807X_MMD7_LED_100N_2 0x8075 ++#define QCA807X_MMD7_LED_1000N_1 0x8076 ++#define QCA807X_MMD7_LED_1000N_2 0x8077 ++ ++#define QCA807X_MMD7_LED_CTRL(x) (0x8074 + ((x) * 2)) ++#define QCA807X_MMD7_LED_FORCE_CTRL(x) (0x8075 + ((x) * 2)) ++ ++#define QCA807X_GPIO_FORCE_EN BIT(15) ++#define QCA807X_GPIO_FORCE_MODE_MASK GENMASK(14, 13) ++ ++#define QCA807X_FUNCTION_CONTROL 0x10 ++#define QCA807X_FC_MDI_CROSSOVER_MODE_MASK GENMASK(6, 5) ++#define QCA807X_FC_MDI_CROSSOVER_AUTO 3 ++#define QCA807X_FC_MDI_CROSSOVER_MANUAL_MDIX 1 ++#define QCA807X_FC_MDI_CROSSOVER_MANUAL_MDI 0 ++ ++/* PQSGMII Analog PHY specific */ ++#define PQSGMII_CTRL_REG 0x0 ++#define PQSGMII_ANALOG_SW_RESET BIT(6) ++#define PQSGMII_DRIVE_CONTROL_1 0xb ++#define PQSGMII_TX_DRIVER_MASK GENMASK(7, 4) ++#define PQSGMII_TX_DRIVER_140MV 0x0 ++#define PQSGMII_TX_DRIVER_160MV 0x1 ++#define PQSGMII_TX_DRIVER_180MV 0x2 ++#define PQSGMII_TX_DRIVER_200MV 0x3 ++#define PQSGMII_TX_DRIVER_220MV 0x4 ++#define PQSGMII_TX_DRIVER_240MV 0x5 ++#define PQSGMII_TX_DRIVER_260MV 0x6 ++#define PQSGMII_TX_DRIVER_280MV 0x7 ++#define PQSGMII_TX_DRIVER_300MV 0x8 ++#define PQSGMII_TX_DRIVER_320MV 0x9 ++#define PQSGMII_TX_DRIVER_400MV 0xa ++#define PQSGMII_TX_DRIVER_500MV 0xb ++#define PQSGMII_TX_DRIVER_600MV 0xc ++#define PQSGMII_MODE_CTRL 0x6d ++#define PQSGMII_MODE_CTRL_AZ_WORKAROUND_MASK BIT(0) ++#define PQSGMII_MMD3_SERDES_CONTROL 0x805a ++ ++#define PHY_ID_QCA8072 0x004dd0b2 ++#define PHY_ID_QCA8075 0x004dd0b1 ++ ++#define QCA807X_COMBO_ADDR_OFFSET 4 ++#define QCA807X_PQSGMII_ADDR_OFFSET 5 ++#define SERDES_RESET_SLEEP 100 ++ ++enum qca807x_global_phy { ++ QCA807X_COMBO_ADDR = 4, ++ QCA807X_PQSGMII_ADDR = 5, ++}; ++ ++struct qca807x_shared_priv { ++ unsigned int package_mode; ++ u32 tx_drive_strength; ++}; ++ ++struct qca807x_gpio_priv { ++ struct phy_device *phy; ++}; ++ ++struct qca807x_priv { ++ bool dac_full_amplitude; ++ bool dac_full_bias_current; ++ bool dac_disable_bias_current_tweak; ++}; ++ ++static int qca807x_cable_test_start(struct phy_device *phydev) ++{ ++ /* we do all the (time consuming) work later */ ++ return 0; ++} ++ ++#ifdef CONFIG_GPIOLIB ++static int qca807x_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) ++{ ++ return GPIO_LINE_DIRECTION_OUT; ++} ++ ++static int qca807x_gpio_get(struct gpio_chip *gc, unsigned int offset) ++{ ++ struct qca807x_gpio_priv *priv = gpiochip_get_data(gc); ++ u16 reg; ++ int val; ++ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(offset); ++ val = phy_read_mmd(priv->phy, MDIO_MMD_AN, reg); ++ ++ return FIELD_GET(QCA807X_GPIO_FORCE_MODE_MASK, val); ++} ++ ++static void qca807x_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) ++{ ++ struct qca807x_gpio_priv *priv = gpiochip_get_data(gc); ++ u16 reg; ++ int val; ++ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(offset); ++ ++ val = phy_read_mmd(priv->phy, MDIO_MMD_AN, reg); ++ val &= ~QCA807X_GPIO_FORCE_MODE_MASK; ++ val |= QCA807X_GPIO_FORCE_EN; ++ val |= FIELD_PREP(QCA807X_GPIO_FORCE_MODE_MASK, value); ++ ++ phy_write_mmd(priv->phy, MDIO_MMD_AN, reg, val); ++} ++ ++static int qca807x_gpio_dir_out(struct gpio_chip *gc, unsigned int offset, int value) ++{ ++ qca807x_gpio_set(gc, offset, value); ++ ++ return 0; ++} ++ ++static int qca807x_gpio(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct qca807x_gpio_priv *priv; ++ struct gpio_chip *gc; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->phy = phydev; ++ ++ gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); ++ if (!gc) ++ return -ENOMEM; ++ ++ gc->label = dev_name(dev); ++ gc->base = -1; ++ gc->ngpio = 2; ++ gc->parent = dev; ++ gc->owner = THIS_MODULE; ++ gc->can_sleep = true; ++ gc->get_direction = qca807x_gpio_get_direction; ++ gc->direction_output = qca807x_gpio_dir_out; ++ gc->get = qca807x_gpio_get; ++ gc->set = qca807x_gpio_set; ++ ++ return devm_gpiochip_add_data(dev, gc, priv); ++} ++#endif ++ ++static int qca807x_read_fiber_status(struct phy_device *phydev) ++{ ++ bool changed; ++ int ss, err; ++ ++ err = genphy_c37_read_status(phydev, &changed); ++ if (err || !changed) ++ return err; ++ ++ /* Read the QCA807x PHY-Specific Status register fiber page, ++ * which indicates the speed and duplex that the PHY is actually ++ * using, irrespective of whether we are in autoneg mode or not. ++ */ ++ ss = phy_read(phydev, AT803X_SPECIFIC_STATUS); ++ if (ss < 0) ++ return ss; ++ ++ phydev->speed = SPEED_UNKNOWN; ++ phydev->duplex = DUPLEX_UNKNOWN; ++ if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) { ++ switch (FIELD_GET(AT803X_SS_SPEED_MASK, ss)) { ++ case AT803X_SS_SPEED_100: ++ phydev->speed = SPEED_100; ++ break; ++ case AT803X_SS_SPEED_1000: ++ phydev->speed = SPEED_1000; ++ break; ++ } ++ ++ if (ss & AT803X_SS_DUPLEX) ++ phydev->duplex = DUPLEX_FULL; ++ else ++ phydev->duplex = DUPLEX_HALF; ++ } ++ ++ return 0; ++} ++ ++static int qca807x_read_status(struct phy_device *phydev) ++{ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported)) { ++ switch (phydev->port) { ++ case PORT_FIBRE: ++ return qca807x_read_fiber_status(phydev); ++ case PORT_TP: ++ return at803x_read_status(phydev); ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ return at803x_read_status(phydev); ++} ++ ++static int qca807x_phy_package_probe_once(struct phy_device *phydev) ++{ ++ struct phy_package_shared *shared = phydev->shared; ++ struct qca807x_shared_priv *priv = shared->priv; ++ unsigned int tx_drive_strength; ++ const char *package_mode_name; ++ ++ /* Default to 600mw if not defined */ ++ if (of_property_read_u32(shared->np, "qcom,tx-drive-strength-milliwatt", ++ &tx_drive_strength)) ++ tx_drive_strength = 600; ++ ++ switch (tx_drive_strength) { ++ case 140: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_140MV; ++ break; ++ case 160: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_160MV; ++ break; ++ case 180: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_180MV; ++ break; ++ case 200: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_200MV; ++ break; ++ case 220: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_220MV; ++ break; ++ case 240: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_240MV; ++ break; ++ case 260: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_260MV; ++ break; ++ case 280: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_280MV; ++ break; ++ case 300: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_300MV; ++ break; ++ case 320: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_320MV; ++ break; ++ case 400: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_400MV; ++ break; ++ case 500: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_500MV; ++ break; ++ case 600: ++ priv->tx_drive_strength = PQSGMII_TX_DRIVER_600MV; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ priv->package_mode = PHY_INTERFACE_MODE_NA; ++ if (!of_property_read_string(shared->np, "qcom,package-mode", ++ &package_mode_name)) { ++ if (!strcasecmp(package_mode_name, ++ phy_modes(PHY_INTERFACE_MODE_PSGMII))) ++ priv->package_mode = PHY_INTERFACE_MODE_PSGMII; ++ else if (!strcasecmp(package_mode_name, ++ phy_modes(PHY_INTERFACE_MODE_QSGMII))) ++ priv->package_mode = PHY_INTERFACE_MODE_QSGMII; ++ else ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int qca807x_phy_package_config_init_once(struct phy_device *phydev) ++{ ++ struct phy_package_shared *shared = phydev->shared; ++ struct qca807x_shared_priv *priv = shared->priv; ++ int val, ret; ++ ++ phy_lock_mdio_bus(phydev); ++ ++ /* Set correct PHY package mode */ ++ val = __phy_package_read(phydev, QCA807X_COMBO_ADDR, ++ QCA807X_CHIP_CONFIGURATION); ++ val &= ~QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK; ++ /* package_mode can be QSGMII or PSGMII and we validate ++ * this in probe_once. ++ * With package_mode to NA, we default to PSGMII. ++ */ ++ switch (priv->package_mode) { ++ case PHY_INTERFACE_MODE_QSGMII: ++ val |= QCA807X_CHIP_CONFIGURATION_MODE_QSGMII_SGMII; ++ break; ++ case PHY_INTERFACE_MODE_PSGMII: ++ default: ++ val |= QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_ALL_COPPER; ++ } ++ ret = __phy_package_write(phydev, QCA807X_COMBO_ADDR, ++ QCA807X_CHIP_CONFIGURATION, val); ++ if (ret) ++ goto exit; ++ ++ /* After mode change Serdes reset is required */ ++ val = __phy_package_read(phydev, QCA807X_PQSGMII_ADDR, ++ PQSGMII_CTRL_REG); ++ val &= ~PQSGMII_ANALOG_SW_RESET; ++ ret = __phy_package_write(phydev, QCA807X_PQSGMII_ADDR, ++ PQSGMII_CTRL_REG, val); ++ if (ret) ++ goto exit; ++ ++ msleep(SERDES_RESET_SLEEP); ++ ++ val = __phy_package_read(phydev, QCA807X_PQSGMII_ADDR, ++ PQSGMII_CTRL_REG); ++ val |= PQSGMII_ANALOG_SW_RESET; ++ ret = __phy_package_write(phydev, QCA807X_PQSGMII_ADDR, ++ PQSGMII_CTRL_REG, val); ++ if (ret) ++ goto exit; ++ ++ /* Workaround to enable AZ transmitting ability */ ++ val = __phy_package_read_mmd(phydev, QCA807X_PQSGMII_ADDR, ++ MDIO_MMD_PMAPMD, PQSGMII_MODE_CTRL); ++ val &= ~PQSGMII_MODE_CTRL_AZ_WORKAROUND_MASK; ++ ret = __phy_package_write_mmd(phydev, QCA807X_PQSGMII_ADDR, ++ MDIO_MMD_PMAPMD, PQSGMII_MODE_CTRL, val); ++ if (ret) ++ goto exit; ++ ++ /* Set PQSGMII TX AMP strength */ ++ val = __phy_package_read(phydev, QCA807X_PQSGMII_ADDR, ++ PQSGMII_DRIVE_CONTROL_1); ++ val &= ~PQSGMII_TX_DRIVER_MASK; ++ val |= FIELD_PREP(PQSGMII_TX_DRIVER_MASK, priv->tx_drive_strength); ++ ret = __phy_package_write(phydev, QCA807X_PQSGMII_ADDR, ++ PQSGMII_DRIVE_CONTROL_1, val); ++ if (ret) ++ goto exit; ++ ++ /* Prevent PSGMII going into hibernation via PSGMII self test */ ++ val = __phy_package_read_mmd(phydev, QCA807X_COMBO_ADDR, ++ MDIO_MMD_PCS, PQSGMII_MMD3_SERDES_CONTROL); ++ val &= ~BIT(1); ++ ret = __phy_package_write_mmd(phydev, QCA807X_COMBO_ADDR, ++ MDIO_MMD_PCS, PQSGMII_MMD3_SERDES_CONTROL, val); ++ ++exit: ++ phy_unlock_mdio_bus(phydev); ++ ++ return ret; ++} ++ ++static int qca807x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++{ ++ struct phy_device *phydev = upstream; ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, }; ++ phy_interface_t iface; ++ int ret; ++ DECLARE_PHY_INTERFACE_MASK(interfaces); ++ ++ sfp_parse_support(phydev->sfp_bus, id, support, interfaces); ++ iface = sfp_select_interface(phydev->sfp_bus, support); ++ ++ dev_info(&phydev->mdio.dev, "%s SFP module inserted\n", phy_modes(iface)); ++ ++ switch (iface) { ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_100BASEX: ++ /* Set PHY mode to PSGMII combo (1/4 copper + combo ports) mode */ ++ ret = phy_modify(phydev, ++ QCA807X_CHIP_CONFIGURATION, ++ QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK, ++ QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_FIBER); ++ /* Enable fiber mode autodection (1000Base-X or 100Base-FX) */ ++ ret = phy_set_bits_mmd(phydev, ++ MDIO_MMD_AN, ++ QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION, ++ QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION_EN); ++ /* Select fiber page */ ++ ret = phy_clear_bits(phydev, ++ QCA807X_CHIP_CONFIGURATION, ++ QCA807X_BT_BX_REG_SEL); ++ ++ phydev->port = PORT_FIBRE; ++ break; ++ default: ++ dev_err(&phydev->mdio.dev, "Incompatible SFP module inserted\n"); ++ return -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static void qca807x_sfp_remove(void *upstream) ++{ ++ struct phy_device *phydev = upstream; ++ ++ /* Select copper page */ ++ phy_set_bits(phydev, ++ QCA807X_CHIP_CONFIGURATION, ++ QCA807X_BT_BX_REG_SEL); ++ ++ phydev->port = PORT_TP; ++} ++ ++static const struct sfp_upstream_ops qca807x_sfp_ops = { ++ .attach = phy_sfp_attach, ++ .detach = phy_sfp_detach, ++ .module_insert = qca807x_sfp_insert, ++ .module_remove = qca807x_sfp_remove, ++}; ++ ++static int qca807x_probe(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ struct qca807x_shared_priv *shared_priv; ++ struct device *dev = &phydev->mdio.dev; ++ struct phy_package_shared *shared; ++ struct qca807x_priv *priv; ++ int ret; ++ ++ ret = devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv)); ++ if (ret) ++ return ret; ++ ++ if (phy_package_probe_once(phydev)) { ++ ret = qca807x_phy_package_probe_once(phydev); ++ if (ret) ++ return ret; ++ } ++ ++ shared = phydev->shared; ++ shared_priv = shared->priv; ++ ++ /* Make sure PHY follow PHY package mode if enforced */ ++ if (shared_priv->package_mode != PHY_INTERFACE_MODE_NA && ++ phydev->interface != shared_priv->package_mode) ++ return -EINVAL; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->dac_full_amplitude = of_property_read_bool(node, "qcom,dac-full-amplitude"); ++ priv->dac_full_bias_current = of_property_read_bool(node, "qcom,dac-full-bias-current"); ++ priv->dac_disable_bias_current_tweak = of_property_read_bool(node, ++ "qcom,dac-disable-bias-current-tweak"); ++ ++ if (IS_ENABLED(CONFIG_GPIOLIB)) { ++ /* Do not register a GPIO controller unless flagged for it */ ++ if (of_property_read_bool(node, "gpio-controller")) { ++ ret = qca807x_gpio(phydev); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ /* Attach SFP bus on combo port*/ ++ if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) { ++ ret = phy_sfp_probe(phydev, &qca807x_sfp_ops); ++ if (ret) ++ return ret; ++ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->advertising); ++ } ++ ++ phydev->priv = priv; ++ ++ return 0; ++} ++ ++static int qca807x_config_init(struct phy_device *phydev) ++{ ++ struct qca807x_priv *priv = phydev->priv; ++ u16 control_dac; ++ int ret; ++ ++ if (phy_package_init_once(phydev)) { ++ ret = qca807x_phy_package_config_init_once(phydev); ++ if (ret) ++ return ret; ++ } ++ ++ control_dac = phy_read_mmd(phydev, MDIO_MMD_AN, ++ QCA807X_MMD7_1000BASE_T_POWER_SAVE_PER_CABLE_LENGTH); ++ control_dac &= ~QCA807X_CONTROL_DAC_MASK; ++ if (!priv->dac_full_amplitude) ++ control_dac |= QCA807X_CONTROL_DAC_DSP_AMPLITUDE; ++ if (!priv->dac_full_amplitude) ++ control_dac |= QCA807X_CONTROL_DAC_DSP_BIAS_CURRENT; ++ if (!priv->dac_disable_bias_current_tweak) ++ control_dac |= QCA807X_CONTROL_DAC_BIAS_CURRENT_TWEAK; ++ return phy_write_mmd(phydev, MDIO_MMD_AN, ++ QCA807X_MMD7_1000BASE_T_POWER_SAVE_PER_CABLE_LENGTH, ++ control_dac); ++} ++ ++static struct phy_driver qca807x_drivers[] = { ++ { ++ PHY_ID_MATCH_EXACT(PHY_ID_QCA8072), ++ .name = "Qualcomm QCA8072", ++ .flags = PHY_POLL_CABLE_TEST, ++ /* PHY_GBIT_FEATURES */ ++ .probe = qca807x_probe, ++ .config_init = qca807x_config_init, ++ .read_status = qca807x_read_status, ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .soft_reset = genphy_soft_reset, ++ .get_tunable = at803x_get_tunable, ++ .set_tunable = at803x_set_tunable, ++ .resume = genphy_resume, ++ .suspend = genphy_suspend, ++ .cable_test_start = qca807x_cable_test_start, ++ .cable_test_get_status = qca808x_cable_test_get_status, ++ }, ++ { ++ PHY_ID_MATCH_EXACT(PHY_ID_QCA8075), ++ .name = "Qualcomm QCA8075", ++ .flags = PHY_POLL_CABLE_TEST, ++ /* PHY_GBIT_FEATURES */ ++ .probe = qca807x_probe, ++ .config_init = qca807x_config_init, ++ .read_status = qca807x_read_status, ++ .config_intr = at803x_config_intr, ++ .handle_interrupt = at803x_handle_interrupt, ++ .soft_reset = genphy_soft_reset, ++ .get_tunable = at803x_get_tunable, ++ .set_tunable = at803x_set_tunable, ++ .resume = genphy_resume, ++ .suspend = genphy_suspend, ++ .cable_test_start = qca807x_cable_test_start, ++ .cable_test_get_status = qca808x_cable_test_get_status, ++ }, ++}; ++module_phy_driver(qca807x_drivers); ++ ++static struct mdio_device_id __maybe_unused qca807x_tbl[] = { ++ { PHY_ID_MATCH_EXACT(PHY_ID_QCA8072) }, ++ { PHY_ID_MATCH_EXACT(PHY_ID_QCA8075) }, ++ { } ++}; ++ ++MODULE_AUTHOR("Robert Marko "); ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_DESCRIPTION("Qualcomm QCA807x PHY driver"); ++MODULE_DEVICE_TABLE(mdio, qca807x_tbl); ++MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/generic/backport-6.1/716-v6.9-08-net-phy-qcom-move-common-qca808x-LED-define-to-share.patch b/lede/target/linux/generic/backport-6.1/716-v6.9-08-net-phy-qcom-move-common-qca808x-LED-define-to-share.patch new file mode 100644 index 0000000000..cf4d74e8c5 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/716-v6.9-08-net-phy-qcom-move-common-qca808x-LED-define-to-share.patch @@ -0,0 +1,179 @@ +From ee9d9807bee0e6af8ca2a4db6f0d1dc0e5b41f44 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 6 Feb 2024 18:31:11 +0100 +Subject: [PATCH 08/10] net: phy: qcom: move common qca808x LED define to + shared header + +The LED implementation of qca808x and qca807x is the same but qca807x +supports also Fiber port and have different hw control bits for Fiber +port. + +In preparation for qca807x introduction, move all the common define to +shared header. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca808x.c | 65 ---------------------------------- + drivers/net/phy/qcom/qcom.h | 65 ++++++++++++++++++++++++++++++++++ + 2 files changed, 65 insertions(+), 65 deletions(-) + +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -62,29 +62,6 @@ + #define QCA808X_DBG_AN_TEST 0xb + #define QCA808X_HIBERNATION_EN BIT(15) + +-#define QCA808X_MMD7_LED_GLOBAL 0x8073 +-#define QCA808X_LED_BLINK_1 GENMASK(11, 6) +-#define QCA808X_LED_BLINK_2 GENMASK(5, 0) +-/* Values are the same for both BLINK_1 and BLINK_2 */ +-#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3) +-#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0) +-#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1) +-#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2) +-#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3) +-#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4) +-#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5) +-#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6) +-#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7) +-#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0) +-#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0) +-#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1) +-#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2) +-#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3) +-#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4) +-#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5) +-#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6) +-#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7) +- + #define QCA808X_MMD7_LED2_CTRL 0x8074 + #define QCA808X_MMD7_LED2_FORCE_CTRL 0x8075 + #define QCA808X_MMD7_LED1_CTRL 0x8076 +@@ -92,51 +69,9 @@ + #define QCA808X_MMD7_LED0_CTRL 0x8078 + #define QCA808X_MMD7_LED_CTRL(x) (0x8078 - ((x) * 2)) + +-/* LED hw control pattern is the same for every LED */ +-#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) +-#define QCA808X_LED_SPEED2500_ON BIT(15) +-#define QCA808X_LED_SPEED2500_BLINK BIT(14) +-/* Follow blink trigger even if duplex or speed condition doesn't match */ +-#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) +-#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) +-#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) +-#define QCA808X_LED_TX_BLINK BIT(10) +-#define QCA808X_LED_RX_BLINK BIT(9) +-#define QCA808X_LED_TX_ON_10MS BIT(8) +-#define QCA808X_LED_RX_ON_10MS BIT(7) +-#define QCA808X_LED_SPEED1000_ON BIT(6) +-#define QCA808X_LED_SPEED100_ON BIT(5) +-#define QCA808X_LED_SPEED10_ON BIT(4) +-#define QCA808X_LED_COLLISION_BLINK BIT(3) +-#define QCA808X_LED_SPEED1000_BLINK BIT(2) +-#define QCA808X_LED_SPEED100_BLINK BIT(1) +-#define QCA808X_LED_SPEED10_BLINK BIT(0) +- + #define QCA808X_MMD7_LED0_FORCE_CTRL 0x8079 + #define QCA808X_MMD7_LED_FORCE_CTRL(x) (0x8079 - ((x) * 2)) + +-/* LED force ctrl is the same for every LED +- * No documentation exist for this, not even internal one +- * with NDA as QCOM gives only info about configuring +- * hw control pattern rules and doesn't indicate any way +- * to force the LED to specific mode. +- * These define comes from reverse and testing and maybe +- * lack of some info or some info are not entirely correct. +- * For the basic LED control and hw control these finding +- * are enough to support LED control in all the required APIs. +- * +- * On doing some comparison with implementation with qca807x, +- * it was found that it's 1:1 equal to it and confirms all the +- * reverse done. It was also found further specification with the +- * force mode and the blink modes. +- */ +-#define QCA808X_LED_FORCE_EN BIT(15) +-#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13) +-#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3) +-#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2) +-#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1) +-#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0) +- + #define QCA808X_MMD7_LED_POLARITY_CTRL 0x901a + /* QSDK sets by default 0x46 to this reg that sets BIT 6 for + * LED to active high. It's not clear what BIT 3 and BIT 4 does. +--- a/drivers/net/phy/qcom/qcom.h ++++ b/drivers/net/phy/qcom/qcom.h +@@ -103,6 +103,71 @@ + /* Added for reference of existence but should be handled by wait_for_completion already */ + #define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) + ++#define QCA808X_MMD7_LED_GLOBAL 0x8073 ++#define QCA808X_LED_BLINK_1 GENMASK(11, 6) ++#define QCA808X_LED_BLINK_2 GENMASK(5, 0) ++/* Values are the same for both BLINK_1 and BLINK_2 */ ++#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3) ++#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0) ++#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1) ++#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2) ++#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3) ++#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4) ++#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5) ++#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6) ++#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7) ++#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0) ++#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0) ++#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1) ++#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2) ++#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3) ++#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4) ++#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5) ++#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6) ++#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7) ++ ++/* LED hw control pattern is the same for every LED */ ++#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) ++#define QCA808X_LED_SPEED2500_ON BIT(15) ++#define QCA808X_LED_SPEED2500_BLINK BIT(14) ++/* Follow blink trigger even if duplex or speed condition doesn't match */ ++#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) ++#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) ++#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) ++#define QCA808X_LED_TX_BLINK BIT(10) ++#define QCA808X_LED_RX_BLINK BIT(9) ++#define QCA808X_LED_TX_ON_10MS BIT(8) ++#define QCA808X_LED_RX_ON_10MS BIT(7) ++#define QCA808X_LED_SPEED1000_ON BIT(6) ++#define QCA808X_LED_SPEED100_ON BIT(5) ++#define QCA808X_LED_SPEED10_ON BIT(4) ++#define QCA808X_LED_COLLISION_BLINK BIT(3) ++#define QCA808X_LED_SPEED1000_BLINK BIT(2) ++#define QCA808X_LED_SPEED100_BLINK BIT(1) ++#define QCA808X_LED_SPEED10_BLINK BIT(0) ++ ++/* LED force ctrl is the same for every LED ++ * No documentation exist for this, not even internal one ++ * with NDA as QCOM gives only info about configuring ++ * hw control pattern rules and doesn't indicate any way ++ * to force the LED to specific mode. ++ * These define comes from reverse and testing and maybe ++ * lack of some info or some info are not entirely correct. ++ * For the basic LED control and hw control these finding ++ * are enough to support LED control in all the required APIs. ++ * ++ * On doing some comparison with implementation with qca807x, ++ * it was found that it's 1:1 equal to it and confirms all the ++ * reverse done. It was also found further specification with the ++ * force mode and the blink modes. ++ */ ++#define QCA808X_LED_FORCE_EN BIT(15) ++#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13) ++#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3) ++#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2) ++#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1) ++#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0) ++ + #define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C + #define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B + #define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A diff --git a/lede/target/linux/generic/backport-6.1/716-v6.9-09-net-phy-qcom-generalize-some-qca808x-LED-functions.patch b/lede/target/linux/generic/backport-6.1/716-v6.9-09-net-phy-qcom-generalize-some-qca808x-LED-functions.patch new file mode 100644 index 0000000000..da73c1d3b8 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/716-v6.9-09-net-phy-qcom-generalize-some-qca808x-LED-functions.patch @@ -0,0 +1,172 @@ +From 47b930d0dd437af927145dba50a2e2ea1ba97c67 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 6 Feb 2024 18:31:12 +0100 +Subject: [PATCH 09/10] net: phy: qcom: generalize some qca808x LED functions + +Generalize some qca808x LED functions in preparation for qca807x LED +support. + +The LED implementation of qca808x and qca807x is the same but qca807x +supports also Fiber port and have different hw control bits for Fiber +port. To limit code duplication introduce micro functions that takes reg +instead of LED index to tweak all the supported LED modes. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca808x.c | 38 +++----------------- + drivers/net/phy/qcom/qcom-phy-lib.c | 54 +++++++++++++++++++++++++++++ + drivers/net/phy/qcom/qcom.h | 7 ++++ + 3 files changed, 65 insertions(+), 34 deletions(-) + +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -437,9 +437,7 @@ static int qca808x_led_hw_control_enable + return -EINVAL; + + reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN); ++ return qca808x_led_reg_hw_control_enable(phydev, reg); + } + + static int qca808x_led_hw_is_supported(struct phy_device *phydev, u8 index, +@@ -480,16 +478,12 @@ static int qca808x_led_hw_control_set(st + static bool qca808x_led_hw_control_status(struct phy_device *phydev, u8 index) + { + u16 reg; +- int val; + + if (index > 2) + return false; + + reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); +- +- return !(val & QCA808X_LED_FORCE_EN); ++ return qca808x_led_reg_hw_control_status(phydev, reg); + } + + static int qca808x_led_hw_control_get(struct phy_device *phydev, u8 index, +@@ -557,44 +551,20 @@ static int qca808x_led_brightness_set(st + } + + reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, +- QCA808X_LED_FORCE_EN | (value ? QCA808X_LED_FORCE_ON : +- QCA808X_LED_FORCE_OFF)); ++ return qca808x_led_reg_brightness_set(phydev, reg, value); + } + + static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, + unsigned long *delay_on, + unsigned long *delay_off) + { +- int ret; + u16 reg; + + if (index > 2) + return -EINVAL; + + reg = QCA808X_MMD7_LED_FORCE_CTRL(index); +- +- /* Set blink to 50% off, 50% on at 4Hz by default */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL, +- QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK, +- QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50); +- if (ret) +- return ret; +- +- /* We use BLINK_1 for normal blinking */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, +- QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1); +- if (ret) +- return ret; +- +- /* We set blink to 4Hz, aka 250ms */ +- *delay_on = 250 / 2; +- *delay_off = 250 / 2; +- +- return 0; ++ return qca808x_led_reg_blink_set(phydev, reg, delay_on, delay_off); + } + + static int qca808x_led_polarity_set(struct phy_device *phydev, int index, +--- a/drivers/net/phy/qcom/qcom-phy-lib.c ++++ b/drivers/net/phy/qcom/qcom-phy-lib.c +@@ -620,3 +620,57 @@ int qca808x_cable_test_get_status(struct + return 0; + } + EXPORT_SYMBOL_GPL(qca808x_cable_test_get_status); ++ ++int qca808x_led_reg_hw_control_enable(struct phy_device *phydev, u16 reg) ++{ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN); ++} ++EXPORT_SYMBOL_GPL(qca808x_led_reg_hw_control_enable); ++ ++bool qca808x_led_reg_hw_control_status(struct phy_device *phydev, u16 reg) ++{ ++ int val; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ return !(val & QCA808X_LED_FORCE_EN); ++} ++EXPORT_SYMBOL_GPL(qca808x_led_reg_hw_control_status); ++ ++int qca808x_led_reg_brightness_set(struct phy_device *phydev, ++ u16 reg, enum led_brightness value) ++{ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | (value ? QCA808X_LED_FORCE_ON : ++ QCA808X_LED_FORCE_OFF)); ++} ++EXPORT_SYMBOL_GPL(qca808x_led_reg_brightness_set); ++ ++int qca808x_led_reg_blink_set(struct phy_device *phydev, u16 reg, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ int ret; ++ ++ /* Set blink to 50% off, 50% on at 4Hz by default */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL, ++ QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK, ++ QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50); ++ if (ret) ++ return ret; ++ ++ /* We use BLINK_1 for normal blinking */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK, ++ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1); ++ if (ret) ++ return ret; ++ ++ /* We set blink to 4Hz, aka 250ms */ ++ *delay_on = 250 / 2; ++ *delay_off = 250 / 2; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(qca808x_led_reg_blink_set); +--- a/drivers/net/phy/qcom/qcom.h ++++ b/drivers/net/phy/qcom/qcom.h +@@ -234,3 +234,10 @@ int at803x_cdt_start(struct phy_device * + int at803x_cdt_wait_for_completion(struct phy_device *phydev, + u32 cdt_en); + int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished); ++int qca808x_led_reg_hw_control_enable(struct phy_device *phydev, u16 reg); ++bool qca808x_led_reg_hw_control_status(struct phy_device *phydev, u16 reg); ++int qca808x_led_reg_brightness_set(struct phy_device *phydev, ++ u16 reg, enum led_brightness value); ++int qca808x_led_reg_blink_set(struct phy_device *phydev, u16 reg, ++ unsigned long *delay_on, ++ unsigned long *delay_off); diff --git a/lede/target/linux/generic/backport-6.1/716-v6.9-10-net-phy-qca807x-add-support-for-configurable-LED.patch b/lede/target/linux/generic/backport-6.1/716-v6.9-10-net-phy-qca807x-add-support-for-configurable-LED.patch new file mode 100644 index 0000000000..3bd36f6ffe --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/716-v6.9-10-net-phy-qca807x-add-support-for-configurable-LED.patch @@ -0,0 +1,326 @@ +From f508a226b517a6a8afd78a317de46bc83e3e3d51 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 6 Feb 2024 18:31:13 +0100 +Subject: [PATCH 10/10] net: phy: qca807x: add support for configurable LED + +QCA8072/5 have up to 2 LEDs attached for PHY. + +LEDs can be configured to be ON/hw blink or be set to HW control. + +Hw blink mode is set to blink at 4Hz or 250ms. + +PHY can support both copper (TP) or fiber (FIBRE) kind and supports +different HW control modes based on the port type. + +HW control modes supported for netdev trigger for copper ports are: +- LINK_10 +- LINK_100 +- LINK_1000 +- TX +- RX +- FULL_DUPLEX +- HALF_DUPLEX + +HW control modes supported for netdev trigger for fiber ports are: +- LINK_100 +- LINK_1000 +- TX +- RX +- FULL_DUPLEX +- HALF_DUPLEX + +LED support conflicts with GPIO controller feature and must be disabled +if gpio-controller is used for the PHY. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca807x.c | 256 ++++++++++++++++++++++++++++++++- + 1 file changed, 254 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/qcom/qca807x.c ++++ b/drivers/net/phy/qcom/qca807x.c +@@ -57,8 +57,18 @@ + #define QCA807X_MMD7_LED_CTRL(x) (0x8074 + ((x) * 2)) + #define QCA807X_MMD7_LED_FORCE_CTRL(x) (0x8075 + ((x) * 2)) + +-#define QCA807X_GPIO_FORCE_EN BIT(15) +-#define QCA807X_GPIO_FORCE_MODE_MASK GENMASK(14, 13) ++/* LED hw control pattern for fiber port */ ++#define QCA807X_LED_FIBER_PATTERN_MASK GENMASK(11, 1) ++#define QCA807X_LED_FIBER_TXACT_BLK_EN BIT(10) ++#define QCA807X_LED_FIBER_RXACT_BLK_EN BIT(9) ++#define QCA807X_LED_FIBER_FDX_ON_EN BIT(6) ++#define QCA807X_LED_FIBER_HDX_ON_EN BIT(5) ++#define QCA807X_LED_FIBER_1000BX_ON_EN BIT(2) ++#define QCA807X_LED_FIBER_100FX_ON_EN BIT(1) ++ ++/* Some device repurpose the LED as GPIO out */ ++#define QCA807X_GPIO_FORCE_EN QCA808X_LED_FORCE_EN ++#define QCA807X_GPIO_FORCE_MODE_MASK QCA808X_LED_FORCE_MODE_MASK + + #define QCA807X_FUNCTION_CONTROL 0x10 + #define QCA807X_FC_MDI_CROSSOVER_MODE_MASK GENMASK(6, 5) +@@ -121,6 +131,233 @@ static int qca807x_cable_test_start(stru + return 0; + } + ++static int qca807x_led_parse_netdev(struct phy_device *phydev, unsigned long rules, ++ u16 *offload_trigger) ++{ ++ /* Parsing specific to netdev trigger */ ++ switch (phydev->port) { ++ case PORT_TP: ++ if (test_bit(TRIGGER_NETDEV_TX, &rules)) ++ *offload_trigger |= QCA808X_LED_TX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_RX, &rules)) ++ *offload_trigger |= QCA808X_LED_RX_BLINK; ++ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED10_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED100_ON; ++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ *offload_trigger |= QCA808X_LED_SPEED1000_ON; ++ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_HALF_DUPLEX_ON; ++ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) ++ *offload_trigger |= QCA808X_LED_FULL_DUPLEX_ON; ++ break; ++ case PORT_FIBRE: ++ if (test_bit(TRIGGER_NETDEV_TX, &rules)) ++ *offload_trigger |= QCA807X_LED_FIBER_TXACT_BLK_EN; ++ if (test_bit(TRIGGER_NETDEV_RX, &rules)) ++ *offload_trigger |= QCA807X_LED_FIBER_RXACT_BLK_EN; ++ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ *offload_trigger |= QCA807X_LED_FIBER_100FX_ON_EN; ++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ *offload_trigger |= QCA807X_LED_FIBER_1000BX_ON_EN; ++ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) ++ *offload_trigger |= QCA807X_LED_FIBER_HDX_ON_EN; ++ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) ++ *offload_trigger |= QCA807X_LED_FIBER_FDX_ON_EN; ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ if (rules && !*offload_trigger) ++ return -EOPNOTSUPP; ++ ++ return 0; ++} ++ ++static int qca807x_led_hw_control_enable(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(index); ++ return qca808x_led_reg_hw_control_enable(phydev, reg); ++} ++ ++static int qca807x_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 offload_trigger = 0; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ return qca807x_led_parse_netdev(phydev, rules, &offload_trigger); ++} ++ ++static int qca807x_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 reg, mask, offload_trigger = 0; ++ int ret; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ ret = qca807x_led_parse_netdev(phydev, rules, &offload_trigger); ++ if (ret) ++ return ret; ++ ++ ret = qca807x_led_hw_control_enable(phydev, index); ++ if (ret) ++ return ret; ++ ++ switch (phydev->port) { ++ case PORT_TP: ++ reg = QCA807X_MMD7_LED_CTRL(index); ++ mask = QCA808X_LED_PATTERN_MASK; ++ break; ++ case PORT_FIBRE: ++ /* HW control pattern bits are in LED FORCE reg */ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(index); ++ mask = QCA807X_LED_FIBER_PATTERN_MASK; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, mask, ++ offload_trigger); ++} ++ ++static bool qca807x_led_hw_control_status(struct phy_device *phydev, u8 index) ++{ ++ u16 reg; ++ ++ if (index > 1) ++ return false; ++ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(index); ++ return qca808x_led_reg_hw_control_status(phydev, reg); ++} ++ ++static int qca807x_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ u16 reg; ++ int val; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ /* Check if we have hw control enabled */ ++ if (qca807x_led_hw_control_status(phydev, index)) ++ return -EINVAL; ++ ++ /* Parsing specific to netdev trigger */ ++ switch (phydev->port) { ++ case PORT_TP: ++ reg = QCA807X_MMD7_LED_CTRL(index); ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ if (val & QCA808X_LED_TX_BLINK) ++ set_bit(TRIGGER_NETDEV_TX, rules); ++ if (val & QCA808X_LED_RX_BLINK) ++ set_bit(TRIGGER_NETDEV_RX, rules); ++ if (val & QCA808X_LED_SPEED10_ON) ++ set_bit(TRIGGER_NETDEV_LINK_10, rules); ++ if (val & QCA808X_LED_SPEED100_ON) ++ set_bit(TRIGGER_NETDEV_LINK_100, rules); ++ if (val & QCA808X_LED_SPEED1000_ON) ++ set_bit(TRIGGER_NETDEV_LINK_1000, rules); ++ if (val & QCA808X_LED_HALF_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); ++ if (val & QCA808X_LED_FULL_DUPLEX_ON) ++ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); ++ break; ++ case PORT_FIBRE: ++ /* HW control pattern bits are in LED FORCE reg */ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(index); ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); ++ if (val & QCA807X_LED_FIBER_TXACT_BLK_EN) ++ set_bit(TRIGGER_NETDEV_TX, rules); ++ if (val & QCA807X_LED_FIBER_RXACT_BLK_EN) ++ set_bit(TRIGGER_NETDEV_RX, rules); ++ if (val & QCA807X_LED_FIBER_100FX_ON_EN) ++ set_bit(TRIGGER_NETDEV_LINK_100, rules); ++ if (val & QCA807X_LED_FIBER_1000BX_ON_EN) ++ set_bit(TRIGGER_NETDEV_LINK_1000, rules); ++ if (val & QCA807X_LED_FIBER_HDX_ON_EN) ++ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); ++ if (val & QCA807X_LED_FIBER_FDX_ON_EN) ++ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int qca807x_led_hw_control_reset(struct phy_device *phydev, u8 index) ++{ ++ u16 reg, mask; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ switch (phydev->port) { ++ case PORT_TP: ++ reg = QCA807X_MMD7_LED_CTRL(index); ++ mask = QCA808X_LED_PATTERN_MASK; ++ break; ++ case PORT_FIBRE: ++ /* HW control pattern bits are in LED FORCE reg */ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(index); ++ mask = QCA807X_LED_FIBER_PATTERN_MASK; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, mask); ++} ++ ++static int qca807x_led_brightness_set(struct phy_device *phydev, ++ u8 index, enum led_brightness value) ++{ ++ u16 reg; ++ int ret; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ /* If we are setting off the LED reset any hw control rule */ ++ if (!value) { ++ ret = qca807x_led_hw_control_reset(phydev, index); ++ if (ret) ++ return ret; ++ } ++ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(index); ++ return qca808x_led_reg_brightness_set(phydev, reg, value); ++} ++ ++static int qca807x_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ u16 reg; ++ ++ if (index > 1) ++ return -EINVAL; ++ ++ reg = QCA807X_MMD7_LED_FORCE_CTRL(index); ++ return qca808x_led_reg_blink_set(phydev, reg, delay_on, delay_off); ++} ++ + #ifdef CONFIG_GPIOLIB + static int qca807x_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) + { +@@ -496,6 +733,16 @@ static int qca807x_probe(struct phy_devi + "qcom,dac-disable-bias-current-tweak"); + + if (IS_ENABLED(CONFIG_GPIOLIB)) { ++ /* Make sure we don't have mixed leds node and gpio-controller ++ * to prevent registering leds and having gpio-controller usage ++ * conflicting with them. ++ */ ++ if (of_find_property(node, "leds", NULL) && ++ of_find_property(node, "gpio-controller", NULL)) { ++ phydev_err(phydev, "Invalid property detected. LEDs and gpio-controller are mutually exclusive."); ++ return -EINVAL; ++ } ++ + /* Do not register a GPIO controller unless flagged for it */ + if (of_property_read_bool(node, "gpio-controller")) { + ret = qca807x_gpio(phydev); +@@ -580,6 +827,11 @@ static struct phy_driver qca807x_drivers + .suspend = genphy_suspend, + .cable_test_start = qca807x_cable_test_start, + .cable_test_get_status = qca808x_cable_test_get_status, ++ .led_brightness_set = qca807x_led_brightness_set, ++ .led_blink_set = qca807x_led_blink_set, ++ .led_hw_is_supported = qca807x_led_hw_is_supported, ++ .led_hw_control_set = qca807x_led_hw_control_set, ++ .led_hw_control_get = qca807x_led_hw_control_get, + }, + }; + module_phy_driver(qca807x_drivers); diff --git a/lede/target/linux/generic/backport-6.1/717-v6.9-net-phy-qca807x-move-interface-mode-check-to-.config.patch b/lede/target/linux/generic/backport-6.1/717-v6.9-net-phy-qca807x-move-interface-mode-check-to-.config.patch new file mode 100644 index 0000000000..53652c38fc --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/717-v6.9-net-phy-qca807x-move-interface-mode-check-to-.config.patch @@ -0,0 +1,51 @@ +From 3be0d950b62852a693182cb678948f481de02825 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 12 Feb 2024 12:49:34 +0100 +Subject: [PATCH] net: phy: qca807x: move interface mode check to + .config_init_once + +Currently, we are checking whether the PHY package mode matches the +individual PHY interface modes at PHY package probe time, but at that time +we only know the PHY package mode and not the individual PHY interface +modes as of_get_phy_mode() that populates it will only get called once the +netdev to which PHY-s are attached to is being probed and thus this check +will always fail and return -EINVAL. + +So, lets move this check to .config_init_once as at that point individual +PHY interface modes should be populated. + +Fixes: d1cb613efbd3 ("net: phy: qcom: add support for QCA807x PHY Family") +Signed-off-by: Robert Marko +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240212115043.1725918-1-robimarko@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/qcom/qca807x.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/qcom/qca807x.c ++++ b/drivers/net/phy/qcom/qca807x.c +@@ -562,6 +562,11 @@ static int qca807x_phy_package_config_in + struct qca807x_shared_priv *priv = shared->priv; + int val, ret; + ++ /* Make sure PHY follow PHY package mode if enforced */ ++ if (priv->package_mode != PHY_INTERFACE_MODE_NA && ++ phydev->interface != priv->package_mode) ++ return -EINVAL; ++ + phy_lock_mdio_bus(phydev); + + /* Set correct PHY package mode */ +@@ -718,11 +723,6 @@ static int qca807x_probe(struct phy_devi + shared = phydev->shared; + shared_priv = shared->priv; + +- /* Make sure PHY follow PHY package mode if enforced */ +- if (shared_priv->package_mode != PHY_INTERFACE_MODE_NA && +- phydev->interface != shared_priv->package_mode) +- return -EINVAL; +- + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; diff --git a/lede/target/linux/generic/backport-6.1/718-v6.9-net-phy-qcom-at803x-fix-kernel-panic-with-at8031_pro.patch b/lede/target/linux/generic/backport-6.1/718-v6.9-net-phy-qcom-at803x-fix-kernel-panic-with-at8031_pro.patch new file mode 100644 index 0000000000..9b9ce2a3cd --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/718-v6.9-net-phy-qcom-at803x-fix-kernel-panic-with-at8031_pro.patch @@ -0,0 +1,45 @@ +From 6a4aee277740d04ac0fd54cfa17cc28261932ddc Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 25 Mar 2024 20:06:19 +0100 +Subject: [PATCH] net: phy: qcom: at803x: fix kernel panic with at8031_probe + +On reworking and splitting the at803x driver, in splitting function of +at803x PHYs it was added a NULL dereference bug where priv is referenced +before it's actually allocated and then is tried to write to for the +is_1000basex and is_fiber variables in the case of at8031, writing on +the wrong address. + +Fix this by correctly setting priv local variable only after +at803x_probe is called and actually allocates priv in the phydev struct. + +Reported-by: William Wortel +Cc: +Fixes: 25d2ba94005f ("net: phy: at803x: move specific at8031 probe mode check to dedicated probe") +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240325190621.2665-1-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/qcom/at803x.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/qcom/at803x.c ++++ b/drivers/net/phy/qcom/at803x.c +@@ -797,7 +797,7 @@ static int at8031_parse_dt(struct phy_de + + static int at8031_probe(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; ++ struct at803x_priv *priv; + int mode_cfg; + int ccr; + int ret; +@@ -806,6 +806,8 @@ static int at8031_probe(struct phy_devic + if (ret) + return ret; + ++ priv = phydev->priv; ++ + /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping + * options. + */ diff --git a/lede/target/linux/generic/backport-6.1/720-v6.9-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch b/lede/target/linux/generic/backport-6.1/720-v6.9-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch new file mode 100644 index 0000000000..e6a240dbda --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/720-v6.9-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch @@ -0,0 +1,205 @@ +From bdce82e960d1205d118662f575cec39379984e34 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 31 Jan 2024 03:26:04 +0100 +Subject: [PATCH] net: mdio: ipq4019: add support for clock-frequency property + +The IPQ4019 MDIO internally divide the clock feed by AHB based on the +MDIO_MODE reg. On reset or power up, the default value for the +divider is 0xff that reflect the divider set to /256. + +This makes the MDC run at a very low rate, that is, considering AHB is +always fixed to 100Mhz, a value of 390KHz. + +This hasn't have been a problem as MDIO wasn't used for time sensitive +operation, it is now that on IPQ807x is usually mounted with PHY that +requires MDIO to load their firmware (example Aquantia PHY). + +To handle this problem and permit to set the correct designed MDC +frequency for the SoC add support for the standard "clock-frequency" +property for the MDIO node. + +The divider supports value from /1 to /256 and the common value are to +set it to /16 to reflect 6.25Mhz or to /8 on newer platform to reflect +12.5Mhz. + +To scan if the requested rate is supported by the divider, loop with +each supported divider and stop when the requested rate match the final +rate with the current divider. An error is returned if the rate doesn't +match any value. + +On MDIO reset, the divider is restored to the requested value to prevent +any kind of downclocking caused by the divider reverting to a default +value. + +To follow 802.3 spec of 2.5MHz of default value, if divider is set at +/256 and "clock-frequency" is not set in DT, assume nobody set the +divider and try to find the closest MDC rate to 2.5MHz. (in the case of +AHB set to 100MHz, it's 1.5625MHz) + +While at is also document other bits of the MDIO_MODE reg to have a +clear idea of what is actually applied there. + +Documentation of some BITs is skipped as they are marked as reserved and +their usage is not clear (RES 11:9 GENPHY 16:13 RES1 19:17) + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/mdio/mdio-ipq4019.c | 109 ++++++++++++++++++++++++++++++-- + 1 file changed, 103 insertions(+), 6 deletions(-) + +--- a/drivers/net/mdio/mdio-ipq4019.c ++++ b/drivers/net/mdio/mdio-ipq4019.c +@@ -14,6 +14,20 @@ + #include + + #define MDIO_MODE_REG 0x40 ++#define MDIO_MODE_MDC_MODE BIT(12) ++/* 0 = Clause 22, 1 = Clause 45 */ ++#define MDIO_MODE_C45 BIT(8) ++#define MDIO_MODE_DIV_MASK GENMASK(7, 0) ++#define MDIO_MODE_DIV(x) FIELD_PREP(MDIO_MODE_DIV_MASK, (x) - 1) ++#define MDIO_MODE_DIV_1 0x0 ++#define MDIO_MODE_DIV_2 0x1 ++#define MDIO_MODE_DIV_4 0x3 ++#define MDIO_MODE_DIV_8 0x7 ++#define MDIO_MODE_DIV_16 0xf ++#define MDIO_MODE_DIV_32 0x1f ++#define MDIO_MODE_DIV_64 0x3f ++#define MDIO_MODE_DIV_128 0x7f ++#define MDIO_MODE_DIV_256 0xff + #define MDIO_ADDR_REG 0x44 + #define MDIO_DATA_WRITE_REG 0x48 + #define MDIO_DATA_READ_REG 0x4c +@@ -26,9 +40,6 @@ + #define MDIO_CMD_ACCESS_CODE_C45_WRITE 1 + #define MDIO_CMD_ACCESS_CODE_C45_READ 2 + +-/* 0 = Clause 22, 1 = Clause 45 */ +-#define MDIO_MODE_C45 BIT(8) +- + #define IPQ4019_MDIO_TIMEOUT 10000 + #define IPQ4019_MDIO_SLEEP 10 + +@@ -41,6 +52,7 @@ struct ipq4019_mdio_data { + void __iomem *membase; + void __iomem *eth_ldo_rdy; + struct clk *mdio_clk; ++ unsigned int mdc_rate; + }; + + static int ipq4019_mdio_wait_busy(struct mii_bus *bus) +@@ -179,6 +191,38 @@ static int ipq4019_mdio_write(struct mii + return 0; + } + ++static int ipq4019_mdio_set_div(struct ipq4019_mdio_data *priv) ++{ ++ unsigned long ahb_rate; ++ int div; ++ u32 val; ++ ++ /* If we don't have a clock for AHB use the fixed value */ ++ ahb_rate = IPQ_MDIO_CLK_RATE; ++ if (priv->mdio_clk) ++ ahb_rate = clk_get_rate(priv->mdio_clk); ++ ++ /* MDC rate is ahb_rate/(MDIO_MODE_DIV + 1) ++ * While supported, internal documentation doesn't ++ * assure correct functionality of the MDIO bus ++ * with divider of 1, 2 or 4. ++ */ ++ for (div = 8; div <= 256; div *= 2) { ++ /* The requested rate is supported by the div */ ++ if (priv->mdc_rate == DIV_ROUND_UP(ahb_rate, div)) { ++ val = readl(priv->membase + MDIO_MODE_REG); ++ val &= ~MDIO_MODE_DIV_MASK; ++ val |= MDIO_MODE_DIV(div); ++ writel(val, priv->membase + MDIO_MODE_REG); ++ ++ return 0; ++ } ++ } ++ ++ /* The requested rate is not supported */ ++ return -EINVAL; ++} ++ + static int ipq_mdio_reset(struct mii_bus *bus) + { + struct ipq4019_mdio_data *priv = bus->priv; +@@ -201,10 +245,58 @@ static int ipq_mdio_reset(struct mii_bus + return ret; + + ret = clk_prepare_enable(priv->mdio_clk); +- if (ret == 0) +- mdelay(10); ++ if (ret) ++ return ret; ++ ++ mdelay(10); + +- return ret; ++ /* Restore MDC rate */ ++ return ipq4019_mdio_set_div(priv); ++} ++ ++static void ipq4019_mdio_select_mdc_rate(struct platform_device *pdev, ++ struct ipq4019_mdio_data *priv) ++{ ++ unsigned long ahb_rate; ++ int div; ++ u32 val; ++ ++ /* MDC rate defined in DT, we don't have to decide a default value */ ++ if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency", ++ &priv->mdc_rate)) ++ return; ++ ++ /* If we don't have a clock for AHB use the fixed value */ ++ ahb_rate = IPQ_MDIO_CLK_RATE; ++ if (priv->mdio_clk) ++ ahb_rate = clk_get_rate(priv->mdio_clk); ++ ++ /* Check what is the current div set */ ++ val = readl(priv->membase + MDIO_MODE_REG); ++ div = FIELD_GET(MDIO_MODE_DIV_MASK, val); ++ ++ /* div is not set to the default value of /256 ++ * Probably someone changed that (bootloader, other drivers) ++ * Keep this and don't overwrite it. ++ */ ++ if (div != MDIO_MODE_DIV_256) { ++ priv->mdc_rate = DIV_ROUND_UP(ahb_rate, div + 1); ++ return; ++ } ++ ++ /* If div is /256 assume nobody have set this value and ++ * try to find one MDC rate that is close the 802.3 spec of ++ * 2.5MHz ++ */ ++ for (div = 256; div >= 8; div /= 2) { ++ /* Stop as soon as we found a divider that ++ * reached the closest value to 2.5MHz ++ */ ++ if (DIV_ROUND_UP(ahb_rate, div) > 2500000) ++ break; ++ ++ priv->mdc_rate = DIV_ROUND_UP(ahb_rate, div); ++ } + } + + static int ipq4019_mdio_probe(struct platform_device *pdev) +@@ -228,6 +320,11 @@ static int ipq4019_mdio_probe(struct pla + if (IS_ERR(priv->mdio_clk)) + return PTR_ERR(priv->mdio_clk); + ++ ipq4019_mdio_select_mdc_rate(pdev, priv); ++ ret = ipq4019_mdio_set_div(priv); ++ if (ret) ++ return ret; ++ + /* The platform resource is provided on the chipset IPQ5018 */ + /* This resource is optional */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); diff --git a/lede/target/linux/generic/backport-6.1/721-v6.7-net-phy-aquantia-drop-wrong-endianness-conversion-fo.patch b/lede/target/linux/generic/backport-6.1/721-v6.7-net-phy-aquantia-drop-wrong-endianness-conversion-fo.patch new file mode 100644 index 0000000000..d32a7edf93 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/721-v6.7-net-phy-aquantia-drop-wrong-endianness-conversion-fo.patch @@ -0,0 +1,92 @@ +From 7edce370d87a23e8ed46af5b76a9fef1e341b67b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 28 Nov 2023 14:59:28 +0100 +Subject: [PATCH] net: phy: aquantia: drop wrong endianness conversion for addr + and CRC + +On further testing on BE target with kernel test robot, it was notice +that the endianness conversion for addr and CRC in fw_load_memory was +wrong. + +Drop the cpu_to_le32 conversion for addr load as it's not needed. + +Use get_unaligned_le32 instead of get_unaligned for FW data word load to +correctly convert data in the correct order to follow system endian. + +Also drop the cpu_to_be32 for CRC calculation as it's wrong and would +cause different CRC on BE system. +The loaded word is swapped internally and MAILBOX calculates the CRC on +the swapped word. To correctly calculate the CRC to be later matched +with the one from MAILBOX, use an u8 struct and swap the word there to +keep the same order on both LE and BE for crc_ccitt_false function. +Also add additional comments on how the CRC verification for the loaded +section works. + +CRC is calculated as we load the section and verified with the MAILBOX +only after the entire section is loaded to skip additional slowdown by +loop the section data again. + +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202311210414.sEJZjlcD-lkp@intel.com/ +Fixes: e93984ebc1c8 ("net: phy: aquantia: add firmware load support") +Tested-by: Robert Marko # ipq8072 LE device +Signed-off-by: Christian Marangi +Link: https://lore.kernel.org/r/20231128135928.9841-1-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/aquantia/aquantia_firmware.c | 24 ++++++++++++-------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/aquantia/aquantia_firmware.c ++++ b/drivers/net/phy/aquantia/aquantia_firmware.c +@@ -93,9 +93,6 @@ static int aqr_fw_load_memory(struct phy + u16 crc = 0, up_crc; + size_t pos; + +- /* PHY expect addr in LE */ +- addr = (__force u32)cpu_to_le32(addr); +- + phy_write_mmd(phydev, MDIO_MMD_VEND1, + VEND1_GLOBAL_MAILBOX_INTERFACE1, + VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET); +@@ -110,10 +107,11 @@ static int aqr_fw_load_memory(struct phy + * If a firmware that is not word aligned is found, please report upstream. + */ + for (pos = 0; pos < len; pos += sizeof(u32)) { ++ u8 crc_data[4]; + u32 word; + + /* FW data is always stored in little-endian */ +- word = get_unaligned((const u32 *)(data + pos)); ++ word = get_unaligned_le32((const u32 *)(data + pos)); + + phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE5, + VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(word)); +@@ -124,15 +122,21 @@ static int aqr_fw_load_memory(struct phy + VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE | + VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE); + +- /* calculate CRC as we load data to the mailbox. +- * We convert word to big-endian as PHY is BE and mailbox will +- * return a BE CRC. ++ /* Word is swapped internally and MAILBOX CRC is calculated ++ * using big-endian order. Mimic what the PHY does to have a ++ * matching CRC... + */ +- word = (__force u32)cpu_to_be32(word); +- crc = crc_ccitt_false(crc, (u8 *)&word, sizeof(word)); +- } ++ crc_data[0] = word >> 24; ++ crc_data[1] = word >> 16; ++ crc_data[2] = word >> 8; ++ crc_data[3] = word; + ++ /* ...calculate CRC as we load data... */ ++ crc = crc_ccitt_false(crc, crc_data, sizeof(crc_data)); ++ } ++ /* ...gets CRC from MAILBOX after we have loaded the entire section... */ + up_crc = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE2); ++ /* ...and make sure it does match our calculated CRC */ + if (crc != up_crc) { + phydev_err(phydev, "CRC mismatch: calculated 0x%04x PHY 0x%04x\n", + crc, up_crc); diff --git a/lede/target/linux/generic/backport-6.1/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch b/lede/target/linux/generic/backport-6.1/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch index 816aa67787..cf0d2a3a89 100644 --- a/lede/target/linux/generic/backport-6.1/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch +++ b/lede/target/linux/generic/backport-6.1/724-v6.2-net-ethernet-mtk_eth_soc-enable-flow-offloading-supp.patch @@ -16,7 +16,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4333,6 +4333,7 @@ static const struct mtk_soc_data mt7986_ +@@ -4332,6 +4332,7 @@ static const struct mtk_soc_data mt7986_ .hw_features = MTK_HW_FEATURES, .required_clks = MT7986_CLKS_BITMAP, .required_pctl = false, diff --git a/lede/target/linux/generic/backport-6.1/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch b/lede/target/linux/generic/backport-6.1/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch index cefe1eefff..5a79242e3b 100644 --- a/lede/target/linux/generic/backport-6.1/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch +++ b/lede/target/linux/generic/backport-6.1/729-07-v6.1-net-ethernet-mtk_eth_soc-remove-cpu_relax-in-mtk_pen.patch @@ -12,7 +12,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3480,11 +3480,8 @@ static void mtk_pending_work(struct work +@@ -3479,11 +3479,8 @@ static void mtk_pending_work(struct work rtnl_lock(); dev_dbg(eth->dev, "[%s][%d] reset\n", __func__, __LINE__); @@ -25,7 +25,7 @@ Signed-off-by: David S. Miller /* stop all devices to make sure that dma is properly shut down */ for (i = 0; i < MTK_MAC_COUNT; i++) { if (!eth->netdev[i]) -@@ -3518,7 +3515,7 @@ static void mtk_pending_work(struct work +@@ -3517,7 +3514,7 @@ static void mtk_pending_work(struct work dev_dbg(eth->dev, "[%s][%d] reset done\n", __func__, __LINE__); diff --git a/lede/target/linux/generic/backport-6.1/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch b/lede/target/linux/generic/backport-6.1/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch index c91861a8f1..fde0af25df 100644 --- a/lede/target/linux/generic/backport-6.1/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch +++ b/lede/target/linux/generic/backport-6.1/729-18-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_reset-util.patch @@ -16,7 +16,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3256,6 +3256,27 @@ static void mtk_set_mcr_max_rx(struct mt +@@ -3255,6 +3255,27 @@ static void mtk_set_mcr_max_rx(struct mt mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id)); } @@ -44,7 +44,7 @@ Signed-off-by: Paolo Abeni static int mtk_hw_init(struct mtk_eth *eth) { u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | -@@ -3295,22 +3316,9 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -3294,22 +3315,9 @@ static int mtk_hw_init(struct mtk_eth *e return 0; } diff --git a/lede/target/linux/generic/backport-6.1/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch b/lede/target/linux/generic/backport-6.1/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch index 6597eb5b74..e6a94f616e 100644 --- a/lede/target/linux/generic/backport-6.1/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch +++ b/lede/target/linux/generic/backport-6.1/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch @@ -17,7 +17,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3277,7 +3277,54 @@ static void mtk_hw_reset(struct mtk_eth +@@ -3276,7 +3276,54 @@ static void mtk_hw_reset(struct mtk_eth 0x3ffffff); } @@ -73,7 +73,7 @@ Signed-off-by: Paolo Abeni { u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | ETHSYS_DMA_AG_MAP_PPE; -@@ -3316,7 +3363,12 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -3315,7 +3362,12 @@ static int mtk_hw_init(struct mtk_eth *e return 0; } @@ -87,7 +87,7 @@ Signed-off-by: Paolo Abeni if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { /* Set FE to PDMAv2 if necessary */ -@@ -3507,7 +3559,7 @@ static void mtk_pending_work(struct work +@@ -3506,7 +3558,7 @@ static void mtk_pending_work(struct work if (eth->dev->pins) pinctrl_select_state(eth->dev->pins->p, eth->dev->pins->default_state); @@ -96,7 +96,7 @@ Signed-off-by: Paolo Abeni /* restart DMA and enable IRQs */ for (i = 0; i < MTK_MAC_COUNT; i++) { -@@ -4109,7 +4161,7 @@ static int mtk_probe(struct platform_dev +@@ -4108,7 +4160,7 @@ static int mtk_probe(struct platform_dev eth->msg_enable = netif_msg_init(mtk_msg_level, MTK_DEFAULT_MSG_ENABLE); INIT_WORK(ð->pending_work, mtk_pending_work); diff --git a/lede/target/linux/generic/backport-6.1/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch b/lede/target/linux/generic/backport-6.1/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch index 55ab19f4c8..7fdf7aa581 100644 --- a/lede/target/linux/generic/backport-6.1/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch +++ b/lede/target/linux/generic/backport-6.1/729-20-v6.3-net-ethernet-mtk_eth_soc-align-reset-procedure-to-ve.patch @@ -16,7 +16,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2844,14 +2844,29 @@ static void mtk_dma_free(struct mtk_eth +@@ -2843,14 +2843,29 @@ static void mtk_dma_free(struct mtk_eth kfree(eth->scratch_head); } @@ -48,7 +48,7 @@ Signed-off-by: Paolo Abeni schedule_work(ð->pending_work); } -@@ -3331,15 +3346,17 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -3330,15 +3345,17 @@ static int mtk_hw_init(struct mtk_eth *e const struct mtk_reg_map *reg_map = eth->soc->reg_map; int i, val, ret; @@ -72,7 +72,7 @@ Signed-off-by: Paolo Abeni if (eth->ethsys) regmap_update_bits(eth->ethsys, ETHSYS_DMA_AG_MAP, dma_mask, -@@ -3468,8 +3485,10 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -3467,8 +3484,10 @@ static int mtk_hw_init(struct mtk_eth *e return 0; err_disable_pm: @@ -85,7 +85,7 @@ Signed-off-by: Paolo Abeni return ret; } -@@ -3531,30 +3550,53 @@ static int mtk_do_ioctl(struct net_devic +@@ -3530,30 +3549,53 @@ static int mtk_do_ioctl(struct net_devic return -EOPNOTSUPP; } @@ -148,7 +148,7 @@ Signed-off-by: Paolo Abeni if (eth->dev->pins) pinctrl_select_state(eth->dev->pins->p, -@@ -3565,15 +3607,19 @@ static void mtk_pending_work(struct work +@@ -3564,15 +3606,19 @@ static void mtk_pending_work(struct work for (i = 0; i < MTK_MAC_COUNT; i++) { if (!test_bit(i, &restart)) continue; diff --git a/lede/target/linux/generic/backport-6.1/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch b/lede/target/linux/generic/backport-6.1/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch index d5a7c0eba2..a77f3da7f8 100644 --- a/lede/target/linux/generic/backport-6.1/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch +++ b/lede/target/linux/generic/backport-6.1/729-21-v6.3-net-ethernet-mtk_eth_soc-add-dma-checks-to-mtk_hw_re.patch @@ -49,7 +49,7 @@ Signed-off-by: Paolo Abeni }; /* strings used by ethtool */ -@@ -3339,6 +3345,102 @@ static void mtk_hw_warm_reset(struct mtk +@@ -3338,6 +3344,102 @@ static void mtk_hw_warm_reset(struct mtk val, rst_mask); } @@ -152,7 +152,7 @@ Signed-off-by: Paolo Abeni static int mtk_hw_init(struct mtk_eth *eth, bool reset) { u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | -@@ -3657,6 +3759,7 @@ static int mtk_cleanup(struct mtk_eth *e +@@ -3656,6 +3758,7 @@ static int mtk_cleanup(struct mtk_eth *e mtk_unreg_dev(eth); mtk_free_dev(eth); cancel_work_sync(ð->pending_work); @@ -160,7 +160,7 @@ Signed-off-by: Paolo Abeni return 0; } -@@ -4094,6 +4197,7 @@ static int mtk_probe(struct platform_dev +@@ -4093,6 +4196,7 @@ static int mtk_probe(struct platform_dev eth->rx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; INIT_WORK(ð->rx_dim.work, mtk_dim_rx); @@ -168,7 +168,7 @@ Signed-off-by: Paolo Abeni eth->tx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; INIT_WORK(ð->tx_dim.work, mtk_dim_tx); -@@ -4296,6 +4400,8 @@ static int mtk_probe(struct platform_dev +@@ -4295,6 +4399,8 @@ static int mtk_probe(struct platform_dev netif_napi_add(ð->dummy_dev, ð->rx_napi, mtk_napi_rx); platform_set_drvdata(pdev, eth); diff --git a/lede/target/linux/generic/backport-6.1/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch b/lede/target/linux/generic/backport-6.1/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch index c21d094ae8..3f047da758 100644 --- a/lede/target/linux/generic/backport-6.1/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch +++ b/lede/target/linux/generic/backport-6.1/729-22-v6.3-net-ethernet-mtk_wed-add-reset-reset_complete-callba.patch @@ -14,7 +14,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3688,6 +3688,11 @@ static void mtk_pending_work(struct work +@@ -3687,6 +3687,11 @@ static void mtk_pending_work(struct work set_bit(MTK_RESETTING, ð->state); mtk_prepare_for_reset(eth); @@ -26,7 +26,7 @@ Signed-off-by: Paolo Abeni /* stop all devices to make sure that dma is properly shut down */ for (i = 0; i < MTK_MAC_COUNT; i++) { -@@ -3725,6 +3730,8 @@ static void mtk_pending_work(struct work +@@ -3724,6 +3729,8 @@ static void mtk_pending_work(struct work clear_bit(MTK_RESETTING, ð->state); diff --git a/lede/target/linux/generic/backport-6.1/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch b/lede/target/linux/generic/backport-6.1/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch index 046a581224..41d1bceac4 100644 --- a/lede/target/linux/generic/backport-6.1/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch +++ b/lede/target/linux/generic/backport-6.1/730-02-v6.3-net-ethernet-mtk_eth_soc-increase-tx-ring-side-for-Q.patch @@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -944,7 +944,7 @@ static int mtk_init_fq_dma(struct mtk_et +@@ -943,7 +943,7 @@ static int mtk_init_fq_dma(struct mtk_et { const struct mtk_soc_data *soc = eth->soc; dma_addr_t phy_ring_tail; @@ -21,7 +21,7 @@ Signed-off-by: Felix Fietkau dma_addr_t dma_addr; int i; -@@ -2208,19 +2208,25 @@ static int mtk_tx_alloc(struct mtk_eth * +@@ -2207,19 +2207,25 @@ static int mtk_tx_alloc(struct mtk_eth * struct mtk_tx_ring *ring = ð->tx_ring; int i, sz = soc->txrx.txd_size; struct mtk_tx_dma_v2 *txd; @@ -51,7 +51,7 @@ Signed-off-by: Felix Fietkau u32 next_ptr = ring->phys + next * sz; txd = ring->dma + i * sz; -@@ -2240,22 +2246,22 @@ static int mtk_tx_alloc(struct mtk_eth * +@@ -2239,22 +2245,22 @@ static int mtk_tx_alloc(struct mtk_eth * * descriptors in ring->dma_pdma. */ if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) { @@ -79,7 +79,7 @@ Signed-off-by: Felix Fietkau ring->thresh = MAX_SKB_FRAGS; /* make sure that all changes to the dma ring are flushed before we -@@ -2267,14 +2273,14 @@ static int mtk_tx_alloc(struct mtk_eth * +@@ -2266,14 +2272,14 @@ static int mtk_tx_alloc(struct mtk_eth * mtk_w32(eth, ring->phys, soc->reg_map->qdma.ctx_ptr); mtk_w32(eth, ring->phys, soc->reg_map->qdma.dtx_ptr); mtk_w32(eth, @@ -96,7 +96,7 @@ Signed-off-by: Felix Fietkau mtk_w32(eth, 0, MT7628_TX_CTX_IDX0); mtk_w32(eth, MT7628_PST_DTX_IDX0, soc->reg_map->pdma.rst_idx); } -@@ -2292,7 +2298,7 @@ static void mtk_tx_clean(struct mtk_eth +@@ -2291,7 +2297,7 @@ static void mtk_tx_clean(struct mtk_eth int i; if (ring->buf) { @@ -105,7 +105,7 @@ Signed-off-by: Felix Fietkau mtk_tx_unmap(eth, &ring->buf[i], NULL, false); kfree(ring->buf); ring->buf = NULL; -@@ -2300,14 +2306,14 @@ static void mtk_tx_clean(struct mtk_eth +@@ -2299,14 +2305,14 @@ static void mtk_tx_clean(struct mtk_eth if (ring->dma) { dma_free_coherent(eth->dma_dev, @@ -122,7 +122,7 @@ Signed-off-by: Felix Fietkau ring->dma_pdma, ring->phys_pdma); ring->dma_pdma = NULL; } -@@ -2832,7 +2838,7 @@ static void mtk_dma_free(struct mtk_eth +@@ -2831,7 +2837,7 @@ static void mtk_dma_free(struct mtk_eth netdev_reset_queue(eth->netdev[i]); if (eth->scratch_ring) { dma_free_coherent(eth->dma_dev, diff --git a/lede/target/linux/generic/backport-6.1/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch b/lede/target/linux/generic/backport-6.1/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch index 7e879ca1d5..c9823daa1d 100644 --- a/lede/target/linux/generic/backport-6.1/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch +++ b/lede/target/linux/generic/backport-6.1/730-03-v6.3-net-ethernet-mtk_eth_soc-avoid-port_mg-assignment-on.patch @@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4479,7 +4479,7 @@ static const struct mtk_soc_data mt7621_ +@@ -4478,7 +4478,7 @@ static const struct mtk_soc_data mt7621_ .hw_features = MTK_HW_FEATURES, .required_clks = MT7621_CLKS_BITMAP, .required_pctl = false, @@ -21,7 +21,7 @@ Signed-off-by: Felix Fietkau .hash_offset = 2, .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, .txrx = { -@@ -4518,7 +4518,7 @@ static const struct mtk_soc_data mt7623_ +@@ -4517,7 +4517,7 @@ static const struct mtk_soc_data mt7623_ .hw_features = MTK_HW_FEATURES, .required_clks = MT7623_CLKS_BITMAP, .required_pctl = true, diff --git a/lede/target/linux/generic/backport-6.1/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch b/lede/target/linux/generic/backport-6.1/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch index 2f669bde3b..0d462b0c85 100644 --- a/lede/target/linux/generic/backport-6.1/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch +++ b/lede/target/linux/generic/backport-6.1/730-04-v6.3-net-ethernet-mtk_eth_soc-implement-multi-queue-suppo.patch @@ -139,7 +139,7 @@ Signed-off-by: Felix Fietkau /* Configure duplex */ if (duplex == DUPLEX_FULL) mcr |= MAC_MCR_FORCE_DPX; -@@ -1105,7 +1180,8 @@ static void mtk_tx_set_dma_desc_v1(struc +@@ -1104,7 +1179,8 @@ static void mtk_tx_set_dma_desc_v1(struc WRITE_ONCE(desc->txd1, info->addr); @@ -149,7 +149,7 @@ Signed-off-by: Felix Fietkau if (info->last) data |= TX_DMA_LS0; WRITE_ONCE(desc->txd3, data); -@@ -1139,9 +1215,6 @@ static void mtk_tx_set_dma_desc_v2(struc +@@ -1138,9 +1214,6 @@ static void mtk_tx_set_dma_desc_v2(struc data |= TX_DMA_LS0; WRITE_ONCE(desc->txd3, data); @@ -159,7 +159,7 @@ Signed-off-by: Felix Fietkau data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */ data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid); WRITE_ONCE(desc->txd4, data); -@@ -1185,11 +1258,12 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1184,11 +1257,12 @@ static int mtk_tx_map(struct sk_buff *sk .gso = gso, .csum = skb->ip_summed == CHECKSUM_PARTIAL, .vlan = skb_vlan_tag_present(skb), @@ -173,7 +173,7 @@ Signed-off-by: Felix Fietkau struct mtk_mac *mac = netdev_priv(dev); struct mtk_eth *eth = mac->hw; const struct mtk_soc_data *soc = eth->soc; -@@ -1197,8 +1271,10 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1196,8 +1270,10 @@ static int mtk_tx_map(struct sk_buff *sk struct mtk_tx_dma *itxd_pdma, *txd_pdma; struct mtk_tx_buf *itx_buf, *tx_buf; int i, n_desc = 1; @@ -184,7 +184,7 @@ Signed-off-by: Felix Fietkau itxd = ring->next_free; itxd_pdma = qdma_to_pdma(ring, itxd); if (itxd == ring->last_free) -@@ -1247,7 +1323,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1246,7 +1322,7 @@ static int mtk_tx_map(struct sk_buff *sk memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); txd_info.size = min_t(unsigned int, frag_size, soc->txrx.dma_max_len); @@ -193,7 +193,7 @@ Signed-off-by: Felix Fietkau txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 && !(frag_size - txd_info.size); txd_info.addr = skb_frag_dma_map(eth->dma_dev, frag, -@@ -1286,7 +1362,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1285,7 +1361,7 @@ static int mtk_tx_map(struct sk_buff *sk txd_pdma->txd2 |= TX_DMA_LS1; } @@ -202,7 +202,7 @@ Signed-off-by: Felix Fietkau skb_tx_timestamp(skb); ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2); -@@ -1298,8 +1374,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1297,8 +1373,7 @@ static int mtk_tx_map(struct sk_buff *sk wmb(); if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) { @@ -212,7 +212,7 @@ Signed-off-by: Felix Fietkau mtk_w32(eth, txd->txd2, soc->reg_map->qdma.ctx_ptr); } else { int next_idx; -@@ -1368,7 +1443,7 @@ static void mtk_wake_queue(struct mtk_et +@@ -1367,7 +1442,7 @@ static void mtk_wake_queue(struct mtk_et for (i = 0; i < MTK_MAC_COUNT; i++) { if (!eth->netdev[i]) continue; @@ -221,7 +221,7 @@ Signed-off-by: Felix Fietkau } } -@@ -1392,7 +1467,7 @@ static netdev_tx_t mtk_start_xmit(struct +@@ -1391,7 +1466,7 @@ static netdev_tx_t mtk_start_xmit(struct tx_num = mtk_cal_txd_req(eth, skb); if (unlikely(atomic_read(&ring->free_count) <= tx_num)) { @@ -230,7 +230,7 @@ Signed-off-by: Felix Fietkau netif_err(eth, tx_queued, dev, "Tx Ring full when queue awake!\n"); spin_unlock(ð->page_lock); -@@ -1418,7 +1493,7 @@ static netdev_tx_t mtk_start_xmit(struct +@@ -1417,7 +1492,7 @@ static netdev_tx_t mtk_start_xmit(struct goto drop; if (unlikely(atomic_read(&ring->free_count) <= ring->thresh)) @@ -239,7 +239,7 @@ Signed-off-by: Felix Fietkau spin_unlock(ð->page_lock); -@@ -1585,10 +1660,12 @@ static int mtk_xdp_submit_frame(struct m +@@ -1584,10 +1659,12 @@ static int mtk_xdp_submit_frame(struct m struct skb_shared_info *sinfo = xdp_get_shared_info_from_frame(xdpf); const struct mtk_soc_data *soc = eth->soc; struct mtk_tx_ring *ring = ð->tx_ring; @@ -252,7 +252,7 @@ Signed-off-by: Felix Fietkau }; int err, index = 0, n_desc = 1, nr_frags; struct mtk_tx_buf *htx_buf, *tx_buf; -@@ -1638,6 +1715,7 @@ static int mtk_xdp_submit_frame(struct m +@@ -1637,6 +1714,7 @@ static int mtk_xdp_submit_frame(struct m memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); txd_info.size = skb_frag_size(&sinfo->frags[index]); txd_info.last = index + 1 == nr_frags; @@ -260,7 +260,7 @@ Signed-off-by: Felix Fietkau data = skb_frag_address(&sinfo->frags[index]); index++; -@@ -1992,8 +2070,46 @@ rx_done: +@@ -1991,8 +2069,46 @@ rx_done: return done; } @@ -308,7 +308,7 @@ Signed-off-by: Felix Fietkau { const struct mtk_reg_map *reg_map = eth->soc->reg_map; struct mtk_tx_ring *ring = ð->tx_ring; -@@ -2025,12 +2141,9 @@ static int mtk_poll_tx_qdma(struct mtk_e +@@ -2024,12 +2140,9 @@ static int mtk_poll_tx_qdma(struct mtk_e break; if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { @@ -323,7 +323,7 @@ Signed-off-by: Felix Fietkau budget--; } mtk_tx_unmap(eth, tx_buf, &bq, true); -@@ -2049,7 +2162,7 @@ static int mtk_poll_tx_qdma(struct mtk_e +@@ -2048,7 +2161,7 @@ static int mtk_poll_tx_qdma(struct mtk_e } static int mtk_poll_tx_pdma(struct mtk_eth *eth, int budget, @@ -332,7 +332,7 @@ Signed-off-by: Felix Fietkau { struct mtk_tx_ring *ring = ð->tx_ring; struct mtk_tx_buf *tx_buf; -@@ -2067,12 +2180,8 @@ static int mtk_poll_tx_pdma(struct mtk_e +@@ -2066,12 +2179,8 @@ static int mtk_poll_tx_pdma(struct mtk_e break; if (tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { @@ -347,7 +347,7 @@ Signed-off-by: Felix Fietkau budget--; } mtk_tx_unmap(eth, tx_buf, &bq, true); -@@ -2094,26 +2203,15 @@ static int mtk_poll_tx(struct mtk_eth *e +@@ -2093,26 +2202,15 @@ static int mtk_poll_tx(struct mtk_eth *e { struct mtk_tx_ring *ring = ð->tx_ring; struct dim_sample dim_sample = {}; @@ -379,7 +379,7 @@ Signed-off-by: Felix Fietkau dim_update_sample(eth->tx_events, eth->tx_packets, eth->tx_bytes, &dim_sample); -@@ -2123,7 +2221,7 @@ static int mtk_poll_tx(struct mtk_eth *e +@@ -2122,7 +2220,7 @@ static int mtk_poll_tx(struct mtk_eth *e (atomic_read(&ring->free_count) > ring->thresh)) mtk_wake_queue(eth); @@ -388,7 +388,7 @@ Signed-off-by: Felix Fietkau } static void mtk_handle_status_irq(struct mtk_eth *eth) -@@ -2209,6 +2307,7 @@ static int mtk_tx_alloc(struct mtk_eth * +@@ -2208,6 +2306,7 @@ static int mtk_tx_alloc(struct mtk_eth * int i, sz = soc->txrx.txd_size; struct mtk_tx_dma_v2 *txd; int ring_size; @@ -396,7 +396,7 @@ Signed-off-by: Felix Fietkau if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) ring_size = MTK_QDMA_RING_SIZE; -@@ -2276,8 +2375,25 @@ static int mtk_tx_alloc(struct mtk_eth * +@@ -2275,8 +2374,25 @@ static int mtk_tx_alloc(struct mtk_eth * ring->phys + ((ring_size - 1) * sz), soc->reg_map->qdma.crx_ptr); mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr); @@ -424,7 +424,7 @@ Signed-off-by: Felix Fietkau } else { mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0); mtk_w32(eth, ring_size, MT7628_TX_MAX_CNT0); -@@ -2962,7 +3078,7 @@ static int mtk_start_dma(struct mtk_eth +@@ -2961,7 +3077,7 @@ static int mtk_start_dma(struct mtk_eth if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) val |= MTK_MUTLI_CNT | MTK_RESV_BUF | MTK_WCOMP_EN | MTK_DMAD_WR_WDONE | @@ -433,7 +433,7 @@ Signed-off-by: Felix Fietkau else val |= MTK_RX_BT_32DWORDS; mtk_w32(eth, val, reg_map->qdma.glo_cfg); -@@ -3008,6 +3124,45 @@ static void mtk_gdm_config(struct mtk_et +@@ -3007,6 +3123,45 @@ static void mtk_gdm_config(struct mtk_et mtk_w32(eth, 0, MTK_RST_GL); } @@ -479,7 +479,7 @@ Signed-off-by: Felix Fietkau static int mtk_open(struct net_device *dev) { struct mtk_mac *mac = netdev_priv(dev); -@@ -3050,7 +3205,8 @@ static int mtk_open(struct net_device *d +@@ -3049,7 +3204,8 @@ static int mtk_open(struct net_device *d refcount_inc(ð->dma_refcnt); phylink_start(mac->phylink); @@ -489,7 +489,7 @@ Signed-off-by: Felix Fietkau return 0; } -@@ -3759,8 +3915,12 @@ static int mtk_unreg_dev(struct mtk_eth +@@ -3758,8 +3914,12 @@ static int mtk_unreg_dev(struct mtk_eth int i; for (i = 0; i < MTK_MAC_COUNT; i++) { @@ -502,7 +502,7 @@ Signed-off-by: Felix Fietkau unregister_netdev(eth->netdev[i]); } -@@ -3977,6 +4137,23 @@ static int mtk_set_rxnfc(struct net_devi +@@ -3976,6 +4136,23 @@ static int mtk_set_rxnfc(struct net_devi return ret; } @@ -526,7 +526,7 @@ Signed-off-by: Felix Fietkau static const struct ethtool_ops mtk_ethtool_ops = { .get_link_ksettings = mtk_get_link_ksettings, .set_link_ksettings = mtk_set_link_ksettings, -@@ -4011,6 +4188,7 @@ static const struct net_device_ops mtk_n +@@ -4010,6 +4187,7 @@ static const struct net_device_ops mtk_n .ndo_setup_tc = mtk_eth_setup_tc, .ndo_bpf = mtk_xdp, .ndo_xdp_xmit = mtk_xdp_xmit, @@ -534,7 +534,7 @@ Signed-off-by: Felix Fietkau }; static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) -@@ -4020,6 +4198,7 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4019,6 +4197,7 @@ static int mtk_add_mac(struct mtk_eth *e struct phylink *phylink; struct mtk_mac *mac; int id, err; @@ -542,7 +542,7 @@ Signed-off-by: Felix Fietkau if (!_id) { dev_err(eth->dev, "missing mac id\n"); -@@ -4037,7 +4216,10 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4036,7 +4215,10 @@ static int mtk_add_mac(struct mtk_eth *e return -EINVAL; } @@ -554,7 +554,7 @@ Signed-off-by: Felix Fietkau if (!eth->netdev[id]) { dev_err(eth->dev, "alloc_etherdev failed\n"); return -ENOMEM; -@@ -4145,6 +4327,11 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4144,6 +4326,11 @@ static int mtk_add_mac(struct mtk_eth *e else eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN; diff --git a/lede/target/linux/generic/backport-6.1/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch b/lede/target/linux/generic/backport-6.1/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch index b8e3452f30..53d8ff472e 100644 --- a/lede/target/linux/generic/backport-6.1/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch +++ b/lede/target/linux/generic/backport-6.1/730-09-v6.3-net-ethernet-mtk_eth_soc-fix-VLAN-rx-hardware-accele.patch @@ -22,7 +22,7 @@ Signed-off-by: Felix Fietkau #include "mtk_eth_soc.h" #include "mtk_wed.h" -@@ -2021,16 +2022,22 @@ static int mtk_poll_rx(struct napi_struc +@@ -2020,16 +2021,22 @@ static int mtk_poll_rx(struct napi_struc htons(RX_DMA_VPID(trxd.rxd4)), RX_DMA_VID(trxd.rxd4)); } else if (trxd.rxd2 & RX_DMA_VTAG) { @@ -52,7 +52,7 @@ Signed-off-by: Felix Fietkau } skb_record_rx_queue(skb, 0); -@@ -2858,15 +2865,30 @@ static netdev_features_t mtk_fix_feature +@@ -2857,15 +2864,30 @@ static netdev_features_t mtk_fix_feature static int mtk_set_features(struct net_device *dev, netdev_features_t features) { @@ -88,7 +88,7 @@ Signed-off-by: Felix Fietkau } /* wait for DMA to finish whatever it is doing before we start using it again */ -@@ -3163,11 +3185,45 @@ found: +@@ -3162,11 +3184,45 @@ found: return NOTIFY_DONE; } @@ -135,7 +135,7 @@ Signed-off-by: Felix Fietkau err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); if (err) { -@@ -3688,6 +3744,10 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -3687,6 +3743,10 @@ static int mtk_hw_init(struct mtk_eth *e */ val = mtk_r32(eth, MTK_CDMQ_IG_CTRL); mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL); @@ -146,7 +146,7 @@ Signed-off-by: Felix Fietkau /* Enable RX VLan Offloading */ mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); -@@ -3907,6 +3967,12 @@ static int mtk_free_dev(struct mtk_eth * +@@ -3906,6 +3966,12 @@ static int mtk_free_dev(struct mtk_eth * free_netdev(eth->netdev[i]); } diff --git a/lede/target/linux/generic/backport-6.1/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch b/lede/target/linux/generic/backport-6.1/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch index a88df2b8e3..08d72fc820 100644 --- a/lede/target/linux/generic/backport-6.1/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch +++ b/lede/target/linux/generic/backport-6.1/730-12-v6.3-net-ethernet-mtk_eth_soc-disable-hardware-DSA-untagg.patch @@ -20,7 +20,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3201,7 +3201,8 @@ static int mtk_open(struct net_device *d +@@ -3200,7 +3200,8 @@ static int mtk_open(struct net_device *d struct mtk_eth *eth = mac->hw; int i, err; @@ -30,7 +30,7 @@ Signed-off-by: Jakub Kicinski for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { struct metadata_dst *md_dst = eth->dsa_meta[i]; -@@ -3218,7 +3219,8 @@ static int mtk_open(struct net_device *d +@@ -3217,7 +3218,8 @@ static int mtk_open(struct net_device *d } } else { /* Hardware special tag parsing needs to be disabled if at least diff --git a/lede/target/linux/generic/backport-6.1/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch b/lede/target/linux/generic/backport-6.1/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch index 8da728b9e9..30c32d5cce 100644 --- a/lede/target/linux/generic/backport-6.1/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch +++ b/lede/target/linux/generic/backport-6.1/730-13-v6.3-net-ethernet-mtk_eth_soc-enable-special-tag-when-any.patch @@ -23,7 +23,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3136,7 +3136,7 @@ static void mtk_gdm_config(struct mtk_et +@@ -3135,7 +3135,7 @@ static void mtk_gdm_config(struct mtk_et val |= config; @@ -32,7 +32,7 @@ Signed-off-by: David S. Miller val |= MTK_GDMA_SPECIAL_TAG; mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); -@@ -3201,8 +3201,7 @@ static int mtk_open(struct net_device *d +@@ -3200,8 +3200,7 @@ static int mtk_open(struct net_device *d struct mtk_eth *eth = mac->hw; int i, err; @@ -42,7 +42,7 @@ Signed-off-by: David S. Miller for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) { struct metadata_dst *md_dst = eth->dsa_meta[i]; -@@ -3219,8 +3218,7 @@ static int mtk_open(struct net_device *d +@@ -3218,8 +3217,7 @@ static int mtk_open(struct net_device *d } } else { /* Hardware special tag parsing needs to be disabled if at least diff --git a/lede/target/linux/generic/backport-6.1/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch b/lede/target/linux/generic/backport-6.1/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch index 51cd572ab2..eb3b0c63bc 100644 --- a/lede/target/linux/generic/backport-6.1/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch +++ b/lede/target/linux/generic/backport-6.1/730-14-v6.3-net-ethernet-mtk_eth_soc-fix-DSA-TX-tag-hwaccel-for-.patch @@ -77,7 +77,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1877,7 +1877,9 @@ static int mtk_poll_rx(struct napi_struc +@@ -1876,7 +1876,9 @@ static int mtk_poll_rx(struct napi_struc while (done < budget) { unsigned int pktlen, *rxdcsum; @@ -87,7 +87,7 @@ Signed-off-by: David S. Miller dma_addr_t dma_addr; u32 hash, reason; int mac = 0; -@@ -2017,27 +2019,29 @@ static int mtk_poll_rx(struct napi_struc +@@ -2016,27 +2018,29 @@ static int mtk_poll_rx(struct napi_struc if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { diff --git a/lede/target/linux/generic/backport-6.1/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch b/lede/target/linux/generic/backport-6.1/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch index a1247218b0..3f3f73183e 100644 --- a/lede/target/linux/generic/backport-6.1/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch +++ b/lede/target/linux/generic/backport-6.1/733-v6.3-18-net-ethernet-mtk_eth_soc-add-support-for-MT7981.patch @@ -57,7 +57,7 @@ Signed-off-by: Jakub Kicinski mtk_eth_path_name(path), __func__, updated); --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4803,6 +4803,26 @@ static const struct mtk_soc_data mt7629_ +@@ -4802,6 +4802,26 @@ static const struct mtk_soc_data mt7629_ }, }; @@ -84,7 +84,7 @@ Signed-off-by: Jakub Kicinski static const struct mtk_soc_data mt7986_data = { .reg_map = &mt7986_reg_map, .ana_rgc3 = 0x128, -@@ -4845,6 +4865,7 @@ const struct of_device_id of_mtk_match[] +@@ -4844,6 +4864,7 @@ const struct of_device_id of_mtk_match[] { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data}, { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data}, { .compatible = "mediatek,mt7629-eth", .data = &mt7629_data}, diff --git a/lede/target/linux/generic/backport-6.1/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch b/lede/target/linux/generic/backport-6.1/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch index 1cb1f40538..c60a4337ef 100644 --- a/lede/target/linux/generic/backport-6.1/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch +++ b/lede/target/linux/generic/backport-6.1/733-v6.3-19-net-ethernet-mtk_eth_soc-set-MDIO-bus-clock-frequenc.patch @@ -21,7 +21,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -744,8 +744,10 @@ static const struct phylink_mac_ops mtk_ +@@ -743,8 +743,10 @@ static const struct phylink_mac_ops mtk_ static int mtk_mdio_init(struct mtk_eth *eth) { @@ -32,7 +32,7 @@ Signed-off-by: Jakub Kicinski mii_np = of_get_child_by_name(eth->dev->of_node, "mdio-bus"); if (!mii_np) { -@@ -772,6 +774,25 @@ static int mtk_mdio_init(struct mtk_eth +@@ -771,6 +773,25 @@ static int mtk_mdio_init(struct mtk_eth eth->mii_bus->parent = eth->dev; snprintf(eth->mii_bus->id, MII_BUS_ID_SIZE, "%pOFn", mii_np); diff --git a/lede/target/linux/generic/backport-6.1/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch b/lede/target/linux/generic/backport-6.1/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch index 110944658d..d73eccedbb 100644 --- a/lede/target/linux/generic/backport-6.1/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch +++ b/lede/target/linux/generic/backport-6.1/733-v6.3-20-net-ethernet-mtk_eth_soc-switch-to-external-PCS-driv.patch @@ -60,7 +60,7 @@ Signed-off-by: Jakub Kicinski } return NULL; -@@ -4016,8 +4017,17 @@ static int mtk_unreg_dev(struct mtk_eth +@@ -4015,8 +4016,17 @@ static int mtk_unreg_dev(struct mtk_eth return 0; } @@ -78,7 +78,7 @@ Signed-off-by: Jakub Kicinski mtk_unreg_dev(eth); mtk_free_dev(eth); cancel_work_sync(ð->pending_work); -@@ -4457,6 +4467,36 @@ void mtk_eth_set_dma_device(struct mtk_e +@@ -4456,6 +4466,36 @@ void mtk_eth_set_dma_device(struct mtk_e rtnl_unlock(); } @@ -115,7 +115,7 @@ Signed-off-by: Jakub Kicinski static int mtk_probe(struct platform_device *pdev) { struct resource *res = NULL; -@@ -4520,13 +4560,7 @@ static int mtk_probe(struct platform_dev +@@ -4519,13 +4559,7 @@ static int mtk_probe(struct platform_dev } if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { @@ -130,7 +130,7 @@ Signed-off-by: Jakub Kicinski if (err) return err; -@@ -4537,14 +4571,17 @@ static int mtk_probe(struct platform_dev +@@ -4536,14 +4570,17 @@ static int mtk_probe(struct platform_dev "mediatek,pctl"); if (IS_ERR(eth->pctl)) { dev_err(&pdev->dev, "no pctl regmap found\n"); @@ -151,7 +151,7 @@ Signed-off-by: Jakub Kicinski } if (eth->soc->offload_version) { -@@ -4703,6 +4740,8 @@ err_deinit_hw: +@@ -4702,6 +4739,8 @@ err_deinit_hw: mtk_hw_deinit(eth); err_wed_exit: mtk_wed_exit(); diff --git a/lede/target/linux/generic/backport-6.1/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch b/lede/target/linux/generic/backport-6.1/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch index 93eaffa19e..5c3de57591 100644 --- a/lede/target/linux/generic/backport-6.1/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch +++ b/lede/target/linux/generic/backport-6.1/733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch @@ -27,7 +27,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4691,8 +4691,8 @@ static int mtk_probe(struct platform_dev +@@ -4690,8 +4690,8 @@ static int mtk_probe(struct platform_dev for (i = 0; i < num_ppe; i++) { u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400; @@ -38,7 +38,7 @@ Signed-off-by: Jakub Kicinski if (!eth->ppe[i]) { err = -ENOMEM; goto err_deinit_ppe; -@@ -4816,6 +4816,7 @@ static const struct mtk_soc_data mt7622_ +@@ -4815,6 +4815,7 @@ static const struct mtk_soc_data mt7622_ .required_pctl = false, .offload_version = 2, .hash_offset = 2, @@ -46,7 +46,7 @@ Signed-off-by: Jakub Kicinski .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, .txrx = { .txd_size = sizeof(struct mtk_tx_dma), -@@ -4853,6 +4854,7 @@ static const struct mtk_soc_data mt7629_ +@@ -4852,6 +4853,7 @@ static const struct mtk_soc_data mt7629_ .hw_features = MTK_HW_FEATURES, .required_clks = MT7629_CLKS_BITMAP, .required_pctl = false, @@ -54,7 +54,7 @@ Signed-off-by: Jakub Kicinski .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4873,6 +4875,7 @@ static const struct mtk_soc_data mt7981_ +@@ -4872,6 +4874,7 @@ static const struct mtk_soc_data mt7981_ .offload_version = 2, .hash_offset = 4, .foe_entry_size = sizeof(struct mtk_foe_entry), @@ -62,7 +62,7 @@ Signed-off-by: Jakub Kicinski .txrx = { .txd_size = sizeof(struct mtk_tx_dma_v2), .rxd_size = sizeof(struct mtk_rx_dma_v2), -@@ -4893,6 +4896,7 @@ static const struct mtk_soc_data mt7986_ +@@ -4892,6 +4895,7 @@ static const struct mtk_soc_data mt7986_ .offload_version = 2, .hash_offset = 4, .foe_entry_size = sizeof(struct mtk_foe_entry), diff --git a/lede/target/linux/generic/backport-6.1/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch b/lede/target/linux/generic/backport-6.1/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch index 217e517c3a..7e3d5a3308 100644 --- a/lede/target/linux/generic/backport-6.1/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch +++ b/lede/target/linux/generic/backport-6.1/733-v6.4-25-net-ethernet-mtk_eth_soc-drop-generic-vlan-rx-offloa.patch @@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1897,9 +1897,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -1896,9 +1896,7 @@ static int mtk_poll_rx(struct napi_struc while (done < budget) { unsigned int pktlen, *rxdcsum; @@ -27,7 +27,7 @@ Signed-off-by: Felix Fietkau dma_addr_t dma_addr; u32 hash, reason; int mac = 0; -@@ -2034,36 +2032,21 @@ static int mtk_poll_rx(struct napi_struc +@@ -2033,36 +2031,21 @@ static int mtk_poll_rx(struct napi_struc skb_checksum_none_assert(skb); skb->protocol = eth_type_trans(skb, netdev); @@ -70,7 +70,7 @@ Signed-off-by: Felix Fietkau skb_record_rx_queue(skb, 0); napi_gro_receive(napi, skb); -@@ -2889,29 +2872,11 @@ static netdev_features_t mtk_fix_feature +@@ -2888,29 +2871,11 @@ static netdev_features_t mtk_fix_feature static int mtk_set_features(struct net_device *dev, netdev_features_t features) { @@ -100,7 +100,7 @@ Signed-off-by: Felix Fietkau return 0; } -@@ -3225,30 +3190,6 @@ static int mtk_open(struct net_device *d +@@ -3224,30 +3189,6 @@ static int mtk_open(struct net_device *d struct mtk_eth *eth = mac->hw; int i, err; @@ -131,7 +131,7 @@ Signed-off-by: Felix Fietkau err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); if (err) { netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, -@@ -3287,6 +3228,35 @@ static int mtk_open(struct net_device *d +@@ -3286,6 +3227,35 @@ static int mtk_open(struct net_device *d phylink_start(mac->phylink); netif_tx_start_all_queues(dev); @@ -167,7 +167,7 @@ Signed-off-by: Felix Fietkau return 0; } -@@ -3771,10 +3741,9 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -3770,10 +3740,9 @@ static int mtk_hw_init(struct mtk_eth *e if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { val = mtk_r32(eth, MTK_CDMP_IG_CTRL); mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); @@ -180,7 +180,7 @@ Signed-off-by: Felix Fietkau /* set interrupt delays based on current Net DIM sample */ mtk_dim_rx(ð->rx_dim.work); -@@ -4414,7 +4383,7 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4413,7 +4382,7 @@ static int mtk_add_mac(struct mtk_eth *e eth->netdev[id]->hw_features |= NETIF_F_LRO; eth->netdev[id]->vlan_features = eth->soc->hw_features & diff --git a/lede/target/linux/generic/backport-6.1/734-v6.8-net-phy-bcm54612e-add-suspend-resume.patch b/lede/target/linux/generic/backport-6.1/734-v6.8-net-phy-bcm54612e-add-suspend-resume.patch new file mode 100644 index 0000000000..64d1b160d3 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/734-v6.8-net-phy-bcm54612e-add-suspend-resume.patch @@ -0,0 +1,27 @@ +From 380b50ae3a04222334a3779b3787eba844b1177f Mon Sep 17 00:00:00 2001 +From: Marco von Rosenberg +Date: Thu, 16 Nov 2023 20:32:31 +0100 +Subject: net: phy: broadcom: Wire suspend/resume for BCM54612E + +The BCM54612E ethernet PHY supports IDDQ-SR. +Therefore wire-up the suspend and resume callbacks +to point to bcm54xx_suspend() and bcm54xx_resume(). + +Signed-off-by: Marco von Rosenberg +Acked-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/phy/broadcom.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/phy/broadcom.c ++++ b/drivers/net/phy/broadcom.c +@@ -942,6 +942,8 @@ static struct phy_driver broadcom_driver + .config_intr = bcm_phy_config_intr, + .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, ++ .suspend = bcm54xx_suspend, ++ .resume = bcm54xx_resume, + }, { + .phy_id = PHY_ID_BCM54616S, + .phy_id_mask = 0xfffffff0, diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch index d7d1c08fce..afce0cf04c 100644 --- a/lede/target/linux/generic/backport-6.1/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-01-net-ethernet-mtk_ppe-add-MTK_FOE_ENTRY_V-1-2-_SIZE-m.patch @@ -17,7 +17,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4765,7 +4765,7 @@ static const struct mtk_soc_data mt7621_ +@@ -4764,7 +4764,7 @@ static const struct mtk_soc_data mt7621_ .required_pctl = false, .offload_version = 1, .hash_offset = 2, @@ -26,7 +26,7 @@ Signed-off-by: David S. Miller .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4786,7 +4786,7 @@ static const struct mtk_soc_data mt7622_ +@@ -4785,7 +4785,7 @@ static const struct mtk_soc_data mt7622_ .offload_version = 2, .hash_offset = 2, .has_accounting = true, @@ -35,7 +35,7 @@ Signed-off-by: David S. Miller .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4805,7 +4805,7 @@ static const struct mtk_soc_data mt7623_ +@@ -4804,7 +4804,7 @@ static const struct mtk_soc_data mt7623_ .required_pctl = true, .offload_version = 1, .hash_offset = 2, @@ -44,7 +44,7 @@ Signed-off-by: David S. Miller .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4843,8 +4843,8 @@ static const struct mtk_soc_data mt7981_ +@@ -4842,8 +4842,8 @@ static const struct mtk_soc_data mt7981_ .required_pctl = false, .offload_version = 2, .hash_offset = 4, @@ -54,7 +54,7 @@ Signed-off-by: David S. Miller .txrx = { .txd_size = sizeof(struct mtk_tx_dma_v2), .rxd_size = sizeof(struct mtk_rx_dma_v2), -@@ -4864,8 +4864,8 @@ static const struct mtk_soc_data mt7986_ +@@ -4863,8 +4863,8 @@ static const struct mtk_soc_data mt7986_ .required_pctl = false, .offload_version = 2, .hash_offset = 4, diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch index fb54f404b2..28bf2b6d5f 100644 --- a/lede/target/linux/generic/backport-6.1/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-02-net-ethernet-mtk_eth_soc-remove-incorrect-PLL-config.patch @@ -95,7 +95,7 @@ Signed-off-by: Paolo Abeni /* mt7623_pad_clk_setup */ for (i = 0 ; i < NUM_TRGMII_CTRL; i++) -@@ -4342,13 +4314,19 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4341,13 +4313,19 @@ static int mtk_add_mac(struct mtk_eth *e mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD; @@ -121,7 +121,7 @@ Signed-off-by: Paolo Abeni if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_TRGMII) && !mac->id) __set_bit(PHY_INTERFACE_MODE_TRGMII, -@@ -4806,6 +4784,7 @@ static const struct mtk_soc_data mt7623_ +@@ -4805,6 +4783,7 @@ static const struct mtk_soc_data mt7623_ .offload_version = 1, .hash_offset = 2, .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch index 500fad3b84..fd458a67bc 100644 --- a/lede/target/linux/generic/backport-6.1/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-03-net-ethernet-mtk_eth_soc-remove-mac_pcs_get_state-an.patch @@ -62,15 +62,15 @@ Signed-off-by: Paolo Abeni static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode, phy_interface_t interface) { -@@ -708,7 +676,6 @@ static void mtk_mac_link_up(struct phyli +@@ -707,7 +675,6 @@ static void mtk_mac_link_up(struct phyli + static const struct phylink_mac_ops mtk_phylink_ops = { - .validate = phylink_generic_validate, .mac_select_pcs = mtk_mac_select_pcs, - .mac_pcs_get_state = mtk_mac_pcs_get_state, .mac_config = mtk_mac_config, .mac_finish = mtk_mac_finish, .mac_link_down = mtk_mac_link_down, -@@ -4309,8 +4276,6 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4308,8 +4275,6 @@ static int mtk_add_mac(struct mtk_eth *e mac->phylink_config.dev = ð->netdev[id]->dev; mac->phylink_config.type = PHYLINK_NETDEV; diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch index 3b1225e94e..aa259e7175 100644 --- a/lede/target/linux/generic/backport-6.1/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-05-net-ethernet-mtk_eth_soc-add-version-in-mtk_soc_data.patch @@ -32,7 +32,7 @@ Signed-off-by: Jakub Kicinski val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; if (IS_ENABLED(CONFIG_SOC_MT7621)) { -@@ -955,7 +955,7 @@ static bool mtk_rx_get_desc(struct mtk_e +@@ -954,7 +954,7 @@ static bool mtk_rx_get_desc(struct mtk_e rxd->rxd1 = READ_ONCE(dma_rxd->rxd1); rxd->rxd3 = READ_ONCE(dma_rxd->rxd3); rxd->rxd4 = READ_ONCE(dma_rxd->rxd4); @@ -41,7 +41,7 @@ Signed-off-by: Jakub Kicinski rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); } -@@ -1013,7 +1013,7 @@ static int mtk_init_fq_dma(struct mtk_et +@@ -1012,7 +1012,7 @@ static int mtk_init_fq_dma(struct mtk_et txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE); txd->txd4 = 0; @@ -50,7 +50,7 @@ Signed-off-by: Jakub Kicinski txd->txd5 = 0; txd->txd6 = 0; txd->txd7 = 0; -@@ -1204,7 +1204,7 @@ static void mtk_tx_set_dma_desc(struct n +@@ -1203,7 +1203,7 @@ static void mtk_tx_set_dma_desc(struct n struct mtk_mac *mac = netdev_priv(dev); struct mtk_eth *eth = mac->hw; @@ -59,7 +59,7 @@ Signed-off-by: Jakub Kicinski mtk_tx_set_dma_desc_v2(dev, txd, info); else mtk_tx_set_dma_desc_v1(dev, txd, info); -@@ -1511,7 +1511,7 @@ static void mtk_update_rx_cpu_idx(struct +@@ -1510,7 +1510,7 @@ static void mtk_update_rx_cpu_idx(struct static bool mtk_page_pool_enabled(struct mtk_eth *eth) { @@ -68,7 +68,7 @@ Signed-off-by: Jakub Kicinski } static struct page_pool *mtk_create_page_pool(struct mtk_eth *eth, -@@ -1853,7 +1853,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -1852,7 +1852,7 @@ static int mtk_poll_rx(struct napi_struc break; /* find out which mac the packet come from. values start at 1 */ @@ -77,7 +77,7 @@ Signed-off-by: Jakub Kicinski mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1; else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) && !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) -@@ -1949,7 +1949,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -1948,7 +1948,7 @@ static int mtk_poll_rx(struct napi_struc skb->dev = netdev; bytes += skb->len; @@ -86,7 +86,7 @@ Signed-off-by: Jakub Kicinski reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5); hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY; if (hash != MTK_RXD5_FOE_ENTRY) -@@ -1974,8 +1974,8 @@ static int mtk_poll_rx(struct napi_struc +@@ -1973,8 +1973,8 @@ static int mtk_poll_rx(struct napi_struc /* When using VLAN untagging in combination with DSA, the * hardware treats the MTK special tag as a VLAN and untags it. */ @@ -97,7 +97,7 @@ Signed-off-by: Jakub Kicinski unsigned int port = RX_DMA_VPID(trxd.rxd3) & GENMASK(2, 0); if (port < ARRAY_SIZE(eth->dsa_meta) && -@@ -2285,7 +2285,7 @@ static int mtk_tx_alloc(struct mtk_eth * +@@ -2284,7 +2284,7 @@ static int mtk_tx_alloc(struct mtk_eth * txd->txd2 = next_ptr; txd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; txd->txd4 = 0; @@ -106,7 +106,7 @@ Signed-off-by: Jakub Kicinski txd->txd5 = 0; txd->txd6 = 0; txd->txd7 = 0; -@@ -2338,14 +2338,14 @@ static int mtk_tx_alloc(struct mtk_eth * +@@ -2337,14 +2337,14 @@ static int mtk_tx_alloc(struct mtk_eth * FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) | FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) | MTK_QTX_SCH_LEAKY_BUCKET_SIZE; @@ -123,7 +123,7 @@ Signed-off-by: Jakub Kicinski mtk_w32(eth, val, soc->reg_map->qdma.tx_sch_rate + 4); } else { mtk_w32(eth, ring->phys_pdma, MT7628_TX_BASE_PTR0); -@@ -2474,7 +2474,7 @@ static int mtk_rx_alloc(struct mtk_eth * +@@ -2473,7 +2473,7 @@ static int mtk_rx_alloc(struct mtk_eth * rxd->rxd3 = 0; rxd->rxd4 = 0; @@ -132,7 +132,7 @@ Signed-off-by: Jakub Kicinski rxd->rxd5 = 0; rxd->rxd6 = 0; rxd->rxd7 = 0; -@@ -3025,7 +3025,7 @@ static int mtk_start_dma(struct mtk_eth +@@ -3024,7 +3024,7 @@ static int mtk_start_dma(struct mtk_eth MTK_TX_BT_32DWORDS | MTK_NDP_CO_PRO | MTK_RX_2B_OFFSET | MTK_TX_WB_DDONE; @@ -141,7 +141,7 @@ Signed-off-by: Jakub Kicinski val |= MTK_MUTLI_CNT | MTK_RESV_BUF | MTK_WCOMP_EN | MTK_DMAD_WR_WDONE | MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN; -@@ -3167,7 +3167,7 @@ static int mtk_open(struct net_device *d +@@ -3166,7 +3166,7 @@ static int mtk_open(struct net_device *d phylink_start(mac->phylink); netif_tx_start_all_queues(dev); @@ -150,7 +150,7 @@ Signed-off-by: Jakub Kicinski return 0; if (mtk_uses_dsa(dev) && !eth->prog) { -@@ -3432,7 +3432,7 @@ static void mtk_hw_reset(struct mtk_eth +@@ -3431,7 +3431,7 @@ static void mtk_hw_reset(struct mtk_eth { u32 val; @@ -159,7 +159,7 @@ Signed-off-by: Jakub Kicinski regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); val = RSTCTRL_PPE0_V2; } else { -@@ -3444,7 +3444,7 @@ static void mtk_hw_reset(struct mtk_eth +@@ -3443,7 +3443,7 @@ static void mtk_hw_reset(struct mtk_eth ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); @@ -168,7 +168,7 @@ Signed-off-by: Jakub Kicinski regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0x3ffffff); } -@@ -3470,7 +3470,7 @@ static void mtk_hw_warm_reset(struct mtk +@@ -3469,7 +3469,7 @@ static void mtk_hw_warm_reset(struct mtk return; } @@ -177,7 +177,7 @@ Signed-off-by: Jakub Kicinski rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V2; else rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0; -@@ -3640,7 +3640,7 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -3639,7 +3639,7 @@ static int mtk_hw_init(struct mtk_eth *e else mtk_hw_reset(eth); @@ -186,7 +186,7 @@ Signed-off-by: Jakub Kicinski /* Set FE to PDMAv2 if necessary */ val = mtk_r32(eth, MTK_FE_GLO_MISC); mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); -@@ -3677,7 +3677,7 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -3676,7 +3676,7 @@ static int mtk_hw_init(struct mtk_eth *e */ val = mtk_r32(eth, MTK_CDMQ_IG_CTRL); mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL); @@ -195,7 +195,7 @@ Signed-off-by: Jakub Kicinski val = mtk_r32(eth, MTK_CDMP_IG_CTRL); mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); -@@ -3699,7 +3699,7 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -3698,7 +3698,7 @@ static int mtk_hw_init(struct mtk_eth *e mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4); mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); @@ -204,7 +204,7 @@ Signed-off-by: Jakub Kicinski /* PSE should not drop port8 and port9 packets from WDMA Tx */ mtk_w32(eth, 0x00000300, PSE_DROP_CFG); -@@ -4488,7 +4488,7 @@ static int mtk_probe(struct platform_dev +@@ -4487,7 +4487,7 @@ static int mtk_probe(struct platform_dev } } @@ -213,7 +213,7 @@ Signed-off-by: Jakub Kicinski res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { err = -EINVAL; -@@ -4596,9 +4596,8 @@ static int mtk_probe(struct platform_dev +@@ -4595,9 +4595,8 @@ static int mtk_probe(struct platform_dev } if (eth->soc->offload_version) { @@ -224,7 +224,7 @@ Signed-off-by: Jakub Kicinski num_ppe = min_t(u32, ARRAY_SIZE(eth->ppe), num_ppe); for (i = 0; i < num_ppe; i++) { u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400; -@@ -4690,6 +4689,7 @@ static const struct mtk_soc_data mt2701_ +@@ -4689,6 +4688,7 @@ static const struct mtk_soc_data mt2701_ .hw_features = MTK_HW_FEATURES, .required_clks = MT7623_CLKS_BITMAP, .required_pctl = true, @@ -232,7 +232,7 @@ Signed-off-by: Jakub Kicinski .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4706,6 +4706,7 @@ static const struct mtk_soc_data mt7621_ +@@ -4705,6 +4705,7 @@ static const struct mtk_soc_data mt7621_ .hw_features = MTK_HW_FEATURES, .required_clks = MT7621_CLKS_BITMAP, .required_pctl = false, @@ -240,7 +240,7 @@ Signed-off-by: Jakub Kicinski .offload_version = 1, .hash_offset = 2, .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, -@@ -4726,6 +4727,7 @@ static const struct mtk_soc_data mt7622_ +@@ -4725,6 +4726,7 @@ static const struct mtk_soc_data mt7622_ .hw_features = MTK_HW_FEATURES, .required_clks = MT7622_CLKS_BITMAP, .required_pctl = false, @@ -248,7 +248,7 @@ Signed-off-by: Jakub Kicinski .offload_version = 2, .hash_offset = 2, .has_accounting = true, -@@ -4746,6 +4748,7 @@ static const struct mtk_soc_data mt7623_ +@@ -4745,6 +4747,7 @@ static const struct mtk_soc_data mt7623_ .hw_features = MTK_HW_FEATURES, .required_clks = MT7623_CLKS_BITMAP, .required_pctl = true, @@ -256,7 +256,7 @@ Signed-off-by: Jakub Kicinski .offload_version = 1, .hash_offset = 2, .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, -@@ -4768,6 +4771,7 @@ static const struct mtk_soc_data mt7629_ +@@ -4767,6 +4770,7 @@ static const struct mtk_soc_data mt7629_ .required_clks = MT7629_CLKS_BITMAP, .required_pctl = false, .has_accounting = true, @@ -264,7 +264,7 @@ Signed-off-by: Jakub Kicinski .txrx = { .txd_size = sizeof(struct mtk_tx_dma), .rxd_size = sizeof(struct mtk_rx_dma), -@@ -4785,6 +4789,7 @@ static const struct mtk_soc_data mt7981_ +@@ -4784,6 +4788,7 @@ static const struct mtk_soc_data mt7981_ .hw_features = MTK_HW_FEATURES, .required_clks = MT7981_CLKS_BITMAP, .required_pctl = false, @@ -272,7 +272,7 @@ Signed-off-by: Jakub Kicinski .offload_version = 2, .hash_offset = 4, .has_accounting = true, -@@ -4806,6 +4811,7 @@ static const struct mtk_soc_data mt7986_ +@@ -4805,6 +4810,7 @@ static const struct mtk_soc_data mt7986_ .hw_features = MTK_HW_FEATURES, .required_clks = MT7986_CLKS_BITMAP, .required_pctl = false, @@ -280,7 +280,7 @@ Signed-off-by: Jakub Kicinski .offload_version = 2, .hash_offset = 4, .has_accounting = true, -@@ -4826,6 +4832,7 @@ static const struct mtk_soc_data rt5350_ +@@ -4825,6 +4831,7 @@ static const struct mtk_soc_data rt5350_ .hw_features = MTK_HW_FEATURES_MT7628, .required_clks = MT7628_CLKS_BITMAP, .required_pctl = false, diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch index 8071658313..3db23f7897 100644 --- a/lede/target/linux/generic/backport-6.1/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-07-net-ethernet-mtk_eth_soc-rely-on-MTK_MAX_DEVS-and-re.patch @@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -881,7 +881,7 @@ static void mtk_stats_update(struct mtk_ +@@ -880,7 +880,7 @@ static void mtk_stats_update(struct mtk_ { int i; @@ -26,7 +26,7 @@ Signed-off-by: Jakub Kicinski if (!eth->mac[i] || !eth->mac[i]->hw_stats) continue; if (spin_trylock(ð->mac[i]->hw_stats->stats_lock)) { -@@ -1386,7 +1386,7 @@ static int mtk_queue_stopped(struct mtk_ +@@ -1385,7 +1385,7 @@ static int mtk_queue_stopped(struct mtk_ { int i; @@ -35,7 +35,7 @@ Signed-off-by: Jakub Kicinski if (!eth->netdev[i]) continue; if (netif_queue_stopped(eth->netdev[i])) -@@ -1400,7 +1400,7 @@ static void mtk_wake_queue(struct mtk_et +@@ -1399,7 +1399,7 @@ static void mtk_wake_queue(struct mtk_et { int i; @@ -44,7 +44,7 @@ Signed-off-by: Jakub Kicinski if (!eth->netdev[i]) continue; netif_tx_wake_all_queues(eth->netdev[i]); -@@ -1859,7 +1859,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -1858,7 +1858,7 @@ static int mtk_poll_rx(struct napi_struc !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) mac = RX_DMA_GET_SPORT(trxd.rxd4) - 1; @@ -53,7 +53,7 @@ Signed-off-by: Jakub Kicinski !eth->netdev[mac])) goto release_desc; -@@ -2899,7 +2899,7 @@ static void mtk_dma_free(struct mtk_eth +@@ -2898,7 +2898,7 @@ static void mtk_dma_free(struct mtk_eth const struct mtk_soc_data *soc = eth->soc; int i; @@ -62,7 +62,7 @@ Signed-off-by: Jakub Kicinski if (eth->netdev[i]) netdev_reset_queue(eth->netdev[i]); if (eth->scratch_ring) { -@@ -3053,8 +3053,13 @@ static void mtk_gdm_config(struct mtk_et +@@ -3052,8 +3052,13 @@ static void mtk_gdm_config(struct mtk_et if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) return; @@ -78,7 +78,7 @@ Signed-off-by: Jakub Kicinski /* default setup the forward port to send frame to PDMA */ val &= ~0xffff; -@@ -3064,7 +3069,7 @@ static void mtk_gdm_config(struct mtk_et +@@ -3063,7 +3068,7 @@ static void mtk_gdm_config(struct mtk_et val |= config; @@ -87,7 +87,7 @@ Signed-off-by: Jakub Kicinski val |= MTK_GDMA_SPECIAL_TAG; mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); -@@ -3661,15 +3666,15 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -3660,15 +3665,15 @@ static int mtk_hw_init(struct mtk_eth *e * up with the more appropriate value when mtk_mac_config call is being * invoked. */ @@ -109,7 +109,7 @@ Signed-off-by: Jakub Kicinski } /* Indicates CDM to parse the MTK special tag from CPU -@@ -3849,7 +3854,7 @@ static void mtk_pending_work(struct work +@@ -3848,7 +3853,7 @@ static void mtk_pending_work(struct work mtk_prepare_for_reset(eth); /* stop all devices to make sure that dma is properly shut down */ @@ -118,7 +118,7 @@ Signed-off-by: Jakub Kicinski if (!eth->netdev[i] || !netif_running(eth->netdev[i])) continue; -@@ -3865,8 +3870,8 @@ static void mtk_pending_work(struct work +@@ -3864,8 +3869,8 @@ static void mtk_pending_work(struct work mtk_hw_init(eth, true); /* restart DMA and enable IRQs */ @@ -129,7 +129,7 @@ Signed-off-by: Jakub Kicinski continue; if (mtk_open(eth->netdev[i])) { -@@ -3893,7 +3898,7 @@ static int mtk_free_dev(struct mtk_eth * +@@ -3892,7 +3897,7 @@ static int mtk_free_dev(struct mtk_eth * { int i; @@ -138,7 +138,7 @@ Signed-off-by: Jakub Kicinski if (!eth->netdev[i]) continue; free_netdev(eth->netdev[i]); -@@ -3912,7 +3917,7 @@ static int mtk_unreg_dev(struct mtk_eth +@@ -3911,7 +3916,7 @@ static int mtk_unreg_dev(struct mtk_eth { int i; @@ -147,7 +147,7 @@ Signed-off-by: Jakub Kicinski struct mtk_mac *mac; if (!eth->netdev[i]) continue; -@@ -4213,7 +4218,7 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4212,7 +4217,7 @@ static int mtk_add_mac(struct mtk_eth *e } id = be32_to_cpup(_id); @@ -156,7 +156,7 @@ Signed-off-by: Jakub Kicinski dev_err(eth->dev, "%d is not a valid mac id\n", id); return -EINVAL; } -@@ -4358,7 +4363,7 @@ void mtk_eth_set_dma_device(struct mtk_e +@@ -4357,7 +4362,7 @@ void mtk_eth_set_dma_device(struct mtk_e rtnl_lock(); @@ -165,7 +165,7 @@ Signed-off-by: Jakub Kicinski dev = eth->netdev[i]; if (!dev || !(dev->flags & IFF_UP)) -@@ -4664,7 +4669,7 @@ static int mtk_remove(struct platform_de +@@ -4663,7 +4668,7 @@ static int mtk_remove(struct platform_de int i; /* stop all devices to make sure that dma is properly shut down */ diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch index 1a9b31f526..e40dc3d0a9 100644 --- a/lede/target/linux/generic/backport-6.1/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-08-net-ethernet-mtk_eth_soc-add-NETSYS_V3-version-suppo.patch @@ -18,7 +18,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -861,17 +861,32 @@ void mtk_stats_update_mac(struct mtk_mac +@@ -860,17 +860,32 @@ void mtk_stats_update_mac(struct mtk_mac mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x20 + offs); hw_stats->rx_flow_control_packets += mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x24 + offs); @@ -62,7 +62,7 @@ Signed-off-by: Jakub Kicinski } u64_stats_update_end(&hw_stats->syncp); -@@ -1175,7 +1190,10 @@ static void mtk_tx_set_dma_desc_v2(struc +@@ -1174,7 +1189,10 @@ static void mtk_tx_set_dma_desc_v2(struc data |= TX_DMA_LS0; WRITE_ONCE(desc->txd3, data); @@ -74,7 +74,7 @@ Signed-off-by: Jakub Kicinski data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid); WRITE_ONCE(desc->txd4, data); -@@ -1186,6 +1204,8 @@ static void mtk_tx_set_dma_desc_v2(struc +@@ -1185,6 +1203,8 @@ static void mtk_tx_set_dma_desc_v2(struc /* tx checksum offload */ if (info->csum) data |= TX_DMA_CHKSUM_V2; @@ -83,7 +83,7 @@ Signed-off-by: Jakub Kicinski } WRITE_ONCE(desc->txd5, data); -@@ -1251,8 +1271,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1250,8 +1270,7 @@ static int mtk_tx_map(struct sk_buff *sk mtk_tx_set_dma_desc(dev, itxd, &txd_info); itx_buf->flags |= MTK_TX_FLAGS_SINGLE0; @@ -93,7 +93,7 @@ Signed-off-by: Jakub Kicinski setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size, k++); -@@ -1300,8 +1319,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1299,8 +1318,7 @@ static int mtk_tx_map(struct sk_buff *sk memset(tx_buf, 0, sizeof(*tx_buf)); tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; tx_buf->flags |= MTK_TX_FLAGS_PAGE0; @@ -103,7 +103,7 @@ Signed-off-by: Jakub Kicinski setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr, txd_info.size, k++); -@@ -1603,7 +1621,7 @@ static int mtk_xdp_frame_map(struct mtk_ +@@ -1602,7 +1620,7 @@ static int mtk_xdp_frame_map(struct mtk_ } mtk_tx_set_dma_desc(dev, txd, txd_info); @@ -112,7 +112,7 @@ Signed-off-by: Jakub Kicinski tx_buf->type = dma_map ? MTK_TYPE_XDP_NDO : MTK_TYPE_XDP_TX; tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; -@@ -1853,11 +1871,24 @@ static int mtk_poll_rx(struct napi_struc +@@ -1852,11 +1870,24 @@ static int mtk_poll_rx(struct napi_struc break; /* find out which mac the packet come from. values start at 1 */ @@ -141,7 +141,7 @@ Signed-off-by: Jakub Kicinski if (unlikely(mac < 0 || mac >= MTK_MAX_DEVS || !eth->netdev[mac])) -@@ -2079,7 +2110,6 @@ static int mtk_poll_tx_qdma(struct mtk_e +@@ -2078,7 +2109,6 @@ static int mtk_poll_tx_qdma(struct mtk_e while ((cpu != dma) && budget) { u32 next_cpu = desc->txd2; @@ -149,7 +149,7 @@ Signed-off-by: Jakub Kicinski desc = mtk_qdma_phys_to_virt(ring, desc->txd2); if ((desc->txd3 & TX_DMA_OWNER_CPU) == 0) -@@ -2087,15 +2117,13 @@ static int mtk_poll_tx_qdma(struct mtk_e +@@ -2086,15 +2116,13 @@ static int mtk_poll_tx_qdma(struct mtk_e tx_buf = mtk_desc_to_tx_buf(ring, desc, eth->soc->txrx.txd_size); @@ -167,7 +167,7 @@ Signed-off-by: Jakub Kicinski budget--; } -@@ -3704,7 +3732,24 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -3703,7 +3731,24 @@ static int mtk_hw_init(struct mtk_eth *e mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4); mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); @@ -193,7 +193,7 @@ Signed-off-by: Jakub Kicinski /* PSE should not drop port8 and port9 packets from WDMA Tx */ mtk_w32(eth, 0x00000300, PSE_DROP_CFG); -@@ -4266,7 +4311,11 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4265,7 +4310,11 @@ static int mtk_add_mac(struct mtk_eth *e } spin_lock_init(&mac->hw_stats->stats_lock); u64_stats_init(&mac->hw_stats->syncp); diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch index 8c24321dd4..8b1493ce14 100644 --- a/lede/target/linux/generic/backport-6.1/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-11-net-ethernet-mtk_eth_soc-add-basic-support-for-MT798.patch @@ -219,7 +219,7 @@ Signed-off-by: Jakub Kicinski return; err_phy: -@@ -725,11 +841,15 @@ static int mtk_mdio_init(struct mtk_eth +@@ -724,11 +840,15 @@ static int mtk_mdio_init(struct mtk_eth } divider = min_t(unsigned int, DIV_ROUND_UP(MDC_MAX_FREQ, max_clk), 63); @@ -239,7 +239,7 @@ Signed-off-by: Jakub Kicinski dev_dbg(eth->dev, "MDC is running on %d Hz\n", MDC_MAX_FREQ / divider); -@@ -1190,10 +1310,19 @@ static void mtk_tx_set_dma_desc_v2(struc +@@ -1189,10 +1309,19 @@ static void mtk_tx_set_dma_desc_v2(struc data |= TX_DMA_LS0; WRITE_ONCE(desc->txd3, data); @@ -263,7 +263,7 @@ Signed-off-by: Jakub Kicinski data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid); WRITE_ONCE(desc->txd4, data); -@@ -4360,6 +4489,17 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4359,6 +4488,17 @@ static int mtk_add_mac(struct mtk_eth *e mac->phylink_config.supported_interfaces); } @@ -281,7 +281,7 @@ Signed-off-by: Jakub Kicinski phylink = phylink_create(&mac->phylink_config, of_fwnode_handle(mac->of_node), phy_mode, &mtk_phylink_ops); -@@ -4880,6 +5020,24 @@ static const struct mtk_soc_data mt7986_ +@@ -4879,6 +5019,24 @@ static const struct mtk_soc_data mt7986_ }, }; @@ -306,7 +306,7 @@ Signed-off-by: Jakub Kicinski static const struct mtk_soc_data rt5350_data = { .reg_map = &mt7628_reg_map, .caps = MT7628_CAPS, -@@ -4898,14 +5056,15 @@ static const struct mtk_soc_data rt5350_ +@@ -4897,14 +5055,15 @@ static const struct mtk_soc_data rt5350_ }; const struct of_device_id of_mtk_match[] = { diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch index 3dc4662d1a..bb48dadec0 100644 --- a/lede/target/linux/generic/backport-6.1/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-12-net-ethernet-mtk_eth_soc-enable-page_pool-support-fo.patch @@ -16,7 +16,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1658,7 +1658,7 @@ static void mtk_update_rx_cpu_idx(struct +@@ -1657,7 +1657,7 @@ static void mtk_update_rx_cpu_idx(struct static bool mtk_page_pool_enabled(struct mtk_eth *eth) { diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch index 32f26d7d27..bb8deb9846 100644 --- a/lede/target/linux/generic/backport-6.1/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-13-net-ethernet-mtk_eth_soc-enable-nft-hw-flowtable_off.patch @@ -18,7 +18,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -5028,6 +5028,9 @@ static const struct mtk_soc_data mt7988_ +@@ -5027,6 +5027,9 @@ static const struct mtk_soc_data mt7988_ .required_clks = MT7988_CLKS_BITMAP, .required_pctl = false, .version = 3, diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch index 876bdd5dd3..c985b6a9c7 100644 --- a/lede/target/linux/generic/backport-6.1/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-14-net-ethernet-mtk_eth_soc-support-per-flow-accounting.patch @@ -20,7 +20,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -5030,6 +5030,7 @@ static const struct mtk_soc_data mt7988_ +@@ -5029,6 +5029,7 @@ static const struct mtk_soc_data mt7988_ .version = 3, .offload_version = 2, .hash_offset = 4, diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch index 05a18364d6..e87e0f2522 100644 --- a/lede/target/linux/generic/backport-6.1/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-17-net-ethernet-mtk_eth_soc-add-reset-bits-for-MT7988.patch @@ -16,7 +16,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3594,19 +3594,34 @@ static void mtk_hw_reset(struct mtk_eth +@@ -3593,19 +3593,34 @@ static void mtk_hw_reset(struct mtk_eth { u32 val; @@ -56,7 +56,7 @@ Signed-off-by: Jakub Kicinski regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0x3ffffff); } -@@ -3632,13 +3647,21 @@ static void mtk_hw_warm_reset(struct mtk +@@ -3631,13 +3646,21 @@ static void mtk_hw_warm_reset(struct mtk return; } @@ -83,7 +83,7 @@ Signed-off-by: Jakub Kicinski regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, rst_mask, rst_mask); -@@ -3990,11 +4013,17 @@ static void mtk_prepare_for_reset(struct +@@ -3989,11 +4012,17 @@ static void mtk_prepare_for_reset(struct u32 val; int i; @@ -106,7 +106,7 @@ Signed-off-by: Jakub Kicinski /* adjust PPE configurations to prepare for reset */ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) -@@ -4055,11 +4084,18 @@ static void mtk_pending_work(struct work +@@ -4054,11 +4083,18 @@ static void mtk_pending_work(struct work } } diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch index 74ac8dc898..2d0951a9ec 100644 --- a/lede/target/linux/generic/backport-6.1/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-18-net-ethernet-mtk_eth_soc-add-support-for-in-SoC-SRAM.patch @@ -20,7 +20,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1118,10 +1118,13 @@ static int mtk_init_fq_dma(struct mtk_et +@@ -1117,10 +1117,13 @@ static int mtk_init_fq_dma(struct mtk_et dma_addr_t dma_addr; int i; @@ -38,7 +38,7 @@ Signed-off-by: Jakub Kicinski if (unlikely(!eth->scratch_ring)) return -ENOMEM; -@@ -2429,8 +2432,14 @@ static int mtk_tx_alloc(struct mtk_eth * +@@ -2428,8 +2431,14 @@ static int mtk_tx_alloc(struct mtk_eth * if (!ring->buf) goto no_tx_mem; @@ -55,7 +55,7 @@ Signed-off-by: Jakub Kicinski if (!ring->dma) goto no_tx_mem; -@@ -2529,8 +2538,7 @@ static void mtk_tx_clean(struct mtk_eth +@@ -2528,8 +2537,7 @@ static void mtk_tx_clean(struct mtk_eth kfree(ring->buf); ring->buf = NULL; } @@ -65,7 +65,7 @@ Signed-off-by: Jakub Kicinski dma_free_coherent(eth->dma_dev, ring->dma_size * soc->txrx.txd_size, ring->dma, ring->phys); -@@ -2549,9 +2557,14 @@ static int mtk_rx_alloc(struct mtk_eth * +@@ -2548,9 +2556,14 @@ static int mtk_rx_alloc(struct mtk_eth * { const struct mtk_reg_map *reg_map = eth->soc->reg_map; struct mtk_rx_ring *ring; @@ -81,7 +81,7 @@ Signed-off-by: Jakub Kicinski if (rx_flag == MTK_RX_FLAGS_QDMA) { if (ring_no) return -EINVAL; -@@ -2586,9 +2599,20 @@ static int mtk_rx_alloc(struct mtk_eth * +@@ -2585,9 +2598,20 @@ static int mtk_rx_alloc(struct mtk_eth * ring->page_pool = pp; } @@ -105,7 +105,7 @@ Signed-off-by: Jakub Kicinski if (!ring->dma) return -ENOMEM; -@@ -2673,7 +2697,7 @@ static int mtk_rx_alloc(struct mtk_eth * +@@ -2672,7 +2696,7 @@ static int mtk_rx_alloc(struct mtk_eth * return 0; } @@ -114,7 +114,7 @@ Signed-off-by: Jakub Kicinski { int i; -@@ -2696,7 +2720,7 @@ static void mtk_rx_clean(struct mtk_eth +@@ -2695,7 +2719,7 @@ static void mtk_rx_clean(struct mtk_eth ring->data = NULL; } @@ -123,7 +123,7 @@ Signed-off-by: Jakub Kicinski dma_free_coherent(eth->dma_dev, ring->dma_size * eth->soc->txrx.rxd_size, ring->dma, ring->phys); -@@ -3059,7 +3083,7 @@ static void mtk_dma_free(struct mtk_eth +@@ -3058,7 +3082,7 @@ static void mtk_dma_free(struct mtk_eth for (i = 0; i < MTK_MAX_DEVS; i++) if (eth->netdev[i]) netdev_reset_queue(eth->netdev[i]); @@ -132,7 +132,7 @@ Signed-off-by: Jakub Kicinski dma_free_coherent(eth->dma_dev, MTK_QDMA_RING_SIZE * soc->txrx.txd_size, eth->scratch_ring, eth->phy_scratch_ring); -@@ -3067,13 +3091,13 @@ static void mtk_dma_free(struct mtk_eth +@@ -3066,13 +3090,13 @@ static void mtk_dma_free(struct mtk_eth eth->phy_scratch_ring = 0; } mtk_tx_clean(eth); @@ -149,7 +149,7 @@ Signed-off-by: Jakub Kicinski } kfree(eth->scratch_head); -@@ -4641,7 +4665,7 @@ static int mtk_sgmii_init(struct mtk_eth +@@ -4640,7 +4664,7 @@ static int mtk_sgmii_init(struct mtk_eth static int mtk_probe(struct platform_device *pdev) { @@ -158,7 +158,7 @@ Signed-off-by: Jakub Kicinski struct device_node *mac_np; struct mtk_eth *eth; int err, i; -@@ -4661,6 +4685,20 @@ static int mtk_probe(struct platform_dev +@@ -4660,6 +4684,20 @@ static int mtk_probe(struct platform_dev if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) eth->ip_align = NET_IP_ALIGN; @@ -179,7 +179,7 @@ Signed-off-by: Jakub Kicinski spin_lock_init(ð->page_lock); spin_lock_init(ð->tx_irq_lock); spin_lock_init(ð->rx_irq_lock); -@@ -4724,6 +4762,18 @@ static int mtk_probe(struct platform_dev +@@ -4723,6 +4761,18 @@ static int mtk_probe(struct platform_dev err = -EINVAL; goto err_destroy_sgmii; } diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch index 1584dfd07c..416c4f48ef 100644 --- a/lede/target/linux/generic/backport-6.1/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-19-net-ethernet-mtk_eth_soc-support-36-bit-DMA-addressi.patch @@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1311,6 +1311,10 @@ static void mtk_tx_set_dma_desc_v2(struc +@@ -1310,6 +1310,10 @@ static void mtk_tx_set_dma_desc_v2(struc data = TX_DMA_PLEN0(info->size); if (info->last) data |= TX_DMA_LS0; @@ -30,7 +30,7 @@ Signed-off-by: Jakub Kicinski WRITE_ONCE(desc->txd3, data); /* set forward port */ -@@ -1980,6 +1984,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -1979,6 +1983,7 @@ static int mtk_poll_rx(struct napi_struc bool xdp_flush = false; int idx; struct sk_buff *skb; @@ -38,7 +38,7 @@ Signed-off-by: Jakub Kicinski u8 *data, *new_data; struct mtk_rx_dma_v2 *rxd, trxd; int done = 0, bytes = 0; -@@ -2095,7 +2100,10 @@ static int mtk_poll_rx(struct napi_struc +@@ -2094,7 +2099,10 @@ static int mtk_poll_rx(struct napi_struc goto release_desc; } @@ -50,7 +50,7 @@ Signed-off-by: Jakub Kicinski ring->buf_size, DMA_FROM_DEVICE); skb = build_skb(data, ring->frag_size); -@@ -2161,6 +2169,9 @@ release_desc: +@@ -2160,6 +2168,9 @@ release_desc: else rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); @@ -60,7 +60,7 @@ Signed-off-by: Jakub Kicinski ring->calc_idx = idx; done++; } -@@ -2653,6 +2664,9 @@ static int mtk_rx_alloc(struct mtk_eth * +@@ -2652,6 +2663,9 @@ static int mtk_rx_alloc(struct mtk_eth * else rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); @@ -70,7 +70,7 @@ Signed-off-by: Jakub Kicinski rxd->rxd3 = 0; rxd->rxd4 = 0; if (mtk_is_netsys_v2_or_greater(eth)) { -@@ -2699,6 +2713,7 @@ static int mtk_rx_alloc(struct mtk_eth * +@@ -2698,6 +2712,7 @@ static int mtk_rx_alloc(struct mtk_eth * static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_sram) { @@ -78,7 +78,7 @@ Signed-off-by: Jakub Kicinski int i; if (ring->data && ring->dma) { -@@ -2712,7 +2727,10 @@ static void mtk_rx_clean(struct mtk_eth +@@ -2711,7 +2726,10 @@ static void mtk_rx_clean(struct mtk_eth if (!rxd->rxd1) continue; @@ -90,7 +90,7 @@ Signed-off-by: Jakub Kicinski ring->buf_size, DMA_FROM_DEVICE); mtk_rx_put_buff(ring, ring->data[i], false); } -@@ -4699,6 +4717,14 @@ static int mtk_probe(struct platform_dev +@@ -4698,6 +4716,14 @@ static int mtk_probe(struct platform_dev } } diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch new file mode 100644 index 0000000000..d761866d0d --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-20-net-ethernet-mtk_eth_soc-fix-uninitialized-variable.patch @@ -0,0 +1,44 @@ +From e10a35abb3da12b812cfb6fc6137926a0c81e39a Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 10 Sep 2023 22:40:30 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix uninitialized variable + +Variable dma_addr in function mtk_poll_rx can be uninitialized on +some of the error paths. In practise this doesn't matter, even random +data present in uninitialized stack memory can safely be used in the +way it happens in the error path. + +However, in order to make Smatch happy make sure the variable is +always initialized. + +Signed-off-by: Daniel Golle +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1987,11 +1987,11 @@ static int mtk_poll_rx(struct napi_struc + u8 *data, *new_data; + struct mtk_rx_dma_v2 *rxd, trxd; + int done = 0, bytes = 0; ++ dma_addr_t dma_addr = DMA_MAPPING_ERROR; + + while (done < budget) { + unsigned int pktlen, *rxdcsum; + struct net_device *netdev; +- dma_addr_t dma_addr; + u32 hash, reason; + int mac = 0; + +@@ -2168,7 +2168,8 @@ release_desc: + else + rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA) && ++ likely(dma_addr != DMA_MAPPING_ERROR)) + rxd->rxd2 |= RX_DMA_PREP_ADDR64(dma_addr); + + ring->calc_idx = idx; diff --git a/lede/target/linux/generic/backport-6.1/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch b/lede/target/linux/generic/backport-6.1/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch new file mode 100644 index 0000000000..ac3e3a3e67 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/750-v6.5-21-net-ethernet-mtk_eth_soc-fix-pse_port-configuration-.patch @@ -0,0 +1,33 @@ +From 5a124b1fd3e6cb15a943f0cdfe96aa8f6d3d2f39 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Sat, 9 Sep 2023 20:41:56 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix pse_port configuration for + MT7988 + +MT7988 SoC support 3 NICs. Fix pse_port configuration in +mtk_flow_set_output_device routine if the traffic is offloaded to eth2. +Rely on mtk_pse_port definitions. + +Fixes: 88efedf517e6 ("net: ethernet: mtk_eth_soc: enable nft hw flowtable_offload for MT7988 SoC") +Signed-off-by: Lorenzo Bianconi +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -214,9 +214,11 @@ mtk_flow_set_output_device(struct mtk_et + dsa_port = mtk_flow_get_dsa_port(&dev); + + if (dev == eth->netdev[0]) +- pse_port = 1; ++ pse_port = PSE_GDM1_PORT; + else if (dev == eth->netdev[1]) +- pse_port = 2; ++ pse_port = PSE_GDM2_PORT; ++ else if (dev == eth->netdev[2]) ++ pse_port = PSE_GDM3_PORT; + else + return -EOPNOTSUPP; + diff --git a/lede/target/linux/generic/pending-6.1/736-01-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch b/lede/target/linux/generic/backport-6.1/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch similarity index 96% rename from lede/target/linux/generic/pending-6.1/736-01-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch rename to lede/target/linux/generic/backport-6.1/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch index c29c63bb1d..46da5b283f 100644 --- a/lede/target/linux/generic/pending-6.1/736-01-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch +++ b/lede/target/linux/generic/backport-6.1/751-01-v6.4-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch @@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -1451,6 +1451,9 @@ int mtk_gmac_rgmii_path_setup(struct mtk +@@ -1435,6 +1435,9 @@ int mtk_gmac_rgmii_path_setup(struct mtk int mtk_eth_offload_init(struct mtk_eth *eth); int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data); @@ -31,7 +31,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -235,7 +235,8 @@ out: +@@ -237,7 +237,8 @@ out: } static int @@ -41,7 +41,7 @@ Signed-off-by: Felix Fietkau { struct flow_rule *rule = flow_cls_offload_flow_rule(f); struct flow_action_entry *act; -@@ -452,6 +453,7 @@ mtk_flow_offload_replace(struct mtk_eth +@@ -454,6 +455,7 @@ mtk_flow_offload_replace(struct mtk_eth entry->cookie = f->cookie; memcpy(&entry->data, &foe, sizeof(entry->data)); entry->wed_index = wed_index; @@ -49,7 +49,7 @@ Signed-off-by: Felix Fietkau err = mtk_foe_entry_commit(eth->ppe[entry->ppe_index], entry); if (err < 0) -@@ -520,25 +522,15 @@ mtk_flow_offload_stats(struct mtk_eth *e +@@ -522,25 +524,15 @@ mtk_flow_offload_stats(struct mtk_eth *e static DEFINE_MUTEX(mtk_flow_offload_mutex); @@ -78,7 +78,7 @@ Signed-off-by: Felix Fietkau break; case FLOW_CLS_DESTROY: err = mtk_flow_offload_destroy(eth, cls); -@@ -556,6 +548,23 @@ mtk_eth_setup_tc_block_cb(enum tc_setup_ +@@ -558,6 +550,23 @@ mtk_eth_setup_tc_block_cb(enum tc_setup_ } static int diff --git a/lede/target/linux/generic/pending-6.1/736-02-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch b/lede/target/linux/generic/backport-6.1/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch similarity index 94% rename from lede/target/linux/generic/pending-6.1/736-02-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch rename to lede/target/linux/generic/backport-6.1/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch index 74cb562a51..b1796641a3 100644 --- a/lede/target/linux/generic/pending-6.1/736-02-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch +++ b/lede/target/linux/generic/backport-6.1/751-02-v6.4-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch @@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -657,10 +657,20 @@ void mtk_foe_entry_clear(struct mtk_ppe +@@ -656,10 +656,20 @@ void mtk_foe_entry_clear(struct mtk_ppe static int mtk_foe_entry_commit_l2(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) { diff --git a/lede/target/linux/generic/pending-6.1/736-03-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch b/lede/target/linux/generic/backport-6.1/751-03-v6.4-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch similarity index 94% rename from lede/target/linux/generic/pending-6.1/736-03-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch rename to lede/target/linux/generic/backport-6.1/751-03-v6.4-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch index ecdb345d69..8b8a8e11c7 100644 --- a/lede/target/linux/generic/pending-6.1/736-03-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch +++ b/lede/target/linux/generic/backport-6.1/751-03-v6.4-net-ethernet-mtk_eth_soc-improve-keeping-track-of-of.patch @@ -15,7 +15,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -477,42 +477,43 @@ int mtk_foe_entry_set_queue(struct mtk_e +@@ -476,42 +476,43 @@ int mtk_foe_entry_set_queue(struct mtk_e return 0; } @@ -75,7 +75,7 @@ Signed-off-by: Felix Fietkau struct mtk_foe_entry *hwe = mtk_foe_get_entry(ppe, entry->hash); hwe->ib1 &= ~MTK_FOE_IB1_STATE; -@@ -532,7 +533,8 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp +@@ -531,7 +532,8 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp if (entry->type != MTK_FLOW_TYPE_L2_SUBFLOW) return; @@ -85,7 +85,7 @@ Signed-off-by: Felix Fietkau kfree(entry); } -@@ -548,66 +550,55 @@ static int __mtk_foe_entry_idle_time(str +@@ -547,66 +549,55 @@ static int __mtk_foe_entry_idle_time(str return now - timestamp; } @@ -181,7 +181,7 @@ Signed-off-by: Felix Fietkau } static void -@@ -650,7 +641,8 @@ __mtk_foe_entry_commit(struct mtk_ppe *p +@@ -649,7 +640,8 @@ __mtk_foe_entry_commit(struct mtk_ppe *p void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) { spin_lock_bh(&ppe_lock); @@ -191,7 +191,7 @@ Signed-off-by: Felix Fietkau spin_unlock_bh(&ppe_lock); } -@@ -697,8 +689,8 @@ mtk_foe_entry_commit_subflow(struct mtk_ +@@ -696,8 +688,8 @@ mtk_foe_entry_commit_subflow(struct mtk_ { const struct mtk_soc_data *soc = ppe->eth->soc; struct mtk_flow_entry *flow_info; @@ -201,7 +201,7 @@ Signed-off-by: Felix Fietkau u32 ib1_mask = mtk_get_ib1_pkt_type_mask(ppe->eth) | MTK_FOE_IB1_UDP; int type; -@@ -706,30 +698,30 @@ mtk_foe_entry_commit_subflow(struct mtk_ +@@ -705,30 +697,30 @@ mtk_foe_entry_commit_subflow(struct mtk_ if (!flow_info) return; @@ -242,7 +242,7 @@ Signed-off-by: Felix Fietkau } void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash) -@@ -739,9 +731,11 @@ void __mtk_ppe_check_skb(struct mtk_ppe +@@ -738,9 +730,11 @@ void __mtk_ppe_check_skb(struct mtk_ppe struct mtk_foe_entry *hwe = mtk_foe_get_entry(ppe, hash); struct mtk_flow_entry *entry; struct mtk_foe_bridge key = {}; @@ -254,7 +254,7 @@ Signed-off-by: Felix Fietkau u8 *tag; spin_lock_bh(&ppe_lock); -@@ -749,20 +743,14 @@ void __mtk_ppe_check_skb(struct mtk_ppe +@@ -748,20 +742,14 @@ void __mtk_ppe_check_skb(struct mtk_ppe if (FIELD_GET(MTK_FOE_IB1_STATE, hwe->ib1) == MTK_FOE_STATE_BIND) goto out; @@ -281,7 +281,7 @@ Signed-off-by: Felix Fietkau continue; } -@@ -813,9 +801,17 @@ out: +@@ -810,9 +798,17 @@ out: int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry) { diff --git a/lede/target/linux/generic/pending-6.1/736-04-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch b/lede/target/linux/generic/backport-6.1/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch similarity index 93% rename from lede/target/linux/generic/pending-6.1/736-04-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch rename to lede/target/linux/generic/backport-6.1/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch index e323baeb18..e20f94f1d4 100644 --- a/lede/target/linux/generic/pending-6.1/736-04-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch +++ b/lede/target/linux/generic/backport-6.1/751-04-v6.4-net-ethernet-mediatek-fix-ppe-flow-accounting-for-L2.patch @@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c -@@ -80,9 +80,9 @@ static int mtk_ppe_mib_wait_busy(struct +@@ -79,9 +79,9 @@ static int mtk_ppe_mib_wait_busy(struct int ret; u32 val; @@ -27,7 +27,7 @@ Signed-off-by: Felix Fietkau if (ret) dev_err(ppe->dev, "MIB table busy"); -@@ -90,17 +90,31 @@ static int mtk_ppe_mib_wait_busy(struct +@@ -89,17 +89,31 @@ static int mtk_ppe_mib_wait_busy(struct return ret; } @@ -61,7 +61,7 @@ Signed-off-by: Felix Fietkau cnt_r0 = readl(ppe->base + MTK_PPE_MIB_SER_R0); cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1); -@@ -109,19 +123,19 @@ static int mtk_mib_entry_read(struct mtk +@@ -108,19 +122,19 @@ static int mtk_mib_entry_read(struct mtk if (mtk_is_netsys_v3_or_greater(ppe->eth)) { /* 64 bit for each counter */ u32 cnt_r3 = readl(ppe->base + MTK_PPE_MIB_SER_R3); @@ -86,7 +86,7 @@ Signed-off-by: Felix Fietkau } static void mtk_ppe_cache_clear(struct mtk_ppe *ppe) -@@ -520,13 +534,6 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp +@@ -519,13 +533,6 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp hwe->ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID); dma_wmb(); mtk_ppe_cache_clear(ppe); @@ -100,7 +100,7 @@ Signed-off-by: Felix Fietkau } entry->hash = 0xffff; -@@ -551,11 +558,14 @@ static int __mtk_foe_entry_idle_time(str +@@ -550,11 +557,14 @@ static int __mtk_foe_entry_idle_time(str } static bool @@ -116,7 +116,7 @@ Signed-off-by: Felix Fietkau int len; if (hash == 0xffff) -@@ -566,18 +576,35 @@ mtk_flow_entry_update(struct mtk_ppe *pp +@@ -565,18 +575,35 @@ mtk_flow_entry_update(struct mtk_ppe *pp memcpy(&foe, hwe, len); if (!mtk_flow_entry_match(ppe->eth, entry, &foe, len) || @@ -155,7 +155,7 @@ Signed-off-by: Felix Fietkau struct mtk_flow_entry *cur; struct hlist_node *tmp; int idle; -@@ -586,7 +613,9 @@ mtk_flow_entry_update_l2(struct mtk_ppe +@@ -585,7 +612,9 @@ mtk_flow_entry_update_l2(struct mtk_ppe hlist_for_each_entry_safe(cur, tmp, &entry->l2_flows, l2_list) { int cur_idle; @@ -166,7 +166,7 @@ Signed-off-by: Felix Fietkau __mtk_foe_entry_clear(ppe, entry, false); continue; } -@@ -601,10 +630,29 @@ mtk_flow_entry_update_l2(struct mtk_ppe +@@ -600,10 +629,29 @@ mtk_flow_entry_update_l2(struct mtk_ppe } } @@ -196,7 +196,7 @@ Signed-off-by: Felix Fietkau struct mtk_eth *eth = ppe->eth; u16 timestamp = mtk_eth_timestamp(eth); struct mtk_foe_entry *hwe; -@@ -635,6 +683,12 @@ __mtk_foe_entry_commit(struct mtk_ppe *p +@@ -634,6 +682,12 @@ __mtk_foe_entry_commit(struct mtk_ppe *p dma_wmb(); @@ -209,7 +209,7 @@ Signed-off-by: Felix Fietkau mtk_ppe_cache_clear(ppe); } -@@ -799,21 +853,6 @@ out: +@@ -796,21 +850,6 @@ out: spin_unlock_bh(&ppe_lock); } @@ -231,7 +231,7 @@ Signed-off-by: Felix Fietkau int mtk_ppe_prepare_reset(struct mtk_ppe *ppe) { if (!ppe) -@@ -841,32 +880,6 @@ int mtk_ppe_prepare_reset(struct mtk_ppe +@@ -838,32 +877,6 @@ int mtk_ppe_prepare_reset(struct mtk_ppe return mtk_ppe_wait_busy(ppe); } @@ -308,7 +308,7 @@ Signed-off-by: Felix Fietkau seq_printf(m, "%05x %s %7s", i, --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -499,24 +499,21 @@ static int +@@ -501,24 +501,21 @@ static int mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f) { struct mtk_flow_entry *entry; diff --git a/lede/target/linux/generic/backport-6.1/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch b/lede/target/linux/generic/backport-6.1/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch new file mode 100644 index 0000000000..a224b62624 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-01-v6.6-net-ethernet-mtk_wed-add-some-more-info-in-wed_txinf.patch @@ -0,0 +1,45 @@ +From: Lorenzo Bianconi +Date: Sun, 27 Aug 2023 19:31:41 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: add some more info in wed_txinfo_show + handler + +Add some new info in Wireless Ethernet Dispatcher wed_txinfo_show +debugfs handler useful during debugging. + +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/3390292655d568180b73d2a25576f61aa63310e5.1693157377.git.lorenzo@kernel.org +Signed-off-by: Jakub Kicinski +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +@@ -127,8 +127,17 @@ wed_txinfo_show(struct seq_file *s, void + DUMP_WDMA_RING(WDMA_RING_RX(0)), + DUMP_WDMA_RING(WDMA_RING_RX(1)), + +- DUMP_STR("TX FREE"), ++ DUMP_STR("WED TX FREE"), + DUMP_WED(WED_RX_MIB(0)), ++ DUMP_WED_RING(WED_RING_RX(0)), ++ DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(0)), ++ DUMP_WED(WED_RX_MIB(1)), ++ DUMP_WED_RING(WED_RING_RX(1)), ++ DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(1)), ++ ++ DUMP_STR("WED WPDMA TX FREE"), ++ DUMP_WED_RING(WED_WPDMA_RING_RX(0)), ++ DUMP_WED_RING(WED_WPDMA_RING_RX(1)), + }; + struct mtk_wed_hw *hw = s->private; + struct mtk_wed_device *dev = hw->wed_dev; +--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -266,6 +266,8 @@ struct mtk_wdma_desc { + + #define MTK_WED_WPDMA_TX_MIB(_n) (0x5a0 + (_n) * 4) + #define MTK_WED_WPDMA_TX_COHERENT_MIB(_n) (0x5d0 + (_n) * 4) ++#define MTK_WED_WPDMA_RX_MIB(_n) (0x5e0 + (_n) * 4) ++#define MTK_WED_WPDMA_RX_COHERENT_MIB(_n) (0x5f0 + (_n) * 4) + + #define MTK_WED_WPDMA_RING_TX(_n) (0x600 + (_n) * 0x10) + #define MTK_WED_WPDMA_RING_RX(_n) (0x700 + (_n) * 0x10) diff --git a/lede/target/linux/generic/backport-6.1/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch b/lede/target/linux/generic/backport-6.1/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch new file mode 100644 index 0000000000..df6edfdf94 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-02-v6.6-net-ethernet-mtk_wed-minor-change-in-wed_-tx-rx-info.patch @@ -0,0 +1,47 @@ +From: Lorenzo Bianconi +Date: Sun, 27 Aug 2023 19:33:47 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: minor change in wed_{tx,rx}info_show + +No functional changes, just cosmetic ones. + +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/71e046c72a978745f0435af265dda610aa9bfbcf.1693157578.git.lorenzo@kernel.org +Signed-off-by: Jakub Kicinski +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +@@ -84,7 +84,6 @@ dump_wed_regs(struct seq_file *s, struct + } + } + +- + static int + wed_txinfo_show(struct seq_file *s, void *data) + { +@@ -142,10 +141,8 @@ wed_txinfo_show(struct seq_file *s, void + struct mtk_wed_hw *hw = s->private; + struct mtk_wed_device *dev = hw->wed_dev; + +- if (!dev) +- return 0; +- +- dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ if (dev) ++ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); + + return 0; + } +@@ -217,10 +214,8 @@ wed_rxinfo_show(struct seq_file *s, void + struct mtk_wed_hw *hw = s->private; + struct mtk_wed_device *dev = hw->wed_dev; + +- if (!dev) +- return 0; +- +- dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ if (dev) ++ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); + + return 0; + } diff --git a/lede/target/linux/generic/backport-6.1/752-03-v6.6-net-ethernet-mtk_eth_soc-rely-on-mtk_pse_port-defini.patch b/lede/target/linux/generic/backport-6.1/752-03-v6.6-net-ethernet-mtk_eth_soc-rely-on-mtk_pse_port-defini.patch new file mode 100644 index 0000000000..0bf9dea24f --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-03-v6.6-net-ethernet-mtk_eth_soc-rely-on-mtk_pse_port-defini.patch @@ -0,0 +1,29 @@ +From: Lorenzo Bianconi +Date: Tue, 12 Sep 2023 10:22:56 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: rely on mtk_pse_port definitions + in mtk_flow_set_output_device + +Similar to ethernet ports, rely on mtk_pse_port definitions for +pse wdma ports as well. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/b86bdb717e963e3246c1dec5f736c810703cf056.1694506814.git.lorenzo@kernel.org +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -196,10 +196,10 @@ mtk_flow_set_output_device(struct mtk_et + if (mtk_is_netsys_v2_or_greater(eth)) { + switch (info.wdma_idx) { + case 0: +- pse_port = 8; ++ pse_port = PSE_WDMA0_PORT; + break; + case 1: +- pse_port = 9; ++ pse_port = PSE_WDMA1_PORT; + break; + default: + return -EINVAL; diff --git a/lede/target/linux/generic/backport-6.1/752-04-v6.6-net-ethernet-mtk_wed-check-update_wo_rx_stats-in-mtk.patch b/lede/target/linux/generic/backport-6.1/752-04-v6.6-net-ethernet-mtk_wed-check-update_wo_rx_stats-in-mtk.patch new file mode 100644 index 0000000000..c99e1334d4 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-04-v6.6-net-ethernet-mtk_wed-check-update_wo_rx_stats-in-mtk.patch @@ -0,0 +1,26 @@ +From: Lorenzo Bianconi +Date: Tue, 12 Sep 2023 10:28:00 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: check update_wo_rx_stats in + mtk_wed_update_rx_stats() + +Check if update_wo_rx_stats function pointer is properly set in +mtk_wed_update_rx_stats routine before accessing it. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/b0d233386e059bccb59f18f69afb79a7806e5ded.1694507226.git.lorenzo@kernel.org +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -68,6 +68,9 @@ mtk_wed_update_rx_stats(struct mtk_wed_d + struct mtk_wed_wo_rx_stats *stats; + int i; + ++ if (!wed->wlan.update_wo_rx_stats) ++ return; ++ + if (count * sizeof(*stats) > skb->len - sizeof(u32)) + return; + diff --git a/lede/target/linux/generic/backport-6.1/752-05-v6.7-net-ethernet-mtk_wed-do-not-assume-offload-callbacks.patch b/lede/target/linux/generic/backport-6.1/752-05-v6.7-net-ethernet-mtk_wed-do-not-assume-offload-callbacks.patch new file mode 100644 index 0000000000..cd7fb92e20 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-05-v6.7-net-ethernet-mtk_wed-do-not-assume-offload-callbacks.patch @@ -0,0 +1,68 @@ +From: Lorenzo Bianconi +Date: Wed, 13 Sep 2023 20:42:47 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: do not assume offload callbacks are + always set + +Check if wlan.offload_enable and wlan.offload_disable callbacks are set +in mtk_wed_flow_add/mtk_wed_flow_remove since mt7996 will not rely +on them. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -1712,19 +1712,20 @@ mtk_wed_irq_set_mask(struct mtk_wed_devi + int mtk_wed_flow_add(int index) + { + struct mtk_wed_hw *hw = hw_list[index]; +- int ret; ++ int ret = 0; + +- if (!hw || !hw->wed_dev) +- return -ENODEV; ++ mutex_lock(&hw_lock); + +- if (hw->num_flows) { +- hw->num_flows++; +- return 0; ++ if (!hw || !hw->wed_dev) { ++ ret = -ENODEV; ++ goto out; + } + +- mutex_lock(&hw_lock); +- if (!hw->wed_dev) { +- ret = -ENODEV; ++ if (!hw->wed_dev->wlan.offload_enable) ++ goto out; ++ ++ if (hw->num_flows) { ++ hw->num_flows++; + goto out; + } + +@@ -1743,14 +1744,15 @@ void mtk_wed_flow_remove(int index) + { + struct mtk_wed_hw *hw = hw_list[index]; + +- if (!hw) +- return; ++ mutex_lock(&hw_lock); + +- if (--hw->num_flows) +- return; ++ if (!hw || !hw->wed_dev) ++ goto out; + +- mutex_lock(&hw_lock); +- if (!hw->wed_dev) ++ if (!hw->wed_dev->wlan.offload_disable) ++ goto out; ++ ++ if (--hw->num_flows) + goto out; + + hw->wed_dev->wlan.offload_disable(hw->wed_dev); diff --git a/lede/target/linux/generic/backport-6.1/752-06-v6.7-net-ethernet-mtk_wed-introduce-versioning-utility-ro.patch b/lede/target/linux/generic/backport-6.1/752-06-v6.7-net-ethernet-mtk_wed-introduce-versioning-utility-ro.patch new file mode 100644 index 0000000000..2948188650 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-06-v6.7-net-ethernet-mtk_wed-introduce-versioning-utility-ro.patch @@ -0,0 +1,232 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:05 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: introduce versioning utility routines + +Similar to mtk_eth_soc, introduce the following wed versioning +utility routines: +- mtk_wed_is_v1 +- mtk_wed_is_v2 + +This is a preliminary patch to introduce WED support for MT7988 SoC + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -277,7 +277,7 @@ mtk_wed_assign(struct mtk_wed_device *de + if (!hw->wed_dev) + goto out; + +- if (hw->version == 1) ++ if (mtk_wed_is_v1(hw)) + return NULL; + + /* MT7986 WED devices do not have any pcie slot restrictions */ +@@ -358,7 +358,7 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d + desc->buf0 = cpu_to_le32(buf_phys); + desc->buf1 = cpu_to_le32(buf_phys + txd_size); + +- if (dev->hw->version == 1) ++ if (mtk_wed_is_v1(dev->hw)) + ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) | + FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1, + MTK_WED_BUF_SIZE - txd_size) | +@@ -497,7 +497,7 @@ mtk_wed_set_ext_int(struct mtk_wed_devic + { + u32 mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; + +- if (dev->hw->version == 1) ++ if (mtk_wed_is_v1(dev->hw)) + mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR; + else + mask |= MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH | +@@ -576,7 +576,7 @@ mtk_wed_dma_disable(struct mtk_wed_devic + MTK_WDMA_GLO_CFG_RX_INFO1_PRERES | + MTK_WDMA_GLO_CFG_RX_INFO2_PRERES); + +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + regmap_write(dev->hw->mirror, dev->hw->index * 4, 0); + wdma_clr(dev, MTK_WDMA_GLO_CFG, + MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); +@@ -605,7 +605,7 @@ mtk_wed_stop(struct mtk_wed_device *dev) + wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); + wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); + +- if (dev->hw->version == 1) ++ if (mtk_wed_is_v1(dev->hw)) + return; + + wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0); +@@ -624,7 +624,7 @@ mtk_wed_deinit(struct mtk_wed_device *de + MTK_WED_CTRL_WED_TX_BM_EN | + MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); + +- if (dev->hw->version == 1) ++ if (mtk_wed_is_v1(dev->hw)) + return; + + wed_clr(dev, MTK_WED_CTRL, +@@ -730,7 +730,7 @@ mtk_wed_bus_init(struct mtk_wed_device * + static void + mtk_wed_set_wpdma(struct mtk_wed_device *dev) + { +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys); + } else { + mtk_wed_bus_init(dev); +@@ -761,7 +761,7 @@ mtk_wed_hw_init_early(struct mtk_wed_dev + MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY; + wed_m32(dev, MTK_WED_WDMA_GLO_CFG, mask, set); + +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + u32 offset = dev->hw->index ? 0x04000400 : 0; + + wdma_set(dev, MTK_WDMA_GLO_CFG, +@@ -934,7 +934,7 @@ mtk_wed_hw_init(struct mtk_wed_device *d + + wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE); + +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + wed_w32(dev, MTK_WED_TX_BM_TKID, + FIELD_PREP(MTK_WED_TX_BM_TKID_START, + dev->wlan.token_start) | +@@ -967,7 +967,7 @@ mtk_wed_hw_init(struct mtk_wed_device *d + + mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); + +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + wed_set(dev, MTK_WED_CTRL, + MTK_WED_CTRL_WED_TX_BM_EN | + MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); +@@ -1217,7 +1217,7 @@ mtk_wed_reset_dma(struct mtk_wed_device + } + + dev->init_done = false; +- if (dev->hw->version == 1) ++ if (mtk_wed_is_v1(dev->hw)) + return; + + if (!busy) { +@@ -1343,7 +1343,7 @@ mtk_wed_configure_irq(struct mtk_wed_dev + MTK_WED_CTRL_WED_TX_BM_EN | + MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); + +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, + MTK_WED_PCIE_INT_TRIGGER_STATUS); + +@@ -1416,7 +1416,7 @@ mtk_wed_dma_enable(struct mtk_wed_device + MTK_WDMA_GLO_CFG_RX_INFO1_PRERES | + MTK_WDMA_GLO_CFG_RX_INFO2_PRERES); + +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + wdma_set(dev, MTK_WDMA_GLO_CFG, + MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); + } else { +@@ -1465,7 +1465,7 @@ mtk_wed_start(struct mtk_wed_device *dev + + mtk_wed_set_ext_int(dev, true); + +- if (dev->hw->version == 1) { ++ if (mtk_wed_is_v1(dev->hw)) { + u32 val = dev->wlan.wpdma_phys | MTK_PCIE_MIRROR_MAP_EN | + FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID, + dev->hw->index); +@@ -1550,7 +1550,7 @@ mtk_wed_attach(struct mtk_wed_device *de + } + + mtk_wed_hw_init_early(dev); +- if (hw->version == 1) { ++ if (mtk_wed_is_v1(hw)) { + regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, + BIT(hw->index), 0); + } else { +@@ -1618,7 +1618,7 @@ static int + mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs) + { + struct mtk_wed_ring *ring = &dev->txfree_ring; +- int i, index = dev->hw->version == 1; ++ int i, index = mtk_wed_is_v1(dev->hw); + + /* + * For txfree event handling, the same DMA ring is shared between WED +@@ -1676,7 +1676,7 @@ mtk_wed_irq_get(struct mtk_wed_device *d + { + u32 val, ext_mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; + +- if (dev->hw->version == 1) ++ if (mtk_wed_is_v1(dev->hw)) + ext_mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR; + else + ext_mask |= MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH | +@@ -1843,7 +1843,7 @@ mtk_wed_setup_tc(struct mtk_wed_device * + { + struct mtk_wed_hw *hw = wed->hw; + +- if (hw->version < 2) ++ if (mtk_wed_is_v1(hw)) + return -EOPNOTSUPP; + + switch (type) { +@@ -1917,9 +1917,9 @@ void mtk_wed_add_hw(struct device_node * + hw->wdma = wdma; + hw->index = index; + hw->irq = irq; +- hw->version = mtk_is_netsys_v1(eth) ? 1 : 2; ++ hw->version = eth->soc->version; + +- if (hw->version == 1) { ++ if (mtk_wed_is_v1(hw)) { + hw->mirror = syscon_regmap_lookup_by_phandle(eth_np, + "mediatek,pcie-mirror"); + hw->hifsys = syscon_regmap_lookup_by_phandle(eth_np, +--- a/drivers/net/ethernet/mediatek/mtk_wed.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -40,6 +40,16 @@ struct mtk_wdma_info { + }; + + #ifdef CONFIG_NET_MEDIATEK_SOC_WED ++static inline bool mtk_wed_is_v1(struct mtk_wed_hw *hw) ++{ ++ return hw->version == 1; ++} ++ ++static inline bool mtk_wed_is_v2(struct mtk_wed_hw *hw) ++{ ++ return hw->version == 2; ++} ++ + static inline void + wed_w32(struct mtk_wed_device *dev, u32 reg, u32 val) + { +--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +@@ -263,7 +263,7 @@ void mtk_wed_hw_add_debugfs(struct mtk_w + debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg); + debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval); + debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops); +- if (hw->version != 1) ++ if (!mtk_wed_is_v1(hw)) + debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, + &wed_rxinfo_fops); + } +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -207,7 +207,7 @@ int mtk_wed_mcu_msg_update(struct mtk_we + { + struct mtk_wed_wo *wo = dev->hw->wed_wo; + +- if (dev->hw->version == 1) ++ if (mtk_wed_is_v1(dev->hw)) + return 0; + + if (WARN_ON(!wo)) diff --git a/lede/target/linux/generic/backport-6.1/752-07-v6.7-net-ethernet-mtk_wed-do-not-configure-rx-offload-if-.patch b/lede/target/linux/generic/backport-6.1/752-07-v6.7-net-ethernet-mtk_wed-do-not-configure-rx-offload-if-.patch new file mode 100644 index 0000000000..bc34aa33a9 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-07-v6.7-net-ethernet-mtk_wed-do-not-configure-rx-offload-if-.patch @@ -0,0 +1,234 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:06 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: do not configure rx offload if not + supported + +Check if rx offload is supported running mtk_wed_get_rx_capa routine +before configuring it. This is a preliminary patch to introduce Wireless +Ethernet Dispatcher (WED) support for MT7988 SoC. + +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -605,7 +605,7 @@ mtk_wed_stop(struct mtk_wed_device *dev) + wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); + wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); + +- if (mtk_wed_is_v1(dev->hw)) ++ if (!mtk_wed_get_rx_capa(dev)) + return; + + wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0); +@@ -732,16 +732,21 @@ mtk_wed_set_wpdma(struct mtk_wed_device + { + if (mtk_wed_is_v1(dev->hw)) { + wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys); +- } else { +- mtk_wed_bus_init(dev); +- +- wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int); +- wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask); +- wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx); +- wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree); +- wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); +- wed_w32(dev, MTK_WED_WPDMA_RX_RING, dev->wlan.wpdma_rx); ++ return; + } ++ ++ mtk_wed_bus_init(dev); ++ ++ wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int); ++ wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask); ++ wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx); ++ wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree); ++ ++ if (!mtk_wed_get_rx_capa(dev)) ++ return; ++ ++ wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); ++ wed_w32(dev, MTK_WED_WPDMA_RX_RING, dev->wlan.wpdma_rx); + } + + static void +@@ -973,15 +978,17 @@ mtk_wed_hw_init(struct mtk_wed_device *d + MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); + } else { + wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE); +- /* rx hw init */ +- wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, +- MTK_WED_WPDMA_RX_D_RST_CRX_IDX | +- MTK_WED_WPDMA_RX_D_RST_DRV_IDX); +- wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); +- +- mtk_wed_rx_buffer_hw_init(dev); +- mtk_wed_rro_hw_init(dev); +- mtk_wed_route_qm_hw_init(dev); ++ if (mtk_wed_get_rx_capa(dev)) { ++ /* rx hw init */ ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, ++ MTK_WED_WPDMA_RX_D_RST_CRX_IDX | ++ MTK_WED_WPDMA_RX_D_RST_DRV_IDX); ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); ++ ++ mtk_wed_rx_buffer_hw_init(dev); ++ mtk_wed_rro_hw_init(dev); ++ mtk_wed_route_qm_hw_init(dev); ++ } + } + + wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE); +@@ -1353,8 +1360,6 @@ mtk_wed_configure_irq(struct mtk_wed_dev + + wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask); + } else { +- wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE, +- GENMASK(1, 0)); + /* initail tx interrupt trigger */ + wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX, + MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN | +@@ -1373,15 +1378,20 @@ mtk_wed_configure_irq(struct mtk_wed_dev + FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG, + dev->wlan.txfree_tbit)); + +- wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX, +- MTK_WED_WPDMA_INT_CTRL_RX0_EN | +- MTK_WED_WPDMA_INT_CTRL_RX0_CLR | +- MTK_WED_WPDMA_INT_CTRL_RX1_EN | +- MTK_WED_WPDMA_INT_CTRL_RX1_CLR | +- FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG, +- dev->wlan.rx_tbit[0]) | +- FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG, +- dev->wlan.rx_tbit[1])); ++ if (mtk_wed_get_rx_capa(dev)) { ++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX, ++ MTK_WED_WPDMA_INT_CTRL_RX0_EN | ++ MTK_WED_WPDMA_INT_CTRL_RX0_CLR | ++ MTK_WED_WPDMA_INT_CTRL_RX1_EN | ++ MTK_WED_WPDMA_INT_CTRL_RX1_CLR | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG, ++ dev->wlan.rx_tbit[0]) | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG, ++ dev->wlan.rx_tbit[1])); ++ ++ wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE, ++ GENMASK(1, 0)); ++ } + + wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask); + wed_set(dev, MTK_WED_WDMA_INT_CTRL, +@@ -1400,6 +1410,8 @@ mtk_wed_configure_irq(struct mtk_wed_dev + static void + mtk_wed_dma_enable(struct mtk_wed_device *dev) + { ++ int i; ++ + wed_set(dev, MTK_WED_WPDMA_INT_CTRL, MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV); + + wed_set(dev, MTK_WED_GLO_CFG, +@@ -1419,33 +1431,33 @@ mtk_wed_dma_enable(struct mtk_wed_device + if (mtk_wed_is_v1(dev->hw)) { + wdma_set(dev, MTK_WDMA_GLO_CFG, + MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); +- } else { +- int i; ++ return; ++ } + +- wed_set(dev, MTK_WED_WPDMA_CTRL, +- MTK_WED_WPDMA_CTRL_SDL1_FIXED); ++ wed_set(dev, MTK_WED_WPDMA_CTRL, ++ MTK_WED_WPDMA_CTRL_SDL1_FIXED); ++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); ++ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP | ++ MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV); + +- wed_set(dev, MTK_WED_WDMA_GLO_CFG, +- MTK_WED_WDMA_GLO_CFG_TX_DRV_EN | +- MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); ++ if (!mtk_wed_get_rx_capa(dev)) ++ return; + +- wed_set(dev, MTK_WED_WPDMA_GLO_CFG, +- MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | +- MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); +- +- wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, +- MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP | +- MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV); ++ wed_set(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_TX_DRV_EN | ++ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); + +- wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, +- MTK_WED_WPDMA_RX_D_RX_DRV_EN | +- FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) | +- FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL, +- 0x2)); ++ wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, ++ MTK_WED_WPDMA_RX_D_RX_DRV_EN | ++ FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) | ++ FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL, ++ 0x2)); + +- for (i = 0; i < MTK_WED_RX_QUEUES; i++) +- mtk_wed_check_wfdma_rx_fill(dev, i); +- } ++ for (i = 0; i < MTK_WED_RX_QUEUES; i++) ++ mtk_wed_check_wfdma_rx_fill(dev, i); + } + + static void +@@ -1472,7 +1484,7 @@ mtk_wed_start(struct mtk_wed_device *dev + + val |= BIT(0) | (BIT(1) * !!dev->hw->index); + regmap_write(dev->hw->mirror, dev->hw->index * 4, val); +- } else { ++ } else if (mtk_wed_get_rx_capa(dev)) { + /* driver set mid ready and only once */ + wed_w32(dev, MTK_WED_EXT_INT_MASK1, + MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY); +@@ -1484,7 +1496,6 @@ mtk_wed_start(struct mtk_wed_device *dev + + if (mtk_wed_rro_cfg(dev)) + return; +- + } + + mtk_wed_set_512_support(dev, dev->wlan.wcid_512); +@@ -1550,13 +1561,14 @@ mtk_wed_attach(struct mtk_wed_device *de + } + + mtk_wed_hw_init_early(dev); +- if (mtk_wed_is_v1(hw)) { ++ if (mtk_wed_is_v1(hw)) + regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, + BIT(hw->index), 0); +- } else { ++ else + dev->rev_id = wed_r32(dev, MTK_WED_REV_ID); ++ ++ if (mtk_wed_get_rx_capa(dev)) + ret = mtk_wed_wo_init(hw); +- } + out: + if (ret) { + dev_err(dev->hw->dev, "failed to attach wed device\n"); +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -207,7 +207,7 @@ int mtk_wed_mcu_msg_update(struct mtk_we + { + struct mtk_wed_wo *wo = dev->hw->wed_wo; + +- if (mtk_wed_is_v1(dev->hw)) ++ if (!mtk_wed_get_rx_capa(dev)) + return 0; + + if (WARN_ON(!wo)) diff --git a/lede/target/linux/generic/backport-6.1/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch b/lede/target/linux/generic/backport-6.1/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch new file mode 100644 index 0000000000..d83434fb2c --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-08-v6.7-net-ethernet-mtk_wed-rename-mtk_rxbm_desc-in-mtk_wed.patch @@ -0,0 +1,52 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:07 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: rename mtk_rxbm_desc in + mtk_wed_bm_desc + +Rename mtk_rxbm_desc structure in mtk_wed_bm_desc since it will be used +even on tx side by MT7988 SoC. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -421,7 +421,7 @@ free_pagelist: + static int + mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev) + { +- struct mtk_rxbm_desc *desc; ++ struct mtk_wed_bm_desc *desc; + dma_addr_t desc_phys; + + dev->rx_buf_ring.size = dev->wlan.rx_nbuf; +@@ -441,7 +441,7 @@ mtk_wed_rx_buffer_alloc(struct mtk_wed_d + static void + mtk_wed_free_rx_buffer(struct mtk_wed_device *dev) + { +- struct mtk_rxbm_desc *desc = dev->rx_buf_ring.desc; ++ struct mtk_wed_bm_desc *desc = dev->rx_buf_ring.desc; + + if (!desc) + return; +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -45,7 +45,7 @@ enum mtk_wed_wo_cmd { + MTK_WED_WO_CMD_WED_END + }; + +-struct mtk_rxbm_desc { ++struct mtk_wed_bm_desc { + __le32 buf0; + __le32 token; + } __packed __aligned(4); +@@ -105,7 +105,7 @@ struct mtk_wed_device { + struct { + int size; + struct page_frag_cache rx_page; +- struct mtk_rxbm_desc *desc; ++ struct mtk_wed_bm_desc *desc; + dma_addr_t desc_phys; + } rx_buf_ring; + diff --git a/lede/target/linux/generic/backport-6.1/752-09-v6.7-net-ethernet-mtk_wed-introduce-mtk_wed_buf-structure.patch b/lede/target/linux/generic/backport-6.1/752-09-v6.7-net-ethernet-mtk_wed-introduce-mtk_wed_buf-structure.patch new file mode 100644 index 0000000000..8000a8759e --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-09-v6.7-net-ethernet-mtk_wed-introduce-mtk_wed_buf-structure.patch @@ -0,0 +1,87 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:08 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: introduce mtk_wed_buf structure + +Introduce mtk_wed_buf structure to store both virtual and physical +addresses allocated in mtk_wed_tx_buffer_alloc() routine. This is a +preliminary patch to add WED support for MT7988 SoC since it relies on a +different dma descriptor layout not storing page dma addresses. + +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -299,9 +299,9 @@ out: + static int + mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) + { ++ struct mtk_wed_buf *page_list; + struct mtk_wdma_desc *desc; + dma_addr_t desc_phys; +- void **page_list; + int token = dev->wlan.token_start; + int ring_size; + int n_pages; +@@ -342,7 +342,8 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d + return -ENOMEM; + } + +- page_list[page_idx++] = page; ++ page_list[page_idx].p = page; ++ page_list[page_idx++].phy_addr = page_phys; + dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE, + DMA_BIDIRECTIONAL); + +@@ -386,8 +387,8 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d + static void + mtk_wed_free_tx_buffer(struct mtk_wed_device *dev) + { ++ struct mtk_wed_buf *page_list = dev->tx_buf_ring.pages; + struct mtk_wdma_desc *desc = dev->tx_buf_ring.desc; +- void **page_list = dev->tx_buf_ring.pages; + int page_idx; + int i; + +@@ -399,13 +400,12 @@ mtk_wed_free_tx_buffer(struct mtk_wed_de + + for (i = 0, page_idx = 0; i < dev->tx_buf_ring.size; + i += MTK_WED_BUF_PER_PAGE) { +- void *page = page_list[page_idx++]; +- dma_addr_t buf_addr; ++ dma_addr_t buf_addr = page_list[page_idx].phy_addr; ++ void *page = page_list[page_idx++].p; + + if (!page) + break; + +- buf_addr = le32_to_cpu(desc[i].buf0); + dma_unmap_page(dev->hw->dev, buf_addr, PAGE_SIZE, + DMA_BIDIRECTIONAL); + __free_page(page); +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -76,6 +76,11 @@ struct mtk_wed_wo_rx_stats { + __le32 rx_drop_cnt; + }; + ++struct mtk_wed_buf { ++ void *p; ++ dma_addr_t phy_addr; ++}; ++ + struct mtk_wed_device { + #ifdef CONFIG_NET_MEDIATEK_SOC_WED + const struct mtk_wed_ops *ops; +@@ -97,7 +102,7 @@ struct mtk_wed_device { + + struct { + int size; +- void **pages; ++ struct mtk_wed_buf *pages; + struct mtk_wdma_desc *desc; + dma_addr_t desc_phys; + } tx_buf_ring; diff --git a/lede/target/linux/generic/backport-6.1/752-10-v6.7-net-ethernet-mtk_wed-move-mem_region-array-out-of-mt.patch b/lede/target/linux/generic/backport-6.1/752-10-v6.7-net-ethernet-mtk_wed-move-mem_region-array-out-of-mt.patch new file mode 100644 index 0000000000..98d782b1d0 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-10-v6.7-net-ethernet-mtk_wed-move-mem_region-array-out-of-mt.patch @@ -0,0 +1,88 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:09 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: move mem_region array out of + mtk_wed_mcu_load_firmware + +Remove mtk_wed_wo_memory_region boot structure in mtk_wed_wo. +This is a preliminary patch to introduce WED support for MT7988 SoC. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -16,14 +16,30 @@ + #include "mtk_wed_wo.h" + #include "mtk_wed.h" + ++static struct mtk_wed_wo_memory_region mem_region[] = { ++ [MTK_WED_WO_REGION_EMI] = { ++ .name = "wo-emi", ++ }, ++ [MTK_WED_WO_REGION_ILM] = { ++ .name = "wo-ilm", ++ }, ++ [MTK_WED_WO_REGION_DATA] = { ++ .name = "wo-data", ++ .shared = true, ++ }, ++ [MTK_WED_WO_REGION_BOOT] = { ++ .name = "wo-boot", ++ }, ++}; ++ + static u32 wo_r32(struct mtk_wed_wo *wo, u32 reg) + { +- return readl(wo->boot.addr + reg); ++ return readl(mem_region[MTK_WED_WO_REGION_BOOT].addr + reg); + } + + static void wo_w32(struct mtk_wed_wo *wo, u32 reg, u32 val) + { +- writel(val, wo->boot.addr + reg); ++ writel(val, mem_region[MTK_WED_WO_REGION_BOOT].addr + reg); + } + + static struct sk_buff * +@@ -294,18 +310,6 @@ next: + static int + mtk_wed_mcu_load_firmware(struct mtk_wed_wo *wo) + { +- static struct mtk_wed_wo_memory_region mem_region[] = { +- [MTK_WED_WO_REGION_EMI] = { +- .name = "wo-emi", +- }, +- [MTK_WED_WO_REGION_ILM] = { +- .name = "wo-ilm", +- }, +- [MTK_WED_WO_REGION_DATA] = { +- .name = "wo-data", +- .shared = true, +- }, +- }; + const struct mtk_wed_fw_trailer *trailer; + const struct firmware *fw; + const char *fw_name; +@@ -319,11 +323,6 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + return ret; + } + +- wo->boot.name = "wo-boot"; +- ret = mtk_wed_get_memory_region(wo, &wo->boot); +- if (ret) +- return ret; +- + /* set dummy cr */ + wed_w32(wo->hw->wed_dev, MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_FWDL, + wo->hw->index + 1); +--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h +@@ -228,7 +228,6 @@ struct mtk_wed_wo_queue { + + struct mtk_wed_wo { + struct mtk_wed_hw *hw; +- struct mtk_wed_wo_memory_region boot; + + struct mtk_wed_wo_queue q_tx; + struct mtk_wed_wo_queue q_rx; diff --git a/lede/target/linux/generic/backport-6.1/752-11-v6.7-net-ethernet-mtk_wed-make-memory-region-optional.patch b/lede/target/linux/generic/backport-6.1/752-11-v6.7-net-ethernet-mtk_wed-make-memory-region-optional.patch new file mode 100644 index 0000000000..48b0d02049 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-11-v6.7-net-ethernet-mtk_wed-make-memory-region-optional.patch @@ -0,0 +1,71 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:10 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: make memory region optional + +Make mtk_wed_wo_memory_region optionals. +This is a preliminary patch to introduce Wireless Ethernet Dispatcher +support for MT7988 SoC since MT7988 WED fw image will have a different +layout. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -234,19 +234,13 @@ int mtk_wed_mcu_msg_update(struct mtk_we + } + + static int +-mtk_wed_get_memory_region(struct mtk_wed_wo *wo, ++mtk_wed_get_memory_region(struct mtk_wed_hw *hw, int index, + struct mtk_wed_wo_memory_region *region) + { + struct reserved_mem *rmem; + struct device_node *np; +- int index; + +- index = of_property_match_string(wo->hw->node, "memory-region-names", +- region->name); +- if (index < 0) +- return index; +- +- np = of_parse_phandle(wo->hw->node, "memory-region", index); ++ np = of_parse_phandle(hw->node, "memory-region", index); + if (!np) + return -ENODEV; + +@@ -258,7 +252,7 @@ mtk_wed_get_memory_region(struct mtk_wed + + region->phy_addr = rmem->base; + region->size = rmem->size; +- region->addr = devm_ioremap(wo->hw->dev, region->phy_addr, region->size); ++ region->addr = devm_ioremap(hw->dev, region->phy_addr, region->size); + + return !region->addr ? -EINVAL : 0; + } +@@ -271,6 +265,9 @@ mtk_wed_mcu_run_firmware(struct mtk_wed_ + const struct mtk_wed_fw_trailer *trailer; + const struct mtk_wed_fw_region *fw_region; + ++ if (!region->phy_addr || !region->size) ++ return 0; ++ + trailer_ptr = fw->data + fw->size - sizeof(*trailer); + trailer = (const struct mtk_wed_fw_trailer *)trailer_ptr; + region_ptr = trailer_ptr - trailer->num_region * sizeof(*fw_region); +@@ -318,7 +315,13 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + + /* load firmware region metadata */ + for (i = 0; i < ARRAY_SIZE(mem_region); i++) { +- ret = mtk_wed_get_memory_region(wo, &mem_region[i]); ++ int index = of_property_match_string(wo->hw->node, ++ "memory-region-names", ++ mem_region[i].name); ++ if (index < 0) ++ continue; ++ ++ ret = mtk_wed_get_memory_region(wo->hw, index, &mem_region[i]); + if (ret) + return ret; + } diff --git a/lede/target/linux/generic/backport-6.1/752-13-v6.7-net-ethernet-mtk_wed-add-mtk_wed_soc_data-structure.patch b/lede/target/linux/generic/backport-6.1/752-13-v6.7-net-ethernet-mtk_wed-add-mtk_wed_soc_data-structure.patch new file mode 100644 index 0000000000..c43114fb5b --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-13-v6.7-net-ethernet-mtk_wed-add-mtk_wed_soc_data-structure.patch @@ -0,0 +1,217 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:12 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: add mtk_wed_soc_data structure + +Introduce mtk_wed_soc_data utility structure to contain per-SoC +definitions. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -48,6 +48,26 @@ struct mtk_wed_flow_block_priv { + struct net_device *dev; + }; + ++static const struct mtk_wed_soc_data mt7622_data = { ++ .regmap = { ++ .tx_bm_tkid = 0x088, ++ .wpdma_rx_ring0 = 0x770, ++ .reset_idx_tx_mask = GENMASK(3, 0), ++ .reset_idx_rx_mask = GENMASK(17, 16), ++ }, ++ .wdma_desc_size = sizeof(struct mtk_wdma_desc), ++}; ++ ++static const struct mtk_wed_soc_data mt7986_data = { ++ .regmap = { ++ .tx_bm_tkid = 0x0c8, ++ .wpdma_rx_ring0 = 0x770, ++ .reset_idx_tx_mask = GENMASK(1, 0), ++ .reset_idx_rx_mask = GENMASK(7, 6), ++ }, ++ .wdma_desc_size = 2 * sizeof(struct mtk_wdma_desc), ++}; ++ + static void + wed_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val) + { +@@ -746,7 +766,7 @@ mtk_wed_set_wpdma(struct mtk_wed_device + return; + + wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); +- wed_w32(dev, MTK_WED_WPDMA_RX_RING, dev->wlan.wpdma_rx); ++ wed_w32(dev, dev->hw->soc->regmap.wpdma_rx_ring0, dev->wlan.wpdma_rx); + } + + static void +@@ -940,22 +960,10 @@ mtk_wed_hw_init(struct mtk_wed_device *d + wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE); + + if (mtk_wed_is_v1(dev->hw)) { +- wed_w32(dev, MTK_WED_TX_BM_TKID, +- FIELD_PREP(MTK_WED_TX_BM_TKID_START, +- dev->wlan.token_start) | +- FIELD_PREP(MTK_WED_TX_BM_TKID_END, +- dev->wlan.token_start + +- dev->wlan.nbuf - 1)); + wed_w32(dev, MTK_WED_TX_BM_DYN_THR, + FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, 1) | + MTK_WED_TX_BM_DYN_THR_HI); + } else { +- wed_w32(dev, MTK_WED_TX_BM_TKID_V2, +- FIELD_PREP(MTK_WED_TX_BM_TKID_START, +- dev->wlan.token_start) | +- FIELD_PREP(MTK_WED_TX_BM_TKID_END, +- dev->wlan.token_start + +- dev->wlan.nbuf - 1)); + wed_w32(dev, MTK_WED_TX_BM_DYN_THR, + FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO_V2, 0) | + MTK_WED_TX_BM_DYN_THR_HI_V2); +@@ -970,6 +978,11 @@ mtk_wed_hw_init(struct mtk_wed_device *d + MTK_WED_TX_TKID_DYN_THR_HI); + } + ++ wed_w32(dev, dev->hw->soc->regmap.tx_bm_tkid, ++ FIELD_PREP(MTK_WED_TX_BM_TKID_START, dev->wlan.token_start) | ++ FIELD_PREP(MTK_WED_TX_BM_TKID_END, ++ dev->wlan.token_start + dev->wlan.nbuf - 1)); ++ + mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); + + if (mtk_wed_is_v1(dev->hw)) { +@@ -1104,13 +1117,8 @@ mtk_wed_rx_reset(struct mtk_wed_device * + if (ret) { + mtk_wed_reset(dev, MTK_WED_RESET_WED_RX_DMA); + } else { +- struct mtk_eth *eth = dev->hw->eth; +- +- if (mtk_is_netsys_v2_or_greater(eth)) +- wed_set(dev, MTK_WED_RESET_IDX, +- MTK_WED_RESET_IDX_RX_V2); +- else +- wed_set(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_RX); ++ wed_set(dev, MTK_WED_RESET_IDX, ++ dev->hw->soc->regmap.reset_idx_rx_mask); + wed_w32(dev, MTK_WED_RESET_IDX, 0); + } + +@@ -1163,7 +1171,8 @@ mtk_wed_reset_dma(struct mtk_wed_device + if (busy) { + mtk_wed_reset(dev, MTK_WED_RESET_WED_TX_DMA); + } else { +- wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_TX); ++ wed_w32(dev, MTK_WED_RESET_IDX, ++ dev->hw->soc->regmap.reset_idx_tx_mask); + wed_w32(dev, MTK_WED_RESET_IDX, 0); + } + +@@ -1255,7 +1264,6 @@ static int + mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size, + bool reset) + { +- u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; + struct mtk_wed_ring *wdma; + + if (idx >= ARRAY_SIZE(dev->rx_wdma)) +@@ -1263,7 +1271,7 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_we + + wdma = &dev->rx_wdma[idx]; + if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, +- desc_size, true)) ++ dev->hw->soc->wdma_desc_size, true)) + return -ENOMEM; + + wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE, +@@ -1284,7 +1292,6 @@ static int + mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size, + bool reset) + { +- u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version; + struct mtk_wed_ring *wdma; + + if (idx >= ARRAY_SIZE(dev->tx_wdma)) +@@ -1292,7 +1299,7 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_we + + wdma = &dev->tx_wdma[idx]; + if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, +- desc_size, true)) ++ dev->hw->soc->wdma_desc_size, true)) + return -ENOMEM; + + wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, +@@ -1931,7 +1938,12 @@ void mtk_wed_add_hw(struct device_node * + hw->irq = irq; + hw->version = eth->soc->version; + +- if (mtk_wed_is_v1(hw)) { ++ switch (hw->version) { ++ case 2: ++ hw->soc = &mt7986_data; ++ break; ++ default: ++ case 1: + hw->mirror = syscon_regmap_lookup_by_phandle(eth_np, + "mediatek,pcie-mirror"); + hw->hifsys = syscon_regmap_lookup_by_phandle(eth_np, +@@ -1945,6 +1957,8 @@ void mtk_wed_add_hw(struct device_node * + regmap_write(hw->mirror, 0, 0); + regmap_write(hw->mirror, 4, 0); + } ++ hw->soc = &mt7622_data; ++ break; + } + + mtk_wed_hw_add_debugfs(hw); +--- a/drivers/net/ethernet/mediatek/mtk_wed.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -12,7 +12,18 @@ + struct mtk_eth; + struct mtk_wed_wo; + ++struct mtk_wed_soc_data { ++ struct { ++ u32 tx_bm_tkid; ++ u32 wpdma_rx_ring0; ++ u32 reset_idx_tx_mask; ++ u32 reset_idx_rx_mask; ++ } regmap; ++ u32 wdma_desc_size; ++}; ++ + struct mtk_wed_hw { ++ const struct mtk_wed_soc_data *soc; + struct device_node *node; + struct mtk_eth *eth; + struct regmap *regs; +--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -100,8 +100,6 @@ struct mtk_wdma_desc { + + #define MTK_WED_TX_BM_BASE 0x084 + +-#define MTK_WED_TX_BM_TKID 0x088 +-#define MTK_WED_TX_BM_TKID_V2 0x0c8 + #define MTK_WED_TX_BM_TKID_START GENMASK(15, 0) + #define MTK_WED_TX_BM_TKID_END GENMASK(31, 16) + +@@ -160,9 +158,6 @@ struct mtk_wdma_desc { + #define MTK_WED_GLO_CFG_RX_2B_OFFSET BIT(31) + + #define MTK_WED_RESET_IDX 0x20c +-#define MTK_WED_RESET_IDX_TX GENMASK(3, 0) +-#define MTK_WED_RESET_IDX_RX GENMASK(17, 16) +-#define MTK_WED_RESET_IDX_RX_V2 GENMASK(7, 6) + #define MTK_WED_RESET_WPDMA_IDX_RX GENMASK(31, 30) + + #define MTK_WED_TX_MIB(_n) (0x2a0 + (_n) * 4) +@@ -286,7 +281,6 @@ struct mtk_wdma_desc { + #define MTK_WED_WPDMA_RX_D_RST_DRV_IDX GENMASK(25, 24) + + #define MTK_WED_WPDMA_RX_GLO_CFG 0x76c +-#define MTK_WED_WPDMA_RX_RING 0x770 + + #define MTK_WED_WPDMA_RX_D_MIB(_n) (0x774 + (_n) * 4) + #define MTK_WED_WPDMA_RX_D_PROCESSED_MIB(_n) (0x784 + (_n) * 4) diff --git a/lede/target/linux/generic/backport-6.1/752-14-v6.7-net-ethernet-mtk_wed-introduce-WED-support-for-MT798.patch b/lede/target/linux/generic/backport-6.1/752-14-v6.7-net-ethernet-mtk_wed-introduce-WED-support-for-MT798.patch new file mode 100644 index 0000000000..f874899c5b --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-14-v6.7-net-ethernet-mtk_wed-introduce-WED-support-for-MT798.patch @@ -0,0 +1,1280 @@ +From: Sujuan Chen +Date: Mon, 18 Sep 2023 12:29:13 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: introduce WED support for MT7988 + +Similar to MT7986 and MT7622, enable Wireless Ethernet Ditpatcher for +MT7988 in order to offload traffic forwarded from LAN/WLAN to WLAN/LAN + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Sujuan Chen +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -195,6 +195,7 @@ static const struct mtk_reg_map mt7988_r + .wdma_base = { + [0] = 0x4800, + [1] = 0x4c00, ++ [2] = 0x5000, + }, + .pse_iq_sta = 0x0180, + .pse_oq_sta = 0x01a0, +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1132,7 +1132,7 @@ struct mtk_reg_map { + u32 gdm1_cnt; + u32 gdma_to_ppe; + u32 ppe_base; +- u32 wdma_base[2]; ++ u32 wdma_base[3]; + u32 pse_iq_sta; + u32 pse_oq_sta; + }; +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -201,6 +201,9 @@ mtk_flow_set_output_device(struct mtk_et + case 1: + pse_port = PSE_WDMA1_PORT; + break; ++ case 2: ++ pse_port = PSE_WDMA2_PORT; ++ break; + default: + return -EINVAL; + } +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -16,17 +16,19 @@ + #include + #include + #include "mtk_eth_soc.h" +-#include "mtk_wed_regs.h" + #include "mtk_wed.h" + #include "mtk_ppe.h" + #include "mtk_wed_wo.h" + + #define MTK_PCIE_BASE(n) (0x1a143000 + (n) * 0x2000) + +-#define MTK_WED_PKT_SIZE 1900 ++#define MTK_WED_PKT_SIZE 1920 + #define MTK_WED_BUF_SIZE 2048 ++#define MTK_WED_PAGE_BUF_SIZE 128 + #define MTK_WED_BUF_PER_PAGE (PAGE_SIZE / 2048) ++#define MTK_WED_RX_PAGE_BUF_PER_PAGE (PAGE_SIZE / 128) + #define MTK_WED_RX_RING_SIZE 1536 ++#define MTK_WED_RX_PG_BM_CNT 8192 + + #define MTK_WED_TX_RING_SIZE 2048 + #define MTK_WED_WDMA_RING_SIZE 1024 +@@ -40,7 +42,10 @@ + #define MTK_WED_RRO_QUE_CNT 8192 + #define MTK_WED_MIOD_ENTRY_CNT 128 + +-static struct mtk_wed_hw *hw_list[2]; ++#define MTK_WED_TX_BM_DMA_SIZE 65536 ++#define MTK_WED_TX_BM_PKT_CNT 32768 ++ ++static struct mtk_wed_hw *hw_list[3]; + static DEFINE_MUTEX(hw_lock); + + struct mtk_wed_flow_block_priv { +@@ -55,6 +60,7 @@ static const struct mtk_wed_soc_data mt7 + .reset_idx_tx_mask = GENMASK(3, 0), + .reset_idx_rx_mask = GENMASK(17, 16), + }, ++ .tx_ring_desc_size = sizeof(struct mtk_wdma_desc), + .wdma_desc_size = sizeof(struct mtk_wdma_desc), + }; + +@@ -65,6 +71,18 @@ static const struct mtk_wed_soc_data mt7 + .reset_idx_tx_mask = GENMASK(1, 0), + .reset_idx_rx_mask = GENMASK(7, 6), + }, ++ .tx_ring_desc_size = sizeof(struct mtk_wdma_desc), ++ .wdma_desc_size = 2 * sizeof(struct mtk_wdma_desc), ++}; ++ ++static const struct mtk_wed_soc_data mt7988_data = { ++ .regmap = { ++ .tx_bm_tkid = 0x0c8, ++ .wpdma_rx_ring0 = 0x7d0, ++ .reset_idx_tx_mask = GENMASK(1, 0), ++ .reset_idx_rx_mask = GENMASK(7, 6), ++ }, ++ .tx_ring_desc_size = sizeof(struct mtk_wed_bm_desc), + .wdma_desc_size = 2 * sizeof(struct mtk_wdma_desc), + }; + +@@ -319,33 +337,38 @@ out: + static int + mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) + { ++ u32 desc_size = dev->hw->soc->tx_ring_desc_size; ++ int i, page_idx = 0, n_pages, ring_size; ++ int token = dev->wlan.token_start; + struct mtk_wed_buf *page_list; +- struct mtk_wdma_desc *desc; + dma_addr_t desc_phys; +- int token = dev->wlan.token_start; +- int ring_size; +- int n_pages; +- int i, page_idx; ++ void *desc_ptr; + +- ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1); +- n_pages = ring_size / MTK_WED_BUF_PER_PAGE; ++ if (!mtk_wed_is_v3_or_greater(dev->hw)) { ++ ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1); ++ dev->tx_buf_ring.size = ring_size; ++ } else { ++ dev->tx_buf_ring.size = MTK_WED_TX_BM_DMA_SIZE; ++ ring_size = MTK_WED_TX_BM_PKT_CNT; ++ } ++ n_pages = dev->tx_buf_ring.size / MTK_WED_BUF_PER_PAGE; + + page_list = kcalloc(n_pages, sizeof(*page_list), GFP_KERNEL); + if (!page_list) + return -ENOMEM; + +- dev->tx_buf_ring.size = ring_size; + dev->tx_buf_ring.pages = page_list; + +- desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc), +- &desc_phys, GFP_KERNEL); +- if (!desc) ++ desc_ptr = dma_alloc_coherent(dev->hw->dev, ++ dev->tx_buf_ring.size * desc_size, ++ &desc_phys, GFP_KERNEL); ++ if (!desc_ptr) + return -ENOMEM; + +- dev->tx_buf_ring.desc = desc; ++ dev->tx_buf_ring.desc = desc_ptr; + dev->tx_buf_ring.desc_phys = desc_phys; + +- for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) { ++ for (i = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) { + dma_addr_t page_phys, buf_phys; + struct page *page; + void *buf; +@@ -371,28 +394,31 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d + buf_phys = page_phys; + + for (s = 0; s < MTK_WED_BUF_PER_PAGE; s++) { +- u32 txd_size; +- u32 ctrl; +- +- txd_size = dev->wlan.init_buf(buf, buf_phys, token++); ++ struct mtk_wdma_desc *desc = desc_ptr; + + desc->buf0 = cpu_to_le32(buf_phys); +- desc->buf1 = cpu_to_le32(buf_phys + txd_size); ++ if (!mtk_wed_is_v3_or_greater(dev->hw)) { ++ u32 txd_size, ctrl; + +- if (mtk_wed_is_v1(dev->hw)) +- ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) | +- FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1, +- MTK_WED_BUF_SIZE - txd_size) | +- MTK_WDMA_DESC_CTRL_LAST_SEG1; +- else +- ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) | +- FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1_V2, +- MTK_WED_BUF_SIZE - txd_size) | +- MTK_WDMA_DESC_CTRL_LAST_SEG0; +- desc->ctrl = cpu_to_le32(ctrl); +- desc->info = 0; +- desc++; ++ txd_size = dev->wlan.init_buf(buf, buf_phys, ++ token++); ++ desc->buf1 = cpu_to_le32(buf_phys + txd_size); ++ ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size); ++ if (mtk_wed_is_v1(dev->hw)) ++ ctrl |= MTK_WDMA_DESC_CTRL_LAST_SEG1 | ++ FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1, ++ MTK_WED_BUF_SIZE - txd_size); ++ else ++ ctrl |= MTK_WDMA_DESC_CTRL_LAST_SEG0 | ++ FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1_V2, ++ MTK_WED_BUF_SIZE - txd_size); ++ desc->ctrl = cpu_to_le32(ctrl); ++ desc->info = 0; ++ } else { ++ desc->ctrl = cpu_to_le32(token << 16); ++ } + ++ desc_ptr += desc_size; + buf += MTK_WED_BUF_SIZE; + buf_phys += MTK_WED_BUF_SIZE; + } +@@ -408,31 +434,31 @@ static void + mtk_wed_free_tx_buffer(struct mtk_wed_device *dev) + { + struct mtk_wed_buf *page_list = dev->tx_buf_ring.pages; +- struct mtk_wdma_desc *desc = dev->tx_buf_ring.desc; +- int page_idx; +- int i; ++ struct mtk_wed_hw *hw = dev->hw; ++ int i, page_idx = 0; + + if (!page_list) + return; + +- if (!desc) ++ if (!dev->tx_buf_ring.desc) + goto free_pagelist; + +- for (i = 0, page_idx = 0; i < dev->tx_buf_ring.size; +- i += MTK_WED_BUF_PER_PAGE) { +- dma_addr_t buf_addr = page_list[page_idx].phy_addr; ++ for (i = 0; i < dev->tx_buf_ring.size; i += MTK_WED_BUF_PER_PAGE) { ++ dma_addr_t page_phy = page_list[page_idx].phy_addr; + void *page = page_list[page_idx++].p; + + if (!page) + break; + +- dma_unmap_page(dev->hw->dev, buf_addr, PAGE_SIZE, ++ dma_unmap_page(dev->hw->dev, page_phy, PAGE_SIZE, + DMA_BIDIRECTIONAL); + __free_page(page); + } + +- dma_free_coherent(dev->hw->dev, dev->tx_buf_ring.size * sizeof(*desc), +- desc, dev->tx_buf_ring.desc_phys); ++ dma_free_coherent(dev->hw->dev, ++ dev->tx_buf_ring.size * hw->soc->tx_ring_desc_size, ++ dev->tx_buf_ring.desc, ++ dev->tx_buf_ring.desc_phys); + + free_pagelist: + kfree(page_list); +@@ -517,13 +543,23 @@ mtk_wed_set_ext_int(struct mtk_wed_devic + { + u32 mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; + +- if (mtk_wed_is_v1(dev->hw)) ++ switch (dev->hw->version) { ++ case 1: + mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR; +- else ++ break; ++ case 2: + mask |= MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH | + MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH | + MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT | + MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR; ++ break; ++ case 3: ++ mask = MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT | ++ MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD; ++ break; ++ default: ++ break; ++ } + + if (!dev->hw->num_flows) + mask &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD; +@@ -535,6 +571,9 @@ mtk_wed_set_ext_int(struct mtk_wed_devic + static void + mtk_wed_set_512_support(struct mtk_wed_device *dev, bool enable) + { ++ if (!mtk_wed_is_v2(dev->hw)) ++ return; ++ + if (enable) { + wed_w32(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR); + wed_w32(dev, MTK_WED_TXP_DW1, +@@ -609,6 +648,14 @@ mtk_wed_dma_disable(struct mtk_wed_devic + MTK_WED_WPDMA_RX_D_RX_DRV_EN); + wed_clr(dev, MTK_WED_WDMA_GLO_CFG, + MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); ++ ++ if (mtk_wed_is_v3_or_greater(dev->hw) && ++ mtk_wed_get_rx_capa(dev)) { ++ wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, ++ MTK_WDMA_PREF_TX_CFG_PREF_EN); ++ wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, ++ MTK_WDMA_PREF_RX_CFG_PREF_EN); ++ } + } + + mtk_wed_set_512_support(dev, false); +@@ -651,6 +698,14 @@ mtk_wed_deinit(struct mtk_wed_device *de + MTK_WED_CTRL_RX_ROUTE_QM_EN | + MTK_WED_CTRL_WED_RX_BM_EN | + MTK_WED_CTRL_RX_RRO_QM_EN); ++ ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN); ++ wed_clr(dev, MTK_WED_RESET, MTK_WED_RESET_TX_AMSDU); ++ wed_clr(dev, MTK_WED_PCIE_INT_CTRL, ++ MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA | ++ MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER); ++ } + } + + static void +@@ -700,21 +755,37 @@ mtk_wed_detach(struct mtk_wed_device *de + mutex_unlock(&hw_lock); + } + +-#define PCIE_BASE_ADDR0 0x11280000 + static void + mtk_wed_bus_init(struct mtk_wed_device *dev) + { + switch (dev->wlan.bus_type) { + case MTK_WED_BUS_PCIE: { + struct device_node *np = dev->hw->eth->dev->of_node; +- struct regmap *regs; + +- regs = syscon_regmap_lookup_by_phandle(np, +- "mediatek,wed-pcie"); +- if (IS_ERR(regs)) +- break; ++ if (mtk_wed_is_v2(dev->hw)) { ++ struct regmap *regs; ++ ++ regs = syscon_regmap_lookup_by_phandle(np, ++ "mediatek,wed-pcie"); ++ if (IS_ERR(regs)) ++ break; + +- regmap_update_bits(regs, 0, BIT(0), BIT(0)); ++ regmap_update_bits(regs, 0, BIT(0), BIT(0)); ++ } ++ ++ if (dev->wlan.msi) { ++ wed_w32(dev, MTK_WED_PCIE_CFG_INTM, ++ dev->hw->pcie_base | 0xc08); ++ wed_w32(dev, MTK_WED_PCIE_CFG_BASE, ++ dev->hw->pcie_base | 0xc04); ++ wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(8)); ++ } else { ++ wed_w32(dev, MTK_WED_PCIE_CFG_INTM, ++ dev->hw->pcie_base | 0x180); ++ wed_w32(dev, MTK_WED_PCIE_CFG_BASE, ++ dev->hw->pcie_base | 0x184); ++ wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24)); ++ } + + wed_w32(dev, MTK_WED_PCIE_INT_CTRL, + FIELD_PREP(MTK_WED_PCIE_INT_CTRL_POLL_EN, 2)); +@@ -722,19 +793,9 @@ mtk_wed_bus_init(struct mtk_wed_device * + /* pcie interrupt control: pola/source selection */ + wed_set(dev, MTK_WED_PCIE_INT_CTRL, + MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA | +- FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL, 1)); +- wed_r32(dev, MTK_WED_PCIE_INT_CTRL); +- +- wed_w32(dev, MTK_WED_PCIE_CFG_INTM, PCIE_BASE_ADDR0 | 0x180); +- wed_w32(dev, MTK_WED_PCIE_CFG_BASE, PCIE_BASE_ADDR0 | 0x184); +- +- /* pcie interrupt status trigger register */ +- wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24)); +- wed_r32(dev, MTK_WED_PCIE_INT_TRIGGER); +- +- /* pola setting */ +- wed_set(dev, MTK_WED_PCIE_INT_CTRL, +- MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA); ++ MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER | ++ FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL, ++ dev->hw->index)); + break; + } + case MTK_WED_BUS_AXI: +@@ -772,18 +833,19 @@ mtk_wed_set_wpdma(struct mtk_wed_device + static void + mtk_wed_hw_init_early(struct mtk_wed_device *dev) + { +- u32 mask, set; ++ u32 set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2); ++ u32 mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE; + + mtk_wed_deinit(dev); + mtk_wed_reset(dev, MTK_WED_RESET_WED); + mtk_wed_set_wpdma(dev); + +- mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE | +- MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE | +- MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE; +- set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2) | +- MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP | +- MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY; ++ if (!mtk_wed_is_v3_or_greater(dev->hw)) { ++ mask |= MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE | ++ MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE; ++ set |= MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP | ++ MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY; ++ } + wed_m32(dev, MTK_WED_WDMA_GLO_CFG, mask, set); + + if (mtk_wed_is_v1(dev->hw)) { +@@ -931,11 +993,18 @@ mtk_wed_route_qm_hw_init(struct mtk_wed_ + } + + /* configure RX_ROUTE_QM */ +- wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); +- wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT); +- wed_set(dev, MTK_WED_RTQM_GLO_CFG, +- FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, 0x3 + dev->hw->index)); +- wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); ++ if (mtk_wed_is_v2(dev->hw)) { ++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); ++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT); ++ wed_set(dev, MTK_WED_RTQM_GLO_CFG, ++ FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, ++ 0x3 + dev->hw->index)); ++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); ++ } else { ++ wed_set(dev, MTK_WED_RTQM_ENQ_CFG0, ++ FIELD_PREP(MTK_WED_RTQM_ENQ_CFG_TXDMAD_FPORT, ++ 0x3 + dev->hw->index)); ++ } + /* enable RX_ROUTE_QM */ + wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN); + } +@@ -948,22 +1017,30 @@ mtk_wed_hw_init(struct mtk_wed_device *d + + dev->init_done = true; + mtk_wed_set_ext_int(dev, false); +- wed_w32(dev, MTK_WED_TX_BM_CTRL, +- MTK_WED_TX_BM_CTRL_PAUSE | +- FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, +- dev->tx_buf_ring.size / 128) | +- FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, +- MTK_WED_TX_RING_SIZE / 256)); + + wed_w32(dev, MTK_WED_TX_BM_BASE, dev->tx_buf_ring.desc_phys); +- + wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE); + + if (mtk_wed_is_v1(dev->hw)) { ++ wed_w32(dev, MTK_WED_TX_BM_CTRL, ++ MTK_WED_TX_BM_CTRL_PAUSE | ++ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, ++ dev->tx_buf_ring.size / 128) | ++ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, ++ MTK_WED_TX_RING_SIZE / 256)); + wed_w32(dev, MTK_WED_TX_BM_DYN_THR, + FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, 1) | + MTK_WED_TX_BM_DYN_THR_HI); +- } else { ++ } else if (mtk_wed_is_v2(dev->hw)) { ++ wed_w32(dev, MTK_WED_TX_BM_CTRL, ++ MTK_WED_TX_BM_CTRL_PAUSE | ++ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, ++ dev->tx_buf_ring.size / 128) | ++ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, ++ MTK_WED_TX_RING_SIZE / 256)); ++ wed_w32(dev, MTK_WED_TX_TKID_DYN_THR, ++ FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) | ++ MTK_WED_TX_TKID_DYN_THR_HI); + wed_w32(dev, MTK_WED_TX_BM_DYN_THR, + FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO_V2, 0) | + MTK_WED_TX_BM_DYN_THR_HI_V2); +@@ -973,9 +1050,6 @@ mtk_wed_hw_init(struct mtk_wed_device *d + dev->tx_buf_ring.size / 128) | + FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM, + dev->tx_buf_ring.size / 128)); +- wed_w32(dev, MTK_WED_TX_TKID_DYN_THR, +- FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) | +- MTK_WED_TX_TKID_DYN_THR_HI); + } + + wed_w32(dev, dev->hw->soc->regmap.tx_bm_tkid, +@@ -985,26 +1059,62 @@ mtk_wed_hw_init(struct mtk_wed_device *d + + mtk_wed_reset(dev, MTK_WED_RESET_TX_BM); + ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ /* switch to new bm architecture */ ++ wed_clr(dev, MTK_WED_TX_BM_CTRL, ++ MTK_WED_TX_BM_CTRL_LEGACY_EN); ++ ++ wed_w32(dev, MTK_WED_TX_TKID_CTRL, ++ MTK_WED_TX_TKID_CTRL_PAUSE | ++ FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM_V3, ++ dev->wlan.nbuf / 128) | ++ FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM_V3, ++ dev->wlan.nbuf / 128)); ++ /* return SKBID + SDP back to bm */ ++ wed_set(dev, MTK_WED_TX_TKID_CTRL, ++ MTK_WED_TX_TKID_CTRL_FREE_FORMAT); ++ ++ wed_w32(dev, MTK_WED_TX_BM_INIT_PTR, ++ MTK_WED_TX_BM_PKT_CNT | ++ MTK_WED_TX_BM_INIT_SW_TAIL_IDX); ++ } ++ + if (mtk_wed_is_v1(dev->hw)) { + wed_set(dev, MTK_WED_CTRL, + MTK_WED_CTRL_WED_TX_BM_EN | + MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); +- } else { +- wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE); +- if (mtk_wed_get_rx_capa(dev)) { +- /* rx hw init */ +- wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, +- MTK_WED_WPDMA_RX_D_RST_CRX_IDX | +- MTK_WED_WPDMA_RX_D_RST_DRV_IDX); +- wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); +- +- mtk_wed_rx_buffer_hw_init(dev); +- mtk_wed_rro_hw_init(dev); +- mtk_wed_route_qm_hw_init(dev); +- } ++ } else if (mtk_wed_get_rx_capa(dev)) { ++ /* rx hw init */ ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, ++ MTK_WED_WPDMA_RX_D_RST_CRX_IDX | ++ MTK_WED_WPDMA_RX_D_RST_DRV_IDX); ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0); ++ ++ /* reset prefetch index of ring */ ++ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX, ++ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR); ++ wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX, ++ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR); ++ ++ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX, ++ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR); ++ wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX, ++ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR); ++ ++ /* reset prefetch FIFO of ring */ ++ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG, ++ MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R0_CLR | ++ MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R1_CLR); ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG, 0); ++ ++ mtk_wed_rx_buffer_hw_init(dev); ++ mtk_wed_rro_hw_init(dev); ++ mtk_wed_route_qm_hw_init(dev); + } + + wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE); ++ if (!mtk_wed_is_v1(dev->hw)) ++ wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE); + } + + static void +@@ -1302,6 +1412,24 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_we + dev->hw->soc->wdma_desc_size, true)) + return -ENOMEM; + ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ struct mtk_wdma_desc *desc = wdma->desc; ++ int i; ++ ++ for (i = 0; i < MTK_WED_WDMA_RING_SIZE; i++) { ++ desc->buf0 = 0; ++ desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE); ++ desc->buf1 = 0; ++ desc->info = cpu_to_le32(MTK_WDMA_TXD0_DESC_INFO_DMA_DONE); ++ desc++; ++ desc->buf0 = 0; ++ desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE); ++ desc->buf1 = 0; ++ desc->info = cpu_to_le32(MTK_WDMA_TXD1_DESC_INFO_DMA_DONE); ++ desc++; ++ } ++ } ++ + wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE, + wdma->desc_phys); + wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT, +@@ -1367,6 +1495,9 @@ mtk_wed_configure_irq(struct mtk_wed_dev + + wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask); + } else { ++ if (mtk_wed_is_v3_or_greater(dev->hw)) ++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_TKID_ALI_EN); ++ + /* initail tx interrupt trigger */ + wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX, + MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN | +@@ -1419,33 +1550,60 @@ mtk_wed_dma_enable(struct mtk_wed_device + { + int i; + +- wed_set(dev, MTK_WED_WPDMA_INT_CTRL, MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV); ++ if (!mtk_wed_is_v3_or_greater(dev->hw)) { ++ wed_set(dev, MTK_WED_WPDMA_INT_CTRL, ++ MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV); ++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN); ++ wdma_set(dev, MTK_WDMA_GLO_CFG, ++ MTK_WDMA_GLO_CFG_TX_DMA_EN | ++ MTK_WDMA_GLO_CFG_RX_INFO1_PRERES | ++ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES); ++ wed_set(dev, MTK_WED_WPDMA_CTRL, MTK_WED_WPDMA_CTRL_SDL1_FIXED); ++ } else { ++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN | ++ MTK_WED_WPDMA_GLO_CFG_RX_DDONE2_WR); ++ wdma_set(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN); ++ } + + wed_set(dev, MTK_WED_GLO_CFG, + MTK_WED_GLO_CFG_TX_DMA_EN | + MTK_WED_GLO_CFG_RX_DMA_EN); +- wed_set(dev, MTK_WED_WPDMA_GLO_CFG, +- MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN | +- MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN); ++ + wed_set(dev, MTK_WED_WDMA_GLO_CFG, + MTK_WED_WDMA_GLO_CFG_RX_DRV_EN); + +- wdma_set(dev, MTK_WDMA_GLO_CFG, +- MTK_WDMA_GLO_CFG_TX_DMA_EN | +- MTK_WDMA_GLO_CFG_RX_INFO1_PRERES | +- MTK_WDMA_GLO_CFG_RX_INFO2_PRERES); +- + if (mtk_wed_is_v1(dev->hw)) { + wdma_set(dev, MTK_WDMA_GLO_CFG, + MTK_WDMA_GLO_CFG_RX_INFO3_PRERES); + return; + } + +- wed_set(dev, MTK_WED_WPDMA_CTRL, +- MTK_WED_WPDMA_CTRL_SDL1_FIXED); + wed_set(dev, MTK_WED_WPDMA_GLO_CFG, + MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC | + MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC); ++ ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ FIELD_PREP(MTK_WED_WDMA_RX_PREF_BURST_SIZE, 0x10) | ++ FIELD_PREP(MTK_WED_WDMA_RX_PREF_LOW_THRES, 0x8)); ++ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ MTK_WED_WDMA_RX_PREF_DDONE2_EN); ++ wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG, MTK_WED_WDMA_RX_PREF_EN); ++ ++ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK_LAST); ++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG, ++ MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_CHK | ++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4); ++ ++ wdma_set(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN); ++ } ++ + wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, + MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP | + MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV); +@@ -1457,11 +1615,22 @@ mtk_wed_dma_enable(struct mtk_wed_device + MTK_WED_WDMA_GLO_CFG_TX_DRV_EN | + MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK); + ++ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RXD_READ_LEN); + wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, + MTK_WED_WPDMA_RX_D_RX_DRV_EN | + FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) | +- FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL, +- 0x2)); ++ FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL, 0x2)); ++ ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_CFG, ++ MTK_WED_WPDMA_RX_D_PREF_EN | ++ FIELD_PREP(MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE, 0x10) | ++ FIELD_PREP(MTK_WED_WPDMA_RX_D_PREF_LOW_THRES, 0x8)); ++ ++ wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_EN); ++ wdma_set(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN); ++ wdma_set(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN); ++ } + + for (i = 0; i < MTK_WED_RX_QUEUES; i++) + mtk_wed_check_wfdma_rx_fill(dev, i); +@@ -1501,6 +1670,12 @@ mtk_wed_start(struct mtk_wed_device *dev + wed_r32(dev, MTK_WED_EXT_INT_MASK1); + wed_r32(dev, MTK_WED_EXT_INT_MASK2); + ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ wed_w32(dev, MTK_WED_EXT_INT_MASK3, ++ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY); ++ wed_r32(dev, MTK_WED_EXT_INT_MASK3); ++ } ++ + if (mtk_wed_rro_cfg(dev)) + return; + } +@@ -1552,6 +1727,7 @@ mtk_wed_attach(struct mtk_wed_device *de + dev->irq = hw->irq; + dev->wdma_idx = hw->index; + dev->version = hw->version; ++ dev->hw->pcie_base = mtk_wed_get_pcie_base(dev); + + if (hw->eth->dma_dev == hw->eth->dev && + of_dma_is_coherent(hw->eth->dev->of_node)) +@@ -1619,6 +1795,23 @@ mtk_wed_tx_ring_setup(struct mtk_wed_dev + ring->reg_base = MTK_WED_RING_TX(idx); + ring->wpdma = regs; + ++ if (mtk_wed_is_v3_or_greater(dev->hw) && idx == 1) { ++ /* reset prefetch index */ ++ wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR | ++ MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR); ++ ++ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR | ++ MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR); ++ ++ /* reset prefetch FIFO */ ++ wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG, ++ MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR | ++ MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR); ++ wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG, 0); ++ } ++ + /* WED -> WPDMA */ + wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys); + wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_COUNT, MTK_WED_TX_RING_SIZE); +@@ -1693,15 +1886,13 @@ mtk_wed_rx_ring_setup(struct mtk_wed_dev + static u32 + mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask) + { +- u32 val, ext_mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; ++ u32 val, ext_mask; + +- if (mtk_wed_is_v1(dev->hw)) +- ext_mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR; ++ if (mtk_wed_is_v3_or_greater(dev->hw)) ++ ext_mask = MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT | ++ MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD; + else +- ext_mask |= MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH | +- MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH | +- MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT | +- MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR; ++ ext_mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK; + + val = wed_r32(dev, MTK_WED_EXT_INT_STATUS); + wed_w32(dev, MTK_WED_EXT_INT_STATUS, val); +@@ -1942,6 +2133,9 @@ void mtk_wed_add_hw(struct device_node * + case 2: + hw->soc = &mt7986_data; + break; ++ case 3: ++ hw->soc = &mt7988_data; ++ break; + default: + case 1: + hw->mirror = syscon_regmap_lookup_by_phandle(eth_np, +--- a/drivers/net/ethernet/mediatek/mtk_wed.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -9,6 +9,8 @@ + #include + #include + ++#include "mtk_wed_regs.h" ++ + struct mtk_eth; + struct mtk_wed_wo; + +@@ -19,6 +21,7 @@ struct mtk_wed_soc_data { + u32 reset_idx_tx_mask; + u32 reset_idx_rx_mask; + } regmap; ++ u32 tx_ring_desc_size; + u32 wdma_desc_size; + }; + +@@ -35,6 +38,7 @@ struct mtk_wed_hw { + struct dentry *debugfs_dir; + struct mtk_wed_device *wed_dev; + struct mtk_wed_wo *wed_wo; ++ u32 pcie_base; + u32 debugfs_reg; + u32 num_flows; + u8 version; +@@ -61,6 +65,16 @@ static inline bool mtk_wed_is_v2(struct + return hw->version == 2; + } + ++static inline bool mtk_wed_is_v3(struct mtk_wed_hw *hw) ++{ ++ return hw->version == 3; ++} ++ ++static inline bool mtk_wed_is_v3_or_greater(struct mtk_wed_hw *hw) ++{ ++ return hw->version > 2; ++} ++ + static inline void + wed_w32(struct mtk_wed_device *dev, u32 reg, u32 val) + { +@@ -143,6 +157,21 @@ wpdma_txfree_w32(struct mtk_wed_device * + writel(val, dev->txfree_ring.wpdma + reg); + } + ++static inline u32 mtk_wed_get_pcie_base(struct mtk_wed_device *dev) ++{ ++ if (!mtk_wed_is_v3_or_greater(dev->hw)) ++ return MTK_WED_PCIE_BASE; ++ ++ switch (dev->hw->index) { ++ case 1: ++ return MTK_WED_PCIE_BASE1; ++ case 2: ++ return MTK_WED_PCIE_BASE2; ++ default: ++ return MTK_WED_PCIE_BASE0; ++ } ++} ++ + void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth, + void __iomem *wdma, phys_addr_t wdma_phy, + int index); +--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +@@ -331,10 +331,22 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + wo->hw->index + 1); + + /* load firmware */ +- if (of_device_is_compatible(wo->hw->node, "mediatek,mt7981-wed")) +- fw_name = MT7981_FIRMWARE_WO; +- else +- fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1 : MT7986_FIRMWARE_WO0; ++ switch (wo->hw->version) { ++ case 2: ++ if (of_device_is_compatible(wo->hw->node, ++ "mediatek,mt7981-wed")) ++ fw_name = MT7981_FIRMWARE_WO; ++ else ++ fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1 ++ : MT7986_FIRMWARE_WO0; ++ break; ++ case 3: ++ fw_name = wo->hw->index ? MT7988_FIRMWARE_WO1 ++ : MT7988_FIRMWARE_WO0; ++ break; ++ default: ++ return -EINVAL; ++ } + + ret = request_firmware(&fw, fw_name, wo->hw->dev); + if (ret) +@@ -355,15 +367,16 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + } + + /* set the start address */ +- boot_cr = wo->hw->index ? MTK_WO_MCU_CFG_LS_WA_BOOT_ADDR_ADDR +- : MTK_WO_MCU_CFG_LS_WM_BOOT_ADDR_ADDR; ++ if (!mtk_wed_is_v3_or_greater(wo->hw) && wo->hw->index) ++ boot_cr = MTK_WO_MCU_CFG_LS_WA_BOOT_ADDR_ADDR; ++ else ++ boot_cr = MTK_WO_MCU_CFG_LS_WM_BOOT_ADDR_ADDR; + wo_w32(wo, boot_cr, mem_region[MTK_WED_WO_REGION_EMI].phy_addr >> 16); + /* wo firmware reset */ + wo_w32(wo, MTK_WO_MCU_CFG_LS_WF_MCCR_CLR_ADDR, 0xc00); + +- val = wo_r32(wo, MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR); +- val |= wo->hw->index ? MTK_WO_MCU_CFG_LS_WF_WM_WA_WA_CPU_RSTB_MASK +- : MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK; ++ val = wo_r32(wo, MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR) | ++ MTK_WO_MCU_CFG_LS_WF_WM_WA_WM_CPU_RSTB_MASK; + wo_w32(wo, MTK_WO_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR, val); + out: + release_firmware(fw); +@@ -398,3 +411,5 @@ int mtk_wed_mcu_init(struct mtk_wed_wo * + MODULE_FIRMWARE(MT7981_FIRMWARE_WO); + MODULE_FIRMWARE(MT7986_FIRMWARE_WO0); + MODULE_FIRMWARE(MT7986_FIRMWARE_WO1); ++MODULE_FIRMWARE(MT7988_FIRMWARE_WO0); ++MODULE_FIRMWARE(MT7988_FIRMWARE_WO1); +--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -13,6 +13,9 @@ + #define MTK_WDMA_DESC_CTRL_LAST_SEG0 BIT(30) + #define MTK_WDMA_DESC_CTRL_DMA_DONE BIT(31) + ++#define MTK_WDMA_TXD0_DESC_INFO_DMA_DONE BIT(29) ++#define MTK_WDMA_TXD1_DESC_INFO_DMA_DONE BIT(31) ++ + struct mtk_wdma_desc { + __le32 buf0; + __le32 ctrl; +@@ -37,6 +40,7 @@ struct mtk_wdma_desc { + #define MTK_WED_RESET_WDMA_INT_AGENT BIT(19) + #define MTK_WED_RESET_RX_RRO_QM BIT(20) + #define MTK_WED_RESET_RX_ROUTE_QM BIT(21) ++#define MTK_WED_RESET_TX_AMSDU BIT(22) + #define MTK_WED_RESET_WED BIT(31) + + #define MTK_WED_CTRL 0x00c +@@ -44,6 +48,9 @@ struct mtk_wdma_desc { + #define MTK_WED_CTRL_WPDMA_INT_AGENT_BUSY BIT(1) + #define MTK_WED_CTRL_WDMA_INT_AGENT_EN BIT(2) + #define MTK_WED_CTRL_WDMA_INT_AGENT_BUSY BIT(3) ++#define MTK_WED_CTRL_WED_RX_IND_CMD_EN BIT(5) ++#define MTK_WED_CTRL_WED_RX_PG_BM_EN BIT(6) ++#define MTK_WED_CTRL_WED_RX_PG_BM_BUSY BIT(7) + #define MTK_WED_CTRL_WED_TX_BM_EN BIT(8) + #define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9) + #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10) +@@ -54,9 +61,14 @@ struct mtk_wdma_desc { + #define MTK_WED_CTRL_RX_RRO_QM_BUSY BIT(15) + #define MTK_WED_CTRL_RX_ROUTE_QM_EN BIT(16) + #define MTK_WED_CTRL_RX_ROUTE_QM_BUSY BIT(17) ++#define MTK_WED_CTRL_TX_TKID_ALI_EN BIT(20) ++#define MTK_WED_CTRL_TX_TKID_ALI_BUSY BIT(21) ++#define MTK_WED_CTRL_TX_AMSDU_EN BIT(22) ++#define MTK_WED_CTRL_TX_AMSDU_BUSY BIT(23) + #define MTK_WED_CTRL_FINAL_DIDX_READ BIT(24) + #define MTK_WED_CTRL_ETH_DMAD_FMT BIT(25) + #define MTK_WED_CTRL_MIB_READ_CLEAR BIT(28) ++#define MTK_WED_CTRL_FLD_MIB_RD_CLR BIT(28) + + #define MTK_WED_EXT_INT_STATUS 0x020 + #define MTK_WED_EXT_INT_STATUS_TF_LEN_ERR BIT(0) +@@ -89,6 +101,7 @@ struct mtk_wdma_desc { + #define MTK_WED_EXT_INT_MASK 0x028 + #define MTK_WED_EXT_INT_MASK1 0x02c + #define MTK_WED_EXT_INT_MASK2 0x030 ++#define MTK_WED_EXT_INT_MASK3 0x034 + + #define MTK_WED_STATUS 0x060 + #define MTK_WED_STATUS_TX GENMASK(15, 8) +@@ -96,9 +109,14 @@ struct mtk_wdma_desc { + #define MTK_WED_TX_BM_CTRL 0x080 + #define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM GENMASK(6, 0) + #define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM GENMASK(22, 16) ++#define MTK_WED_TX_BM_CTRL_LEGACY_EN BIT(26) ++#define MTK_WED_TX_TKID_CTRL_FREE_FORMAT BIT(27) + #define MTK_WED_TX_BM_CTRL_PAUSE BIT(28) + + #define MTK_WED_TX_BM_BASE 0x084 ++#define MTK_WED_TX_BM_INIT_PTR 0x088 ++#define MTK_WED_TX_BM_SW_TAIL_IDX GENMASK(16, 0) ++#define MTK_WED_TX_BM_INIT_SW_TAIL_IDX BIT(16) + + #define MTK_WED_TX_BM_TKID_START GENMASK(15, 0) + #define MTK_WED_TX_BM_TKID_END GENMASK(31, 16) +@@ -122,6 +140,9 @@ struct mtk_wdma_desc { + #define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM GENMASK(22, 16) + #define MTK_WED_TX_TKID_CTRL_PAUSE BIT(28) + ++#define MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM_V3 GENMASK(7, 0) ++#define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM_V3 GENMASK(23, 16) ++ + #define MTK_WED_TX_TKID_DYN_THR 0x0e0 + #define MTK_WED_TX_TKID_DYN_THR_LO GENMASK(6, 0) + #define MTK_WED_TX_TKID_DYN_THR_HI GENMASK(22, 16) +@@ -199,12 +220,15 @@ struct mtk_wdma_desc { + #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R1_PKT_PROC BIT(5) + #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC BIT(6) + #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R1_CRX_SYNC BIT(7) +-#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_VER GENMASK(18, 16) ++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_VER GENMASK(15, 12) ++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4 BIT(18) + #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNSUPPORT_FMT BIT(19) +-#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UEVENT_PKT_FMT_CHK BIT(20) ++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_CHK BIT(20) + #define MTK_WED_WPDMA_GLO_CFG_RX_DDONE2_WR BIT(21) + #define MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP BIT(24) ++#define MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK_LAST BIT(25) + #define MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV BIT(28) ++#define MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK BIT(30) + + #define MTK_WED_WPDMA_RESET_IDX 0x50c + #define MTK_WED_WPDMA_RESET_IDX_TX GENMASK(3, 0) +@@ -250,9 +274,10 @@ struct mtk_wdma_desc { + #define MTK_WED_PCIE_INT_TRIGGER_STATUS BIT(16) + + #define MTK_WED_PCIE_INT_CTRL 0x57c +-#define MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA BIT(20) +-#define MTK_WED_PCIE_INT_CTRL_SRC_SEL GENMASK(17, 16) + #define MTK_WED_PCIE_INT_CTRL_POLL_EN GENMASK(13, 12) ++#define MTK_WED_PCIE_INT_CTRL_SRC_SEL GENMASK(17, 16) ++#define MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA BIT(20) ++#define MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER BIT(21) + + #define MTK_WED_WPDMA_CFG_BASE 0x580 + #define MTK_WED_WPDMA_CFG_INT_MASK 0x584 +@@ -286,6 +311,20 @@ struct mtk_wdma_desc { + #define MTK_WED_WPDMA_RX_D_PROCESSED_MIB(_n) (0x784 + (_n) * 4) + #define MTK_WED_WPDMA_RX_D_COHERENT_MIB 0x78c + ++#define MTK_WED_WPDMA_RX_D_PREF_CFG 0x7b4 ++#define MTK_WED_WPDMA_RX_D_PREF_EN BIT(0) ++#define MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE GENMASK(12, 8) ++#define MTK_WED_WPDMA_RX_D_PREF_LOW_THRES GENMASK(21, 16) ++ ++#define MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX 0x7b8 ++#define MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR BIT(15) ++ ++#define MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX 0x7bc ++ ++#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG 0x7c0 ++#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R0_CLR BIT(0) ++#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R1_CLR BIT(16) ++ + #define MTK_WED_WDMA_RING_TX 0x800 + + #define MTK_WED_WDMA_TX_MIB 0x810 +@@ -293,6 +332,18 @@ struct mtk_wdma_desc { + #define MTK_WED_WDMA_RING_RX(_n) (0x900 + (_n) * 0x10) + #define MTK_WED_WDMA_RX_THRES(_n) (0x940 + (_n) * 0x4) + ++#define MTK_WED_WDMA_RX_PREF_CFG 0x950 ++#define MTK_WED_WDMA_RX_PREF_EN BIT(0) ++#define MTK_WED_WDMA_RX_PREF_BURST_SIZE GENMASK(12, 8) ++#define MTK_WED_WDMA_RX_PREF_LOW_THRES GENMASK(21, 16) ++#define MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR BIT(24) ++#define MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR BIT(25) ++#define MTK_WED_WDMA_RX_PREF_DDONE2_EN BIT(26) ++ ++#define MTK_WED_WDMA_RX_PREF_FIFO_CFG 0x95C ++#define MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR BIT(0) ++#define MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR BIT(16) ++ + #define MTK_WED_WDMA_GLO_CFG 0xa04 + #define MTK_WED_WDMA_GLO_CFG_TX_DRV_EN BIT(0) + #define MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK BIT(1) +@@ -325,6 +376,7 @@ struct mtk_wdma_desc { + #define MTK_WED_WDMA_INT_TRIGGER_RX_DONE GENMASK(17, 16) + + #define MTK_WED_WDMA_INT_CTRL 0xa2c ++#define MTK_WED_WDMA_INT_POLL_PRD GENMASK(7, 0) + #define MTK_WED_WDMA_INT_CTRL_POLL_SRC_SEL GENMASK(17, 16) + + #define MTK_WED_WDMA_CFG_BASE 0xaa0 +@@ -388,6 +440,18 @@ struct mtk_wdma_desc { + #define MTK_WDMA_INT_GRP1 0x250 + #define MTK_WDMA_INT_GRP2 0x254 + ++#define MTK_WDMA_PREF_TX_CFG 0x2d0 ++#define MTK_WDMA_PREF_TX_CFG_PREF_EN BIT(0) ++ ++#define MTK_WDMA_PREF_RX_CFG 0x2dc ++#define MTK_WDMA_PREF_RX_CFG_PREF_EN BIT(0) ++ ++#define MTK_WDMA_WRBK_TX_CFG 0x300 ++#define MTK_WDMA_WRBK_TX_CFG_WRBK_EN BIT(30) ++ ++#define MTK_WDMA_WRBK_RX_CFG 0x344 ++#define MTK_WDMA_WRBK_RX_CFG_WRBK_EN BIT(30) ++ + #define MTK_PCIE_MIRROR_MAP(n) ((n) ? 0x4 : 0x0) + #define MTK_PCIE_MIRROR_MAP_EN BIT(0) + #define MTK_PCIE_MIRROR_MAP_WED_ID BIT(1) +@@ -401,6 +465,30 @@ struct mtk_wdma_desc { + #define MTK_WED_RTQM_Q_DBG_BYPASS BIT(5) + #define MTK_WED_RTQM_TXDMAD_FPORT GENMASK(23, 20) + ++#define MTK_WED_RTQM_IGRS0_I2HW_DMAD_CNT 0xb1c ++#define MTK_WED_RTQM_IGRS0_I2H_DMAD_CNT(_n) (0xb20 + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS0_I2HW_PKT_CNT 0xb28 ++#define MTK_WED_RTQM_IGRS0_I2H_PKT_CNT(_n) (0xb2c + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS0_FDROP_CNT 0xb34 ++ ++#define MTK_WED_RTQM_IGRS1_I2HW_DMAD_CNT 0xb44 ++#define MTK_WED_RTQM_IGRS1_I2H_DMAD_CNT(_n) (0xb48 + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS1_I2HW_PKT_CNT 0xb50 ++#define MTK_WED_RTQM_IGRS1_I2H_PKT_CNT(_n) (0xb54 + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS1_FDROP_CNT 0xb5c ++ ++#define MTK_WED_RTQM_IGRS2_I2HW_DMAD_CNT 0xb6c ++#define MTK_WED_RTQM_IGRS2_I2H_DMAD_CNT(_n) (0xb70 + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS2_I2HW_PKT_CNT 0xb78 ++#define MTK_WED_RTQM_IGRS2_I2H_PKT_CNT(_n) (0xb7c + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS2_FDROP_CNT 0xb84 ++ ++#define MTK_WED_RTQM_IGRS3_I2HW_DMAD_CNT 0xb94 ++#define MTK_WED_RTQM_IGRS3_I2H_DMAD_CNT(_n) (0xb98 + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS3_I2HW_PKT_CNT 0xba0 ++#define MTK_WED_RTQM_IGRS3_I2H_PKT_CNT(_n) (0xba4 + (_n) * 0x4) ++#define MTK_WED_RTQM_IGRS3_FDROP_CNT 0xbac ++ + #define MTK_WED_RTQM_R2H_MIB(_n) (0xb70 + (_n) * 0x4) + #define MTK_WED_RTQM_R2Q_MIB(_n) (0xb78 + (_n) * 0x4) + #define MTK_WED_RTQM_Q2N_MIB 0xb80 +@@ -409,6 +497,24 @@ struct mtk_wdma_desc { + #define MTK_WED_RTQM_Q2B_MIB 0xb8c + #define MTK_WED_RTQM_PFDBK_MIB 0xb90 + ++#define MTK_WED_RTQM_ENQ_CFG0 0xbb8 ++#define MTK_WED_RTQM_ENQ_CFG_TXDMAD_FPORT GENMASK(15, 12) ++ ++#define MTK_WED_RTQM_FDROP_MIB 0xb84 ++#define MTK_WED_RTQM_ENQ_I2Q_DMAD_CNT 0xbbc ++#define MTK_WED_RTQM_ENQ_I2N_DMAD_CNT 0xbc0 ++#define MTK_WED_RTQM_ENQ_I2Q_PKT_CNT 0xbc4 ++#define MTK_WED_RTQM_ENQ_I2N_PKT_CNT 0xbc8 ++#define MTK_WED_RTQM_ENQ_USED_ENTRY_CNT 0xbcc ++#define MTK_WED_RTQM_ENQ_ERR_CNT 0xbd0 ++ ++#define MTK_WED_RTQM_DEQ_DMAD_CNT 0xbd8 ++#define MTK_WED_RTQM_DEQ_Q2I_DMAD_CNT 0xbdc ++#define MTK_WED_RTQM_DEQ_PKT_CNT 0xbe0 ++#define MTK_WED_RTQM_DEQ_Q2I_PKT_CNT 0xbe4 ++#define MTK_WED_RTQM_DEQ_USED_PFDBK_CNT 0xbe8 ++#define MTK_WED_RTQM_DEQ_ERR_CNT 0xbec ++ + #define MTK_WED_RROQM_GLO_CFG 0xc04 + #define MTK_WED_RROQM_RST_IDX 0xc08 + #define MTK_WED_RROQM_RST_IDX_MIOD BIT(0) +@@ -458,7 +564,116 @@ struct mtk_wdma_desc { + #define MTK_WED_RX_BM_INTF 0xd9c + #define MTK_WED_RX_BM_ERR_STS 0xda8 + ++#define MTK_RRO_IND_CMD_SIGNATURE 0xe00 ++#define MTK_RRO_IND_CMD_DMA_IDX GENMASK(11, 0) ++#define MTK_RRO_IND_CMD_MAGIC_CNT GENMASK(30, 28) ++ ++#define MTK_WED_IND_CMD_RX_CTRL0 0xe04 ++#define MTK_WED_IND_CMD_PROC_IDX GENMASK(11, 0) ++#define MTK_WED_IND_CMD_PREFETCH_FREE_CNT GENMASK(19, 16) ++#define MTK_WED_IND_CMD_MAGIC_CNT GENMASK(30, 28) ++ ++#define MTK_WED_IND_CMD_RX_CTRL1 0xe08 ++#define MTK_WED_IND_CMD_RX_CTRL2 0xe0c ++#define MTK_WED_IND_CMD_MAX_CNT GENMASK(11, 0) ++#define MTK_WED_IND_CMD_BASE_M GENMASK(19, 16) ++ ++#define MTK_WED_RRO_CFG0 0xe10 ++#define MTK_WED_RRO_CFG1 0xe14 ++#define MTK_WED_RRO_CFG1_MAX_WIN_SZ GENMASK(31, 29) ++#define MTK_WED_RRO_CFG1_ACK_SN_BASE_M GENMASK(19, 16) ++#define MTK_WED_RRO_CFG1_PARTICL_SE_ID GENMASK(11, 0) ++ ++#define MTK_WED_ADDR_ELEM_CFG0 0xe18 ++#define MTK_WED_ADDR_ELEM_CFG1 0xe1c ++#define MTK_WED_ADDR_ELEM_PREFETCH_FREE_CNT GENMASK(19, 16) ++ ++#define MTK_WED_ADDR_ELEM_TBL_CFG 0xe20 ++#define MTK_WED_ADDR_ELEM_TBL_OFFSET GENMASK(6, 0) ++#define MTK_WED_ADDR_ELEM_TBL_RD_RDY BIT(28) ++#define MTK_WED_ADDR_ELEM_TBL_WR_RDY BIT(29) ++#define MTK_WED_ADDR_ELEM_TBL_RD BIT(30) ++#define MTK_WED_ADDR_ELEM_TBL_WR BIT(31) ++ ++#define MTK_WED_RADDR_ELEM_TBL_WDATA 0xe24 ++#define MTK_WED_RADDR_ELEM_TBL_RDATA 0xe28 ++ ++#define MTK_WED_PN_CHECK_CFG 0xe30 ++#define MTK_WED_PN_CHECK_SE_ID GENMASK(11, 0) ++#define MTK_WED_PN_CHECK_RD_RDY BIT(28) ++#define MTK_WED_PN_CHECK_WR_RDY BIT(29) ++#define MTK_WED_PN_CHECK_RD BIT(30) ++#define MTK_WED_PN_CHECK_WR BIT(31) ++ ++#define MTK_WED_PN_CHECK_WDATA_M 0xe38 ++#define MTK_WED_PN_CHECK_IS_FIRST BIT(17) ++ ++#define MTK_WED_RRO_MSDU_PG_RING_CFG(_n) (0xe44 + (_n) * 0x8) ++ ++#define MTK_WED_RRO_MSDU_PG_RING2_CFG 0xe58 ++#define MTK_WED_RRO_MSDU_PG_DRV_CLR BIT(26) ++#define MTK_WED_RRO_MSDU_PG_DRV_EN BIT(31) ++ ++#define MTK_WED_RRO_MSDU_PG_CTRL0(_n) (0xe5c + (_n) * 0xc) ++#define MTK_WED_RRO_MSDU_PG_CTRL1(_n) (0xe60 + (_n) * 0xc) ++#define MTK_WED_RRO_MSDU_PG_CTRL2(_n) (0xe64 + (_n) * 0xc) ++ ++#define MTK_WED_RRO_RX_D_RX(_n) (0xe80 + (_n) * 0x10) ++ ++#define MTK_WED_RRO_RX_MAGIC_CNT BIT(13) ++ ++#define MTK_WED_RRO_RX_D_CFG(_n) (0xea0 + (_n) * 0x4) ++#define MTK_WED_RRO_RX_D_DRV_CLR BIT(26) ++#define MTK_WED_RRO_RX_D_DRV_EN BIT(31) ++ ++#define MTK_WED_RRO_PG_BM_RX_DMAM 0xeb0 ++#define MTK_WED_RRO_PG_BM_RX_SDL0 GENMASK(13, 0) ++ ++#define MTK_WED_RRO_PG_BM_BASE 0xeb4 ++#define MTK_WED_RRO_PG_BM_INIT_PTR 0xeb8 ++#define MTK_WED_RRO_PG_BM_SW_TAIL_IDX GENMASK(15, 0) ++#define MTK_WED_RRO_PG_BM_INIT_SW_TAIL_IDX BIT(16) ++ ++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX 0xeec ++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_EN BIT(0) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_CLR BIT(1) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_DONE_TRIG GENMASK(6, 2) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_EN BIT(8) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_CLR BIT(9) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_DONE_TRIG GENMASK(14, 10) ++ ++#define MTK_WED_WPDMA_INT_CTRL_RRO_MSDU_PG 0xef4 ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_EN BIT(0) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_CLR BIT(1) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_DONE_TRIG GENMASK(6, 2) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_EN BIT(8) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_CLR BIT(9) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_DONE_TRIG GENMASK(14, 10) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_EN BIT(16) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR BIT(17) ++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG GENMASK(22, 18) ++ ++#define MTK_WED_RX_IND_CMD_CNT0 0xf20 ++#define MTK_WED_RX_IND_CMD_DBG_CNT_EN BIT(31) ++ ++#define MTK_WED_RX_IND_CMD_CNT(_n) (0xf20 + (_n) * 0x4) ++#define MTK_WED_IND_CMD_MAGIC_CNT_FAIL_CNT GENMASK(15, 0) ++ ++#define MTK_WED_RX_ADDR_ELEM_CNT(_n) (0xf48 + (_n) * 0x4) ++#define MTK_WED_ADDR_ELEM_SIG_FAIL_CNT GENMASK(15, 0) ++#define MTK_WED_ADDR_ELEM_FIRST_SIG_FAIL_CNT GENMASK(31, 16) ++#define MTK_WED_ADDR_ELEM_ACKSN_CNT GENMASK(27, 0) ++ ++#define MTK_WED_RX_MSDU_PG_CNT(_n) (0xf5c + (_n) * 0x4) ++ ++#define MTK_WED_RX_PN_CHK_CNT 0xf70 ++#define MTK_WED_PN_CHK_FAIL_CNT GENMASK(15, 0) ++ + #define MTK_WED_WOCPU_VIEW_MIOD_BASE 0x8000 + #define MTK_WED_PCIE_INT_MASK 0x0 + ++#define MTK_WED_PCIE_BASE 0x11280000 ++#define MTK_WED_PCIE_BASE0 0x11300000 ++#define MTK_WED_PCIE_BASE1 0x11310000 ++#define MTK_WED_PCIE_BASE2 0x11290000 + #endif +--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h +@@ -91,6 +91,8 @@ enum mtk_wed_dummy_cr_idx { + #define MT7981_FIRMWARE_WO "mediatek/mt7981_wo.bin" + #define MT7986_FIRMWARE_WO0 "mediatek/mt7986_wo_0.bin" + #define MT7986_FIRMWARE_WO1 "mediatek/mt7986_wo_1.bin" ++#define MT7988_FIRMWARE_WO0 "mediatek/mt7988_wo_0.bin" ++#define MT7988_FIRMWARE_WO1 "mediatek/mt7988_wo_1.bin" + + #define MTK_WO_MCU_CFG_LS_BASE 0 + #define MTK_WO_MCU_CFG_LS_HW_VER_ADDR (MTK_WO_MCU_CFG_LS_BASE + 0x000) +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -139,6 +139,8 @@ struct mtk_wed_device { + u32 wpdma_rx; + + bool wcid_512; ++ bool hw_rro; ++ bool msi; + + u16 token_start; + unsigned int nbuf; +@@ -212,10 +214,12 @@ mtk_wed_device_attach(struct mtk_wed_dev + return ret; + } + +-static inline bool +-mtk_wed_get_rx_capa(struct mtk_wed_device *dev) ++static inline bool mtk_wed_get_rx_capa(struct mtk_wed_device *dev) + { + #ifdef CONFIG_NET_MEDIATEK_SOC_WED ++ if (dev->version == 3) ++ return dev->wlan.hw_rro; ++ + return dev->version != 1; + #else + return false; diff --git a/lede/target/linux/generic/backport-6.1/752-15-v6.7-net-ethernet-mtk_wed-refactor-mtk_wed_check_wfdma_rx.patch b/lede/target/linux/generic/backport-6.1/752-15-v6.7-net-ethernet-mtk_wed-refactor-mtk_wed_check_wfdma_rx.patch new file mode 100644 index 0000000000..e91ae69d08 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-15-v6.7-net-ethernet-mtk_wed-refactor-mtk_wed_check_wfdma_rx.patch @@ -0,0 +1,95 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:14 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: refactor mtk_wed_check_wfdma_rx_fill + routine + +Refactor mtk_wed_check_wfdma_rx_fill() in order to be reused adding HW +receive offload support for MT7988 SoC. + +Co-developed-by: Sujuan Chen +Signed-off-by: Sujuan Chen +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -585,22 +585,15 @@ mtk_wed_set_512_support(struct mtk_wed_d + } + } + +-#define MTK_WFMDA_RX_DMA_EN BIT(2) +-static void +-mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx) ++static int ++mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, ++ struct mtk_wed_ring *ring) + { +- u32 val; + int i; + +- if (!(dev->rx_ring[idx].flags & MTK_WED_RING_CONFIGURED)) +- return; /* queue is not configured by mt76 */ +- + for (i = 0; i < 3; i++) { +- u32 cur_idx; ++ u32 cur_idx = readl(ring->wpdma + MTK_WED_RING_OFS_CPU_IDX); + +- cur_idx = wed_r32(dev, +- MTK_WED_WPDMA_RING_RX_DATA(idx) + +- MTK_WED_RING_OFS_CPU_IDX); + if (cur_idx == MTK_WED_RX_RING_SIZE - 1) + break; + +@@ -609,12 +602,10 @@ mtk_wed_check_wfdma_rx_fill(struct mtk_w + + if (i == 3) { + dev_err(dev->hw->dev, "rx dma enable failed\n"); +- return; ++ return -ETIMEDOUT; + } + +- val = wifi_r32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base) | +- MTK_WFMDA_RX_DMA_EN; +- wifi_w32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base, val); ++ return 0; + } + + static void +@@ -1545,6 +1536,7 @@ mtk_wed_configure_irq(struct mtk_wed_dev + wed_w32(dev, MTK_WED_INT_MASK, irq_mask); + } + ++#define MTK_WFMDA_RX_DMA_EN BIT(2) + static void + mtk_wed_dma_enable(struct mtk_wed_device *dev) + { +@@ -1632,8 +1624,26 @@ mtk_wed_dma_enable(struct mtk_wed_device + wdma_set(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN); + } + +- for (i = 0; i < MTK_WED_RX_QUEUES; i++) +- mtk_wed_check_wfdma_rx_fill(dev, i); ++ for (i = 0; i < MTK_WED_RX_QUEUES; i++) { ++ struct mtk_wed_ring *ring = &dev->rx_ring[i]; ++ u32 val; ++ ++ if (!(ring->flags & MTK_WED_RING_CONFIGURED)) ++ continue; /* queue is not configured by mt76 */ ++ ++ if (mtk_wed_check_wfdma_rx_fill(dev, ring)) { ++ dev_err(dev->hw->dev, ++ "rx_ring(%d) dma enable failed\n", i); ++ continue; ++ } ++ ++ val = wifi_r32(dev, ++ dev->wlan.wpdma_rx_glo - ++ dev->wlan.phy_base) | MTK_WFMDA_RX_DMA_EN; ++ wifi_w32(dev, ++ dev->wlan.wpdma_rx_glo - dev->wlan.phy_base, ++ val); ++ } + } + + static void diff --git a/lede/target/linux/generic/backport-6.1/752-16-v6.7-net-ethernet-mtk_wed-introduce-partial-AMSDU-offload.patch b/lede/target/linux/generic/backport-6.1/752-16-v6.7-net-ethernet-mtk_wed-introduce-partial-AMSDU-offload.patch new file mode 100644 index 0000000000..6534d73d8e --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-16-v6.7-net-ethernet-mtk_wed-introduce-partial-AMSDU-offload.patch @@ -0,0 +1,465 @@ +From: Sujuan Chen +Date: Mon, 18 Sep 2023 12:29:15 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: introduce partial AMSDU offload + support for MT7988 + +Introduce partial AMSDU offload support for MT7988 SoC in order to merge +in hw packets belonging to the same AMSDU before passing them to the +WLAN nic. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Sujuan Chen +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -438,7 +438,8 @@ int mtk_foe_entry_set_pppoe(struct mtk_e + } + + int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry, +- int wdma_idx, int txq, int bss, int wcid) ++ int wdma_idx, int txq, int bss, int wcid, ++ bool amsdu_en) + { + struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(eth, entry); + u32 *ib2 = mtk_foe_entry_ib2(eth, entry); +@@ -450,6 +451,7 @@ int mtk_foe_entry_set_wdma(struct mtk_et + MTK_FOE_IB2_WDMA_WINFO_V2; + l2->w3info = FIELD_PREP(MTK_FOE_WINFO_WCID_V3, wcid) | + FIELD_PREP(MTK_FOE_WINFO_BSS_V3, bss); ++ l2->amsdu = FIELD_PREP(MTK_FOE_WINFO_AMSDU_EN, amsdu_en); + break; + case 2: + *ib2 &= ~MTK_FOE_IB2_PORT_MG_V2; +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -88,13 +88,13 @@ enum { + #define MTK_FOE_WINFO_BSS_V3 GENMASK(23, 16) + #define MTK_FOE_WINFO_WCID_V3 GENMASK(15, 0) + +-#define MTK_FOE_WINFO_PAO_USR_INFO GENMASK(15, 0) +-#define MTK_FOE_WINFO_PAO_TID GENMASK(19, 16) +-#define MTK_FOE_WINFO_PAO_IS_FIXEDRATE BIT(20) +-#define MTK_FOE_WINFO_PAO_IS_PRIOR BIT(21) +-#define MTK_FOE_WINFO_PAO_IS_SP BIT(22) +-#define MTK_FOE_WINFO_PAO_HF BIT(23) +-#define MTK_FOE_WINFO_PAO_AMSDU_EN BIT(24) ++#define MTK_FOE_WINFO_AMSDU_USR_INFO GENMASK(15, 0) ++#define MTK_FOE_WINFO_AMSDU_TID GENMASK(19, 16) ++#define MTK_FOE_WINFO_AMSDU_IS_FIXEDRATE BIT(20) ++#define MTK_FOE_WINFO_AMSDU_IS_PRIOR BIT(21) ++#define MTK_FOE_WINFO_AMSDU_IS_SP BIT(22) ++#define MTK_FOE_WINFO_AMSDU_HF BIT(23) ++#define MTK_FOE_WINFO_AMSDU_EN BIT(24) + + enum { + MTK_FOE_STATE_INVALID, +@@ -123,7 +123,7 @@ struct mtk_foe_mac_info { + + /* netsys_v3 */ + u32 w3info; +- u32 wpao; ++ u32 amsdu; + }; + + /* software-only entry type */ +@@ -394,7 +394,8 @@ int mtk_foe_entry_set_vlan(struct mtk_et + int mtk_foe_entry_set_pppoe(struct mtk_eth *eth, struct mtk_foe_entry *entry, + int sid); + int mtk_foe_entry_set_wdma(struct mtk_eth *eth, struct mtk_foe_entry *entry, +- int wdma_idx, int txq, int bss, int wcid); ++ int wdma_idx, int txq, int bss, int wcid, ++ bool amsdu_en); + int mtk_foe_entry_set_queue(struct mtk_eth *eth, struct mtk_foe_entry *entry, + unsigned int queue); + int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -111,6 +111,7 @@ mtk_flow_get_wdma_info(struct net_device + info->queue = path->mtk_wdma.queue; + info->bss = path->mtk_wdma.bss; + info->wcid = path->mtk_wdma.wcid; ++ info->amsdu = path->mtk_wdma.amsdu; + + return 0; + } +@@ -192,7 +193,7 @@ mtk_flow_set_output_device(struct mtk_et + + if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) { + mtk_foe_entry_set_wdma(eth, foe, info.wdma_idx, info.queue, +- info.bss, info.wcid); ++ info.bss, info.wcid, info.amsdu); + if (mtk_is_netsys_v2_or_greater(eth)) { + switch (info.wdma_idx) { + case 0: +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -29,6 +29,8 @@ + #define MTK_WED_RX_PAGE_BUF_PER_PAGE (PAGE_SIZE / 128) + #define MTK_WED_RX_RING_SIZE 1536 + #define MTK_WED_RX_PG_BM_CNT 8192 ++#define MTK_WED_AMSDU_BUF_SIZE (PAGE_SIZE << 4) ++#define MTK_WED_AMSDU_NPAGES 32 + + #define MTK_WED_TX_RING_SIZE 2048 + #define MTK_WED_WDMA_RING_SIZE 1024 +@@ -172,6 +174,23 @@ mtk_wdma_rx_reset(struct mtk_wed_device + return ret; + } + ++static u32 ++mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask) ++{ ++ return !!(wed_r32(dev, reg) & mask); ++} ++ ++static int ++mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask) ++{ ++ int sleep = 15000; ++ int timeout = 100 * sleep; ++ u32 val; ++ ++ return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep, ++ timeout, false, dev, reg, mask); ++} ++ + static void + mtk_wdma_tx_reset(struct mtk_wed_device *dev) + { +@@ -335,6 +354,118 @@ out: + } + + static int ++mtk_wed_amsdu_buffer_alloc(struct mtk_wed_device *dev) ++{ ++ struct mtk_wed_hw *hw = dev->hw; ++ struct mtk_wed_amsdu *wed_amsdu; ++ int i; ++ ++ if (!mtk_wed_is_v3_or_greater(hw)) ++ return 0; ++ ++ wed_amsdu = devm_kcalloc(hw->dev, MTK_WED_AMSDU_NPAGES, ++ sizeof(*wed_amsdu), GFP_KERNEL); ++ if (!wed_amsdu) ++ return -ENOMEM; ++ ++ for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++) { ++ void *ptr; ++ ++ /* each segment is 64K */ ++ ptr = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN | ++ __GFP_ZERO | __GFP_COMP | ++ GFP_DMA32, ++ get_order(MTK_WED_AMSDU_BUF_SIZE)); ++ if (!ptr) ++ goto error; ++ ++ wed_amsdu[i].txd = ptr; ++ wed_amsdu[i].txd_phy = dma_map_single(hw->dev, ptr, ++ MTK_WED_AMSDU_BUF_SIZE, ++ DMA_TO_DEVICE); ++ if (dma_mapping_error(hw->dev, wed_amsdu[i].txd_phy)) ++ goto error; ++ } ++ dev->hw->wed_amsdu = wed_amsdu; ++ ++ return 0; ++ ++error: ++ for (i--; i >= 0; i--) ++ dma_unmap_single(hw->dev, wed_amsdu[i].txd_phy, ++ MTK_WED_AMSDU_BUF_SIZE, DMA_TO_DEVICE); ++ return -ENOMEM; ++} ++ ++static void ++mtk_wed_amsdu_free_buffer(struct mtk_wed_device *dev) ++{ ++ struct mtk_wed_amsdu *wed_amsdu = dev->hw->wed_amsdu; ++ int i; ++ ++ if (!wed_amsdu) ++ return; ++ ++ for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++) { ++ dma_unmap_single(dev->hw->dev, wed_amsdu[i].txd_phy, ++ MTK_WED_AMSDU_BUF_SIZE, DMA_TO_DEVICE); ++ free_pages((unsigned long)wed_amsdu[i].txd, ++ get_order(MTK_WED_AMSDU_BUF_SIZE)); ++ } ++} ++ ++static int ++mtk_wed_amsdu_init(struct mtk_wed_device *dev) ++{ ++ struct mtk_wed_amsdu *wed_amsdu = dev->hw->wed_amsdu; ++ int i, ret; ++ ++ if (!wed_amsdu) ++ return 0; ++ ++ for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++) ++ wed_w32(dev, MTK_WED_AMSDU_HIFTXD_BASE_L(i), ++ wed_amsdu[i].txd_phy); ++ ++ /* init all sta parameter */ ++ wed_w32(dev, MTK_WED_AMSDU_STA_INFO_INIT, MTK_WED_AMSDU_STA_RMVL | ++ MTK_WED_AMSDU_STA_WTBL_HDRT_MODE | ++ FIELD_PREP(MTK_WED_AMSDU_STA_MAX_AMSDU_LEN, ++ dev->wlan.amsdu_max_len >> 8) | ++ FIELD_PREP(MTK_WED_AMSDU_STA_MAX_AMSDU_NUM, ++ dev->wlan.amsdu_max_subframes)); ++ ++ wed_w32(dev, MTK_WED_AMSDU_STA_INFO, MTK_WED_AMSDU_STA_INFO_DO_INIT); ++ ++ ret = mtk_wed_poll_busy(dev, MTK_WED_AMSDU_STA_INFO, ++ MTK_WED_AMSDU_STA_INFO_DO_INIT); ++ if (ret) { ++ dev_err(dev->hw->dev, "amsdu initialization failed\n"); ++ return ret; ++ } ++ ++ /* init partial amsdu offload txd src */ ++ wed_set(dev, MTK_WED_AMSDU_HIFTXD_CFG, ++ FIELD_PREP(MTK_WED_AMSDU_HIFTXD_SRC, dev->hw->index)); ++ ++ /* init qmem */ ++ wed_set(dev, MTK_WED_AMSDU_PSE, MTK_WED_AMSDU_PSE_RESET); ++ ret = mtk_wed_poll_busy(dev, MTK_WED_MON_AMSDU_QMEM_STS1, BIT(29)); ++ if (ret) { ++ pr_info("%s: amsdu qmem initialization failed\n", __func__); ++ return ret; ++ } ++ ++ /* eagle E1 PCIE1 tx ring 22 flow control issue */ ++ if (dev->wlan.id == 0x7991) ++ wed_clr(dev, MTK_WED_AMSDU_FIFO, MTK_WED_AMSDU_IS_PRIOR0_RING); ++ ++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN); ++ ++ return 0; ++} ++ ++static int + mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev) + { + u32 desc_size = dev->hw->soc->tx_ring_desc_size; +@@ -708,6 +839,7 @@ __mtk_wed_detach(struct mtk_wed_device * + + mtk_wdma_rx_reset(dev); + mtk_wed_reset(dev, MTK_WED_RESET_WED); ++ mtk_wed_amsdu_free_buffer(dev); + mtk_wed_free_tx_buffer(dev); + mtk_wed_free_tx_rings(dev); + +@@ -1128,23 +1260,6 @@ mtk_wed_ring_reset(struct mtk_wed_ring * + } + } + +-static u32 +-mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask) +-{ +- return !!(wed_r32(dev, reg) & mask); +-} +- +-static int +-mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask) +-{ +- int sleep = 15000; +- int timeout = 100 * sleep; +- u32 val; +- +- return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep, +- timeout, false, dev, reg, mask); +-} +- + static int + mtk_wed_rx_reset(struct mtk_wed_device *dev) + { +@@ -1691,6 +1806,7 @@ mtk_wed_start(struct mtk_wed_device *dev + } + + mtk_wed_set_512_support(dev, dev->wlan.wcid_512); ++ mtk_wed_amsdu_init(dev); + + mtk_wed_dma_enable(dev); + dev->running = true; +@@ -1747,6 +1863,10 @@ mtk_wed_attach(struct mtk_wed_device *de + if (ret) + goto out; + ++ ret = mtk_wed_amsdu_buffer_alloc(dev); ++ if (ret) ++ goto out; ++ + if (mtk_wed_get_rx_capa(dev)) { + ret = mtk_wed_rro_alloc(dev); + if (ret) +--- a/drivers/net/ethernet/mediatek/mtk_wed.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -25,6 +25,11 @@ struct mtk_wed_soc_data { + u32 wdma_desc_size; + }; + ++struct mtk_wed_amsdu { ++ void *txd; ++ dma_addr_t txd_phy; ++}; ++ + struct mtk_wed_hw { + const struct mtk_wed_soc_data *soc; + struct device_node *node; +@@ -38,6 +43,7 @@ struct mtk_wed_hw { + struct dentry *debugfs_dir; + struct mtk_wed_device *wed_dev; + struct mtk_wed_wo *wed_wo; ++ struct mtk_wed_amsdu *wed_amsdu; + u32 pcie_base; + u32 debugfs_reg; + u32 num_flows; +@@ -52,6 +58,7 @@ struct mtk_wdma_info { + u8 queue; + u16 wcid; + u8 bss; ++ u8 amsdu; + }; + + #ifdef CONFIG_NET_MEDIATEK_SOC_WED +--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -672,6 +672,82 @@ struct mtk_wdma_desc { + #define MTK_WED_WOCPU_VIEW_MIOD_BASE 0x8000 + #define MTK_WED_PCIE_INT_MASK 0x0 + ++#define MTK_WED_AMSDU_FIFO 0x1800 ++#define MTK_WED_AMSDU_IS_PRIOR0_RING BIT(10) ++ ++#define MTK_WED_AMSDU_STA_INFO 0x01810 ++#define MTK_WED_AMSDU_STA_INFO_DO_INIT BIT(0) ++#define MTK_WED_AMSDU_STA_INFO_SET_INIT BIT(1) ++ ++#define MTK_WED_AMSDU_STA_INFO_INIT 0x01814 ++#define MTK_WED_AMSDU_STA_WTBL_HDRT_MODE BIT(0) ++#define MTK_WED_AMSDU_STA_RMVL BIT(1) ++#define MTK_WED_AMSDU_STA_MAX_AMSDU_LEN GENMASK(7, 2) ++#define MTK_WED_AMSDU_STA_MAX_AMSDU_NUM GENMASK(11, 8) ++ ++#define MTK_WED_AMSDU_HIFTXD_BASE_L(_n) (0x1980 + (_n) * 0x4) ++ ++#define MTK_WED_AMSDU_PSE 0x1910 ++#define MTK_WED_AMSDU_PSE_RESET BIT(16) ++ ++#define MTK_WED_AMSDU_HIFTXD_CFG 0x1968 ++#define MTK_WED_AMSDU_HIFTXD_SRC GENMASK(16, 15) ++ ++#define MTK_WED_MON_AMSDU_FIFO_DMAD 0x1a34 ++ ++#define MTK_WED_MON_AMSDU_ENG_DMAD(_n) (0x1a80 + (_n) * 0x50) ++#define MTK_WED_MON_AMSDU_ENG_QFPL(_n) (0x1a84 + (_n) * 0x50) ++#define MTK_WED_MON_AMSDU_ENG_QENI(_n) (0x1a88 + (_n) * 0x50) ++#define MTK_WED_MON_AMSDU_ENG_QENO(_n) (0x1a8c + (_n) * 0x50) ++#define MTK_WED_MON_AMSDU_ENG_MERG(_n) (0x1a90 + (_n) * 0x50) ++ ++#define MTK_WED_MON_AMSDU_ENG_CNT8(_n) (0x1a94 + (_n) * 0x50) ++#define MTK_WED_AMSDU_ENG_MAX_QGPP_CNT GENMASK(10, 0) ++#define MTK_WED_AMSDU_ENG_MAX_PL_CNT GENMASK(27, 16) ++ ++#define MTK_WED_MON_AMSDU_ENG_CNT9(_n) (0x1a98 + (_n) * 0x50) ++#define MTK_WED_AMSDU_ENG_CUR_ENTRY GENMASK(10, 0) ++#define MTK_WED_AMSDU_ENG_MAX_BUF_MERGED GENMASK(20, 16) ++#define MTK_WED_AMSDU_ENG_MAX_MSDU_MERGED GENMASK(28, 24) ++ ++#define MTK_WED_MON_AMSDU_QMEM_STS1 0x1e04 ++ ++#define MTK_WED_MON_AMSDU_QMEM_CNT(_n) (0x1e0c + (_n) * 0x4) ++#define MTK_WED_AMSDU_QMEM_FQ_CNT GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_SP_QCNT GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID0_QCNT GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID1_QCNT GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID2_QCNT GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID3_QCNT GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID4_QCNT GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID5_QCNT GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID6_QCNT GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID7_QCNT GENMASK(11, 0) ++ ++#define MTK_WED_MON_AMSDU_QMEM_PTR(_n) (0x1e20 + (_n) * 0x4) ++#define MTK_WED_AMSDU_QMEM_FQ_HEAD GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_SP_QHEAD GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID0_QHEAD GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID1_QHEAD GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID2_QHEAD GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID3_QHEAD GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID4_QHEAD GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID5_QHEAD GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID6_QHEAD GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID7_QHEAD GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_FQ_TAIL GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_SP_QTAIL GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID0_QTAIL GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID1_QTAIL GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID2_QTAIL GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID3_QTAIL GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID4_QTAIL GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID5_QTAIL GENMASK(11, 0) ++#define MTK_WED_AMSDU_QMEM_TID6_QTAIL GENMASK(27, 16) ++#define MTK_WED_AMSDU_QMEM_TID7_QTAIL GENMASK(11, 0) ++ ++#define MTK_WED_MON_AMSDU_HIFTXD_FETCH_MSDU(_n) (0x1ec4 + (_n) * 0x4) ++ + #define MTK_WED_PCIE_BASE 0x11280000 + #define MTK_WED_PCIE_BASE0 0x11300000 + #define MTK_WED_PCIE_BASE1 0x11310000 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -928,6 +928,7 @@ struct net_device_path { + u8 queue; + u16 wcid; + u8 bss; ++ u8 amsdu; + } mtk_wdma; + }; + }; +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -129,6 +129,7 @@ struct mtk_wed_device { + enum mtk_wed_bus_tye bus_type; + void __iomem *base; + u32 phy_base; ++ u32 id; + + u32 wpdma_phys; + u32 wpdma_int; +@@ -147,10 +148,12 @@ struct mtk_wed_device { + unsigned int rx_nbuf; + unsigned int rx_npkt; + unsigned int rx_size; ++ unsigned int amsdu_max_len; + + u8 tx_tbit[MTK_WED_TX_QUEUES]; + u8 rx_tbit[MTK_WED_RX_QUEUES]; + u8 txfree_tbit; ++ u8 amsdu_max_subframes; + + u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id); + int (*offload_enable)(struct mtk_wed_device *wed); +@@ -224,6 +227,15 @@ static inline bool mtk_wed_get_rx_capa(s + #else + return false; + #endif ++} ++ ++static inline bool mtk_wed_is_amsdu_supported(struct mtk_wed_device *dev) ++{ ++#ifdef CONFIG_NET_MEDIATEK_SOC_WED ++ return dev->version == 3; ++#else ++ return false; ++#endif + } + + #ifdef CONFIG_NET_MEDIATEK_SOC_WED diff --git a/lede/target/linux/generic/backport-6.1/752-17-v6.7-net-ethernet-mtk_wed-introduce-hw_rro-support-for-MT.patch b/lede/target/linux/generic/backport-6.1/752-17-v6.7-net-ethernet-mtk_wed-introduce-hw_rro-support-for-MT.patch new file mode 100644 index 0000000000..0cf4c18875 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-17-v6.7-net-ethernet-mtk_wed-introduce-hw_rro-support-for-MT.patch @@ -0,0 +1,483 @@ +From: Sujuan Chen +Date: Mon, 18 Sep 2023 12:29:16 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: introduce hw_rro support for MT7988 + +MT7988 SoC support 802.11 receive reordering offload in hw while +MT7986 SoC implements it through the firmware running on the mcu. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Sujuan Chen +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -26,7 +26,7 @@ + #define MTK_WED_BUF_SIZE 2048 + #define MTK_WED_PAGE_BUF_SIZE 128 + #define MTK_WED_BUF_PER_PAGE (PAGE_SIZE / 2048) +-#define MTK_WED_RX_PAGE_BUF_PER_PAGE (PAGE_SIZE / 128) ++#define MTK_WED_RX_BUF_PER_PAGE (PAGE_SIZE / MTK_WED_PAGE_BUF_SIZE) + #define MTK_WED_RX_RING_SIZE 1536 + #define MTK_WED_RX_PG_BM_CNT 8192 + #define MTK_WED_AMSDU_BUF_SIZE (PAGE_SIZE << 4) +@@ -596,6 +596,68 @@ free_pagelist: + } + + static int ++mtk_wed_hwrro_buffer_alloc(struct mtk_wed_device *dev) ++{ ++ int n_pages = MTK_WED_RX_PG_BM_CNT / MTK_WED_RX_BUF_PER_PAGE; ++ struct mtk_wed_buf *page_list; ++ struct mtk_wed_bm_desc *desc; ++ dma_addr_t desc_phys; ++ int i, page_idx = 0; ++ ++ if (!dev->wlan.hw_rro) ++ return 0; ++ ++ page_list = kcalloc(n_pages, sizeof(*page_list), GFP_KERNEL); ++ if (!page_list) ++ return -ENOMEM; ++ ++ dev->hw_rro.size = dev->wlan.rx_nbuf & ~(MTK_WED_BUF_PER_PAGE - 1); ++ dev->hw_rro.pages = page_list; ++ desc = dma_alloc_coherent(dev->hw->dev, ++ dev->wlan.rx_nbuf * sizeof(*desc), ++ &desc_phys, GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ ++ dev->hw_rro.desc = desc; ++ dev->hw_rro.desc_phys = desc_phys; ++ ++ for (i = 0; i < MTK_WED_RX_PG_BM_CNT; i += MTK_WED_RX_BUF_PER_PAGE) { ++ dma_addr_t page_phys, buf_phys; ++ struct page *page; ++ int s; ++ ++ page = __dev_alloc_page(GFP_KERNEL); ++ if (!page) ++ return -ENOMEM; ++ ++ page_phys = dma_map_page(dev->hw->dev, page, 0, PAGE_SIZE, ++ DMA_BIDIRECTIONAL); ++ if (dma_mapping_error(dev->hw->dev, page_phys)) { ++ __free_page(page); ++ return -ENOMEM; ++ } ++ ++ page_list[page_idx].p = page; ++ page_list[page_idx++].phy_addr = page_phys; ++ dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE, ++ DMA_BIDIRECTIONAL); ++ ++ buf_phys = page_phys; ++ for (s = 0; s < MTK_WED_RX_BUF_PER_PAGE; s++) { ++ desc->buf0 = cpu_to_le32(buf_phys); ++ buf_phys += MTK_WED_PAGE_BUF_SIZE; ++ desc++; ++ } ++ ++ dma_sync_single_for_device(dev->hw->dev, page_phys, PAGE_SIZE, ++ DMA_BIDIRECTIONAL); ++ } ++ ++ return 0; ++} ++ ++static int + mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev) + { + struct mtk_wed_bm_desc *desc; +@@ -612,7 +674,42 @@ mtk_wed_rx_buffer_alloc(struct mtk_wed_d + dev->rx_buf_ring.desc_phys = desc_phys; + dev->wlan.init_rx_buf(dev, dev->wlan.rx_npkt); + +- return 0; ++ return mtk_wed_hwrro_buffer_alloc(dev); ++} ++ ++static void ++mtk_wed_hwrro_free_buffer(struct mtk_wed_device *dev) ++{ ++ struct mtk_wed_buf *page_list = dev->hw_rro.pages; ++ struct mtk_wed_bm_desc *desc = dev->hw_rro.desc; ++ int i, page_idx = 0; ++ ++ if (!dev->wlan.hw_rro) ++ return; ++ ++ if (!page_list) ++ return; ++ ++ if (!desc) ++ goto free_pagelist; ++ ++ for (i = 0; i < MTK_WED_RX_PG_BM_CNT; i += MTK_WED_RX_BUF_PER_PAGE) { ++ dma_addr_t buf_addr = page_list[page_idx].phy_addr; ++ void *page = page_list[page_idx++].p; ++ ++ if (!page) ++ break; ++ ++ dma_unmap_page(dev->hw->dev, buf_addr, PAGE_SIZE, ++ DMA_BIDIRECTIONAL); ++ __free_page(page); ++ } ++ ++ dma_free_coherent(dev->hw->dev, dev->hw_rro.size * sizeof(*desc), ++ desc, dev->hw_rro.desc_phys); ++ ++free_pagelist: ++ kfree(page_list); + } + + static void +@@ -626,6 +723,28 @@ mtk_wed_free_rx_buffer(struct mtk_wed_de + dev->wlan.release_rx_buf(dev); + dma_free_coherent(dev->hw->dev, dev->rx_buf_ring.size * sizeof(*desc), + desc, dev->rx_buf_ring.desc_phys); ++ ++ mtk_wed_hwrro_free_buffer(dev); ++} ++ ++static void ++mtk_wed_hwrro_init(struct mtk_wed_device *dev) ++{ ++ if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hw_rro) ++ return; ++ ++ wed_set(dev, MTK_WED_RRO_PG_BM_RX_DMAM, ++ FIELD_PREP(MTK_WED_RRO_PG_BM_RX_SDL0, 128)); ++ ++ wed_w32(dev, MTK_WED_RRO_PG_BM_BASE, dev->hw_rro.desc_phys); ++ ++ wed_w32(dev, MTK_WED_RRO_PG_BM_INIT_PTR, ++ MTK_WED_RRO_PG_BM_INIT_SW_TAIL_IDX | ++ FIELD_PREP(MTK_WED_RRO_PG_BM_SW_TAIL_IDX, ++ MTK_WED_RX_PG_BM_CNT)); ++ ++ /* enable rx_page_bm to fetch dmad */ ++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_PG_BM_EN); + } + + static void +@@ -639,6 +758,8 @@ mtk_wed_rx_buffer_hw_init(struct mtk_wed + wed_w32(dev, MTK_WED_RX_BM_DYN_ALLOC_TH, + FIELD_PREP(MTK_WED_RX_BM_DYN_ALLOC_TH_H, 0xffff)); + wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN); ++ ++ mtk_wed_hwrro_init(dev); + } + + static void +@@ -934,6 +1055,8 @@ mtk_wed_bus_init(struct mtk_wed_device * + static void + mtk_wed_set_wpdma(struct mtk_wed_device *dev) + { ++ int i; ++ + if (mtk_wed_is_v1(dev->hw)) { + wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys); + return; +@@ -951,6 +1074,15 @@ mtk_wed_set_wpdma(struct mtk_wed_device + + wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); + wed_w32(dev, dev->hw->soc->regmap.wpdma_rx_ring0, dev->wlan.wpdma_rx); ++ ++ if (!dev->wlan.hw_rro) ++ return; ++ ++ wed_w32(dev, MTK_WED_RRO_RX_D_CFG(0), dev->wlan.wpdma_rx_rro[0]); ++ wed_w32(dev, MTK_WED_RRO_RX_D_CFG(1), dev->wlan.wpdma_rx_rro[1]); ++ for (i = 0; i < MTK_WED_RX_PAGE_QUEUES; i++) ++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING_CFG(i), ++ dev->wlan.wpdma_rx_pg + i * 0x10); + } + + static void +@@ -1762,6 +1894,165 @@ mtk_wed_dma_enable(struct mtk_wed_device + } + + static void ++mtk_wed_start_hw_rro(struct mtk_wed_device *dev, u32 irq_mask, bool reset) ++{ ++ int i; ++ ++ wed_w32(dev, MTK_WED_WPDMA_INT_MASK, irq_mask); ++ wed_w32(dev, MTK_WED_INT_MASK, irq_mask); ++ ++ if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hw_rro) ++ return; ++ ++ wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_MSDU_PG_DRV_CLR); ++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, ++ MTK_WED_RRO_MSDU_PG_DRV_CLR); ++ ++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RRO_RX, ++ MTK_WED_WPDMA_INT_CTRL_RRO_RX0_EN | ++ MTK_WED_WPDMA_INT_CTRL_RRO_RX0_CLR | ++ MTK_WED_WPDMA_INT_CTRL_RRO_RX1_EN | ++ MTK_WED_WPDMA_INT_CTRL_RRO_RX1_CLR | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_RX0_DONE_TRIG, ++ dev->wlan.rro_rx_tbit[0]) | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_RX1_DONE_TRIG, ++ dev->wlan.rro_rx_tbit[1])); ++ ++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RRO_MSDU_PG, ++ MTK_WED_WPDMA_INT_CTRL_RRO_PG0_EN | ++ MTK_WED_WPDMA_INT_CTRL_RRO_PG0_CLR | ++ MTK_WED_WPDMA_INT_CTRL_RRO_PG1_EN | ++ MTK_WED_WPDMA_INT_CTRL_RRO_PG1_CLR | ++ MTK_WED_WPDMA_INT_CTRL_RRO_PG2_EN | ++ MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG0_DONE_TRIG, ++ dev->wlan.rx_pg_tbit[0]) | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG1_DONE_TRIG, ++ dev->wlan.rx_pg_tbit[1]) | ++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG, ++ dev->wlan.rx_pg_tbit[2])); ++ ++ /* RRO_MSDU_PG_RING2_CFG1_FLD_DRV_EN should be enabled after ++ * WM FWDL completed, otherwise RRO_MSDU_PG ring may broken ++ */ ++ wed_set(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, ++ MTK_WED_RRO_MSDU_PG_DRV_EN); ++ ++ for (i = 0; i < MTK_WED_RX_QUEUES; i++) { ++ struct mtk_wed_ring *ring = &dev->rx_rro_ring[i]; ++ ++ if (!(ring->flags & MTK_WED_RING_CONFIGURED)) ++ continue; ++ ++ if (mtk_wed_check_wfdma_rx_fill(dev, ring)) ++ dev_err(dev->hw->dev, ++ "rx_rro_ring(%d) initialization failed\n", i); ++ } ++ ++ for (i = 0; i < MTK_WED_RX_PAGE_QUEUES; i++) { ++ struct mtk_wed_ring *ring = &dev->rx_page_ring[i]; ++ ++ if (!(ring->flags & MTK_WED_RING_CONFIGURED)) ++ continue; ++ ++ if (mtk_wed_check_wfdma_rx_fill(dev, ring)) ++ dev_err(dev->hw->dev, ++ "rx_page_ring(%d) initialization failed\n", i); ++ } ++} ++ ++static void ++mtk_wed_rro_rx_ring_setup(struct mtk_wed_device *dev, int idx, ++ void __iomem *regs) ++{ ++ struct mtk_wed_ring *ring = &dev->rx_rro_ring[idx]; ++ ++ ring->wpdma = regs; ++ wed_w32(dev, MTK_WED_RRO_RX_D_RX(idx) + MTK_WED_RING_OFS_BASE, ++ readl(regs)); ++ wed_w32(dev, MTK_WED_RRO_RX_D_RX(idx) + MTK_WED_RING_OFS_COUNT, ++ readl(regs + MTK_WED_RING_OFS_COUNT)); ++ ring->flags |= MTK_WED_RING_CONFIGURED; ++} ++ ++static void ++mtk_wed_msdu_pg_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs) ++{ ++ struct mtk_wed_ring *ring = &dev->rx_page_ring[idx]; ++ ++ ring->wpdma = regs; ++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_CTRL0(idx) + MTK_WED_RING_OFS_BASE, ++ readl(regs)); ++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_CTRL0(idx) + MTK_WED_RING_OFS_COUNT, ++ readl(regs + MTK_WED_RING_OFS_COUNT)); ++ ring->flags |= MTK_WED_RING_CONFIGURED; ++} ++ ++static int ++mtk_wed_ind_rx_ring_setup(struct mtk_wed_device *dev, void __iomem *regs) ++{ ++ struct mtk_wed_ring *ring = &dev->ind_cmd_ring; ++ u32 val = readl(regs + MTK_WED_RING_OFS_COUNT); ++ int i, count = 0; ++ ++ ring->wpdma = regs; ++ wed_w32(dev, MTK_WED_IND_CMD_RX_CTRL1 + MTK_WED_RING_OFS_BASE, ++ readl(regs) & 0xfffffff0); ++ ++ wed_w32(dev, MTK_WED_IND_CMD_RX_CTRL1 + MTK_WED_RING_OFS_COUNT, ++ readl(regs + MTK_WED_RING_OFS_COUNT)); ++ ++ /* ack sn cr */ ++ wed_w32(dev, MTK_WED_RRO_CFG0, dev->wlan.phy_base + ++ dev->wlan.ind_cmd.ack_sn_addr); ++ wed_w32(dev, MTK_WED_RRO_CFG1, ++ FIELD_PREP(MTK_WED_RRO_CFG1_MAX_WIN_SZ, ++ dev->wlan.ind_cmd.win_size) | ++ FIELD_PREP(MTK_WED_RRO_CFG1_PARTICL_SE_ID, ++ dev->wlan.ind_cmd.particular_sid)); ++ ++ /* particular session addr element */ ++ wed_w32(dev, MTK_WED_ADDR_ELEM_CFG0, ++ dev->wlan.ind_cmd.particular_se_phys); ++ ++ for (i = 0; i < dev->wlan.ind_cmd.se_group_nums; i++) { ++ wed_w32(dev, MTK_WED_RADDR_ELEM_TBL_WDATA, ++ dev->wlan.ind_cmd.addr_elem_phys[i] >> 4); ++ wed_w32(dev, MTK_WED_ADDR_ELEM_TBL_CFG, ++ MTK_WED_ADDR_ELEM_TBL_WR | (i & 0x7f)); ++ ++ val = wed_r32(dev, MTK_WED_ADDR_ELEM_TBL_CFG); ++ while (!(val & MTK_WED_ADDR_ELEM_TBL_WR_RDY) && count++ < 100) ++ val = wed_r32(dev, MTK_WED_ADDR_ELEM_TBL_CFG); ++ if (count >= 100) ++ dev_err(dev->hw->dev, ++ "write ba session base failed\n"); ++ } ++ ++ /* pn check init */ ++ for (i = 0; i < dev->wlan.ind_cmd.particular_sid; i++) { ++ wed_w32(dev, MTK_WED_PN_CHECK_WDATA_M, ++ MTK_WED_PN_CHECK_IS_FIRST); ++ ++ wed_w32(dev, MTK_WED_PN_CHECK_CFG, MTK_WED_PN_CHECK_WR | ++ FIELD_PREP(MTK_WED_PN_CHECK_SE_ID, i)); ++ ++ count = 0; ++ val = wed_r32(dev, MTK_WED_PN_CHECK_CFG); ++ while (!(val & MTK_WED_PN_CHECK_WR_RDY) && count++ < 100) ++ val = wed_r32(dev, MTK_WED_PN_CHECK_CFG); ++ if (count >= 100) ++ dev_err(dev->hw->dev, ++ "session(%d) initialization failed\n", i); ++ } ++ ++ wed_w32(dev, MTK_WED_RX_IND_CMD_CNT0, MTK_WED_RX_IND_CMD_DBG_CNT_EN); ++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_IND_CMD_EN); ++ ++ return 0; ++} ++ ++static void + mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask) + { + int i; +@@ -2215,6 +2506,10 @@ void mtk_wed_add_hw(struct device_node * + .detach = mtk_wed_detach, + .ppe_check = mtk_wed_ppe_check, + .setup_tc = mtk_wed_setup_tc, ++ .start_hw_rro = mtk_wed_start_hw_rro, ++ .rro_rx_ring_setup = mtk_wed_rro_rx_ring_setup, ++ .msdu_pg_rx_ring_setup = mtk_wed_msdu_pg_rx_ring_setup, ++ .ind_rx_ring_setup = mtk_wed_ind_rx_ring_setup, + }; + struct device_node *eth_np = eth->dev->of_node; + struct platform_device *pdev; +--- a/include/linux/soc/mediatek/mtk_wed.h ++++ b/include/linux/soc/mediatek/mtk_wed.h +@@ -10,6 +10,7 @@ + + #define MTK_WED_TX_QUEUES 2 + #define MTK_WED_RX_QUEUES 2 ++#define MTK_WED_RX_PAGE_QUEUES 3 + + #define WED_WO_STA_REC 0x6 + +@@ -99,6 +100,9 @@ struct mtk_wed_device { + struct mtk_wed_ring txfree_ring; + struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES]; + struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES]; ++ struct mtk_wed_ring rx_rro_ring[MTK_WED_RX_QUEUES]; ++ struct mtk_wed_ring rx_page_ring[MTK_WED_RX_PAGE_QUEUES]; ++ struct mtk_wed_ring ind_cmd_ring; + + struct { + int size; +@@ -120,6 +124,13 @@ struct mtk_wed_device { + dma_addr_t fdbk_phys; + } rro; + ++ struct { ++ int size; ++ struct mtk_wed_buf *pages; ++ struct mtk_wed_bm_desc *desc; ++ dma_addr_t desc_phys; ++ } hw_rro; ++ + /* filled by driver: */ + struct { + union { +@@ -138,6 +149,8 @@ struct mtk_wed_device { + u32 wpdma_txfree; + u32 wpdma_rx_glo; + u32 wpdma_rx; ++ u32 wpdma_rx_rro[MTK_WED_RX_QUEUES]; ++ u32 wpdma_rx_pg; + + bool wcid_512; + bool hw_rro; +@@ -152,9 +165,20 @@ struct mtk_wed_device { + + u8 tx_tbit[MTK_WED_TX_QUEUES]; + u8 rx_tbit[MTK_WED_RX_QUEUES]; ++ u8 rro_rx_tbit[MTK_WED_RX_QUEUES]; ++ u8 rx_pg_tbit[MTK_WED_RX_PAGE_QUEUES]; + u8 txfree_tbit; + u8 amsdu_max_subframes; + ++ struct { ++ u8 se_group_nums; ++ u16 win_size; ++ u16 particular_sid; ++ u32 ack_sn_addr; ++ dma_addr_t particular_se_phys; ++ dma_addr_t addr_elem_phys[1024]; ++ } ind_cmd; ++ + u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id); + int (*offload_enable)(struct mtk_wed_device *wed); + void (*offload_disable)(struct mtk_wed_device *wed); +@@ -193,6 +217,14 @@ struct mtk_wed_ops { + void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask); + int (*setup_tc)(struct mtk_wed_device *wed, struct net_device *dev, + enum tc_setup_type type, void *type_data); ++ void (*start_hw_rro)(struct mtk_wed_device *dev, u32 irq_mask, ++ bool reset); ++ void (*rro_rx_ring_setup)(struct mtk_wed_device *dev, int ring, ++ void __iomem *regs); ++ void (*msdu_pg_rx_ring_setup)(struct mtk_wed_device *dev, int ring, ++ void __iomem *regs); ++ int (*ind_rx_ring_setup)(struct mtk_wed_device *dev, ++ void __iomem *regs); + }; + + extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops; +@@ -264,6 +296,15 @@ static inline bool mtk_wed_is_amsdu_supp + #define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev) + #define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) \ + (_dev)->ops->setup_tc(_dev, _netdev, _type, _type_data) ++#define mtk_wed_device_start_hw_rro(_dev, _mask, _reset) \ ++ (_dev)->ops->start_hw_rro(_dev, _mask, _reset) ++#define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) \ ++ (_dev)->ops->rro_rx_ring_setup(_dev, _ring, _regs) ++#define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs) \ ++ (_dev)->ops->msdu_pg_rx_ring_setup(_dev, _ring, _regs) ++#define mtk_wed_device_ind_rx_ring_setup(_dev, _regs) \ ++ (_dev)->ops->ind_rx_ring_setup(_dev, _regs) ++ + #else + static inline bool mtk_wed_device_active(struct mtk_wed_device *dev) + { +@@ -283,6 +324,10 @@ static inline bool mtk_wed_device_active + #define mtk_wed_device_stop(_dev) do {} while (0) + #define mtk_wed_device_dma_reset(_dev) do {} while (0) + #define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) -EOPNOTSUPP ++#define mtk_wed_device_start_hw_rro(_dev, _mask, _reset) do {} while (0) ++#define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) -ENODEV ++#define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs) -ENODEV ++#define mtk_wed_device_ind_rx_ring_setup(_dev, _regs) -ENODEV + #endif + + #endif diff --git a/lede/target/linux/generic/backport-6.1/752-18-v6.7-net-ethernet-mtk_wed-debugfs-move-wed_v2-specific-re.patch b/lede/target/linux/generic/backport-6.1/752-18-v6.7-net-ethernet-mtk_wed-debugfs-move-wed_v2-specific-re.patch new file mode 100644 index 0000000000..5ea43a4445 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-18-v6.7-net-ethernet-mtk_wed-debugfs-move-wed_v2-specific-re.patch @@ -0,0 +1,78 @@ +From: Lorenzo Bianconi +Date: Mon, 18 Sep 2023 12:29:17 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: debugfs: move wed_v2 specific regs + out of regs array + +Move specific WED2.0 debugfs entries out of regs array. This is a +preliminary patch to introduce WED 3.0 debugfs info. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +@@ -151,7 +151,7 @@ DEFINE_SHOW_ATTRIBUTE(wed_txinfo); + static int + wed_rxinfo_show(struct seq_file *s, void *data) + { +- static const struct reg_dump regs[] = { ++ static const struct reg_dump regs_common[] = { + DUMP_STR("WPDMA RX"), + DUMP_WPDMA_RX_RING(0), + DUMP_WPDMA_RX_RING(1), +@@ -169,7 +169,7 @@ wed_rxinfo_show(struct seq_file *s, void + DUMP_WED_RING(WED_RING_RX_DATA(0)), + DUMP_WED_RING(WED_RING_RX_DATA(1)), + +- DUMP_STR("WED RRO"), ++ DUMP_STR("WED WO RRO"), + DUMP_WED_RRO_RING(WED_RROQM_MIOD_CTRL0), + DUMP_WED(WED_RROQM_MID_MIB), + DUMP_WED(WED_RROQM_MOD_MIB), +@@ -180,17 +180,6 @@ wed_rxinfo_show(struct seq_file *s, void + DUMP_WED(WED_RROQM_FDBK_ANC_MIB), + DUMP_WED(WED_RROQM_FDBK_ANC2H_MIB), + +- DUMP_STR("WED Route QM"), +- DUMP_WED(WED_RTQM_R2H_MIB(0)), +- DUMP_WED(WED_RTQM_R2Q_MIB(0)), +- DUMP_WED(WED_RTQM_Q2H_MIB(0)), +- DUMP_WED(WED_RTQM_R2H_MIB(1)), +- DUMP_WED(WED_RTQM_R2Q_MIB(1)), +- DUMP_WED(WED_RTQM_Q2H_MIB(1)), +- DUMP_WED(WED_RTQM_Q2N_MIB), +- DUMP_WED(WED_RTQM_Q2B_MIB), +- DUMP_WED(WED_RTQM_PFDBK_MIB), +- + DUMP_STR("WED WDMA TX"), + DUMP_WED(WED_WDMA_TX_MIB), + DUMP_WED_RING(WED_WDMA_RING_TX), +@@ -211,11 +200,25 @@ wed_rxinfo_show(struct seq_file *s, void + DUMP_WED(WED_RX_BM_INTF), + DUMP_WED(WED_RX_BM_ERR_STS), + }; ++ static const struct reg_dump regs_wed_v2[] = { ++ DUMP_STR("WED Route QM"), ++ DUMP_WED(WED_RTQM_R2H_MIB(0)), ++ DUMP_WED(WED_RTQM_R2Q_MIB(0)), ++ DUMP_WED(WED_RTQM_Q2H_MIB(0)), ++ DUMP_WED(WED_RTQM_R2H_MIB(1)), ++ DUMP_WED(WED_RTQM_R2Q_MIB(1)), ++ DUMP_WED(WED_RTQM_Q2H_MIB(1)), ++ DUMP_WED(WED_RTQM_Q2N_MIB), ++ DUMP_WED(WED_RTQM_Q2B_MIB), ++ DUMP_WED(WED_RTQM_PFDBK_MIB), ++ }; + struct mtk_wed_hw *hw = s->private; + struct mtk_wed_device *dev = hw->wed_dev; + +- if (dev) +- dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ if (dev) { ++ dump_wed_regs(s, dev, regs_common, ARRAY_SIZE(regs_common)); ++ dump_wed_regs(s, dev, regs_wed_v2, ARRAY_SIZE(regs_wed_v2)); ++ } + + return 0; + } diff --git a/lede/target/linux/generic/backport-6.1/752-19-v6.7-net-ethernet-mtk_wed-debugfs-add-WED-3.0-debugfs-ent.patch b/lede/target/linux/generic/backport-6.1/752-19-v6.7-net-ethernet-mtk_wed-debugfs-add-WED-3.0-debugfs-ent.patch new file mode 100644 index 0000000000..f491d2fd80 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-19-v6.7-net-ethernet-mtk_wed-debugfs-add-WED-3.0-debugfs-ent.patch @@ -0,0 +1,432 @@ +From: Sujuan Chen +Date: Mon, 18 Sep 2023 12:29:18 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: debugfs: add WED 3.0 debugfs entries + +Introduce WED3.0 debugfs entries useful for debugging. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Sujuan Chen +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +@@ -11,6 +11,7 @@ struct reg_dump { + u16 offset; + u8 type; + u8 base; ++ u32 mask; + }; + + enum { +@@ -25,6 +26,8 @@ enum { + + #define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING } + #define DUMP_REG(_reg, ...) { #_reg, MTK_##_reg, __VA_ARGS__ } ++#define DUMP_REG_MASK(_reg, _mask) \ ++ { #_mask, MTK_##_reg, DUMP_TYPE_WED, 0, MTK_##_mask } + #define DUMP_RING(_prefix, _base, ...) \ + { _prefix " BASE", _base, __VA_ARGS__ }, \ + { _prefix " CNT", _base + 0x4, __VA_ARGS__ }, \ +@@ -32,6 +35,7 @@ enum { + { _prefix " DIDX", _base + 0xc, __VA_ARGS__ } + + #define DUMP_WED(_reg) DUMP_REG(_reg, DUMP_TYPE_WED) ++#define DUMP_WED_MASK(_reg, _mask) DUMP_REG_MASK(_reg, _mask) + #define DUMP_WED_RING(_base) DUMP_RING(#_base, MTK_##_base, DUMP_TYPE_WED) + + #define DUMP_WDMA(_reg) DUMP_REG(_reg, DUMP_TYPE_WDMA) +@@ -212,12 +216,58 @@ wed_rxinfo_show(struct seq_file *s, void + DUMP_WED(WED_RTQM_Q2B_MIB), + DUMP_WED(WED_RTQM_PFDBK_MIB), + }; ++ static const struct reg_dump regs_wed_v3[] = { ++ DUMP_STR("WED RX RRO DATA"), ++ DUMP_WED_RING(WED_RRO_RX_D_RX(0)), ++ DUMP_WED_RING(WED_RRO_RX_D_RX(1)), ++ ++ DUMP_STR("WED RX MSDU PAGE"), ++ DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(0)), ++ DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(1)), ++ DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(2)), ++ ++ DUMP_STR("WED RX IND CMD"), ++ DUMP_WED(WED_IND_CMD_RX_CTRL1), ++ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL2, WED_IND_CMD_MAX_CNT), ++ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0, WED_IND_CMD_PROC_IDX), ++ DUMP_WED_MASK(RRO_IND_CMD_SIGNATURE, RRO_IND_CMD_DMA_IDX), ++ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0, WED_IND_CMD_MAGIC_CNT), ++ DUMP_WED_MASK(RRO_IND_CMD_SIGNATURE, RRO_IND_CMD_MAGIC_CNT), ++ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0, ++ WED_IND_CMD_PREFETCH_FREE_CNT), ++ DUMP_WED_MASK(WED_RRO_CFG1, WED_RRO_CFG1_PARTICL_SE_ID), ++ ++ DUMP_STR("WED ADDR ELEM"), ++ DUMP_WED(WED_ADDR_ELEM_CFG0), ++ DUMP_WED_MASK(WED_ADDR_ELEM_CFG1, ++ WED_ADDR_ELEM_PREFETCH_FREE_CNT), ++ ++ DUMP_STR("WED Route QM"), ++ DUMP_WED(WED_RTQM_ENQ_I2Q_DMAD_CNT), ++ DUMP_WED(WED_RTQM_ENQ_I2N_DMAD_CNT), ++ DUMP_WED(WED_RTQM_ENQ_I2Q_PKT_CNT), ++ DUMP_WED(WED_RTQM_ENQ_I2N_PKT_CNT), ++ DUMP_WED(WED_RTQM_ENQ_USED_ENTRY_CNT), ++ DUMP_WED(WED_RTQM_ENQ_ERR_CNT), ++ ++ DUMP_WED(WED_RTQM_DEQ_DMAD_CNT), ++ DUMP_WED(WED_RTQM_DEQ_Q2I_DMAD_CNT), ++ DUMP_WED(WED_RTQM_DEQ_PKT_CNT), ++ DUMP_WED(WED_RTQM_DEQ_Q2I_PKT_CNT), ++ DUMP_WED(WED_RTQM_DEQ_USED_PFDBK_CNT), ++ DUMP_WED(WED_RTQM_DEQ_ERR_CNT), ++ }; + struct mtk_wed_hw *hw = s->private; + struct mtk_wed_device *dev = hw->wed_dev; + + if (dev) { + dump_wed_regs(s, dev, regs_common, ARRAY_SIZE(regs_common)); +- dump_wed_regs(s, dev, regs_wed_v2, ARRAY_SIZE(regs_wed_v2)); ++ if (mtk_wed_is_v2(hw)) ++ dump_wed_regs(s, dev, ++ regs_wed_v2, ARRAY_SIZE(regs_wed_v2)); ++ else ++ dump_wed_regs(s, dev, ++ regs_wed_v3, ARRAY_SIZE(regs_wed_v3)); + } + + return 0; +@@ -225,6 +275,314 @@ wed_rxinfo_show(struct seq_file *s, void + DEFINE_SHOW_ATTRIBUTE(wed_rxinfo); + + static int ++wed_amsdu_show(struct seq_file *s, void *data) ++{ ++ static const struct reg_dump regs[] = { ++ DUMP_STR("WED AMDSU INFO"), ++ DUMP_WED(WED_MON_AMSDU_FIFO_DMAD), ++ ++ DUMP_STR("WED AMDSU ENG0 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(0)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(0)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(0)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(0)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(0)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(0), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(0), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(0), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(0), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(0), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG1 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(1)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(1)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(1)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(1)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(1)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(1), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(1), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(1), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG2 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(2)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(2)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(2)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(2)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(2)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(2), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(2), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG3 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(3)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(3)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(3)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(3)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(3)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(3), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(3), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(3), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(3), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(3), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG4 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(4)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(4)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(4)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(4)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(4)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(4), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(4), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG5 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(5)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(5)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(5)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(5)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(5)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(5), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(5), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(5), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(5), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(5), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG6 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(6)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(6)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(6)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(6)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(6)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(6), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(6), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(6), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(6), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(6), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG7 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(7)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(7)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(7)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(7)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(7)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(7), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(7), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(7), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(7), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED AMDSU ENG8 INFO"), ++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(8)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(8)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(8)), ++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(8)), ++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(8)), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(8), ++ WED_AMSDU_ENG_MAX_PL_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(8), ++ WED_AMSDU_ENG_MAX_QGPP_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(8), ++ WED_AMSDU_ENG_CUR_ENTRY), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(8), ++ WED_AMSDU_ENG_MAX_BUF_MERGED), ++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(8), ++ WED_AMSDU_ENG_MAX_MSDU_MERGED), ++ ++ DUMP_STR("WED QMEM INFO"), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(0), WED_AMSDU_QMEM_FQ_CNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(0), WED_AMSDU_QMEM_SP_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(1), WED_AMSDU_QMEM_TID0_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(1), WED_AMSDU_QMEM_TID1_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(2), WED_AMSDU_QMEM_TID2_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(2), WED_AMSDU_QMEM_TID3_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(3), WED_AMSDU_QMEM_TID4_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(3), WED_AMSDU_QMEM_TID5_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(4), WED_AMSDU_QMEM_TID6_QCNT), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(4), WED_AMSDU_QMEM_TID7_QCNT), ++ ++ DUMP_STR("WED QMEM HEAD INFO"), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(0), WED_AMSDU_QMEM_FQ_HEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(0), WED_AMSDU_QMEM_SP_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(1), WED_AMSDU_QMEM_TID0_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(1), WED_AMSDU_QMEM_TID1_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(2), WED_AMSDU_QMEM_TID2_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(2), WED_AMSDU_QMEM_TID3_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(3), WED_AMSDU_QMEM_TID4_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(3), WED_AMSDU_QMEM_TID5_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(4), WED_AMSDU_QMEM_TID6_QHEAD), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(4), WED_AMSDU_QMEM_TID7_QHEAD), ++ ++ DUMP_STR("WED QMEM TAIL INFO"), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(5), WED_AMSDU_QMEM_FQ_TAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(5), WED_AMSDU_QMEM_SP_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(6), WED_AMSDU_QMEM_TID0_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(6), WED_AMSDU_QMEM_TID1_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(7), WED_AMSDU_QMEM_TID2_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(7), WED_AMSDU_QMEM_TID3_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(8), WED_AMSDU_QMEM_TID4_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(8), WED_AMSDU_QMEM_TID5_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(9), WED_AMSDU_QMEM_TID6_QTAIL), ++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(9), WED_AMSDU_QMEM_TID7_QTAIL), ++ ++ DUMP_STR("WED HIFTXD MSDU INFO"), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(1)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(2)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(3)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(4)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(5)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(6)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(7)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(8)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(9)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(10)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(11)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(12)), ++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(13)), ++ }; ++ struct mtk_wed_hw *hw = s->private; ++ struct mtk_wed_device *dev = hw->wed_dev; ++ ++ if (dev) ++ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(wed_amsdu); ++ ++static int ++wed_rtqm_show(struct seq_file *s, void *data) ++{ ++ static const struct reg_dump regs[] = { ++ DUMP_STR("WED Route QM IGRS0(N2H + Recycle)"), ++ DUMP_WED(WED_RTQM_IGRS0_I2HW_DMAD_CNT), ++ DUMP_WED(WED_RTQM_IGRS0_I2H_DMAD_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS0_I2H_DMAD_CNT(1)), ++ DUMP_WED(WED_RTQM_IGRS0_I2HW_PKT_CNT), ++ DUMP_WED(WED_RTQM_IGRS0_I2H_PKT_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS0_I2H_PKT_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS0_FDROP_CNT), ++ ++ DUMP_STR("WED Route QM IGRS1(Legacy)"), ++ DUMP_WED(WED_RTQM_IGRS1_I2HW_DMAD_CNT), ++ DUMP_WED(WED_RTQM_IGRS1_I2H_DMAD_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS1_I2H_DMAD_CNT(1)), ++ DUMP_WED(WED_RTQM_IGRS1_I2HW_PKT_CNT), ++ DUMP_WED(WED_RTQM_IGRS1_I2H_PKT_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS1_I2H_PKT_CNT(1)), ++ DUMP_WED(WED_RTQM_IGRS1_FDROP_CNT), ++ ++ DUMP_STR("WED Route QM IGRS2(RRO3.0)"), ++ DUMP_WED(WED_RTQM_IGRS2_I2HW_DMAD_CNT), ++ DUMP_WED(WED_RTQM_IGRS2_I2H_DMAD_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS2_I2H_DMAD_CNT(1)), ++ DUMP_WED(WED_RTQM_IGRS2_I2HW_PKT_CNT), ++ DUMP_WED(WED_RTQM_IGRS2_I2H_PKT_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS2_I2H_PKT_CNT(1)), ++ DUMP_WED(WED_RTQM_IGRS2_FDROP_CNT), ++ ++ DUMP_STR("WED Route QM IGRS3(DEBUG)"), ++ DUMP_WED(WED_RTQM_IGRS2_I2HW_DMAD_CNT), ++ DUMP_WED(WED_RTQM_IGRS3_I2H_DMAD_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS3_I2H_DMAD_CNT(1)), ++ DUMP_WED(WED_RTQM_IGRS3_I2HW_PKT_CNT), ++ DUMP_WED(WED_RTQM_IGRS3_I2H_PKT_CNT(0)), ++ DUMP_WED(WED_RTQM_IGRS3_I2H_PKT_CNT(1)), ++ DUMP_WED(WED_RTQM_IGRS3_FDROP_CNT), ++ }; ++ struct mtk_wed_hw *hw = s->private; ++ struct mtk_wed_device *dev = hw->wed_dev; ++ ++ if (dev) ++ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(wed_rtqm); ++ ++static int ++wed_rro_show(struct seq_file *s, void *data) ++{ ++ static const struct reg_dump regs[] = { ++ DUMP_STR("RRO/IND CMD CNT"), ++ DUMP_WED(WED_RX_IND_CMD_CNT(1)), ++ DUMP_WED(WED_RX_IND_CMD_CNT(2)), ++ DUMP_WED(WED_RX_IND_CMD_CNT(3)), ++ DUMP_WED(WED_RX_IND_CMD_CNT(4)), ++ DUMP_WED(WED_RX_IND_CMD_CNT(5)), ++ DUMP_WED(WED_RX_IND_CMD_CNT(6)), ++ DUMP_WED(WED_RX_IND_CMD_CNT(7)), ++ DUMP_WED(WED_RX_IND_CMD_CNT(8)), ++ DUMP_WED_MASK(WED_RX_IND_CMD_CNT(9), ++ WED_IND_CMD_MAGIC_CNT_FAIL_CNT), ++ ++ DUMP_WED(WED_RX_ADDR_ELEM_CNT(0)), ++ DUMP_WED_MASK(WED_RX_ADDR_ELEM_CNT(1), ++ WED_ADDR_ELEM_SIG_FAIL_CNT), ++ DUMP_WED(WED_RX_MSDU_PG_CNT(1)), ++ DUMP_WED(WED_RX_MSDU_PG_CNT(2)), ++ DUMP_WED(WED_RX_MSDU_PG_CNT(3)), ++ DUMP_WED(WED_RX_MSDU_PG_CNT(4)), ++ DUMP_WED(WED_RX_MSDU_PG_CNT(5)), ++ DUMP_WED_MASK(WED_RX_PN_CHK_CNT, ++ WED_PN_CHK_FAIL_CNT), ++ }; ++ struct mtk_wed_hw *hw = s->private; ++ struct mtk_wed_device *dev = hw->wed_dev; ++ ++ if (dev) ++ dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); ++ ++ return 0; ++} ++DEFINE_SHOW_ATTRIBUTE(wed_rro); ++ ++static int + mtk_wed_reg_set(void *data, u64 val) + { + struct mtk_wed_hw *hw = data; +@@ -266,7 +624,16 @@ void mtk_wed_hw_add_debugfs(struct mtk_w + debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg); + debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval); + debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops); +- if (!mtk_wed_is_v1(hw)) ++ if (!mtk_wed_is_v1(hw)) { + debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, + &wed_rxinfo_fops); ++ if (mtk_wed_is_v3_or_greater(hw)) { ++ debugfs_create_file_unsafe("amsdu", 0400, dir, hw, ++ &wed_amsdu_fops); ++ debugfs_create_file_unsafe("rtqm", 0400, dir, hw, ++ &wed_rtqm_fops); ++ debugfs_create_file_unsafe("rro", 0400, dir, hw, ++ &wed_rro_fops); ++ } ++ } + } diff --git a/lede/target/linux/generic/backport-6.1/752-20-v6.7-net-ethernet-mtk_wed-add-wed-3.0-reset-support.patch b/lede/target/linux/generic/backport-6.1/752-20-v6.7-net-ethernet-mtk_wed-add-wed-3.0-reset-support.patch new file mode 100644 index 0000000000..aaaabf05e8 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/752-20-v6.7-net-ethernet-mtk_wed-add-wed-3.0-reset-support.patch @@ -0,0 +1,587 @@ +From: Sujuan Chen +Date: Mon, 18 Sep 2023 12:29:19 +0200 +Subject: [PATCH] net: ethernet: mtk_wed: add wed 3.0 reset support + +Introduce support for resetting Wireless Ethernet Dispatcher 3.0 +available on MT988 SoC. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Sujuan Chen +Signed-off-by: Paolo Abeni +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -148,6 +148,90 @@ mtk_wdma_read_reset(struct mtk_wed_devic + return wdma_r32(dev, MTK_WDMA_GLO_CFG); + } + ++static void ++mtk_wdma_v3_rx_reset(struct mtk_wed_device *dev) ++{ ++ u32 status; ++ ++ if (!mtk_wed_is_v3_or_greater(dev->hw)) ++ return; ++ ++ wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN); ++ wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_PREF_TX_CFG_PREF_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_PREF_TX_CFG)) ++ dev_err(dev->hw->dev, "rx reset failed\n"); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_PREF_RX_CFG_PREF_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_PREF_RX_CFG)) ++ dev_err(dev->hw->dev, "rx reset failed\n"); ++ ++ wdma_clr(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN); ++ wdma_clr(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_WRBK_TX_CFG)) ++ dev_err(dev->hw->dev, "rx reset failed\n"); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_WRBK_RX_CFG)) ++ dev_err(dev->hw->dev, "rx reset failed\n"); ++ ++ /* prefetch FIFO */ ++ wdma_w32(dev, MTK_WDMA_PREF_RX_FIFO_CFG, ++ MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR | ++ MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR); ++ wdma_clr(dev, MTK_WDMA_PREF_RX_FIFO_CFG, ++ MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR | ++ MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR); ++ ++ /* core FIFO */ ++ wdma_w32(dev, MTK_WDMA_XDMA_RX_FIFO_CFG, ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR); ++ wdma_clr(dev, MTK_WDMA_XDMA_RX_FIFO_CFG, ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR | ++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR); ++ ++ /* writeback FIFO */ ++ wdma_w32(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(0), ++ MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR); ++ wdma_w32(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(1), ++ MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR); ++ ++ wdma_clr(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(0), ++ MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR); ++ wdma_clr(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(1), ++ MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR); ++ ++ /* prefetch ring status */ ++ wdma_w32(dev, MTK_WDMA_PREF_SIDX_CFG, ++ MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR); ++ wdma_clr(dev, MTK_WDMA_PREF_SIDX_CFG, ++ MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR); ++ ++ /* writeback ring status */ ++ wdma_w32(dev, MTK_WDMA_WRBK_SIDX_CFG, ++ MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR); ++ wdma_clr(dev, MTK_WDMA_WRBK_SIDX_CFG, ++ MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR); ++} ++ + static int + mtk_wdma_rx_reset(struct mtk_wed_device *dev) + { +@@ -160,6 +244,7 @@ mtk_wdma_rx_reset(struct mtk_wed_device + if (ret) + dev_err(dev->hw->dev, "rx reset failed\n"); + ++ mtk_wdma_v3_rx_reset(dev); + wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX); + wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); + +@@ -192,6 +277,84 @@ mtk_wed_poll_busy(struct mtk_wed_device + } + + static void ++mtk_wdma_v3_tx_reset(struct mtk_wed_device *dev) ++{ ++ u32 status; ++ ++ if (!mtk_wed_is_v3_or_greater(dev->hw)) ++ return; ++ ++ wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN); ++ wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_PREF_TX_CFG_PREF_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_PREF_TX_CFG)) ++ dev_err(dev->hw->dev, "tx reset failed\n"); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_PREF_RX_CFG_PREF_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_PREF_RX_CFG)) ++ dev_err(dev->hw->dev, "tx reset failed\n"); ++ ++ wdma_clr(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN); ++ wdma_clr(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_WRBK_TX_CFG)) ++ dev_err(dev->hw->dev, "tx reset failed\n"); ++ ++ if (read_poll_timeout(wdma_r32, status, ++ !(status & MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY), ++ 0, 10000, false, dev, MTK_WDMA_WRBK_RX_CFG)) ++ dev_err(dev->hw->dev, "tx reset failed\n"); ++ ++ /* prefetch FIFO */ ++ wdma_w32(dev, MTK_WDMA_PREF_TX_FIFO_CFG, ++ MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR | ++ MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR); ++ wdma_clr(dev, MTK_WDMA_PREF_TX_FIFO_CFG, ++ MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR | ++ MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR); ++ ++ /* core FIFO */ ++ wdma_w32(dev, MTK_WDMA_XDMA_TX_FIFO_CFG, ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR | ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR); ++ wdma_clr(dev, MTK_WDMA_XDMA_TX_FIFO_CFG, ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR | ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR | ++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR); ++ ++ /* writeback FIFO */ ++ wdma_w32(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(0), ++ MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR); ++ wdma_w32(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(1), ++ MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR); ++ ++ wdma_clr(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(0), ++ MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR); ++ wdma_clr(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(1), ++ MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR); ++ ++ /* prefetch ring status */ ++ wdma_w32(dev, MTK_WDMA_PREF_SIDX_CFG, ++ MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR); ++ wdma_clr(dev, MTK_WDMA_PREF_SIDX_CFG, ++ MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR); ++ ++ /* writeback ring status */ ++ wdma_w32(dev, MTK_WDMA_WRBK_SIDX_CFG, ++ MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR); ++ wdma_clr(dev, MTK_WDMA_WRBK_SIDX_CFG, ++ MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR); ++} ++ ++static void + mtk_wdma_tx_reset(struct mtk_wed_device *dev) + { + u32 status, mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY; +@@ -202,6 +365,7 @@ mtk_wdma_tx_reset(struct mtk_wed_device + !(status & mask), 0, 10000)) + dev_err(dev->hw->dev, "tx reset failed\n"); + ++ mtk_wdma_v3_tx_reset(dev); + wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX); + wdma_w32(dev, MTK_WDMA_RESET_IDX, 0); + +@@ -1405,13 +1569,33 @@ mtk_wed_rx_reset(struct mtk_wed_device * + if (ret) + return ret; + ++ if (dev->wlan.hw_rro) { ++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_IND_CMD_EN); ++ mtk_wed_poll_busy(dev, MTK_WED_RRO_RX_HW_STS, ++ MTK_WED_RX_IND_CMD_BUSY); ++ mtk_wed_reset(dev, MTK_WED_RESET_RRO_RX_TO_PG); ++ } ++ + wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RX_DRV_EN); + ret = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, + MTK_WED_WPDMA_RX_D_RX_DRV_BUSY); ++ if (!ret && mtk_wed_is_v3_or_greater(dev->hw)) ++ ret = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_PREF_CFG, ++ MTK_WED_WPDMA_RX_D_PREF_BUSY); + if (ret) { + mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT); + mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_D_DRV); + } else { ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ /* 1.a. disable prefetch HW */ ++ wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_CFG, ++ MTK_WED_WPDMA_RX_D_PREF_EN); ++ mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_PREF_CFG, ++ MTK_WED_WPDMA_RX_D_PREF_BUSY); ++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, ++ MTK_WED_WPDMA_RX_D_RST_DRV_IDX_ALL); ++ } ++ + wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, + MTK_WED_WPDMA_RX_D_RST_CRX_IDX | + MTK_WED_WPDMA_RX_D_RST_DRV_IDX); +@@ -1439,23 +1623,52 @@ mtk_wed_rx_reset(struct mtk_wed_device * + wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0); + } + ++ if (dev->wlan.hw_rro) { ++ /* disable rro msdu page drv */ ++ wed_clr(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, ++ MTK_WED_RRO_MSDU_PG_DRV_EN); ++ ++ /* disable rro data drv */ ++ wed_clr(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_EN); ++ ++ /* rro msdu page drv reset */ ++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, ++ MTK_WED_RRO_MSDU_PG_DRV_CLR); ++ mtk_wed_poll_busy(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, ++ MTK_WED_RRO_MSDU_PG_DRV_CLR); ++ ++ /* rro data drv reset */ ++ wed_w32(dev, MTK_WED_RRO_RX_D_CFG(2), ++ MTK_WED_RRO_RX_D_DRV_CLR); ++ mtk_wed_poll_busy(dev, MTK_WED_RRO_RX_D_CFG(2), ++ MTK_WED_RRO_RX_D_DRV_CLR); ++ } ++ + /* reset route qm */ + wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN); + ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL, + MTK_WED_CTRL_RX_ROUTE_QM_BUSY); +- if (ret) ++ if (ret) { + mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM); +- else +- wed_set(dev, MTK_WED_RTQM_GLO_CFG, +- MTK_WED_RTQM_Q_RST); ++ } else if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ wed_set(dev, MTK_WED_RTQM_RST, BIT(0)); ++ wed_clr(dev, MTK_WED_RTQM_RST, BIT(0)); ++ mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM); ++ } else { ++ wed_set(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST); ++ } + + /* reset tx wdma */ + mtk_wdma_tx_reset(dev); + + /* reset tx wdma drv */ + wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_TX_DRV_EN); +- mtk_wed_poll_busy(dev, MTK_WED_CTRL, +- MTK_WED_CTRL_WDMA_INT_AGENT_BUSY); ++ if (mtk_wed_is_v3_or_greater(dev->hw)) ++ mtk_wed_poll_busy(dev, MTK_WED_WPDMA_STATUS, ++ MTK_WED_WPDMA_STATUS_TX_DRV); ++ else ++ mtk_wed_poll_busy(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_WDMA_INT_AGENT_BUSY); + mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV); + + /* reset wed rx dma */ +@@ -1476,6 +1689,14 @@ mtk_wed_rx_reset(struct mtk_wed_device * + MTK_WED_CTRL_WED_RX_BM_BUSY); + mtk_wed_reset(dev, MTK_WED_RESET_RX_BM); + ++ if (dev->wlan.hw_rro) { ++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_PG_BM_EN); ++ mtk_wed_poll_busy(dev, MTK_WED_CTRL, ++ MTK_WED_CTRL_WED_RX_PG_BM_BUSY); ++ wed_set(dev, MTK_WED_RESET, MTK_WED_RESET_RX_PG_BM); ++ wed_clr(dev, MTK_WED_RESET, MTK_WED_RESET_RX_PG_BM); ++ } ++ + /* wo change to enable state */ + val = MTK_WED_WO_STATE_ENABLE; + ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, +@@ -1493,6 +1714,7 @@ mtk_wed_rx_reset(struct mtk_wed_device * + false); + } + mtk_wed_free_rx_buffer(dev); ++ mtk_wed_hwrro_free_buffer(dev); + + return 0; + } +@@ -1526,15 +1748,41 @@ mtk_wed_reset_dma(struct mtk_wed_device + + /* 2. reset WDMA rx DMA */ + busy = !!mtk_wdma_rx_reset(dev); +- wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN); ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ val = MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE | ++ wed_r32(dev, MTK_WED_WDMA_GLO_CFG); ++ val &= ~MTK_WED_WDMA_GLO_CFG_RX_DRV_EN; ++ wed_w32(dev, MTK_WED_WDMA_GLO_CFG, val); ++ } else { ++ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, ++ MTK_WED_WDMA_GLO_CFG_RX_DRV_EN); ++ } ++ + if (!busy) + busy = mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG, + MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY); ++ if (!busy && mtk_wed_is_v3_or_greater(dev->hw)) ++ busy = mtk_wed_poll_busy(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ MTK_WED_WDMA_RX_PREF_BUSY); + + if (busy) { + mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT); + mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV); + } else { ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ /* 1.a. disable prefetch HW */ ++ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ MTK_WED_WDMA_RX_PREF_EN); ++ mtk_wed_poll_busy(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ MTK_WED_WDMA_RX_PREF_BUSY); ++ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG, ++ MTK_WED_WDMA_RX_PREF_DDONE2_EN); ++ ++ /* 2. Reset dma index */ ++ wed_w32(dev, MTK_WED_WDMA_RESET_IDX, ++ MTK_WED_WDMA_RESET_IDX_RX_ALL); ++ } ++ + wed_w32(dev, MTK_WED_WDMA_RESET_IDX, + MTK_WED_WDMA_RESET_IDX_RX | MTK_WED_WDMA_RESET_IDX_DRV); + wed_w32(dev, MTK_WED_WDMA_RESET_IDX, 0); +@@ -1550,8 +1798,13 @@ mtk_wed_reset_dma(struct mtk_wed_device + wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_FREE_AGENT_EN); + + for (i = 0; i < 100; i++) { +- val = wed_r32(dev, MTK_WED_TX_BM_INTF); +- if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40) ++ if (mtk_wed_is_v1(dev->hw)) ++ val = FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, ++ wed_r32(dev, MTK_WED_TX_BM_INTF)); ++ else ++ val = FIELD_GET(MTK_WED_TX_TKID_INTF_TKFIFO_FDEP, ++ wed_r32(dev, MTK_WED_TX_TKID_INTF)); ++ if (val == 0x40) + break; + } + +@@ -1573,6 +1826,8 @@ mtk_wed_reset_dma(struct mtk_wed_device + mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT); + mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV); + mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_DRV); ++ if (mtk_wed_is_v3_or_greater(dev->hw)) ++ wed_w32(dev, MTK_WED_RX1_CTRL2, 0); + } else { + wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, + MTK_WED_WPDMA_RESET_IDX_TX | +@@ -1589,7 +1844,14 @@ mtk_wed_reset_dma(struct mtk_wed_device + wed_w32(dev, MTK_WED_RESET_IDX, 0); + } + +- mtk_wed_rx_reset(dev); ++ if (mtk_wed_is_v3_or_greater(dev->hw)) { ++ /* reset amsdu engine */ ++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN); ++ mtk_wed_reset(dev, MTK_WED_RESET_TX_AMSDU); ++ } ++ ++ if (mtk_wed_get_rx_capa(dev)) ++ mtk_wed_rx_reset(dev); + } + + static int +@@ -1841,6 +2103,7 @@ mtk_wed_dma_enable(struct mtk_wed_device + MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4); + + wdma_set(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN); ++ wdma_set(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN); + } + + wed_clr(dev, MTK_WED_WPDMA_GLO_CFG, +@@ -1904,6 +2167,12 @@ mtk_wed_start_hw_rro(struct mtk_wed_devi + if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hw_rro) + return; + ++ if (reset) { ++ wed_set(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, ++ MTK_WED_RRO_MSDU_PG_DRV_EN); ++ return; ++ } ++ + wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_MSDU_PG_DRV_CLR); + wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, + MTK_WED_RRO_MSDU_PG_DRV_CLR); +--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h +@@ -28,6 +28,8 @@ struct mtk_wdma_desc { + #define MTK_WED_RESET 0x008 + #define MTK_WED_RESET_TX_BM BIT(0) + #define MTK_WED_RESET_RX_BM BIT(1) ++#define MTK_WED_RESET_RX_PG_BM BIT(2) ++#define MTK_WED_RESET_RRO_RX_TO_PG BIT(3) + #define MTK_WED_RESET_TX_FREE_AGENT BIT(4) + #define MTK_WED_RESET_WPDMA_TX_DRV BIT(8) + #define MTK_WED_RESET_WPDMA_RX_DRV BIT(9) +@@ -106,6 +108,9 @@ struct mtk_wdma_desc { + #define MTK_WED_STATUS 0x060 + #define MTK_WED_STATUS_TX GENMASK(15, 8) + ++#define MTK_WED_WPDMA_STATUS 0x068 ++#define MTK_WED_WPDMA_STATUS_TX_DRV GENMASK(15, 8) ++ + #define MTK_WED_TX_BM_CTRL 0x080 + #define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM GENMASK(6, 0) + #define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM GENMASK(22, 16) +@@ -140,6 +145,9 @@ struct mtk_wdma_desc { + #define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM GENMASK(22, 16) + #define MTK_WED_TX_TKID_CTRL_PAUSE BIT(28) + ++#define MTK_WED_TX_TKID_INTF 0x0dc ++#define MTK_WED_TX_TKID_INTF_TKFIFO_FDEP GENMASK(25, 16) ++ + #define MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM_V3 GENMASK(7, 0) + #define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM_V3 GENMASK(23, 16) + +@@ -190,6 +198,7 @@ struct mtk_wdma_desc { + #define MTK_WED_RING_RX_DATA(_n) (0x420 + (_n) * 0x10) + + #define MTK_WED_SCR0 0x3c0 ++#define MTK_WED_RX1_CTRL2 0x418 + #define MTK_WED_WPDMA_INT_TRIGGER 0x504 + #define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE BIT(1) + #define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE GENMASK(5, 4) +@@ -303,6 +312,7 @@ struct mtk_wdma_desc { + + #define MTK_WED_WPDMA_RX_D_RST_IDX 0x760 + #define MTK_WED_WPDMA_RX_D_RST_CRX_IDX GENMASK(17, 16) ++#define MTK_WED_WPDMA_RX_D_RST_DRV_IDX_ALL BIT(20) + #define MTK_WED_WPDMA_RX_D_RST_DRV_IDX GENMASK(25, 24) + + #define MTK_WED_WPDMA_RX_GLO_CFG 0x76c +@@ -313,6 +323,7 @@ struct mtk_wdma_desc { + + #define MTK_WED_WPDMA_RX_D_PREF_CFG 0x7b4 + #define MTK_WED_WPDMA_RX_D_PREF_EN BIT(0) ++#define MTK_WED_WPDMA_RX_D_PREF_BUSY BIT(1) + #define MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE GENMASK(12, 8) + #define MTK_WED_WPDMA_RX_D_PREF_LOW_THRES GENMASK(21, 16) + +@@ -334,11 +345,13 @@ struct mtk_wdma_desc { + + #define MTK_WED_WDMA_RX_PREF_CFG 0x950 + #define MTK_WED_WDMA_RX_PREF_EN BIT(0) ++#define MTK_WED_WDMA_RX_PREF_BUSY BIT(1) + #define MTK_WED_WDMA_RX_PREF_BURST_SIZE GENMASK(12, 8) + #define MTK_WED_WDMA_RX_PREF_LOW_THRES GENMASK(21, 16) + #define MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR BIT(24) + #define MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR BIT(25) + #define MTK_WED_WDMA_RX_PREF_DDONE2_EN BIT(26) ++#define MTK_WED_WDMA_RX_PREF_DDONE2_BUSY BIT(27) + + #define MTK_WED_WDMA_RX_PREF_FIFO_CFG 0x95C + #define MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR BIT(0) +@@ -367,6 +380,7 @@ struct mtk_wdma_desc { + + #define MTK_WED_WDMA_RESET_IDX 0xa08 + #define MTK_WED_WDMA_RESET_IDX_RX GENMASK(17, 16) ++#define MTK_WED_WDMA_RESET_IDX_RX_ALL BIT(20) + #define MTK_WED_WDMA_RESET_IDX_DRV GENMASK(25, 24) + + #define MTK_WED_WDMA_INT_CLR 0xa24 +@@ -437,21 +451,62 @@ struct mtk_wdma_desc { + #define MTK_WDMA_INT_MASK_RX_DELAY BIT(30) + #define MTK_WDMA_INT_MASK_RX_COHERENT BIT(31) + ++#define MTK_WDMA_XDMA_TX_FIFO_CFG 0x238 ++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR BIT(0) ++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR BIT(4) ++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR BIT(8) ++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR BIT(12) ++ ++#define MTK_WDMA_XDMA_RX_FIFO_CFG 0x23c ++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR BIT(0) ++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR BIT(4) ++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR BIT(8) ++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR BIT(12) ++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR BIT(15) ++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR BIT(18) ++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR BIT(21) ++ + #define MTK_WDMA_INT_GRP1 0x250 + #define MTK_WDMA_INT_GRP2 0x254 + + #define MTK_WDMA_PREF_TX_CFG 0x2d0 + #define MTK_WDMA_PREF_TX_CFG_PREF_EN BIT(0) ++#define MTK_WDMA_PREF_TX_CFG_PREF_BUSY BIT(1) + + #define MTK_WDMA_PREF_RX_CFG 0x2dc + #define MTK_WDMA_PREF_RX_CFG_PREF_EN BIT(0) ++#define MTK_WDMA_PREF_RX_CFG_PREF_BUSY BIT(1) ++ ++#define MTK_WDMA_PREF_RX_FIFO_CFG 0x2e0 ++#define MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR BIT(0) ++#define MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR BIT(16) ++ ++#define MTK_WDMA_PREF_TX_FIFO_CFG 0x2d4 ++#define MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR BIT(0) ++#define MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR BIT(16) ++ ++#define MTK_WDMA_PREF_SIDX_CFG 0x2e4 ++#define MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR GENMASK(3, 0) ++#define MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR GENMASK(5, 4) + + #define MTK_WDMA_WRBK_TX_CFG 0x300 ++#define MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY BIT(0) + #define MTK_WDMA_WRBK_TX_CFG_WRBK_EN BIT(30) + ++#define MTK_WDMA_WRBK_TX_FIFO_CFG(_n) (0x304 + (_n) * 0x4) ++#define MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR BIT(0) ++ + #define MTK_WDMA_WRBK_RX_CFG 0x344 ++#define MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY BIT(0) + #define MTK_WDMA_WRBK_RX_CFG_WRBK_EN BIT(30) + ++#define MTK_WDMA_WRBK_RX_FIFO_CFG(_n) (0x348 + (_n) * 0x4) ++#define MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR BIT(0) ++ ++#define MTK_WDMA_WRBK_SIDX_CFG 0x388 ++#define MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR GENMASK(3, 0) ++#define MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR GENMASK(5, 4) ++ + #define MTK_PCIE_MIRROR_MAP(n) ((n) ? 0x4 : 0x0) + #define MTK_PCIE_MIRROR_MAP_EN BIT(0) + #define MTK_PCIE_MIRROR_MAP_WED_ID BIT(1) +@@ -465,6 +520,8 @@ struct mtk_wdma_desc { + #define MTK_WED_RTQM_Q_DBG_BYPASS BIT(5) + #define MTK_WED_RTQM_TXDMAD_FPORT GENMASK(23, 20) + ++#define MTK_WED_RTQM_RST 0xb04 ++ + #define MTK_WED_RTQM_IGRS0_I2HW_DMAD_CNT 0xb1c + #define MTK_WED_RTQM_IGRS0_I2H_DMAD_CNT(_n) (0xb20 + (_n) * 0x4) + #define MTK_WED_RTQM_IGRS0_I2HW_PKT_CNT 0xb28 +@@ -653,6 +710,9 @@ struct mtk_wdma_desc { + #define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR BIT(17) + #define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG GENMASK(22, 18) + ++#define MTK_WED_RRO_RX_HW_STS 0xf00 ++#define MTK_WED_RX_IND_CMD_BUSY GENMASK(31, 0) ++ + #define MTK_WED_RX_IND_CMD_CNT0 0xf20 + #define MTK_WED_RX_IND_CMD_DBG_CNT_EN BIT(31) + diff --git a/lede/target/linux/generic/backport-6.1/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch b/lede/target/linux/generic/backport-6.1/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch new file mode 100644 index 0000000000..32ac37e8d0 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/760-v6.9-net-phy-aquantia-add-AQR111-and-AQR111B0-PHY-ID.patch @@ -0,0 +1,102 @@ +From 038ba1dc4e54d51d953f5618d8eb5dd39bd9de25 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 13 Feb 2024 14:35:51 +0100 +Subject: [PATCH] net: phy: aquantia: add AQR111 and AQR111B0 PHY ID + +Add Aquantia AQR111 and AQR111B0 PHY ID. These PHY advertise 10G speed +but actually supports up to 5G speed, hence some manual fixup is needed. + +The Aquantia AQR111B0 PHY is just a variant of the AQR111 with smaller +chip size. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240213133558.1836-1-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/aquantia/aquantia_main.c | 52 ++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -22,6 +22,8 @@ + #define PHY_ID_AQR107 0x03a1b4e0 + #define PHY_ID_AQCS109 0x03a1b5c2 + #define PHY_ID_AQR405 0x03a1b4b0 ++#define PHY_ID_AQR111 0x03a1b610 ++#define PHY_ID_AQR111B0 0x03a1b612 + #define PHY_ID_AQR113C 0x31c31c12 + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 +@@ -670,6 +672,16 @@ static int aqr107_probe(struct phy_devic + return aqr_hwmon_probe(phydev); + } + ++static int aqr111_config_init(struct phy_device *phydev) ++{ ++ /* AQR111 reports supporting speed up to 10G, ++ * however only speeds up to 5G are supported. ++ */ ++ phy_set_max_speed(phydev, SPEED_5000); ++ ++ return aqr107_config_init(phydev); ++} ++ + static struct phy_driver aqr_driver[] = { + { + PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), +@@ -744,6 +756,44 @@ static struct phy_driver aqr_driver[] = + .link_change_notify = aqr107_link_change_notify, + }, + { ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR111), ++ .name = "Aquantia AQR111", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr111_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0), ++ .name = "Aquantia AQR111B0", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr111_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR405), + .name = "Aquantia AQR405", + .config_aneg = aqr_config_aneg, +@@ -782,6 +832,8 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR111) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { } + }; diff --git a/lede/target/linux/generic/backport-6.1/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch b/lede/target/linux/generic/backport-6.1/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch new file mode 100644 index 0000000000..073bbbd49d --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/761-v6.9-net-phy-aquantia-add-AQR113-PHY-ID.patch @@ -0,0 +1,60 @@ +From 71b605d32017e5b8d257db7344bc2f8e8fcc973e Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 15 Feb 2024 16:30:05 +0100 +Subject: [PATCH] net: phy: aquantia: add AQR113 PHY ID + +Add Aquantia AQR113 PHY ID. Aquantia AQR113 is just a chip size variant of +the already supported AQR133C where the only difference is the PHY ID +and the hw chip size. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia/aquantia_main.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -24,6 +24,7 @@ + #define PHY_ID_AQR405 0x03a1b4b0 + #define PHY_ID_AQR111 0x03a1b610 + #define PHY_ID_AQR111B0 0x03a1b612 ++#define PHY_ID_AQR113 0x31c31c40 + #define PHY_ID_AQR113C 0x31c31c12 + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 +@@ -802,6 +803,25 @@ static struct phy_driver aqr_driver[] = + .read_status = aqr_read_status, + }, + { ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR113), ++ .name = "Aquantia AQR113", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), + .name = "Aquantia AQR113C", + .probe = aqr107_probe, +@@ -834,6 +854,7 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR111) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { } + }; diff --git a/lede/target/linux/generic/backport-6.1/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch b/lede/target/linux/generic/backport-6.1/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch new file mode 100644 index 0000000000..965b8c91b2 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/762-v6.9-net-phy-aquantia-add-AQR813-PHY-ID.patch @@ -0,0 +1,59 @@ +From 6d47302a3f0ba31445478d518d98bd55918bc8ab Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 15 Feb 2024 22:43:30 +0100 +Subject: [PATCH] net: phy: aquantia: add AQR813 PHY ID + +Aquantia AQR813 is the Octal Port variant of the AQR113. Add PHY ID for +it to provide support for it. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia/aquantia_main.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -26,6 +26,7 @@ + #define PHY_ID_AQR111B0 0x03a1b612 + #define PHY_ID_AQR113 0x31c31c40 + #define PHY_ID_AQR113C 0x31c31c12 ++#define PHY_ID_AQR813 0x31c31cb2 + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +@@ -840,6 +841,25 @@ static struct phy_driver aqr_driver[] = + .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, + }, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR813), ++ .name = "Aquantia AQR813", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, + }; + + module_phy_driver(aqr_driver); +@@ -856,6 +876,7 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, + { } + }; + diff --git a/lede/target/linux/generic/backport-6.1/765-v6.10-net-dsa-introduce-dsa_phylink_to_port.patch b/lede/target/linux/generic/backport-6.1/765-v6.10-net-dsa-introduce-dsa_phylink_to_port.patch new file mode 100644 index 0000000000..4cef7194eb --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/765-v6.10-net-dsa-introduce-dsa_phylink_to_port.patch @@ -0,0 +1,99 @@ +From f13b2b33c7674fa0988dfaa9adb95d7d912b489f Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 10 Apr 2024 20:42:38 +0100 +Subject: [PATCH 1/2] net: dsa: introduce dsa_phylink_to_port() + +We convert from a phylink_config struct to a dsa_port struct in many +places, let's provide a helper for this. + +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: Russell King (Oracle) +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/E1rudqA-006K9B-85@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + include/net/dsa.h | 6 ++++++ + net/dsa/port.c | 12 ++++++------ + 2 files changed, 12 insertions(+), 6 deletions(-) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -337,6 +337,12 @@ struct dsa_port { + struct list_head vlans; + }; + ++static inline struct dsa_port * ++dsa_phylink_to_port(struct phylink_config *config) ++{ ++ return container_of(config, struct dsa_port, pl_config); ++} ++ + /* TODO: ideally DSA ports would have a single dp->link_dp member, + * and no dst->rtable nor this struct dsa_link would be needed, + * but this would require some more complex tree walking, +--- a/net/dsa/port.c ++++ b/net/dsa/port.c +@@ -1552,7 +1552,7 @@ static void dsa_port_phylink_validate(st + unsigned long *supported, + struct phylink_link_state *state) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + + if (!ds->ops->phylink_validate) { +@@ -1567,7 +1567,7 @@ static void dsa_port_phylink_validate(st + static void dsa_port_phylink_mac_pcs_get_state(struct phylink_config *config, + struct phylink_link_state *state) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + int err; + +@@ -1589,7 +1589,7 @@ static struct phylink_pcs * + dsa_port_phylink_mac_select_pcs(struct phylink_config *config, + phy_interface_t interface) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct phylink_pcs *pcs = ERR_PTR(-EOPNOTSUPP); + struct dsa_switch *ds = dp->ds; + +@@ -1603,7 +1603,7 @@ static void dsa_port_phylink_mac_config( + unsigned int mode, + const struct phylink_link_state *state) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + + if (!ds->ops->phylink_mac_config) +@@ -1614,7 +1614,7 @@ static void dsa_port_phylink_mac_config( + + static void dsa_port_phylink_mac_an_restart(struct phylink_config *config) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + + if (!ds->ops->phylink_mac_an_restart) +@@ -1627,7 +1627,7 @@ static void dsa_port_phylink_mac_link_do + unsigned int mode, + phy_interface_t interface) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct phy_device *phydev = NULL; + struct dsa_switch *ds = dp->ds; + +@@ -1650,7 +1650,7 @@ static void dsa_port_phylink_mac_link_up + int speed, int duplex, + bool tx_pause, bool rx_pause) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + + if (!ds->ops->phylink_mac_link_up) { diff --git a/lede/target/linux/generic/backport-6.1/766-v6.10-net-dsa-allow-DSA-switch-drivers-to-provide-their-ow.patch b/lede/target/linux/generic/backport-6.1/766-v6.10-net-dsa-allow-DSA-switch-drivers-to-provide-their-ow.patch new file mode 100644 index 0000000000..0119925ab0 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/766-v6.10-net-dsa-allow-DSA-switch-drivers-to-provide-their-ow.patch @@ -0,0 +1,117 @@ +From c22d8240fcd73a1c3ec8dcb055bd583fb970c375 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 10 Apr 2024 20:42:43 +0100 +Subject: [PATCH 2/2] net: dsa: allow DSA switch drivers to provide their own + phylink mac ops + +Rather than having a shim for each and every phylink MAC operation, +allow DSA switch drivers to provide their own ops structure. When a +DSA driver provides the phylink MAC operations, the shimmed ops must +not be provided, so fail an attempt to register a switch with both +the phylink_mac_ops in struct dsa_switch and the phylink_mac_* +operations populated in dsa_switch_ops populated. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/E1rudqF-006K9H-Cc@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + include/net/dsa.h | 5 +++++ + net/dsa/dsa.c | 11 +++++++++++ + net/dsa/port.c | 26 ++++++++++++++++++++------ + 3 files changed, 36 insertions(+), 6 deletions(-) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -468,6 +468,11 @@ struct dsa_switch { + const struct dsa_switch_ops *ops; + + /* ++ * Allow a DSA switch driver to override the phylink MAC ops ++ */ ++ const struct phylink_mac_ops *phylink_mac_ops; ++ ++ /* + * Slave mii_bus and devices for the individual ports. + */ + u32 phys_mii_mask; +--- a/net/dsa/port.c ++++ b/net/dsa/port.c +@@ -1675,6 +1675,7 @@ static const struct phylink_mac_ops dsa_ + + int dsa_port_phylink_create(struct dsa_port *dp) + { ++ const struct phylink_mac_ops *mac_ops; + struct dsa_switch *ds = dp->ds; + phy_interface_t mode; + struct phylink *pl; +@@ -1694,8 +1695,12 @@ int dsa_port_phylink_create(struct dsa_p + if (ds->ops->phylink_get_caps) + ds->ops->phylink_get_caps(ds, dp->index, &dp->pl_config); + +- pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn), +- mode, &dsa_port_phylink_mac_ops); ++ mac_ops = &dsa_port_phylink_mac_ops; ++ if (ds->phylink_mac_ops) ++ mac_ops = ds->phylink_mac_ops; ++ ++ pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn), mode, ++ mac_ops); + if (IS_ERR(pl)) { + pr_err("error creating PHYLINK: %ld\n", PTR_ERR(pl)); + return PTR_ERR(pl); +@@ -1961,12 +1966,23 @@ static void dsa_shared_port_validate_of( + dn, dsa_port_is_cpu(dp) ? "CPU" : "DSA", dp->index); + } + ++static void dsa_shared_port_link_down(struct dsa_port *dp) ++{ ++ struct dsa_switch *ds = dp->ds; ++ ++ if (ds->phylink_mac_ops && ds->phylink_mac_ops->mac_link_down) ++ ds->phylink_mac_ops->mac_link_down(&dp->pl_config, MLO_AN_FIXED, ++ PHY_INTERFACE_MODE_NA); ++ else if (ds->ops->phylink_mac_link_down) ++ ds->ops->phylink_mac_link_down(ds, dp->index, MLO_AN_FIXED, ++ PHY_INTERFACE_MODE_NA); ++} ++ + int dsa_shared_port_link_register_of(struct dsa_port *dp) + { + struct dsa_switch *ds = dp->ds; + bool missing_link_description; + bool missing_phy_mode; +- int port = dp->index; + + dsa_shared_port_validate_of(dp, &missing_phy_mode, + &missing_link_description); +@@ -1982,9 +1998,7 @@ int dsa_shared_port_link_register_of(str + "Skipping phylink registration for %s port %d\n", + dsa_port_is_cpu(dp) ? "CPU" : "DSA", dp->index); + } else { +- if (ds->ops->phylink_mac_link_down) +- ds->ops->phylink_mac_link_down(ds, port, +- MLO_AN_FIXED, PHY_INTERFACE_MODE_NA); ++ dsa_shared_port_link_down(dp); + + return dsa_shared_port_phylink_register(dp); + } +--- a/net/dsa/dsa2.c ++++ b/net/dsa/dsa2.c +@@ -1758,6 +1758,15 @@ static int dsa_switch_probe(struct dsa_s + if (!ds->num_ports) + return -EINVAL; + ++ if (ds->phylink_mac_ops) { ++ if (ds->ops->phylink_mac_select_pcs || ++ ds->ops->phylink_mac_config || ++ ds->ops->phylink_mac_link_down || ++ ds->ops->phylink_mac_link_up || ++ ds->ops->adjust_link) ++ return -EINVAL; ++ } ++ + if (np) { + err = dsa_switch_parse_of(ds, np); + if (err) diff --git a/lede/target/linux/generic/backport-6.1/770-net-introduce-napi_is_scheduled-helper.patch b/lede/target/linux/generic/backport-6.1/770-net-introduce-napi_is_scheduled-helper.patch new file mode 100644 index 0000000000..789b93e9f9 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/770-net-introduce-napi_is_scheduled-helper.patch @@ -0,0 +1,96 @@ +From 7f3eb2174512fe6c9c0f062e96eccb0d3cc6d5cd Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 18 Oct 2023 14:35:47 +0200 +Subject: [PATCH] net: introduce napi_is_scheduled helper + +We currently have napi_if_scheduled_mark_missed that can be used to +check if napi is scheduled but that does more thing than simply checking +it and return a bool. Some driver already implement custom function to +check if napi is scheduled. + +Drop these custom function and introduce napi_is_scheduled that simply +check if napi is scheduled atomically. + +Update any driver and code that implement a similar check and instead +use this new helper. + +Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/chelsio/cxgb3/sge.c | 8 -------- + drivers/net/wireless/realtek/rtw89/core.c | 2 +- + include/linux/netdevice.h | 23 +++++++++++++++++++++++ + net/core/dev.c | 2 +- + 4 files changed, 25 insertions(+), 10 deletions(-) + +--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c ++++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c +@@ -2507,14 +2507,6 @@ static int napi_rx_handler(struct napi_s + return work_done; + } + +-/* +- * Returns true if the device is already scheduled for polling. +- */ +-static inline int napi_is_scheduled(struct napi_struct *napi) +-{ +- return test_bit(NAPI_STATE_SCHED, &napi->state); +-} +- + /** + * process_pure_responses - process pure responses from a response queue + * @adap: the adapter +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -1479,7 +1479,7 @@ static void rtw89_core_rx_to_mac80211(st + struct napi_struct *napi = &rtwdev->napi; + + /* In low power mode, napi isn't scheduled. Receive it to netif. */ +- if (unlikely(!test_bit(NAPI_STATE_SCHED, &napi->state))) ++ if (unlikely(!napi_is_scheduled(napi))) + napi = NULL; + + rtw89_core_hw_to_sband_rate(rx_status); +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -468,6 +468,29 @@ static inline bool napi_prefer_busy_poll + return test_bit(NAPI_STATE_PREFER_BUSY_POLL, &n->state); + } + ++/** ++ * napi_is_scheduled - test if NAPI is scheduled ++ * @n: NAPI context ++ * ++ * This check is "best-effort". With no locking implemented, ++ * a NAPI can be scheduled or terminate right after this check ++ * and produce not precise results. ++ * ++ * NAPI_STATE_SCHED is an internal state, napi_is_scheduled ++ * should not be used normally and napi_schedule should be ++ * used instead. ++ * ++ * Use only if the driver really needs to check if a NAPI ++ * is scheduled for example in the context of delayed timer ++ * that can be skipped if a NAPI is already scheduled. ++ * ++ * Return True if NAPI is scheduled, False otherwise. ++ */ ++static inline bool napi_is_scheduled(struct napi_struct *n) ++{ ++ return test_bit(NAPI_STATE_SCHED, &n->state); ++} ++ + bool napi_schedule_prep(struct napi_struct *n); + + /** +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -6533,7 +6533,7 @@ static int __napi_poll(struct napi_struc + * accidentally calling ->poll() when NAPI is not scheduled. + */ + work = 0; +- if (test_bit(NAPI_STATE_SCHED, &n->state)) { ++ if (napi_is_scheduled(n)) { + work = n->poll(n, weight); + trace_napi_poll(n, work, weight); + } diff --git a/lede/target/linux/generic/backport-6.1/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch b/lede/target/linux/generic/backport-6.1/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch new file mode 100644 index 0000000000..aa0d730bc8 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch @@ -0,0 +1,77 @@ +From 2d1a42cf7f77cda54dbbee18d00b1200e7bc22aa Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 18 Oct 2023 14:35:48 +0200 +Subject: [PATCH 1/3] net: stmmac: improve TX timer arm logic + +There is currently a problem with the TX timer getting armed multiple +unnecessary times causing big performance regression on some device that +suffer from heavy handling of hrtimer rearm. + +The use of the TX timer is an old implementation that predates the napi +implementation and the interrupt enable/disable handling. + +Due to stmmac being a very old code, the TX timer was never evaluated +again with this new implementation and was kept there causing +performance regression. The performance regression started to appear +with kernel version 4.19 with 8fce33317023 ("net: stmmac: Rework coalesce +timer and fix multi-queue races") where the timer was reduced to 1ms +causing it to be armed 40 times more than before. + +Decreasing the timer made the problem more present and caused the +regression in the other of 600-700mbps on some device (regression where +this was notice is ipq806x). + +The problem is in the fact that handling the hrtimer on some target is +expensive and recent kernel made the timer armed much more times. +A solution that was proposed was reverting the hrtimer change and use +mod_timer but such solution would still hide the real problem in the +current implementation. + +To fix the regression, apply some additional logic and skip arming the +timer when not needed. + +Arm the timer ONLY if a napi is not already scheduled. Running the timer +is redundant since the same function (stmmac_tx_clean) will run in the +napi TX poll. Also try to cancel any timer if a napi is scheduled to +prevent redundant run of TX call. + +With the following new logic the original performance are restored while +keeping using the hrtimer. + +Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni +--- + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -2974,13 +2974,25 @@ static void stmmac_tx_timer_arm(struct s + { + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; + u32 tx_coal_timer = priv->tx_coal_timer[queue]; ++ struct stmmac_channel *ch; ++ struct napi_struct *napi; + + if (!tx_coal_timer) + return; + +- hrtimer_start(&tx_q->txtimer, +- STMMAC_COAL_TIMER(tx_coal_timer), +- HRTIMER_MODE_REL); ++ ch = &priv->channel[tx_q->queue_index]; ++ napi = tx_q->xsk_pool ? &ch->rxtx_napi : &ch->tx_napi; ++ ++ /* Arm timer only if napi is not already scheduled. ++ * Try to cancel any timer if napi is scheduled, timer will be armed ++ * again in the next scheduled napi. ++ */ ++ if (unlikely(!napi_is_scheduled(napi))) ++ hrtimer_start(&tx_q->txtimer, ++ STMMAC_COAL_TIMER(tx_coal_timer), ++ HRTIMER_MODE_REL); ++ else ++ hrtimer_try_to_cancel(&tx_q->txtimer); + } + + /** diff --git a/lede/target/linux/generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch b/lede/target/linux/generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch new file mode 100644 index 0000000000..8736120654 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch @@ -0,0 +1,96 @@ +From a594166387fe08e6f5a32130c400249a35b298f9 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 18 Oct 2023 14:35:49 +0200 +Subject: [PATCH 2/3] net: stmmac: move TX timer arm after DMA enable + +Move TX timer arm call after DMA interrupt is enabled again. + +The TX timer arm function changed logic and now is skipped if a napi is +already scheduled. By moving the TX timer arm call after DMA is enabled, +we permit to correctly skip if a DMA interrupt has been fired and a napi +has been scheduled again. + +Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni +--- + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 22 +++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -2527,9 +2527,13 @@ static void stmmac_bump_dma_threshold(st + * @priv: driver private structure + * @budget: napi budget limiting this functions packet handling + * @queue: TX queue index ++ * @pending_packets: signal to arm the TX coal timer + * Description: it reclaims the transmit resources after transmission completes. ++ * If some packets still needs to be handled, due to TX coalesce, set ++ * pending_packets to true to make NAPI arm the TX coal timer. + */ +-static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue) ++static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue, ++ bool *pending_packets) + { + struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; + unsigned int bytes_compl = 0, pkts_compl = 0; +@@ -2692,7 +2696,7 @@ static int stmmac_tx_clean(struct stmmac + + /* We still have pending packets, let's call for a new scheduling */ + if (tx_q->dirty_tx != tx_q->cur_tx) +- stmmac_tx_timer_arm(priv, queue); ++ *pending_packets = true; + + __netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue)); + +@@ -5490,12 +5494,13 @@ static int stmmac_napi_poll_tx(struct na + struct stmmac_channel *ch = + container_of(napi, struct stmmac_channel, tx_napi); + struct stmmac_priv *priv = ch->priv_data; ++ bool pending_packets = false; + u32 chan = ch->index; + int work_done; + + priv->xstats.napi_poll++; + +- work_done = stmmac_tx_clean(priv, budget, chan); ++ work_done = stmmac_tx_clean(priv, budget, chan, &pending_packets); + work_done = min(work_done, budget); + + if (work_done < budget && napi_complete_done(napi, work_done)) { +@@ -5506,6 +5511,10 @@ static int stmmac_napi_poll_tx(struct na + spin_unlock_irqrestore(&ch->lock, flags); + } + ++ /* TX still have packet to handle, check if we need to arm tx timer */ ++ if (pending_packets) ++ stmmac_tx_timer_arm(priv, chan); ++ + return work_done; + } + +@@ -5514,12 +5523,13 @@ static int stmmac_napi_poll_rxtx(struct + struct stmmac_channel *ch = + container_of(napi, struct stmmac_channel, rxtx_napi); + struct stmmac_priv *priv = ch->priv_data; ++ bool tx_pending_packets = false; + int rx_done, tx_done, rxtx_done; + u32 chan = ch->index; + + priv->xstats.napi_poll++; + +- tx_done = stmmac_tx_clean(priv, budget, chan); ++ tx_done = stmmac_tx_clean(priv, budget, chan, &tx_pending_packets); + tx_done = min(tx_done, budget); + + rx_done = stmmac_rx_zc(priv, budget, chan); +@@ -5544,6 +5554,10 @@ static int stmmac_napi_poll_rxtx(struct + spin_unlock_irqrestore(&ch->lock, flags); + } + ++ /* TX still have packet to handle, check if we need to arm tx timer */ ++ if (tx_pending_packets) ++ stmmac_tx_timer_arm(priv, chan); ++ + return min(rxtx_done, budget - 1); + } + diff --git a/lede/target/linux/generic/backport-6.1/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch b/lede/target/linux/generic/backport-6.1/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch new file mode 100644 index 0000000000..bce54eba4f --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch @@ -0,0 +1,38 @@ +From 039550960a2235cfe2dfaa773df9f98f8da31a0c Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 18 Oct 2023 14:35:50 +0200 +Subject: [PATCH 3/3] net: stmmac: increase TX coalesce timer to 5ms + +Commit 8fce33317023 ("net: stmmac: Rework coalesce timer and fix +multi-queue races") decreased the TX coalesce timer from 40ms to 1ms. + +This caused some performance regression on some target (regression was +reported at least on ipq806x) in the order of 600mbps dropping from +gigabit handling to only 200mbps. + +The problem was identified in the TX timer getting armed too much time. +While this was fixed and improved in another commit, performance can be +improved even further by increasing the timer delay a bit moving from +1ms to 5ms. + +The value is a good balance between battery saving by prevending too +much interrupt to be generated and permitting good performance for +internet oriented devices. + +Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/stmicro/stmmac/common.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/common.h ++++ b/drivers/net/ethernet/stmicro/stmmac/common.h +@@ -287,7 +287,7 @@ struct stmmac_safety_stats { + #define MIN_DMA_RIWT 0x10 + #define DEF_DMA_RIWT 0xa0 + /* Tx coalesce parameters */ +-#define STMMAC_COAL_TX_TIMER 1000 ++#define STMMAC_COAL_TX_TIMER 5000 + #define STMMAC_MAX_COAL_TX_TICK 100000 + #define STMMAC_TX_MAX_FRAMES 256 + #define STMMAC_TX_FRAMES 25 diff --git a/lede/target/linux/generic/backport-6.1/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch b/lede/target/linux/generic/backport-6.1/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch new file mode 100644 index 0000000000..9331fd536d --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/778-v6.3-01-net-dsa-qca8k-add-QCA8K_ATU_TABLE_SIZE-define-for-fd.patch @@ -0,0 +1,63 @@ +From e03cea60c3db8c6b011cc36ecef9281dff8377f3 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 25 Jan 2023 21:35:16 +0100 +Subject: [PATCH] net: dsa: qca8k: add QCA8K_ATU_TABLE_SIZE define for fdb + access + +Add and use QCA8K_ATU_TABLE_SIZE instead of hardcoding the ATU size with +a pure number and using sizeof on the array. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-common.c | 10 ++++++---- + drivers/net/dsa/qca/qca8k.h | 2 ++ + 2 files changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-common.c ++++ b/drivers/net/dsa/qca/qca8k-common.c +@@ -150,11 +150,12 @@ static int qca8k_busy_wait(struct qca8k_ + + static int qca8k_fdb_read(struct qca8k_priv *priv, struct qca8k_fdb *fdb) + { +- u32 reg[3]; ++ u32 reg[QCA8K_ATU_TABLE_SIZE]; + int ret; + + /* load the ARL table into an array */ +- ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, sizeof(reg)); ++ ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, ++ QCA8K_ATU_TABLE_SIZE * sizeof(u32)); + if (ret) + return ret; + +@@ -178,7 +179,7 @@ static int qca8k_fdb_read(struct qca8k_p + static void qca8k_fdb_write(struct qca8k_priv *priv, u16 vid, u8 port_mask, + const u8 *mac, u8 aging) + { +- u32 reg[3] = { 0 }; ++ u32 reg[QCA8K_ATU_TABLE_SIZE] = { 0 }; + + /* vid - 83:72 */ + reg[2] = FIELD_PREP(QCA8K_ATU_VID_MASK, vid); +@@ -195,7 +196,8 @@ static void qca8k_fdb_write(struct qca8k + reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]); + + /* load the array into the ARL table */ +- qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, sizeof(reg)); ++ qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, ++ QCA8K_ATU_TABLE_SIZE * sizeof(u32)); + } + + static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, +--- a/drivers/net/dsa/qca/qca8k.h ++++ b/drivers/net/dsa/qca/qca8k.h +@@ -148,6 +148,8 @@ + #define QCA8K_REG_IPV4_PRI_ADDR_MASK 0x474 + + /* Lookup registers */ ++#define QCA8K_ATU_TABLE_SIZE 3 /* 12 bytes wide table / sizeof(u32) */ ++ + #define QCA8K_REG_ATU_DATA0 0x600 + #define QCA8K_ATU_ADDR2_MASK GENMASK(31, 24) + #define QCA8K_ATU_ADDR3_MASK GENMASK(23, 16) diff --git a/lede/target/linux/generic/backport-6.1/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch b/lede/target/linux/generic/backport-6.1/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch new file mode 100644 index 0000000000..b8f8071b0a --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/778-v6.3-02-net-dsa-qca8k-convert-to-regmap-read-write-API.patch @@ -0,0 +1,261 @@ +From c766e077d927e1775902c18827205ea2ade3a35d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 25 Jan 2023 21:35:17 +0100 +Subject: [PATCH] net: dsa: qca8k: convert to regmap read/write API + +Convert qca8k to regmap read/write bulk API. The mgmt eth can write up +to 32 bytes of data at times. Currently we use a custom function to do +it but regmap now supports declaration of read/write bulk even without a +bus. + +Drop the custom function and rework the regmap function to this new +implementation. + +Rework the qca8k_fdb_read/write function to use the new +regmap_bulk_read/write as the old qca8k_bulk_read/write are now dropped. + +Cc: Mark Brown +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 92 ++++++++++++++++++++++++------ + drivers/net/dsa/qca/qca8k-common.c | 47 ++------------- + drivers/net/dsa/qca/qca8k.h | 3 - + 3 files changed, 77 insertions(+), 65 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -425,16 +425,12 @@ qca8k_regmap_update_bits_eth(struct qca8 + } + + static int +-qca8k_regmap_read(void *ctx, uint32_t reg, uint32_t *val) ++qca8k_read_mii(struct qca8k_priv *priv, uint32_t reg, uint32_t *val) + { +- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; + struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + int ret; + +- if (!qca8k_read_eth(priv, reg, val, sizeof(*val))) +- return 0; +- + qca8k_split_addr(reg, &r1, &r2, &page); + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); +@@ -451,16 +447,12 @@ exit: + } + + static int +-qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) ++qca8k_write_mii(struct qca8k_priv *priv, uint32_t reg, uint32_t val) + { +- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; + struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + int ret; + +- if (!qca8k_write_eth(priv, reg, &val, sizeof(val))) +- return 0; +- + qca8k_split_addr(reg, &r1, &r2, &page); + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); +@@ -477,17 +469,14 @@ exit: + } + + static int +-qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_val) ++qca8k_regmap_update_bits_mii(struct qca8k_priv *priv, uint32_t reg, ++ uint32_t mask, uint32_t write_val) + { +- struct qca8k_priv *priv = (struct qca8k_priv *)ctx; + struct mii_bus *bus = priv->bus; + u16 r1, r2, page; + u32 val; + int ret; + +- if (!qca8k_regmap_update_bits_eth(priv, reg, mask, write_val)) +- return 0; +- + qca8k_split_addr(reg, &r1, &r2, &page); + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); +@@ -510,17 +499,84 @@ exit: + return ret; + } + ++static int ++qca8k_bulk_read(void *ctx, const void *reg_buf, size_t reg_len, ++ void *val_buf, size_t val_len) ++{ ++ int i, count = val_len / sizeof(u32), ret; ++ u32 reg = *(u32 *)reg_buf & U16_MAX; ++ struct qca8k_priv *priv = ctx; ++ ++ if (priv->mgmt_master && ++ !qca8k_read_eth(priv, reg, val_buf, val_len)) ++ return 0; ++ ++ /* loop count times and increment reg of 4 */ ++ for (i = 0; i < count; i++, reg += sizeof(u32)) { ++ ret = qca8k_read_mii(priv, reg, val_buf + i); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ++qca8k_bulk_gather_write(void *ctx, const void *reg_buf, size_t reg_len, ++ const void *val_buf, size_t val_len) ++{ ++ int i, count = val_len / sizeof(u32), ret; ++ u32 reg = *(u32 *)reg_buf & U16_MAX; ++ struct qca8k_priv *priv = ctx; ++ u32 *val = (u32 *)val_buf; ++ ++ if (priv->mgmt_master && ++ !qca8k_write_eth(priv, reg, val, val_len)) ++ return 0; ++ ++ /* loop count times, increment reg of 4 and increment val ptr to ++ * the next value ++ */ ++ for (i = 0; i < count; i++, reg += sizeof(u32), val++) { ++ ret = qca8k_write_mii(priv, reg, *val); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ++qca8k_bulk_write(void *ctx, const void *data, size_t bytes) ++{ ++ return qca8k_bulk_gather_write(ctx, data, sizeof(u16), data + sizeof(u16), ++ bytes - sizeof(u16)); ++} ++ ++static int ++qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_val) ++{ ++ struct qca8k_priv *priv = ctx; ++ ++ if (!qca8k_regmap_update_bits_eth(priv, reg, mask, write_val)) ++ return 0; ++ ++ return qca8k_regmap_update_bits_mii(priv, reg, mask, write_val); ++} ++ + static struct regmap_config qca8k_regmap_config = { + .reg_bits = 16, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x16ac, /* end MIB - Port6 range */ +- .reg_read = qca8k_regmap_read, +- .reg_write = qca8k_regmap_write, ++ .read = qca8k_bulk_read, ++ .write = qca8k_bulk_write, + .reg_update_bits = qca8k_regmap_update_bits, + .rd_table = &qca8k_readable_table, + .disable_locking = true, /* Locking is handled by qca8k read/write */ + .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */ ++ .max_raw_read = 32, /* mgmt eth can read/write up to 8 registers at time */ ++ .max_raw_write = 32, + }; + + static int +@@ -2112,8 +2168,6 @@ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, + + static const struct qca8k_info_ops qca8xxx_ops = { + .autocast_mib = qca8k_get_ethtool_stats_eth, +- .read_eth = qca8k_read_eth, +- .write_eth = qca8k_write_eth, + }; + + static const struct qca8k_match_data qca8327 = { +--- a/drivers/net/dsa/qca/qca8k-common.c ++++ b/drivers/net/dsa/qca/qca8k-common.c +@@ -101,45 +101,6 @@ const struct regmap_access_table qca8k_r + .n_yes_ranges = ARRAY_SIZE(qca8k_readable_ranges), + }; + +-/* TODO: remove these extra ops when we can support regmap bulk read/write */ +-static int qca8k_bulk_read(struct qca8k_priv *priv, u32 reg, u32 *val, int len) +-{ +- int i, count = len / sizeof(u32), ret; +- +- if (priv->mgmt_master && priv->info->ops->read_eth && +- !priv->info->ops->read_eth(priv, reg, val, len)) +- return 0; +- +- for (i = 0; i < count; i++) { +- ret = regmap_read(priv->regmap, reg + (i * 4), val + i); +- if (ret < 0) +- return ret; +- } +- +- return 0; +-} +- +-/* TODO: remove these extra ops when we can support regmap bulk read/write */ +-static int qca8k_bulk_write(struct qca8k_priv *priv, u32 reg, u32 *val, int len) +-{ +- int i, count = len / sizeof(u32), ret; +- u32 tmp; +- +- if (priv->mgmt_master && priv->info->ops->write_eth && +- !priv->info->ops->write_eth(priv, reg, val, len)) +- return 0; +- +- for (i = 0; i < count; i++) { +- tmp = val[i]; +- +- ret = regmap_write(priv->regmap, reg + (i * 4), tmp); +- if (ret < 0) +- return ret; +- } +- +- return 0; +-} +- + static int qca8k_busy_wait(struct qca8k_priv *priv, u32 reg, u32 mask) + { + u32 val; +@@ -154,8 +115,8 @@ static int qca8k_fdb_read(struct qca8k_p + int ret; + + /* load the ARL table into an array */ +- ret = qca8k_bulk_read(priv, QCA8K_REG_ATU_DATA0, reg, +- QCA8K_ATU_TABLE_SIZE * sizeof(u32)); ++ ret = regmap_bulk_read(priv->regmap, QCA8K_REG_ATU_DATA0, reg, ++ QCA8K_ATU_TABLE_SIZE); + if (ret) + return ret; + +@@ -196,8 +157,8 @@ static void qca8k_fdb_write(struct qca8k + reg[0] |= FIELD_PREP(QCA8K_ATU_ADDR5_MASK, mac[5]); + + /* load the array into the ARL table */ +- qca8k_bulk_write(priv, QCA8K_REG_ATU_DATA0, reg, +- QCA8K_ATU_TABLE_SIZE * sizeof(u32)); ++ regmap_bulk_write(priv->regmap, QCA8K_REG_ATU_DATA0, reg, ++ QCA8K_ATU_TABLE_SIZE); + } + + static int qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, +--- a/drivers/net/dsa/qca/qca8k.h ++++ b/drivers/net/dsa/qca/qca8k.h +@@ -330,9 +330,6 @@ struct qca8k_priv; + + struct qca8k_info_ops { + int (*autocast_mib)(struct dsa_switch *ds, int port, u64 *data); +- /* TODO: remove these extra ops when we can support regmap bulk read/write */ +- int (*read_eth)(struct qca8k_priv *priv, u32 reg, u32 *val, int len); +- int (*write_eth)(struct qca8k_priv *priv, u32 reg, u32 *val, int len); + }; + + struct qca8k_match_data { diff --git a/lede/target/linux/generic/backport-6.1/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch b/lede/target/linux/generic/backport-6.1/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch new file mode 100644 index 0000000000..3619440f07 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch @@ -0,0 +1,78 @@ +From 2c39dd025da489cf87d26469d9f5ff19715324a0 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 24 Jul 2023 05:25:28 +0200 +Subject: [PATCH 1/4] net: dsa: qca8k: enable use_single_write for qca8xxx + +The qca8xxx switch supports 2 way to write reg values, a slow way using +mdio and a fast way by sending specially crafted mgmt packet to +read/write reg. + +The fast way can support up to 32 bytes of data as eth packet are used +to send/receive. + +This correctly works for almost the entire regmap of the switch but with +the use of some kernel selftests for dsa drivers it was found a funny +and interesting hw defect/limitation. + +For some specific reg, bulk write won't work and will result in writing +only part of the requested regs resulting in half data written. This was +especially hard to track and discover due to the total strangeness of +the problem and also by the specific regs where this occurs. + +This occurs in the specific regs of the ATU table, where multiple entry +needs to be written to compose the entire entry. +It was discovered that with a bulk write of 12 bytes on +QCA8K_REG_ATU_DATA0 only QCA8K_REG_ATU_DATA0 and QCA8K_REG_ATU_DATA2 +were written, but QCA8K_REG_ATU_DATA1 was always zero. +Tcpdump was used to make sure the specially crafted packet was correct +and this was confirmed. + +The problem was hard to track as the lack of QCA8K_REG_ATU_DATA1 +resulted in an entry somehow possible as the first bytes of the mac +address are set in QCA8K_REG_ATU_DATA0 and the entry type is set in +QCA8K_REG_ATU_DATA2. + +Funlly enough writing QCA8K_REG_ATU_DATA1 results in the same problem +with QCA8K_REG_ATU_DATA2 empty and QCA8K_REG_ATU_DATA1 and +QCA8K_REG_ATU_FUNC correctly written. +A speculation on the problem might be that there are some kind of +indirection internally when accessing these regs and they can't be +accessed all together, due to the fact that it's really a table mapped +somewhere in the switch SRAM. + +Even more funny is the fact that every other reg was tested with all +kind of combination and they are not affected by this problem. Read +operation was also tested and always worked so it's not affected by this +problem. + +The problem is not present if we limit writing a single reg at times. + +To handle this hardware defect, enable use_single_write so that bulk +api can correctly split the write in multiple different operation +effectively reverting to a non-bulk write. + +Cc: Mark Brown +Fixes: c766e077d927 ("net: dsa: qca8k: convert to regmap read/write API") +Signed-off-by: Christian Marangi +Cc: stable@vger.kernel.org +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -575,8 +575,11 @@ static struct regmap_config qca8k_regmap + .rd_table = &qca8k_readable_table, + .disable_locking = true, /* Locking is handled by qca8k read/write */ + .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */ +- .max_raw_read = 32, /* mgmt eth can read/write up to 8 registers at time */ +- .max_raw_write = 32, ++ .max_raw_read = 32, /* mgmt eth can read up to 8 registers at time */ ++ /* ATU regs suffer from a bug where some data are not correctly ++ * written. Disable bulk write to correctly write ATU entry. ++ */ ++ .use_single_write = true, + }; + + static int diff --git a/lede/target/linux/generic/backport-6.1/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch b/lede/target/linux/generic/backport-6.1/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch new file mode 100644 index 0000000000..d31789370e --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/780-v6.6-01-net-dsa-qca8k-make-learning-configurable-and-keep-of.patch @@ -0,0 +1,146 @@ +From 23cfc7172e5297d0bee49ac6f6f8248d1cf0820d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 30 Jul 2023 09:41:10 +0200 +Subject: [PATCH 1/4] net: dsa: qca8k: make learning configurable and keep off + if standalone + +Address learning should initially be turned off by the driver for port +operation in standalone mode, then the DSA core handles changes to it +via ds->ops->port_bridge_flags(). + +Currently this is not the case for qca8k where learning is enabled +unconditionally in qca8k_setup for every user port. + +Handle ports configured in standalone mode by making the learning +configurable and not enabling it by default. + +Implement .port_pre_bridge_flags and .port_bridge_flags dsa ops to +enable learning for bridge that request it and tweak +.port_stp_state_set to correctly disable learning when port is +configured in standalone mode. + +Signed-off-by: Christian Marangi +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20230730074113.21889-2-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 7 +++-- + drivers/net/dsa/qca/qca8k-common.c | 48 ++++++++++++++++++++++++++++++ + drivers/net/dsa/qca/qca8k.h | 6 ++++ + 3 files changed, 58 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -1905,9 +1905,8 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + +- /* Enable ARP Auto-learning by default */ +- ret = regmap_set_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_LEARN); ++ ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), ++ QCA8K_PORT_LOOKUP_LEARN); + if (ret) + return ret; + +@@ -2013,6 +2012,8 @@ static const struct dsa_switch_ops qca8k + .port_change_mtu = qca8k_port_change_mtu, + .port_max_mtu = qca8k_port_max_mtu, + .port_stp_state_set = qca8k_port_stp_state_set, ++ .port_pre_bridge_flags = qca8k_port_pre_bridge_flags, ++ .port_bridge_flags = qca8k_port_bridge_flags, + .port_bridge_join = qca8k_port_bridge_join, + .port_bridge_leave = qca8k_port_bridge_leave, + .port_fast_age = qca8k_port_fast_age, +--- a/drivers/net/dsa/qca/qca8k-common.c ++++ b/drivers/net/dsa/qca/qca8k-common.c +@@ -565,9 +565,26 @@ int qca8k_get_mac_eee(struct dsa_switch + return 0; + } + ++static int qca8k_port_configure_learning(struct dsa_switch *ds, int port, ++ bool learning) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ ++ if (learning) ++ return regmap_set_bits(priv->regmap, ++ QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_LEARN); ++ else ++ return regmap_clear_bits(priv->regmap, ++ QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_LEARN); ++} ++ + void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) + { ++ struct dsa_port *dp = dsa_to_port(ds, port); + struct qca8k_priv *priv = ds->priv; ++ bool learning = false; + u32 stp_state; + + switch (state) { +@@ -582,8 +599,11 @@ void qca8k_port_stp_state_set(struct dsa + break; + case BR_STATE_LEARNING: + stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING; ++ learning = dp->learning; + break; + case BR_STATE_FORWARDING: ++ learning = dp->learning; ++ fallthrough; + default: + stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD; + break; +@@ -591,6 +611,34 @@ void qca8k_port_stp_state_set(struct dsa + + qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), + QCA8K_PORT_LOOKUP_STATE_MASK, stp_state); ++ ++ qca8k_port_configure_learning(ds, port, learning); ++} ++ ++int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, ++ struct switchdev_brport_flags flags, ++ struct netlink_ext_ack *extack) ++{ ++ if (flags.mask & ~BR_LEARNING) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++int qca8k_port_bridge_flags(struct dsa_switch *ds, int port, ++ struct switchdev_brport_flags flags, ++ struct netlink_ext_ack *extack) ++{ ++ int ret; ++ ++ if (flags.mask & BR_LEARNING) { ++ ret = qca8k_port_configure_learning(ds, port, ++ flags.val & BR_LEARNING); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; + } + + int qca8k_port_bridge_join(struct dsa_switch *ds, int port, +--- a/drivers/net/dsa/qca/qca8k.h ++++ b/drivers/net/dsa/qca/qca8k.h +@@ -448,6 +448,12 @@ int qca8k_get_mac_eee(struct dsa_switch + + /* Common bridge function */ + void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state); ++int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, ++ struct switchdev_brport_flags flags, ++ struct netlink_ext_ack *extack); ++int qca8k_port_bridge_flags(struct dsa_switch *ds, int port, ++ struct switchdev_brport_flags flags, ++ struct netlink_ext_ack *extack); + int qca8k_port_bridge_join(struct dsa_switch *ds, int port, + struct dsa_bridge bridge, + bool *tx_fwd_offload, diff --git a/lede/target/linux/generic/backport-6.1/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch b/lede/target/linux/generic/backport-6.1/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch new file mode 100644 index 0000000000..4b457f67de --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/780-v6.6-02-net-dsa-qca8k-limit-user-ports-access-to-the-first-C.patch @@ -0,0 +1,53 @@ +From 18e8feae4a807994e4906d659116d249bfecd4c5 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 30 Jul 2023 09:41:11 +0200 +Subject: [PATCH 2/4] net: dsa: qca8k: limit user ports access to the first CPU + port on setup + +In preparation for multi-CPU support, set CPU port LOOKUP MEMBER outside +the port loop and setup the LOOKUP MEMBER mask for user ports only to +the first CPU port. + +This is to handle flooding condition where every CPU port is set as +target and prevent packet duplication for unknown frames from user ports. + +Secondary CPU port LOOKUP MEMBER mask will be setup later when +port_change_master will be implemented. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Reviewed-by: Florian Fainelli +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20230730074113.21889-3-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -1885,18 +1885,16 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + ++ /* CPU port gets connected to all user ports of the switch */ ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(cpu_port), ++ QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); ++ if (ret) ++ return ret; ++ + /* Setup connection between CPU port & user ports + * Configure specific switch configuration for ports + */ + for (i = 0; i < QCA8K_NUM_PORTS; i++) { +- /* CPU port gets connected to all user ports of the switch */ +- if (dsa_is_cpu_port(ds, i)) { +- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); +- if (ret) +- return ret; +- } +- + /* Individual user ports get connected to CPU port only */ + if (dsa_is_user_port(ds, i)) { + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), diff --git a/lede/target/linux/generic/backport-6.1/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch b/lede/target/linux/generic/backport-6.1/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch new file mode 100644 index 0000000000..f556628b5b --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/780-v6.6-03-net-dsa-qca8k-move-qca8xxx-hol-fixup-to-separate-fun.patch @@ -0,0 +1,111 @@ +From a9108b0712bf018dc69020864b21485b71b17dfc Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 30 Jul 2023 09:41:12 +0200 +Subject: [PATCH 3/4] net: dsa: qca8k: move qca8xxx hol fixup to separate + function + +Move qca8xxx hol fixup to separate function to tidy things up and to +permit using a more efficent loop in future patch. + +Signed-off-by: Christian Marangi +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20230730074113.21889-4-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 78 +++++++++++++++++--------------- + 1 file changed, 42 insertions(+), 36 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -1795,6 +1795,46 @@ static int qca8k_connect_tag_protocol(st + return 0; + } + ++static void qca8k_setup_hol_fixup(struct qca8k_priv *priv, int port) ++{ ++ u32 mask; ++ ++ switch (port) { ++ /* The 2 CPU port and port 5 requires some different ++ * priority than any other ports. ++ */ ++ case 0: ++ case 5: ++ case 6: ++ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) | ++ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e); ++ break; ++ default: ++ mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) | ++ QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) | ++ QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19); ++ } ++ regmap_write(priv->regmap, QCA8K_REG_PORT_HOL_CTRL0(port), mask); ++ ++ mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) | ++ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_WRED_EN; ++ regmap_update_bits(priv->regmap, QCA8K_REG_PORT_HOL_CTRL1(port), ++ QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK | ++ QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | ++ QCA8K_PORT_HOL_CTRL1_WRED_EN, ++ mask); ++} ++ + static int + qca8k_setup(struct dsa_switch *ds) + { +@@ -1930,42 +1970,8 @@ qca8k_setup(struct dsa_switch *ds) + * missing settings to improve switch stability under load condition. + * This problem is limited to qca8337 and other qca8k switch are not affected. + */ +- if (priv->switch_id == QCA8K_ID_QCA8337) { +- switch (i) { +- /* The 2 CPU port and port 5 requires some different +- * priority than any other ports. +- */ +- case 0: +- case 5: +- case 6: +- mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x4) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x4) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI4(0x6) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI5(0x8) | +- QCA8K_PORT_HOL_CTRL0_EG_PORT(0x1e); +- break; +- default: +- mask = QCA8K_PORT_HOL_CTRL0_EG_PRI0(0x3) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI1(0x4) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI2(0x6) | +- QCA8K_PORT_HOL_CTRL0_EG_PRI3(0x8) | +- QCA8K_PORT_HOL_CTRL0_EG_PORT(0x19); +- } +- qca8k_write(priv, QCA8K_REG_PORT_HOL_CTRL0(i), mask); +- +- mask = QCA8K_PORT_HOL_CTRL1_ING(0x6) | +- QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | +- QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | +- QCA8K_PORT_HOL_CTRL1_WRED_EN; +- qca8k_rmw(priv, QCA8K_REG_PORT_HOL_CTRL1(i), +- QCA8K_PORT_HOL_CTRL1_ING_BUF_MASK | +- QCA8K_PORT_HOL_CTRL1_EG_PRI_BUF_EN | +- QCA8K_PORT_HOL_CTRL1_EG_PORT_BUF_EN | +- QCA8K_PORT_HOL_CTRL1_WRED_EN, +- mask); +- } ++ if (priv->switch_id == QCA8K_ID_QCA8337) ++ qca8k_setup_hol_fixup(priv, i); + } + + /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ diff --git a/lede/target/linux/generic/backport-6.1/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch b/lede/target/linux/generic/backport-6.1/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch new file mode 100644 index 0000000000..faa0142ca9 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/780-v6.6-04-net-dsa-qca8k-use-dsa_for_each-macro-instead-of-for-.patch @@ -0,0 +1,158 @@ +From 01e6f8ad8d26ced14b0cf288c42e55d03a7c5070 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 30 Jul 2023 09:41:13 +0200 +Subject: [PATCH 4/4] net: dsa: qca8k: use dsa_for_each macro instead of for + loop + +Convert for loop to dsa_for_each macro to save some redundant write on +unconnected/unused port and tidy things up. + +Signed-off-by: Christian Marangi +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20230730074113.21889-5-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 107 ++++++++++++++++--------------- + 1 file changed, 54 insertions(+), 53 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -1839,7 +1839,8 @@ static int + qca8k_setup(struct dsa_switch *ds) + { + struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; +- int cpu_port, ret, i; ++ struct dsa_port *dp; ++ int cpu_port, ret; + u32 mask; + + cpu_port = qca8k_find_cpu_port(ds); +@@ -1890,27 +1891,27 @@ qca8k_setup(struct dsa_switch *ds) + dev_warn(priv->dev, "mib init failed"); + + /* Initial setup of all ports */ +- for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ dsa_switch_for_each_port(dp, ds) { + /* Disable forwarding by default on all ports */ +- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(dp->index), + QCA8K_PORT_LOOKUP_MEMBER, 0); + if (ret) + return ret; ++ } + +- /* Enable QCA header mode on all cpu ports */ +- if (dsa_is_cpu_port(ds, i)) { +- ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(i), +- FIELD_PREP(QCA8K_PORT_HDR_CTRL_TX_MASK, QCA8K_PORT_HDR_CTRL_ALL) | +- FIELD_PREP(QCA8K_PORT_HDR_CTRL_RX_MASK, QCA8K_PORT_HDR_CTRL_ALL)); +- if (ret) { +- dev_err(priv->dev, "failed enabling QCA header mode"); +- return ret; +- } ++ /* Disable MAC by default on all user ports */ ++ dsa_switch_for_each_user_port(dp, ds) ++ qca8k_port_set_status(priv, dp->index, 0); ++ ++ /* Enable QCA header mode on all cpu ports */ ++ dsa_switch_for_each_cpu_port(dp, ds) { ++ ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(dp->index), ++ FIELD_PREP(QCA8K_PORT_HDR_CTRL_TX_MASK, QCA8K_PORT_HDR_CTRL_ALL) | ++ FIELD_PREP(QCA8K_PORT_HDR_CTRL_RX_MASK, QCA8K_PORT_HDR_CTRL_ALL)); ++ if (ret) { ++ dev_err(priv->dev, "failed enabling QCA header mode on port %d", dp->index); ++ return ret; + } +- +- /* Disable MAC by default on all user ports */ +- if (dsa_is_user_port(ds, i)) +- qca8k_port_set_status(priv, i, 0); + } + + /* Forward all unknown frames to CPU port for Linux processing +@@ -1932,48 +1933,48 @@ qca8k_setup(struct dsa_switch *ds) + return ret; + + /* Setup connection between CPU port & user ports +- * Configure specific switch configuration for ports ++ * Individual user ports get connected to CPU port only + */ +- for (i = 0; i < QCA8K_NUM_PORTS; i++) { +- /* Individual user ports get connected to CPU port only */ +- if (dsa_is_user_port(ds, i)) { +- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_MEMBER, +- BIT(cpu_port)); +- if (ret) +- return ret; +- +- ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i), +- QCA8K_PORT_LOOKUP_LEARN); +- if (ret) +- return ret; +- +- /* For port based vlans to work we need to set the +- * default egress vid +- */ +- ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i), +- QCA8K_EGREES_VLAN_PORT_MASK(i), +- QCA8K_EGREES_VLAN_PORT(i, QCA8K_PORT_VID_DEF)); +- if (ret) +- return ret; +- +- ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i), +- QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | +- QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); +- if (ret) +- return ret; +- } ++ dsa_switch_for_each_user_port(dp, ds) { ++ u8 port = dp->index; + +- /* The port 5 of the qca8337 have some problem in flood condition. The +- * original legacy driver had some specific buffer and priority settings +- * for the different port suggested by the QCA switch team. Add this +- * missing settings to improve switch stability under load condition. +- * This problem is limited to qca8337 and other qca8k switch are not affected. ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_MEMBER, ++ BIT(cpu_port)); ++ if (ret) ++ return ret; ++ ++ ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_LEARN); ++ if (ret) ++ return ret; ++ ++ /* For port based vlans to work we need to set the ++ * default egress vid + */ +- if (priv->switch_id == QCA8K_ID_QCA8337) +- qca8k_setup_hol_fixup(priv, i); ++ ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port), ++ QCA8K_EGREES_VLAN_PORT_MASK(port), ++ QCA8K_EGREES_VLAN_PORT(port, QCA8K_PORT_VID_DEF)); ++ if (ret) ++ return ret; ++ ++ ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port), ++ QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | ++ QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); ++ if (ret) ++ return ret; + } + ++ /* The port 5 of the qca8337 have some problem in flood condition. The ++ * original legacy driver had some specific buffer and priority settings ++ * for the different port suggested by the QCA switch team. Add this ++ * missing settings to improve switch stability under load condition. ++ * This problem is limited to qca8337 and other qca8k switch are not affected. ++ */ ++ if (priv->switch_id == QCA8K_ID_QCA8337) ++ dsa_switch_for_each_available_port(dp, ds) ++ qca8k_setup_hol_fixup(priv, dp->index); ++ + /* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */ + if (priv->switch_id == QCA8K_ID_QCA8327) { + mask = QCA8K_GLOBAL_FC_GOL_XON_THRES(288) | diff --git a/lede/target/linux/generic/backport-6.1/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch b/lede/target/linux/generic/backport-6.1/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch new file mode 100644 index 0000000000..632f422d1f --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/781-v6.6-01-net-dsa-qca8k-fix-regmap-bulk-read-write-methods-on-.patch @@ -0,0 +1,61 @@ +From 5652d1741574eb89cc02576e50ee3e348bd6dd77 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Wed, 4 Oct 2023 11:19:03 +0200 +Subject: [PATCH 1/2] net: dsa: qca8k: fix regmap bulk read/write methods on + big endian systems +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit c766e077d927 ("net: dsa: qca8k: convert to regmap read/write +API") introduced bulk read/write methods to qca8k's regmap. + +The regmap bulk read/write methods get the register address in a buffer +passed as a void pointer parameter (the same buffer contains also the +read/written values). The register address occupies only as many bytes +as it requires at the beginning of this buffer. For example if the +.reg_bits member in regmap_config is 16 (as is the case for this +driver), the register address occupies only the first 2 bytes in this +buffer, so it can be cast to u16. + +But the original commit implementing these bulk read/write methods cast +the buffer to u32: + u32 reg = *(u32 *)reg_buf & U16_MAX; +taking the first 4 bytes. This works on little endian systems where the +first 2 bytes of the buffer correspond to the low 16-bits, but it +obviously cannot work on big endian systems. + +Fix this by casting the beginning of the buffer to u16 as + u32 reg = *(u16 *)reg_buf; + +Fixes: c766e077d927 ("net: dsa: qca8k: convert to regmap read/write API") +Signed-off-by: Marek Behún +Tested-by: Christian Marangi +Reviewed-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -504,8 +504,8 @@ qca8k_bulk_read(void *ctx, const void *r + void *val_buf, size_t val_len) + { + int i, count = val_len / sizeof(u32), ret; +- u32 reg = *(u32 *)reg_buf & U16_MAX; + struct qca8k_priv *priv = ctx; ++ u32 reg = *(u16 *)reg_buf; + + if (priv->mgmt_master && + !qca8k_read_eth(priv, reg, val_buf, val_len)) +@@ -526,8 +526,8 @@ qca8k_bulk_gather_write(void *ctx, const + const void *val_buf, size_t val_len) + { + int i, count = val_len / sizeof(u32), ret; +- u32 reg = *(u32 *)reg_buf & U16_MAX; + struct qca8k_priv *priv = ctx; ++ u32 reg = *(u16 *)reg_buf; + u32 *val = (u32 *)val_buf; + + if (priv->mgmt_master && diff --git a/lede/target/linux/generic/backport-6.1/790-01-v6.2-net-dsa-mt7530-remove-redundant-assignment.patch b/lede/target/linux/generic/backport-6.1/790-01-v6.2-net-dsa-mt7530-remove-redundant-assignment.patch new file mode 100644 index 0000000000..e0319fd355 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-01-v6.2-net-dsa-mt7530-remove-redundant-assignment.patch @@ -0,0 +1,32 @@ +From 27b692012840f658c84a3102c0aeca2676f03132 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 15 Dec 2022 03:47:59 +0000 +Subject: [PATCH 01/48] net: dsa: mt7530: remove redundant assignment + +Russell King correctly pointed out that the MAC_2500FD capability is +already added for port 5 (if not in RGMII mode) and port 6 (which only +supports SGMII) by mt7531_mac_port_get_caps. Remove the reduntant +setting of this capability flag which was added by a previous commit. + +Fixes: e19de30d2080 ("net: dsa: mt7530: add support for in-band link status") +Reported-by: Russell King (Oracle) +Reviewed-by: Russell King (Oracle) +Signed-off-by: Daniel Golle +Link: https://lore.kernel.org/r/Y5qY7x6la5TxZxzX@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -3198,9 +3198,6 @@ static void mt753x_phylink_get_caps(stru + config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10 | MAC_100 | MAC_1000FD; + +- if ((priv->id == ID_MT7531) && mt753x_is_mac_port(port)) +- config->mac_capabilities |= MAC_2500FD; +- + /* This driver does not make use of the speed, duplex, pause or the + * advertisement in its mac_config, so it is safe to mark this driver + * as non-legacy. diff --git a/lede/target/linux/generic/backport-6.1/788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch b/lede/target/linux/generic/backport-6.1/790-02-v6.4-net-dsa-mt7530-use-external-PCS-driver.patch similarity index 84% rename from lede/target/linux/generic/backport-6.1/788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch rename to lede/target/linux/generic/backport-6.1/790-02-v6.4-net-dsa-mt7530-use-external-PCS-driver.patch index c6570badd7..2697f2e563 100644 --- a/lede/target/linux/generic/backport-6.1/788-v6.3-net-dsa-mt7530-use-external-PCS-driver.patch +++ b/lede/target/linux/generic/backport-6.1/790-02-v6.4-net-dsa-mt7530-use-external-PCS-driver.patch @@ -1,60 +1,23 @@ -From patchwork Thu Mar 9 10:57:44 2023 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -X-Patchwork-Submitter: Daniel Golle -X-Patchwork-Id: 13167235 -X-Patchwork-Delegate: kuba@kernel.org -Return-Path: -Date: Thu, 9 Mar 2023 10:57:44 +0000 +From 05dc5ea089f947a69a5db092ef4cad6a0f3c96ce Mon Sep 17 00:00:00 2001 From: Daniel Golle -To: netdev@vger.kernel.org, linux-mediatek@lists.infradead.org, - linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, - Russell King , - Heiner Kallweit , - Lorenzo Bianconi , - Mark Lee , - John Crispin , Felix Fietkau , - AngeloGioacchino Del Regno - , - Matthias Brugger , - DENG Qingfang , - Landen Chao , - Sean Wang , - Paolo Abeni , - Jakub Kicinski , - Eric Dumazet , - "David S. Miller" , - Vladimir Oltean , - Florian Fainelli , - Andrew Lunn , - Vladimir Oltean -Cc: =?iso-8859-1?q?Bj=F8rn?= Mork , - Frank Wunderlich , - Alexander Couzens -Subject: [PATCH net-next v13 11/16] net: dsa: mt7530: use external PCS driver -Message-ID: - <2ac2ee40d3b0e705461b50613fda6a7edfdbc4b3.1678357225.git.daniel@makrotopia.org> -References: +Date: Sun, 19 Mar 2023 12:58:43 +0000 +Subject: [PATCH 02/48] net: dsa: mt7530: use external PCS driver MIME-Version: 1.0 -Content-Disposition: inline -In-Reply-To: -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -X-Patchwork-Delegate: kuba@kernel.org +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Implement regmap access wrappers, for now only to be used by the -pcs-mtk driver. -Make use of external PCS driver and drop the reduntant implementation -in mt7530.c. +pcs-mtk-lynxi driver. +Make use of this external PCS driver and drop the now reduntant +implementation in mt7530.c. As a nice side effect the SGMII registers can now also more easily be inspected for debugging via /sys/kernel/debug/regmap. -Reviewed-by: Russell King (Oracle) Tested-by: Bjørn Mork Signed-off-by: Daniel Golle Tested-by: Frank Wunderlich +Reviewed-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski --- drivers/net/dsa/Kconfig | 1 + drivers/net/dsa/mt7530.c | 277 ++++++++++----------------------------- @@ -238,7 +201,7 @@ Tested-by: Frank Wunderlich default: return NULL; } -@@ -3257,86 +3141,6 @@ static void mt7530_pcs_get_state(struct +@@ -3254,86 +3138,6 @@ static void mt7530_pcs_get_state(struct state->pause |= MLO_PAUSE_TX; } @@ -325,7 +288,7 @@ Tested-by: Frank Wunderlich static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode, phy_interface_t interface, const unsigned long *advertising, -@@ -3356,18 +3160,57 @@ static const struct phylink_pcs_ops mt75 +@@ -3353,18 +3157,57 @@ static const struct phylink_pcs_ops mt75 .pcs_an_restart = mt7530_pcs_an_restart, }; @@ -389,7 +352,7 @@ Tested-by: Frank Wunderlich int i, ret; /* Initialise the PCS devices */ -@@ -3375,8 +3218,6 @@ mt753x_setup(struct dsa_switch *ds) +@@ -3372,8 +3215,6 @@ mt753x_setup(struct dsa_switch *ds) priv->pcs[i].pcs.ops = priv->info->pcs_ops; priv->pcs[i].priv = priv; priv->pcs[i].port = i; @@ -398,7 +361,7 @@ Tested-by: Frank Wunderlich } ret = priv->info->sw_setup(ds); -@@ -3391,6 +3232,16 @@ mt753x_setup(struct dsa_switch *ds) +@@ -3388,6 +3229,16 @@ mt753x_setup(struct dsa_switch *ds) if (ret && priv->irq) mt7530_free_irq_common(priv); @@ -415,7 +378,7 @@ Tested-by: Frank Wunderlich return ret; } -@@ -3483,7 +3334,7 @@ static const struct mt753x_info mt753x_t +@@ -3480,7 +3331,7 @@ static const struct mt753x_info mt753x_t }, [ID_MT7531] = { .id = ID_MT7531, @@ -424,7 +387,7 @@ Tested-by: Frank Wunderlich .sw_setup = mt7531_setup, .phy_read = mt7531_ind_phy_read, .phy_write = mt7531_ind_phy_write, -@@ -3591,7 +3442,7 @@ static void +@@ -3588,7 +3439,7 @@ static void mt7530_remove(struct mdio_device *mdiodev) { struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); @@ -433,7 +396,7 @@ Tested-by: Frank Wunderlich if (!priv) return; -@@ -3610,6 +3461,10 @@ mt7530_remove(struct mdio_device *mdiode +@@ -3607,6 +3458,10 @@ mt7530_remove(struct mdio_device *mdiode mt7530_free_irq(priv); dsa_unregister_switch(priv->ds); diff --git a/lede/target/linux/generic/backport-6.1/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch b/lede/target/linux/generic/backport-6.1/790-03-v6.4-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch similarity index 88% rename from lede/target/linux/generic/backport-6.1/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch rename to lede/target/linux/generic/backport-6.1/790-03-v6.4-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch index 4d024b063a..d8f559b416 100644 --- a/lede/target/linux/generic/backport-6.1/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch +++ b/lede/target/linux/generic/backport-6.1/790-03-v6.4-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch @@ -1,7 +1,7 @@ -From c3552d3f85f06cf4b4818bd84c4fcc09d8d45165 Mon Sep 17 00:00:00 2001 +From cafbb70e148e7a4e318dcc1e36a96643815b6245 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 3 Apr 2023 02:17:19 +0100 -Subject: [PATCH 01/13] net: dsa: mt7530: make some noise if register read +Subject: [PATCH 03/48] net: dsa: mt7530: make some noise if register read fails Simply returning the negative error value instead of the read value diff --git a/lede/target/linux/generic/backport-6.1/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch b/lede/target/linux/generic/backport-6.1/790-04-v6.4-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch similarity index 92% rename from lede/target/linux/generic/backport-6.1/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch rename to lede/target/linux/generic/backport-6.1/790-04-v6.4-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch index ef0bdeedd1..1bf19a813e 100644 --- a/lede/target/linux/generic/backport-6.1/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch +++ b/lede/target/linux/generic/backport-6.1/790-04-v6.4-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch @@ -1,7 +1,7 @@ -From b896355fc4988216d4f38582d07add9252a795ae Mon Sep 17 00:00:00 2001 +From 8f83ad87e2df26ddf9b8afd4d2873644a872d929 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 3 Apr 2023 02:17:30 +0100 -Subject: [PATCH 02/13] net: dsa: mt7530: refactor SGMII PCS creation +Subject: [PATCH 04/48] net: dsa: mt7530: refactor SGMII PCS creation Instead of macro templates use a dedidated function and allocated regmap_config when creating the regmaps for the pcs-mtk-lynxi @@ -18,7 +18,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c -@@ -3192,26 +3192,56 @@ static const struct regmap_bus mt7531_re +@@ -3189,26 +3189,56 @@ static const struct regmap_bus mt7531_re .reg_update_bits = mt7530_regmap_update_bits, }; @@ -88,7 +88,7 @@ Signed-off-by: David S. Miller int i, ret; /* Initialise the PCS devices */ -@@ -3233,15 +3263,11 @@ mt753x_setup(struct dsa_switch *ds) +@@ -3230,15 +3260,11 @@ mt753x_setup(struct dsa_switch *ds) if (ret && priv->irq) mt7530_free_irq_common(priv); diff --git a/lede/target/linux/generic/backport-6.1/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch b/lede/target/linux/generic/backport-6.1/790-05-v6.4-net-dsa-mt7530-use-unlocked-regmap-accessors.patch similarity index 86% rename from lede/target/linux/generic/backport-6.1/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch rename to lede/target/linux/generic/backport-6.1/790-05-v6.4-net-dsa-mt7530-use-unlocked-regmap-accessors.patch index dad12607a9..bd28b4be76 100644 --- a/lede/target/linux/generic/backport-6.1/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch +++ b/lede/target/linux/generic/backport-6.1/790-05-v6.4-net-dsa-mt7530-use-unlocked-regmap-accessors.patch @@ -1,7 +1,7 @@ -From 33396408776385f3d2f6069646169a6b5b28e3b3 Mon Sep 17 00:00:00 2001 +From efb41b8e9b7bbb08ace1930373bff63d4f5cc6e2 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 3 Apr 2023 02:17:40 +0100 -Subject: [PATCH 03/13] net: dsa: mt7530: use unlocked regmap accessors +Subject: [PATCH 05/48] net: dsa: mt7530: use unlocked regmap accessors Instead of wrapping the locked register accessor functions, use the unlocked variants and add locking wrapper functions to let regmap @@ -19,7 +19,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c -@@ -3165,7 +3165,7 @@ static int mt7530_regmap_read(void *cont +@@ -3162,7 +3162,7 @@ static int mt7530_regmap_read(void *cont { struct mt7530_priv *priv = context; @@ -28,7 +28,7 @@ Signed-off-by: David S. Miller return 0; }; -@@ -3173,23 +3173,25 @@ static int mt7530_regmap_write(void *con +@@ -3170,23 +3170,25 @@ static int mt7530_regmap_write(void *con { struct mt7530_priv *priv = context; @@ -62,7 +62,7 @@ Signed-off-by: David S. Miller }; static int -@@ -3215,6 +3217,9 @@ mt7531_create_sgmii(struct mt7530_priv * +@@ -3212,6 +3214,9 @@ mt7531_create_sgmii(struct mt7530_priv * mt7531_pcs_config[i]->reg_stride = 4; mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i); mt7531_pcs_config[i]->max_register = 0x17c; diff --git a/lede/target/linux/generic/backport-6.1/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch b/lede/target/linux/generic/backport-6.1/790-06-v6.4-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch similarity index 92% rename from lede/target/linux/generic/backport-6.1/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch rename to lede/target/linux/generic/backport-6.1/790-06-v6.4-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch index 7dc524dbbe..42c225d91c 100644 --- a/lede/target/linux/generic/backport-6.1/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch +++ b/lede/target/linux/generic/backport-6.1/790-06-v6.4-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch @@ -1,7 +1,7 @@ -From 743cba4345cb366248f9d375c6a9e50243dc0677 Mon Sep 17 00:00:00 2001 +From c7945d11a060797c31b3f47d9c9e515b0bf2082f Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 3 Apr 2023 02:17:52 +0100 -Subject: [PATCH 04/13] net: dsa: mt7530: use regmap to access switch register +Subject: [PATCH 06/48] net: dsa: mt7530: use regmap to access switch register space Use regmap API to access the switch register space. @@ -133,7 +133,7 @@ Signed-off-by: David S. Miller } static void -@@ -3161,22 +3182,6 @@ static const struct phylink_pcs_ops mt75 +@@ -3158,22 +3179,6 @@ static const struct phylink_pcs_ops mt75 .pcs_an_restart = mt7530_pcs_an_restart, }; @@ -156,7 +156,7 @@ Signed-off-by: David S. Miller static void mt7530_mdio_regmap_lock(void *mdio_lock) { -@@ -3189,7 +3194,7 @@ mt7530_mdio_regmap_unlock(void *mdio_loc +@@ -3186,7 +3191,7 @@ mt7530_mdio_regmap_unlock(void *mdio_loc mutex_unlock(mdio_lock); } @@ -165,7 +165,7 @@ Signed-off-by: David S. Miller .reg_write = mt7530_regmap_write, .reg_read = mt7530_regmap_read, }; -@@ -3222,7 +3227,7 @@ mt7531_create_sgmii(struct mt7530_priv * +@@ -3219,7 +3224,7 @@ mt7531_create_sgmii(struct mt7530_priv * mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock; regmap = devm_regmap_init(priv->dev, @@ -174,7 +174,7 @@ Signed-off-by: David S. Miller mt7531_pcs_config[i]); if (IS_ERR(regmap)) { ret = PTR_ERR(regmap); -@@ -3388,6 +3393,7 @@ MODULE_DEVICE_TABLE(of, mt7530_of_match) +@@ -3385,6 +3390,7 @@ MODULE_DEVICE_TABLE(of, mt7530_of_match) static int mt7530_probe(struct mdio_device *mdiodev) { @@ -182,7 +182,7 @@ Signed-off-by: David S. Miller struct mt7530_priv *priv; struct device_node *dn; -@@ -3467,6 +3473,21 @@ mt7530_probe(struct mdio_device *mdiodev +@@ -3464,6 +3470,21 @@ mt7530_probe(struct mdio_device *mdiodev mutex_init(&priv->reg_mutex); dev_set_drvdata(&mdiodev->dev, priv); diff --git a/lede/target/linux/generic/backport-6.1/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch b/lede/target/linux/generic/backport-6.1/790-07-v6.4-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch similarity index 79% rename from lede/target/linux/generic/backport-6.1/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch rename to lede/target/linux/generic/backport-6.1/790-07-v6.4-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch index a9fefab77c..9cd817c056 100644 --- a/lede/target/linux/generic/backport-6.1/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch +++ b/lede/target/linux/generic/backport-6.1/790-07-v6.4-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch @@ -1,7 +1,7 @@ -From f3cf1d06e2aef644b426c23b4bb570780b1f8d47 Mon Sep 17 00:00:00 2001 +From 6b64b5bc3045a7e1ee5278df4f4ff315cd43d88a Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 3 Apr 2023 02:18:04 +0100 -Subject: [PATCH 05/13] net: dsa: mt7530: move SGMII PCS creation to +Subject: [PATCH 07/48] net: dsa: mt7530: move SGMII PCS creation to mt7530_probe function Move creating the SGMII PCS from mt753x_setup() to the more appropriate @@ -18,7 +18,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c -@@ -3273,12 +3273,6 @@ mt753x_setup(struct dsa_switch *ds) +@@ -3270,12 +3270,6 @@ mt753x_setup(struct dsa_switch *ds) if (ret && priv->irq) mt7530_free_irq_common(priv); @@ -31,7 +31,7 @@ Signed-off-by: David S. Miller return ret; } -@@ -3396,6 +3390,7 @@ mt7530_probe(struct mdio_device *mdiodev +@@ -3393,6 +3387,7 @@ mt7530_probe(struct mdio_device *mdiodev static struct regmap_config *regmap_config; struct mt7530_priv *priv; struct device_node *dn; @@ -39,7 +39,7 @@ Signed-off-by: David S. Miller dn = mdiodev->dev.of_node; -@@ -3488,6 +3483,12 @@ mt7530_probe(struct mdio_device *mdiodev +@@ -3485,6 +3480,12 @@ mt7530_probe(struct mdio_device *mdiodev if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap); diff --git a/lede/target/linux/generic/backport-6.1/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch b/lede/target/linux/generic/backport-6.1/790-08-v6.4-net-dsa-mt7530-introduce-mutex-helpers.patch similarity index 98% rename from lede/target/linux/generic/backport-6.1/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch rename to lede/target/linux/generic/backport-6.1/790-08-v6.4-net-dsa-mt7530-introduce-mutex-helpers.patch index a063f78bb0..4f77078eef 100644 --- a/lede/target/linux/generic/backport-6.1/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch +++ b/lede/target/linux/generic/backport-6.1/790-08-v6.4-net-dsa-mt7530-introduce-mutex-helpers.patch @@ -1,7 +1,7 @@ -From e4729ae7c095c0c87794bff47ea43e35d69de986 Mon Sep 17 00:00:00 2001 +From 504d39cbda402df3e6fd123d040520393b6a6297 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 3 Apr 2023 02:18:16 +0100 -Subject: [PATCH 06/13] net: dsa: mt7530: introduce mutex helpers +Subject: [PATCH 08/48] net: dsa: mt7530: introduce mutex helpers As the MDIO bus lock only needs to be involved if actually operating on an MDIO-connected switch we will need to skip locking for built-in diff --git a/lede/target/linux/generic/backport-6.1/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch b/lede/target/linux/generic/backport-6.1/790-09-v6.4-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch similarity index 94% rename from lede/target/linux/generic/backport-6.1/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch rename to lede/target/linux/generic/backport-6.1/790-09-v6.4-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch index cc5ca51677..9cb0b2dd61 100644 --- a/lede/target/linux/generic/backport-6.1/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch +++ b/lede/target/linux/generic/backport-6.1/790-09-v6.4-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch @@ -1,7 +1,7 @@ -From 0d7ae94a0c581f86939bebec0b6ccd66e640d1d8 Mon Sep 17 00:00:00 2001 +From dbef24b66807eef7498740fa8b8441bee64a96c4 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 3 Apr 2023 02:18:28 +0100 -Subject: [PATCH 07/13] net: dsa: mt7530: move p5_intf_modes() function to +Subject: [PATCH 09/48] net: dsa: mt7530: move p5_intf_modes() function to mt7530.c In preparation of splitting mt7530.c into a driver for MDIO-connected diff --git a/lede/target/linux/generic/backport-6.1/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch b/lede/target/linux/generic/backport-6.1/790-10-v6.4-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch similarity index 93% rename from lede/target/linux/generic/backport-6.1/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch rename to lede/target/linux/generic/backport-6.1/790-10-v6.4-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch index 3dc6f389cb..a6af682826 100644 --- a/lede/target/linux/generic/backport-6.1/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch +++ b/lede/target/linux/generic/backport-6.1/790-10-v6.4-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch @@ -1,7 +1,7 @@ -From 4d632005c90e253c000d0db73b7cdb9d8dc2e2dd Mon Sep 17 00:00:00 2001 +From a0c6527a38d518ff175c1b6ce248e9b06cc98d3b Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 3 Apr 2023 02:18:39 +0100 -Subject: [PATCH 08/13] net: dsa: mt7530: introduce mt7530_probe_common helper +Subject: [PATCH 10/48] net: dsa: mt7530: introduce mt7530_probe_common helper function Move commonly used parts from mt7530_probe into new mt7530_probe_common @@ -17,7 +17,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c -@@ -3402,44 +3402,21 @@ static const struct of_device_id mt7530_ +@@ -3399,44 +3399,21 @@ static const struct of_device_id mt7530_ MODULE_DEVICE_TABLE(of, mt7530_of_match); static int @@ -67,7 +67,7 @@ Signed-off-by: David S. Miller if (!priv->info) return -EINVAL; -@@ -3453,23 +3430,53 @@ mt7530_probe(struct mdio_device *mdiodev +@@ -3450,23 +3427,53 @@ mt7530_probe(struct mdio_device *mdiodev return -EINVAL; priv->id = priv->info->id; @@ -131,7 +131,7 @@ Signed-off-by: David S. Miller priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(priv->reset)) { -@@ -3478,12 +3485,15 @@ mt7530_probe(struct mdio_device *mdiodev +@@ -3475,12 +3482,15 @@ mt7530_probe(struct mdio_device *mdiodev } } diff --git a/lede/target/linux/generic/backport-6.1/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch b/lede/target/linux/generic/backport-6.1/790-11-v6.4-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch similarity index 83% rename from lede/target/linux/generic/backport-6.1/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch rename to lede/target/linux/generic/backport-6.1/790-11-v6.4-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch index 9c9f1ac7f7..4192753e89 100644 --- a/lede/target/linux/generic/backport-6.1/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch +++ b/lede/target/linux/generic/backport-6.1/790-11-v6.4-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch @@ -1,7 +1,7 @@ -From 69b838d2629e6b82bcd9e0ab3c1c03f46e5e01d3 Mon Sep 17 00:00:00 2001 +From a7783b0b6f3b38abd34cecf515811691714dee57 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 3 Apr 2023 02:18:50 +0100 -Subject: [PATCH 09/13] net: dsa: mt7530: introduce mt7530_remove_common helper +Subject: [PATCH 11/48] net: dsa: mt7530: introduce mt7530_remove_common helper function Move commonly used parts from mt7530_remove into new @@ -17,7 +17,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c -@@ -3520,6 +3520,17 @@ mt7530_probe(struct mdio_device *mdiodev +@@ -3517,6 +3517,17 @@ mt7530_probe(struct mdio_device *mdiodev } static void @@ -35,7 +35,7 @@ Signed-off-by: David S. Miller mt7530_remove(struct mdio_device *mdiodev) { struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); -@@ -3538,15 +3549,10 @@ mt7530_remove(struct mdio_device *mdiode +@@ -3535,15 +3546,10 @@ mt7530_remove(struct mdio_device *mdiode dev_err(priv->dev, "Failed to disable io pwr: %d\n", ret); diff --git a/lede/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch b/lede/target/linux/generic/backport-6.1/790-12-v6.4-net-dsa-mt7530-introduce-separate-MDIO-driver.patch similarity index 95% rename from lede/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch rename to lede/target/linux/generic/backport-6.1/790-12-v6.4-net-dsa-mt7530-introduce-separate-MDIO-driver.patch index 82008223e0..72a499381f 100644 --- a/lede/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch +++ b/lede/target/linux/generic/backport-6.1/790-12-v6.4-net-dsa-mt7530-introduce-separate-MDIO-driver.patch @@ -1,7 +1,7 @@ -From 8eceed6dbd74067dbf4d8e39f14734f4d2f35176 Mon Sep 17 00:00:00 2001 +From 5313432ca1e1a0677ad7b4f17a7e0186473f47aa Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 3 Apr 2023 02:19:13 +0100 -Subject: [PATCH 10/13] net: dsa: mt7530: introduce separate MDIO driver +Subject: [PATCH 12/48] net: dsa: mt7530: introduce separate MDIO driver Split MT7530 switch driver into a common part and a part specific for MDIO connected switches and multi-chip modules. @@ -15,12 +15,12 @@ Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- MAINTAINERS | 1 + - drivers/net/dsa/Kconfig | 16 +- + drivers/net/dsa/Kconfig | 18 ++- drivers/net/dsa/Makefile | 1 + drivers/net/dsa/mt7530-mdio.c | 271 ++++++++++++++++++++++++++++++++++ drivers/net/dsa/mt7530.c | 264 +-------------------------------- drivers/net/dsa/mt7530.h | 6 + - 6 files changed, 301 insertions(+), 258 deletions(-) + 6 files changed, 302 insertions(+), 259 deletions(-) create mode 100644 drivers/net/dsa/mt7530-mdio.c --- a/MAINTAINERS @@ -35,10 +35,13 @@ Signed-off-by: David S. Miller --- a/drivers/net/dsa/Kconfig +++ b/drivers/net/dsa/Kconfig -@@ -37,10 +37,22 @@ config NET_DSA_MT7530 - tristate "MediaTek MT753x and MT7621 Ethernet switch support" +@@ -34,13 +34,25 @@ config NET_DSA_LANTIQ_GSWIP + the xrx200 / VR9 SoC. + + config NET_DSA_MT7530 +- tristate "MediaTek MT753x and MT7621 Ethernet switch support" ++ tristate "MediaTek MT7530 and MT7531 Ethernet switch support" select NET_DSA_TAG_MTK - select MEDIATEK_GE_PHY + imply NET_DSA_MT7530_MDIO + help + This enables support for the MediaTek MT7530 and MT7531 Ethernet @@ -49,6 +52,7 @@ Signed-off-by: David S. Miller +config NET_DSA_MT7530_MDIO + tristate "MediaTek MT7530 MDIO interface driver" + depends on NET_DSA_MT7530 + select MEDIATEK_GE_PHY select PCS_MTK_LYNXI help - This enables support for the MediaTek MT7530, MT7531, and MT7621 @@ -416,7 +420,7 @@ Signed-off-by: David S. Miller static u32 mt7530_mii_read(struct mt7530_priv *priv, u32 reg) { -@@ -3199,72 +3150,6 @@ static const struct phylink_pcs_ops mt75 +@@ -3196,72 +3147,6 @@ static const struct phylink_pcs_ops mt75 .pcs_an_restart = mt7530_pcs_an_restart, }; @@ -489,7 +493,7 @@ Signed-off-by: David S. Miller static int mt753x_setup(struct dsa_switch *ds) { -@@ -3323,7 +3208,7 @@ static int mt753x_set_mac_eee(struct dsa +@@ -3320,7 +3205,7 @@ static int mt753x_set_mac_eee(struct dsa return 0; } @@ -498,7 +502,7 @@ Signed-off-by: David S. Miller .get_tag_protocol = mtk_get_tag_protocol, .setup = mt753x_setup, .preferred_default_local_cpu_port = mt753x_preferred_default_local_cpu_port, -@@ -3358,8 +3243,9 @@ static const struct dsa_switch_ops mt753 +@@ -3355,8 +3240,9 @@ static const struct dsa_switch_ops mt753 .get_mac_eee = mt753x_get_mac_eee, .set_mac_eee = mt753x_set_mac_eee, }; @@ -509,7 +513,7 @@ Signed-off-by: David S. Miller [ID_MT7621] = { .id = ID_MT7621, .pcs_ops = &mt7530_pcs_ops, -@@ -3392,16 +3278,9 @@ static const struct mt753x_info mt753x_t +@@ -3389,16 +3275,9 @@ static const struct mt753x_info mt753x_t .mac_port_config = mt7531_mac_config, }, }; @@ -528,7 +532,7 @@ Signed-off-by: David S. Miller mt7530_probe_common(struct mt7530_priv *priv) { struct device *dev = priv->dev; -@@ -3438,88 +3317,9 @@ mt7530_probe_common(struct mt7530_priv * +@@ -3435,88 +3314,9 @@ mt7530_probe_common(struct mt7530_priv * return 0; } @@ -619,7 +623,7 @@ Signed-off-by: David S. Miller mt7530_remove_common(struct mt7530_priv *priv) { if (priv->irq) -@@ -3529,55 +3329,7 @@ mt7530_remove_common(struct mt7530_priv +@@ -3526,55 +3326,7 @@ mt7530_remove_common(struct mt7530_priv mutex_destroy(&priv->reg_mutex); } diff --git a/lede/target/linux/generic/backport-6.1/790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch b/lede/target/linux/generic/backport-6.1/790-13-v6.4-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch similarity index 91% rename from lede/target/linux/generic/backport-6.1/790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch rename to lede/target/linux/generic/backport-6.1/790-13-v6.4-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch index 01011ed1a0..dae7dd4a48 100644 --- a/lede/target/linux/generic/backport-6.1/790-v6.4-0011-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch +++ b/lede/target/linux/generic/backport-6.1/790-13-v6.4-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch @@ -1,7 +1,7 @@ -From a52cadbf76593f8fcb2f4f62cb006e3f2a22ad06 Mon Sep 17 00:00:00 2001 +From 86e1168a214b7ab0883acf1e7a6885a7a949e3e7 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 3 Apr 2023 02:19:28 +0100 -Subject: [PATCH 11/13] net: dsa: mt7530: skip locking if MDIO bus isn't +Subject: [PATCH 13/48] net: dsa: mt7530: skip locking if MDIO bus isn't present As MT7530 and MT7531 internally use 32-bit wide registers, each access diff --git a/lede/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch b/lede/target/linux/generic/backport-6.1/790-14-v6.4-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch similarity index 97% rename from lede/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch rename to lede/target/linux/generic/backport-6.1/790-14-v6.4-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch index b158a89468..f5573fc6c4 100644 --- a/lede/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch +++ b/lede/target/linux/generic/backport-6.1/790-14-v6.4-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch @@ -1,7 +1,7 @@ -From b361015763fedea439f13b336b15ef7bdf1f7d4f Mon Sep 17 00:00:00 2001 +From a1b87b6322db9186c8689710fe3e98f59e540949 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 3 Apr 2023 02:19:40 +0100 -Subject: [PATCH 12/13] net: dsa: mt7530: introduce driver for MT7988 built-in +Subject: [PATCH 14/48] net: dsa: mt7530: introduce driver for MT7988 built-in switch Add driver for the built-in Gigabit Ethernet switch which can be found @@ -42,9 +42,9 @@ Signed-off-by: David S. Miller --- a/drivers/net/dsa/Kconfig +++ b/drivers/net/dsa/Kconfig -@@ -38,6 +38,7 @@ config NET_DSA_MT7530 +@@ -37,6 +37,7 @@ config NET_DSA_MT7530 + tristate "MediaTek MT7530 and MT7531 Ethernet switch support" select NET_DSA_TAG_MTK - select MEDIATEK_GE_PHY imply NET_DSA_MT7530_MDIO + imply NET_DSA_MT7530_MMIO help @@ -336,7 +336,7 @@ Signed-off-by: David S. Miller static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port, struct phylink_config *config) { -@@ -3210,6 +3305,27 @@ static int mt753x_set_mac_eee(struct dsa +@@ -3207,6 +3302,27 @@ static int mt753x_set_mac_eee(struct dsa return 0; } @@ -364,7 +364,7 @@ Signed-off-by: David S. Miller const struct dsa_switch_ops mt7530_switch_ops = { .get_tag_protocol = mtk_get_tag_protocol, .setup = mt753x_setup, -@@ -3279,6 +3395,17 @@ const struct mt753x_info mt753x_table[] +@@ -3276,6 +3392,17 @@ const struct mt753x_info mt753x_table[] .mac_port_get_caps = mt7531_mac_port_get_caps, .mac_port_config = mt7531_mac_config, }, diff --git a/lede/target/linux/generic/backport-6.1/790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch b/lede/target/linux/generic/backport-6.1/790-15-v6.4-net-dsa-mt7530-fix-support-for-MT7531BE.patch similarity index 95% rename from lede/target/linux/generic/backport-6.1/790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch rename to lede/target/linux/generic/backport-6.1/790-15-v6.4-net-dsa-mt7530-fix-support-for-MT7531BE.patch index 35f8cf939c..40209b0305 100644 --- a/lede/target/linux/generic/backport-6.1/790-v6.4-0013-net-dsa-mt7530-fix-support-for-MT7531BE.patch +++ b/lede/target/linux/generic/backport-6.1/790-15-v6.4-net-dsa-mt7530-fix-support-for-MT7531BE.patch @@ -1,7 +1,7 @@ -From eb1dd407b4be7ca38166a38c56c8edf52c6a399f Mon Sep 17 00:00:00 2001 +From ed01748319b25456c5226ed0cb5e49e970da0e4f Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sun, 16 Apr 2023 13:08:14 +0100 -Subject: [PATCH 13/13] net: dsa: mt7530: fix support for MT7531BE +Subject: [PATCH 15/48] net: dsa: mt7530: fix support for MT7531BE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -73,7 +73,7 @@ Signed-off-by: Jakub Kicinski } --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c -@@ -3272,6 +3272,12 @@ mt753x_setup(struct dsa_switch *ds) +@@ -3269,6 +3269,12 @@ mt753x_setup(struct dsa_switch *ds) if (ret && priv->irq) mt7530_free_irq_common(priv); diff --git a/lede/target/linux/generic/backport-6.1/790-17-v6.5-net-dsa-mt7530-update-PCS-driver-to-use-neg_mode.patch b/lede/target/linux/generic/backport-6.1/790-17-v6.5-net-dsa-mt7530-update-PCS-driver-to-use-neg_mode.patch new file mode 100644 index 0000000000..78e332b1c2 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-17-v6.5-net-dsa-mt7530-update-PCS-driver-to-use-neg_mode.patch @@ -0,0 +1,35 @@ +From fb6858e2c3b931433ea4d25871c272ee4c01bd99 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 16 Jun 2023 13:07:29 +0100 +Subject: [PATCH 17/48] net: dsa: mt7530: update PCS driver to use neg_mode + +Update mt7530's embedded PCS driver to use neg_mode, even though it +makes no use of it or the "mode" argument. This makes the driver +consistent with converted drivers. + +Signed-off-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/E1qA8Ej-00EaGR-Fk@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -3225,7 +3225,7 @@ static void mt7530_pcs_get_state(struct + state->pause |= MLO_PAUSE_TX; + } + +-static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) +@@ -3253,6 +3253,7 @@ mt753x_setup(struct dsa_switch *ds) + /* Initialise the PCS devices */ + for (i = 0; i < priv->ds->num_ports; i++) { + priv->pcs[i].pcs.ops = priv->info->pcs_ops; ++ priv->pcs[i].pcs.neg_mode = true; + priv->pcs[i].priv = priv; + priv->pcs[i].port = i; + } diff --git a/lede/target/linux/generic/backport-6.1/790-18-v6.7-net-dsa-mt7530-Convert-to-platform-remove-callback-r.patch b/lede/target/linux/generic/backport-6.1/790-18-v6.7-net-dsa-mt7530-Convert-to-platform-remove-callback-r.patch new file mode 100644 index 0000000000..ffcf51dab5 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-18-v6.7-net-dsa-mt7530-Convert-to-platform-remove-callback-r.patch @@ -0,0 +1,58 @@ +From 03ede98ecc29b59fb364f735d6de0e6a4c1735fc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Mon, 18 Sep 2023 21:19:12 +0200 +Subject: [PATCH 18/48] net: dsa: mt7530: Convert to platform remove callback + returning void +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The .remove() callback for a platform driver returns an int which makes +many driver authors wrongly assume it's possible to do error handling by +returning an error code. However the value returned is ignored (apart +from emitting a warning) and this typically results in resource leaks. +To improve here there is a quest to make the remove callback return +void. In the first step of this quest all drivers are converted to +.remove_new() which already returns void. Eventually after all drivers +are converted, .remove_new() is renamed to .remove(). + +Trivially convert this driver from always returning zero in the remove +callback to the void returning variant. + +Signed-off-by: Uwe Kleine-König +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Acked-by: Daniel Golle +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530-mmio.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +--- a/drivers/net/dsa/mt7530-mmio.c ++++ b/drivers/net/dsa/mt7530-mmio.c +@@ -62,15 +62,12 @@ mt7988_probe(struct platform_device *pde + return dsa_register_switch(priv->ds); + } + +-static int +-mt7988_remove(struct platform_device *pdev) ++static void mt7988_remove(struct platform_device *pdev) + { + struct mt7530_priv *priv = platform_get_drvdata(pdev); + + if (priv) + mt7530_remove_common(priv); +- +- return 0; + } + + static void mt7988_shutdown(struct platform_device *pdev) +@@ -87,7 +84,7 @@ static void mt7988_shutdown(struct platf + + static struct platform_driver mt7988_platform_driver = { + .probe = mt7988_probe, +- .remove = mt7988_remove, ++ .remove_new = mt7988_remove, + .shutdown = mt7988_shutdown, + .driver = { + .name = "mt7530-mmio", diff --git a/lede/target/linux/generic/backport-6.1/790-19-v6.7-net-dsa-mt753x-remove-mt753x_phylink_pcs_link_up.patch b/lede/target/linux/generic/backport-6.1/790-19-v6.7-net-dsa-mt753x-remove-mt753x_phylink_pcs_link_up.patch new file mode 100644 index 0000000000..d69ee7f104 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-19-v6.7-net-dsa-mt753x-remove-mt753x_phylink_pcs_link_up.patch @@ -0,0 +1,51 @@ +From 1a1a723d47c046d6c251651c9ade589040dafacf Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 27 Sep 2023 13:13:56 +0100 +Subject: [PATCH 19/48] net: dsa: mt753x: remove mt753x_phylink_pcs_link_up() + +Remove the mt753x_phylink_pcs_link_up() function for two reasons: + +1) priv->pcs[i].pcs.neg_mode is set true, meaning it doesn't take a + MLO_AN_FIXED anymore, but one of PHYLINK_PCS_NEG_*. However, this + is inconsequential due to... +2) priv->pcs[port].pcs.ops is always initialised to point at + mt7530_pcs_ops, which does not have a pcs_link_up() member. + +So, let's remove mt753x_phylink_pcs_link_up() entirely. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/E1qlTQS-008BWe-Va@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 11 ----------- + 1 file changed, 11 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -3040,15 +3040,6 @@ static void mt753x_phylink_mac_link_down + mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); + } + +-static void mt753x_phylink_pcs_link_up(struct phylink_pcs *pcs, +- unsigned int mode, +- phy_interface_t interface, +- int speed, int duplex) +-{ +- if (pcs->ops->pcs_link_up) +- pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex); +-} +- + static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, +@@ -3137,8 +3128,6 @@ mt7531_cpu_port_config(struct dsa_switch + return ret; + mt7530_write(priv, MT7530_PMCR_P(port), + PMCR_CPU_PORT_SETTING(priv->id)); +- mt753x_phylink_pcs_link_up(&priv->pcs[port].pcs, MLO_AN_FIXED, +- interface, speed, DUPLEX_FULL); + mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL, + speed, DUPLEX_FULL, true, true); + diff --git a/lede/target/linux/generic/backport-6.1/790-20-v6.7-net-dsa-mt7530-replace-deprecated-strncpy-with-ethto.patch b/lede/target/linux/generic/backport-6.1/790-20-v6.7-net-dsa-mt7530-replace-deprecated-strncpy-with-ethto.patch new file mode 100644 index 0000000000..8af6820270 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-20-v6.7-net-dsa-mt7530-replace-deprecated-strncpy-with-ethto.patch @@ -0,0 +1,40 @@ +From 51e9c79a4d40fa3a64c0fbdab1ebbebf7cce2dba Mon Sep 17 00:00:00 2001 +From: Justin Stitt +Date: Mon, 9 Oct 2023 18:29:19 +0000 +Subject: [PATCH 20/48] net: dsa: mt7530: replace deprecated strncpy with + ethtool_sprintf + +`strncpy` is deprecated for use on NUL-terminated destination strings +[1] and as such we should prefer more robust and less ambiguous string +interfaces. + +ethtool_sprintf() is designed specifically for get_strings() usage. +Let's replace strncpy in favor of this more robust and easier to +understand interface. + +Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1] +Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2] +Link: https://github.com/KSPP/linux/issues/90 +Signed-off-by: Justin Stitt +Reviewed-by: Kees Cook +Acked-by: Daniel Golle +Reviewed-by: Florian Fainelli +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20231009-strncpy-drivers-net-dsa-mt7530-c-v1-1-ec6677a6436a@google.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -843,8 +843,7 @@ mt7530_get_strings(struct dsa_switch *ds + return; + + for (i = 0; i < ARRAY_SIZE(mt7530_mib); i++) +- strncpy(data + i * ETH_GSTRING_LEN, mt7530_mib[i].name, +- ETH_GSTRING_LEN); ++ ethtool_sprintf(&data, "%s", mt7530_mib[i].name); + } + + static void diff --git a/lede/target/linux/generic/backport-6.1/790-21-v6.9-net-dsa-mt7530-support-OF-based-registration-of-swit.patch b/lede/target/linux/generic/backport-6.1/790-21-v6.9-net-dsa-mt7530-support-OF-based-registration-of-swit.patch new file mode 100644 index 0000000000..4c6c057739 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-21-v6.9-net-dsa-mt7530-support-OF-based-registration-of-swit.patch @@ -0,0 +1,116 @@ +From 38be6fdf7e93431e91aac3884837b22236325f68 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Jan 2024 08:34:31 +0300 +Subject: [PATCH 21/48] net: dsa: mt7530: support OF-based registration of + switch MDIO bus +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently the MDIO bus of the switches the MT7530 DSA subdriver controls +can only be registered as non-OF-based. Bring support for registering the +bus OF-based. + +The subdrivers that control switches [with MDIO bus] probed on OF must +follow this logic to support all cases properly: + +No switch MDIO bus defined: Populate ds->user_mii_bus, register the MDIO +bus, set the interrupts for PHYs if "interrupt-controller" is defined at +the switch node. This case should only be covered for the switches which +their dt-bindings documentation didn't document the MDIO bus from the +start. This is to keep supporting the device trees that do not describe the +MDIO bus on the device tree but the MDIO bus is being used nonetheless. + +Switch MDIO bus defined: Don't populate ds->user_mii_bus, register the MDIO +bus, set the interrupts for PHYs if ["interrupt-controller" is defined at +the switch node and "interrupts" is defined at the PHY nodes under the +switch MDIO bus node]. + +Switch MDIO bus defined but explicitly disabled: If the device tree says +status = "disabled" for the MDIO bus, we shouldn't need an MDIO bus at all. +Instead, just exit as early as possible and do not call any MDIO API. + +The use of ds->user_mii_bus is inappropriate when the MDIO bus of the +switch is described on the device tree [1], which is why we don't populate +ds->user_mii_bus in that case. + +Link: https://lore.kernel.org/netdev/20231213120656.x46fyad6ls7sqyzv@skbuf/ [1] +Suggested-by: David Bauer +Signed-off-by: Arınç ÜNAL +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20240122053431.7751-1-arinc.unal@arinc9.com +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 34 ++++++++++++++++++++++++++-------- + 1 file changed, 26 insertions(+), 8 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2350,24 +2350,40 @@ mt7530_free_irq_common(struct mt7530_pri + static void + mt7530_free_irq(struct mt7530_priv *priv) + { +- mt7530_free_mdio_irq(priv); ++ struct device_node *mnp, *np = priv->dev->of_node; ++ ++ mnp = of_get_child_by_name(np, "mdio"); ++ if (!mnp) ++ mt7530_free_mdio_irq(priv); ++ of_node_put(mnp); ++ + mt7530_free_irq_common(priv); + } + + static int + mt7530_setup_mdio(struct mt7530_priv *priv) + { ++ struct device_node *mnp, *np = priv->dev->of_node; + struct dsa_switch *ds = priv->ds; + struct device *dev = priv->dev; + struct mii_bus *bus; + static int idx; +- int ret; ++ int ret = 0; ++ ++ mnp = of_get_child_by_name(np, "mdio"); ++ ++ if (mnp && !of_device_is_available(mnp)) ++ goto out; + + bus = devm_mdiobus_alloc(dev); +- if (!bus) +- return -ENOMEM; ++ if (!bus) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ if (!mnp) ++ ds->slave_mii_bus = bus; + +- ds->slave_mii_bus = bus; + bus->priv = priv; + bus->name = KBUILD_MODNAME "-mii"; + snprintf(bus->id, MII_BUS_ID_SIZE, KBUILD_MODNAME "-%d", idx++); +@@ -2376,16 +2392,18 @@ mt7530_setup_mdio(struct mt7530_priv *pr + bus->parent = dev; + bus->phy_mask = ~ds->phys_mii_mask; + +- if (priv->irq) ++ if (priv->irq && !mnp) + mt7530_setup_mdio_irq(priv); + +- ret = devm_mdiobus_register(dev, bus); ++ ret = devm_of_mdiobus_register(dev, bus, mnp); + if (ret) { + dev_err(dev, "failed to register MDIO bus: %d\n", ret); +- if (priv->irq) ++ if (priv->irq && !mnp) + mt7530_free_mdio_irq(priv); + } + ++out: ++ of_node_put(mnp); + return ret; + } + diff --git a/lede/target/linux/generic/backport-6.1/790-22-v6.8-net-dsa-mt7530-fix-10M-100M-speed-on-MT7988-switch.patch b/lede/target/linux/generic/backport-6.1/790-22-v6.8-net-dsa-mt7530-fix-10M-100M-speed-on-MT7988-switch.patch new file mode 100644 index 0000000000..0b141b4a3f --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-22-v6.8-net-dsa-mt7530-fix-10M-100M-speed-on-MT7988-switch.patch @@ -0,0 +1,34 @@ +From 022a254fafce88367914dfc8168fe687fc528cdb Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 24 Jan 2024 05:17:25 +0000 +Subject: [PATCH 22/48] net: dsa: mt7530: fix 10M/100M speed on MT7988 switch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Setup PMCR port register for actual speed and duplex on internally +connected PHYs of the MT7988 built-in switch. This fixes links with +speeds other than 1000M. + +Fixes: 110c18bfed41 ("net: dsa: mt7530: introduce driver for MT7988 built-in switch") +Signed-off-by: Daniel Golle +Reviewed-by: Vladimir Oltean +Acked-by: Arınç ÜNAL +Link: https://lore.kernel.org/r/a5b04dfa8256d8302f402545a51ac4c626fdba25.1706071272.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -3072,8 +3072,7 @@ static void mt753x_phylink_mac_link_up(s + /* MT753x MAC works in 1G full duplex mode for all up-clocked + * variants. + */ +- if (interface == PHY_INTERFACE_MODE_INTERNAL || +- interface == PHY_INTERFACE_MODE_TRGMII || ++ if (interface == PHY_INTERFACE_MODE_TRGMII || + (phy_interface_mode_is_8023z(interface))) { + speed = SPEED_1000; + duplex = DUPLEX_FULL; diff --git a/lede/target/linux/generic/backport-6.1/790-23-v6.9-net-dsa-mt7530-always-trap-frames-to-active-CPU-port.patch b/lede/target/linux/generic/backport-6.1/790-23-v6.9-net-dsa-mt7530-always-trap-frames-to-active-CPU-port.patch new file mode 100644 index 0000000000..44d8e07c12 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-23-v6.9-net-dsa-mt7530-always-trap-frames-to-active-CPU-port.patch @@ -0,0 +1,125 @@ +From a385398f77fad9eabe7cdc253e1a356484acc316 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Jan 2024 08:35:52 +0300 +Subject: [PATCH 23/48] net: dsa: mt7530: always trap frames to active CPU port + on MT7530 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +On the MT7530 switch, the CPU_PORT field indicates which CPU port to trap +frames to, regardless of the affinity of the inbound user port. + +When multiple CPU ports are in use, if the DSA conduit interface is down, +trapped frames won't be passed to the conduit interface. + +To make trapping frames work including this case, implement +ds->ops->conduit_state_change() on this subdriver and set the CPU_PORT +field to the numerically smallest CPU port whose conduit interface is up. +Introduce the active_cpu_ports field to store the information of the active +CPU ports. Correct the macros, CPU_PORT is bits 4 through 6 of the +register. + +Add a comment to explain frame trapping for this switch. + +Currently, the driver doesn't support the use of multiple CPU ports so this +is not necessarily a bug fix. + +Suggested-by: Vladimir Oltean +Suggested-by: Russell King (Oracle) +Signed-off-by: Arınç ÜNAL +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20240122-for-netnext-mt7530-improvements-1-v3-1-042401f2b279@arinc9.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 35 +++++++++++++++++++++++++++++++---- + drivers/net/dsa/mt7530.h | 6 ++++-- + 2 files changed, 35 insertions(+), 6 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1239,10 +1239,6 @@ mt753x_cpu_port_enable(struct dsa_switch + mt7530_set(priv, MT7530_MFC, BC_FFP(BIT(port)) | UNM_FFP(BIT(port)) | + UNU_FFP(BIT(port))); + +- /* Set CPU port number */ +- if (priv->id == ID_MT7530 || priv->id == ID_MT7621) +- mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port)); +- + /* Add the CPU port to the CPU port bitmap for MT7531. Trapped frames + * will be forwarded to the CPU port that is affine to the inbound user + * port. +@@ -3314,6 +3310,36 @@ static int mt753x_set_mac_eee(struct dsa + return 0; + } + ++static void ++mt753x_conduit_state_change(struct dsa_switch *ds, ++ const struct net_device *conduit, ++ bool operational) ++{ ++ struct dsa_port *cpu_dp = conduit->dsa_ptr; ++ struct mt7530_priv *priv = ds->priv; ++ int val = 0; ++ u8 mask; ++ ++ /* Set the CPU port to trap frames to for MT7530. Trapped frames will be ++ * forwarded to the numerically smallest CPU port whose conduit ++ * interface is up. ++ */ ++ if (priv->id != ID_MT7530 && priv->id != ID_MT7621) ++ return; ++ ++ mask = BIT(cpu_dp->index); ++ ++ if (operational) ++ priv->active_cpu_ports |= mask; ++ else ++ priv->active_cpu_ports &= ~mask; ++ ++ if (priv->active_cpu_ports) ++ val = CPU_EN | CPU_PORT(__ffs(priv->active_cpu_ports)); ++ ++ mt7530_rmw(priv, MT7530_MFC, CPU_EN | CPU_PORT_MASK, val); ++} ++ + static int mt7988_pad_setup(struct dsa_switch *ds, phy_interface_t interface) + { + return 0; +@@ -3369,6 +3395,7 @@ const struct dsa_switch_ops mt7530_switc + .phylink_mac_link_up = mt753x_phylink_mac_link_up, + .get_mac_eee = mt753x_get_mac_eee, + .set_mac_eee = mt753x_set_mac_eee, ++ .master_state_change = mt753x_conduit_state_change, + }; + EXPORT_SYMBOL_GPL(mt7530_switch_ops); + +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -45,8 +45,8 @@ enum mt753x_id { + #define UNU_FFP(x) (((x) & 0xff) << 8) + #define UNU_FFP_MASK UNU_FFP(~0) + #define CPU_EN BIT(7) +-#define CPU_PORT(x) ((x) << 4) +-#define CPU_MASK (0xf << 4) ++#define CPU_PORT_MASK GENMASK(6, 4) ++#define CPU_PORT(x) FIELD_PREP(CPU_PORT_MASK, x) + #define MIRROR_EN BIT(3) + #define MIRROR_PORT(x) ((x) & 0x7) + #define MIRROR_MASK 0x7 +@@ -783,6 +783,7 @@ struct mt753x_info { + * @irq_domain: IRQ domain of the switch irq_chip + * @irq_enable: IRQ enable bits, synced to SYS_INT_EN + * @create_sgmii: Pointer to function creating SGMII PCS instance(s) ++ * @active_cpu_ports: Holding the active CPU ports + */ + struct mt7530_priv { + struct device *dev; +@@ -809,6 +810,7 @@ struct mt7530_priv { + struct irq_domain *irq_domain; + u32 irq_enable; + int (*create_sgmii)(struct mt7530_priv *priv, bool dual_sgmii); ++ u8 active_cpu_ports; + }; + + struct mt7530_hw_vlan_entry { diff --git a/lede/target/linux/generic/backport-6.1/790-24-v6.9-net-dsa-mt7530-use-p5_interface_select-as-data-type-.patch b/lede/target/linux/generic/backport-6.1/790-24-v6.9-net-dsa-mt7530-use-p5_interface_select-as-data-type-.patch new file mode 100644 index 0000000000..3454948b86 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-24-v6.9-net-dsa-mt7530-use-p5_interface_select-as-data-type-.patch @@ -0,0 +1,45 @@ +From e3c8f69af69e6c4022094309445c009faf5e8cef Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Jan 2024 08:35:53 +0300 +Subject: [PATCH 24/48] net: dsa: mt7530: use p5_interface_select as data type + for p5_intf_sel +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use the p5_interface_select enumeration as the data type for the +p5_intf_sel field. This ensures p5_intf_sel can only take the values +defined in the p5_interface_select enumeration. + +Remove the explicit assignment of 0 to P5_DISABLED as the first enum item +is automatically assigned 0. + +Signed-off-by: Arınç ÜNAL +Acked-by: Daniel Golle +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20240122-for-netnext-mt7530-improvements-1-v3-2-042401f2b279@arinc9.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -713,7 +713,7 @@ struct mt7530_port { + + /* Port 5 interface select definitions */ + enum p5_interface_select { +- P5_DISABLED = 0, ++ P5_DISABLED, + P5_INTF_SEL_PHY_P0, + P5_INTF_SEL_PHY_P4, + P5_INTF_SEL_GMAC5, +@@ -799,7 +799,7 @@ struct mt7530_priv { + bool mcm; + phy_interface_t p6_interface; + phy_interface_t p5_interface; +- unsigned int p5_intf_sel; ++ enum p5_interface_select p5_intf_sel; + u8 mirror_rx; + u8 mirror_tx; + struct mt7530_port ports[MT7530_NUM_PORTS]; diff --git a/lede/target/linux/generic/backport-6.1/790-25-v6.9-net-dsa-mt7530-store-port-5-SGMII-capability-of-MT75.patch b/lede/target/linux/generic/backport-6.1/790-25-v6.9-net-dsa-mt7530-store-port-5-SGMII-capability-of-MT75.patch new file mode 100644 index 0000000000..357579e2bd --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-25-v6.9-net-dsa-mt7530-store-port-5-SGMII-capability-of-MT75.patch @@ -0,0 +1,227 @@ +From b0d590a5cdd95ed863717b279751d6166083889f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Jan 2024 08:35:54 +0300 +Subject: [PATCH 25/48] net: dsa: mt7530: store port 5 SGMII capability of + MT7531 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce the p5_sgmii field to store the information for whether port 5 +has got SGMII or not. Instead of reading the MT7531_TOP_SIG_SR register +multiple times, the register will be read once and the value will be +stored on the p5_sgmii field. This saves unnecessary reads of the +register. + +Move the comment about MT7531AE and MT7531BE to mt7531_setup(), where the +switch is identified. + +Get rid of mt7531_dual_sgmii_supported() now that priv->p5_sgmii stores the +information. Address the code where mt7531_dual_sgmii_supported() is used. + +Get rid of mt7531_is_rgmii_port() which just prints the opposite of +priv->p5_sgmii. + +Instead of calling mt7531_pll_setup() then returning, do not call it if +port 5 is SGMII. + +Remove P5_INTF_SEL_GMAC5_SGMII. The p5_interface_select enum is supposed to +represent the mode that port 5 is being used in, not the hardware +information of port 5. Set p5_intf_sel to P5_INTF_SEL_GMAC5 instead, if +port 5 is not dsa_is_unused_port(). + +Signed-off-by: Arınç ÜNAL +Acked-by: Daniel Golle +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20240122-for-netnext-mt7530-improvements-1-v3-3-042401f2b279@arinc9.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530-mdio.c | 7 ++--- + drivers/net/dsa/mt7530.c | 48 ++++++++++++----------------------- + drivers/net/dsa/mt7530.h | 6 +++-- + 3 files changed, 22 insertions(+), 39 deletions(-) + +--- a/drivers/net/dsa/mt7530-mdio.c ++++ b/drivers/net/dsa/mt7530-mdio.c +@@ -81,17 +81,14 @@ static const struct regmap_bus mt7530_re + }; + + static int +-mt7531_create_sgmii(struct mt7530_priv *priv, bool dual_sgmii) ++mt7531_create_sgmii(struct mt7530_priv *priv) + { + struct regmap_config *mt7531_pcs_config[2] = {}; + struct phylink_pcs *pcs; + struct regmap *regmap; + int i, ret = 0; + +- /* MT7531AE has two SGMII units for port 5 and port 6 +- * MT7531BE has only one SGMII unit for port 6 +- */ +- for (i = dual_sgmii ? 0 : 1; i < 2; i++) { ++ for (i = priv->p5_sgmii ? 0 : 1; i < 2; i++) { + mt7531_pcs_config[i] = devm_kzalloc(priv->dev, + sizeof(struct regmap_config), + GFP_KERNEL); +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -487,15 +487,6 @@ mt7530_pad_clk_setup(struct dsa_switch * + return 0; + } + +-static bool mt7531_dual_sgmii_supported(struct mt7530_priv *priv) +-{ +- u32 val; +- +- val = mt7530_read(priv, MT7531_TOP_SIG_SR); +- +- return (val & PAD_DUAL_SGMII_EN) != 0; +-} +- + static int + mt7531_pad_setup(struct dsa_switch *ds, phy_interface_t interface) + { +@@ -510,9 +501,6 @@ mt7531_pll_setup(struct mt7530_priv *pri + u32 xtal; + u32 val; + +- if (mt7531_dual_sgmii_supported(priv)) +- return; +- + val = mt7530_read(priv, MT7531_CREV); + top_sig = mt7530_read(priv, MT7531_TOP_SIG_SR); + hwstrap = mt7530_read(priv, MT7531_HWTRAP); +@@ -927,8 +915,6 @@ static const char *p5_intf_modes(unsigne + return "PHY P4"; + case P5_INTF_SEL_GMAC5: + return "GMAC5"; +- case P5_INTF_SEL_GMAC5_SGMII: +- return "GMAC5_SGMII"; + default: + return "unknown"; + } +@@ -2697,6 +2683,12 @@ mt7531_setup(struct dsa_switch *ds) + return -ENODEV; + } + ++ /* MT7531AE has got two SGMII units. One for port 5, one for port 6. ++ * MT7531BE has got only one SGMII unit which is for port 6. ++ */ ++ val = mt7530_read(priv, MT7531_TOP_SIG_SR); ++ priv->p5_sgmii = !!(val & PAD_DUAL_SGMII_EN); ++ + /* all MACs must be forced link-down before sw reset */ + for (i = 0; i < MT7530_NUM_PORTS; i++) + mt7530_write(priv, MT7530_PMCR_P(i), MT7531_FORCE_LNK); +@@ -2706,21 +2698,18 @@ mt7531_setup(struct dsa_switch *ds) + SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | + SYS_CTRL_REG_RST); + +- mt7531_pll_setup(priv); +- +- if (mt7531_dual_sgmii_supported(priv)) { +- priv->p5_intf_sel = P5_INTF_SEL_GMAC5_SGMII; +- ++ if (!priv->p5_sgmii) { ++ mt7531_pll_setup(priv); ++ } else { + /* Let ds->slave_mii_bus be able to access external phy. */ + mt7530_rmw(priv, MT7531_GPIO_MODE1, MT7531_GPIO11_RG_RXD2_MASK, + MT7531_EXT_P_MDC_11); + mt7530_rmw(priv, MT7531_GPIO_MODE1, MT7531_GPIO12_RG_RXD3_MASK, + MT7531_EXT_P_MDIO_12); +- } else { +- priv->p5_intf_sel = P5_INTF_SEL_GMAC5; + } +- dev_dbg(ds->dev, "P5 support %s interface\n", +- p5_intf_modes(priv->p5_intf_sel)); ++ ++ if (!dsa_is_unused_port(ds, 5)) ++ priv->p5_intf_sel = P5_INTF_SEL_GMAC5; + + mt7530_rmw(priv, MT7531_GPIO_MODE0, MT7531_GPIO0_MASK, + MT7531_GPIO0_INTERRUPT); +@@ -2787,11 +2776,6 @@ static void mt7530_mac_port_get_caps(str + } + } + +-static bool mt7531_is_rgmii_port(struct mt7530_priv *priv, u32 port) +-{ +- return (port == 5) && (priv->p5_intf_sel != P5_INTF_SEL_GMAC5_SGMII); +-} +- + static void mt7531_mac_port_get_caps(struct dsa_switch *ds, int port, + struct phylink_config *config) + { +@@ -2804,7 +2788,7 @@ static void mt7531_mac_port_get_caps(str + break; + + case 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */ +- if (mt7531_is_rgmii_port(priv, port)) { ++ if (!priv->p5_sgmii) { + phy_interface_set_rgmii(config->supported_interfaces); + break; + } +@@ -2871,7 +2855,7 @@ static int mt7531_rgmii_setup(struct mt7 + { + u32 val; + +- if (!mt7531_is_rgmii_port(priv, port)) { ++ if (priv->p5_sgmii) { + dev_err(priv->dev, "RGMII mode is not available for port %d\n", + port); + return -EINVAL; +@@ -3114,7 +3098,7 @@ mt7531_cpu_port_config(struct dsa_switch + + switch (port) { + case 5: +- if (mt7531_is_rgmii_port(priv, port)) ++ if (!priv->p5_sgmii) + interface = PHY_INTERFACE_MODE_RGMII; + else + interface = PHY_INTERFACE_MODE_2500BASEX; +@@ -3272,7 +3256,7 @@ mt753x_setup(struct dsa_switch *ds) + mt7530_free_irq_common(priv); + + if (priv->create_sgmii) { +- ret = priv->create_sgmii(priv, mt7531_dual_sgmii_supported(priv)); ++ ret = priv->create_sgmii(priv); + if (ret && priv->irq) + mt7530_free_irq(priv); + } +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -717,7 +717,6 @@ enum p5_interface_select { + P5_INTF_SEL_PHY_P0, + P5_INTF_SEL_PHY_P4, + P5_INTF_SEL_GMAC5, +- P5_INTF_SEL_GMAC5_SGMII, + }; + + struct mt7530_priv; +@@ -779,6 +778,8 @@ struct mt753x_info { + * registers + * @p6_interface Holding the current port 6 interface + * @p5_intf_sel: Holding the current port 5 interface select ++ * @p5_sgmii: Flag for distinguishing if port 5 of the MT7531 switch ++ * has got SGMII + * @irq: IRQ number of the switch + * @irq_domain: IRQ domain of the switch irq_chip + * @irq_enable: IRQ enable bits, synced to SYS_INT_EN +@@ -800,6 +801,7 @@ struct mt7530_priv { + phy_interface_t p6_interface; + phy_interface_t p5_interface; + enum p5_interface_select p5_intf_sel; ++ bool p5_sgmii; + u8 mirror_rx; + u8 mirror_tx; + struct mt7530_port ports[MT7530_NUM_PORTS]; +@@ -809,7 +811,7 @@ struct mt7530_priv { + int irq; + struct irq_domain *irq_domain; + u32 irq_enable; +- int (*create_sgmii)(struct mt7530_priv *priv, bool dual_sgmii); ++ int (*create_sgmii)(struct mt7530_priv *priv); + u8 active_cpu_ports; + }; + diff --git a/lede/target/linux/generic/backport-6.1/790-26-v6.9-net-dsa-mt7530-improve-comments-regarding-switch-por.patch b/lede/target/linux/generic/backport-6.1/790-26-v6.9-net-dsa-mt7530-improve-comments-regarding-switch-por.patch new file mode 100644 index 0000000000..46dbd53ede --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-26-v6.9-net-dsa-mt7530-improve-comments-regarding-switch-por.patch @@ -0,0 +1,133 @@ +From 0dcde4c1e7c47822a6b00d6f96b7f19e51536026 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Jan 2024 08:35:55 +0300 +Subject: [PATCH 26/48] net: dsa: mt7530: improve comments regarding switch + ports +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There's no logic to numerically order the CPU ports. Just state the port +number instead. + +Remove the irrelevant PHY muxing information from +mt7530_mac_port_get_caps(). Explain the supported MII modes instead. + +Remove the out of place PHY muxing information from +mt753x_phylink_mac_config(). The function is for MT7530, MT7531, and the +switch on the MT7988 SoC but there's no PHY muxing on MT7531 or the switch +on the MT7988 SoC. + +These comments were gradually introduced with the commits below. +commit ca366d6c889b ("net: dsa: mt7530: Convert to PHYLINK API") +commit 38f790a80560 ("net: dsa: mt7530: Add support for port 5") +commit 88bdef8be9f6 ("net: dsa: mt7530: Extend device data ready for adding +a new hardware") +commit c288575f7810 ("net: dsa: mt7530: Add the support of MT7531 switch") + +Signed-off-by: Arınç ÜNAL +Acked-by: Daniel Golle +Reviewed-by: Andrew Lunn +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20240122-for-netnext-mt7530-improvements-1-v3-4-042401f2b279@arinc9.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 30 ++++++++++++++++++++---------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2754,12 +2754,14 @@ static void mt7530_mac_port_get_caps(str + struct phylink_config *config) + { + switch (port) { +- case 0 ... 4: /* Internal phy */ ++ /* Ports which are connected to switch PHYs. There is no MII pinout. */ ++ case 0 ... 4: + __set_bit(PHY_INTERFACE_MODE_GMII, + config->supported_interfaces); + break; + +- case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ ++ /* Port 5 supports rgmii with delays, mii, and gmii. */ ++ case 5: + phy_interface_set_rgmii(config->supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_MII, + config->supported_interfaces); +@@ -2767,7 +2769,8 @@ static void mt7530_mac_port_get_caps(str + config->supported_interfaces); + break; + +- case 6: /* 1st cpu port */ ++ /* Port 6 supports rgmii and trgmii. */ ++ case 6: + __set_bit(PHY_INTERFACE_MODE_RGMII, + config->supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_TRGMII, +@@ -2782,19 +2785,24 @@ static void mt7531_mac_port_get_caps(str + struct mt7530_priv *priv = ds->priv; + + switch (port) { +- case 0 ... 4: /* Internal phy */ ++ /* Ports which are connected to switch PHYs. There is no MII pinout. */ ++ case 0 ... 4: + __set_bit(PHY_INTERFACE_MODE_GMII, + config->supported_interfaces); + break; + +- case 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */ ++ /* Port 5 supports rgmii with delays on MT7531BE, sgmii/802.3z on ++ * MT7531AE. ++ */ ++ case 5: + if (!priv->p5_sgmii) { + phy_interface_set_rgmii(config->supported_interfaces); + break; + } + fallthrough; + +- case 6: /* 1st cpu port supports sgmii/8023z only */ ++ /* Port 6 supports sgmii/802.3z. */ ++ case 6: + __set_bit(PHY_INTERFACE_MODE_SGMII, + config->supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_1000BASEX, +@@ -2813,11 +2821,13 @@ static void mt7988_mac_port_get_caps(str + phy_interface_zero(config->supported_interfaces); + + switch (port) { +- case 0 ... 4: /* Internal phy */ ++ /* Ports which are connected to switch PHYs. There is no MII pinout. */ ++ case 0 ... 4: + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + config->supported_interfaces); + break; + ++ /* Port 6 is connected to SoC's XGMII MAC. There is no MII pinout. */ + case 6: + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + config->supported_interfaces); +@@ -2981,12 +2991,12 @@ mt753x_phylink_mac_config(struct dsa_swi + u32 mcr_cur, mcr_new; + + switch (port) { +- case 0 ... 4: /* Internal phy */ ++ case 0 ... 4: + if (state->interface != PHY_INTERFACE_MODE_GMII && + state->interface != PHY_INTERFACE_MODE_INTERNAL) + goto unsupported; + break; +- case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ ++ case 5: + if (priv->p5_interface == state->interface) + break; + +@@ -2996,7 +3006,7 @@ mt753x_phylink_mac_config(struct dsa_swi + if (priv->p5_intf_sel != P5_DISABLED) + priv->p5_interface = state->interface; + break; +- case 6: /* 1st cpu port */ ++ case 6: + if (priv->p6_interface == state->interface) + break; + diff --git a/lede/target/linux/generic/backport-6.1/790-27-v6.9-net-dsa-mt7530-improve-code-path-for-setting-up-port.patch b/lede/target/linux/generic/backport-6.1/790-27-v6.9-net-dsa-mt7530-improve-code-path-for-setting-up-port.patch new file mode 100644 index 0000000000..43f629b243 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-27-v6.9-net-dsa-mt7530-improve-code-path-for-setting-up-port.patch @@ -0,0 +1,95 @@ +From 0f03d9bfa1da1d26cb950e4b35b1ff7b9be1828f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Jan 2024 08:35:56 +0300 +Subject: [PATCH 27/48] net: dsa: mt7530: improve code path for setting up port + 5 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There're two code paths for setting up port 5: + +mt7530_setup() +-> mt7530_setup_port5() + +mt753x_phylink_mac_config() +-> mt753x_mac_config() + -> mt7530_mac_config() + -> mt7530_setup_port5() + +Currently mt7530_setup_port5() from mt7530_setup() always runs. If port 5 +is used as a CPU, DSA, or user port, mt7530_setup_port5() from +mt753x_phylink_mac_config() won't run. That is because priv->p5_interface +set on mt7530_setup_port5() will match state->interface on +mt753x_phylink_mac_config() which will stop running mt7530_setup_port5() +again. + +Therefore, mt7530_setup_port5() will never run from +mt753x_phylink_mac_config(). + +Address this by not running mt7530_setup_port5() from mt7530_setup() if +port 5 is used as a CPU, DSA, or user port. This driver isn't in the +dsa_switches_apply_workarounds[] array so phylink will always be present. + +To keep the cases where port 5 isn't controlled by phylink working as +before, preserve the mt7530_setup_port5() call from mt7530_setup(). + +Do not set priv->p5_intf_sel to P5_DISABLED. It is already set to that when +"priv" is allocated. + +Move setting the interface to a more specific location. It's supposed to be +overwritten if PHY muxing is detected. + +Improve the comment which explains the process. + +Signed-off-by: Arınç ÜNAL +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20240122-for-netnext-mt7530-improvements-1-v3-5-042401f2b279@arinc9.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 17 ++++++++--------- + 1 file changed, 8 insertions(+), 9 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2532,16 +2532,15 @@ mt7530_setup(struct dsa_switch *ds) + return ret; + + /* Setup port 5 */ +- priv->p5_intf_sel = P5_DISABLED; +- interface = PHY_INTERFACE_MODE_NA; +- + if (!dsa_is_unused_port(ds, 5)) { + priv->p5_intf_sel = P5_INTF_SEL_GMAC5; +- ret = of_get_phy_mode(dsa_to_port(ds, 5)->dn, &interface); +- if (ret && ret != -ENODEV) +- return ret; + } else { +- /* Scan the ethernet nodes. look for GMAC1, lookup used phy */ ++ /* Scan the ethernet nodes. Look for GMAC1, lookup the used PHY. ++ * Set priv->p5_intf_sel to the appropriate value if PHY muxing ++ * is detected. ++ */ ++ interface = PHY_INTERFACE_MODE_NA; ++ + for_each_child_of_node(dn, mac_np) { + if (!of_device_is_compatible(mac_np, + "mediatek,eth-mac")) +@@ -2572,6 +2571,8 @@ mt7530_setup(struct dsa_switch *ds) + of_node_put(phy_node); + break; + } ++ ++ mt7530_setup_port5(ds, interface); + } + + #ifdef CONFIG_GPIOLIB +@@ -2582,8 +2583,6 @@ mt7530_setup(struct dsa_switch *ds) + } + #endif /* CONFIG_GPIOLIB */ + +- mt7530_setup_port5(ds, interface); +- + /* Flush the FDB table */ + ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL); + if (ret < 0) diff --git a/lede/target/linux/generic/backport-6.1/790-28-v6.9-net-dsa-mt7530-do-not-set-priv-p5_interface-on-mt753.patch b/lede/target/linux/generic/backport-6.1/790-28-v6.9-net-dsa-mt7530-do-not-set-priv-p5_interface-on-mt753.patch new file mode 100644 index 0000000000..385d587729 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-28-v6.9-net-dsa-mt7530-do-not-set-priv-p5_interface-on-mt753.patch @@ -0,0 +1,42 @@ +From 120581c81ad19704a9325505c83a82b7e760e96e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Jan 2024 08:35:57 +0300 +Subject: [PATCH 28/48] net: dsa: mt7530: do not set priv->p5_interface on + mt7530_setup_port5() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Running mt7530_setup_port5() from mt7530_setup() used to handle all cases +of configuring port 5, including phylink. + +Setting priv->p5_interface under mt7530_setup_port5() makes sure that +mt7530_setup_port5() from mt753x_phylink_mac_config() won't run. + +The commit ("net: dsa: mt7530: improve code path for setting up port 5") +makes so that mt7530_setup_port5() from mt7530_setup() runs only on +non-phylink cases. + +Get rid of unnecessarily setting priv->p5_interface under +mt7530_setup_port5() as port 5 phylink configuration will be done by +running mt7530_setup_port5() from mt753x_phylink_mac_config() now. + +Signed-off-by: Arınç ÜNAL +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20240122-for-netnext-mt7530-improvements-1-v3-6-042401f2b279@arinc9.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -985,8 +985,6 @@ static void mt7530_setup_port5(struct ds + dev_dbg(ds->dev, "Setup P5, HWTRAP=0x%x, intf_sel=%s, phy-mode=%s\n", + val, p5_intf_modes(priv->p5_intf_sel), phy_modes(interface)); + +- priv->p5_interface = interface; +- + unlock_exit: + mutex_unlock(&priv->reg_mutex); + } diff --git a/lede/target/linux/generic/backport-6.1/790-29-v6.9-net-dsa-mt7530-do-not-run-mt7530_setup_port5-if-port.patch b/lede/target/linux/generic/backport-6.1/790-29-v6.9-net-dsa-mt7530-do-not-run-mt7530_setup_port5-if-port.patch new file mode 100644 index 0000000000..b4c0b75c49 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-29-v6.9-net-dsa-mt7530-do-not-run-mt7530_setup_port5-if-port.patch @@ -0,0 +1,62 @@ +From 3b423061eb3a62e59b57939ae1e1234756a0f6a1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Jan 2024 08:35:58 +0300 +Subject: [PATCH 29/48] net: dsa: mt7530: do not run mt7530_setup_port5() if + port 5 is disabled +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There's no need to run all the code on mt7530_setup_port5() if port 5 is +disabled. The only case for calling mt7530_setup_port5() from +mt7530_setup() is when PHY muxing is enabled. That is because port 5 is not +defined as a port on the devicetree, therefore, it cannot be controlled by +phylink. + +Because of this, run mt7530_setup_port5() if priv->p5_intf_sel is +P5_INTF_SEL_PHY_P0 or P5_INTF_SEL_PHY_P4. Remove the P5_DISABLED case from +mt7530_setup_port5(). + +Stop initialising the interface variable as the remaining cases will always +call mt7530_setup_port5() with it initialised. + +Signed-off-by: Arınç ÜNAL +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20240122-for-netnext-mt7530-improvements-1-v3-7-042401f2b279@arinc9.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -949,9 +949,6 @@ static void mt7530_setup_port5(struct ds + /* MT7530_P5_MODE_GMAC: P5 -> External phy or 2nd GMAC */ + val &= ~MHWTRAP_P5_DIS; + break; +- case P5_DISABLED: +- interface = PHY_INTERFACE_MODE_NA; +- break; + default: + dev_err(ds->dev, "Unsupported p5_intf_sel %d\n", + priv->p5_intf_sel); +@@ -2537,8 +2534,6 @@ mt7530_setup(struct dsa_switch *ds) + * Set priv->p5_intf_sel to the appropriate value if PHY muxing + * is detected. + */ +- interface = PHY_INTERFACE_MODE_NA; +- + for_each_child_of_node(dn, mac_np) { + if (!of_device_is_compatible(mac_np, + "mediatek,eth-mac")) +@@ -2570,7 +2565,9 @@ mt7530_setup(struct dsa_switch *ds) + break; + } + +- mt7530_setup_port5(ds, interface); ++ if (priv->p5_intf_sel == P5_INTF_SEL_PHY_P0 || ++ priv->p5_intf_sel == P5_INTF_SEL_PHY_P4) ++ mt7530_setup_port5(ds, interface); + } + + #ifdef CONFIG_GPIOLIB diff --git a/lede/target/linux/generic/backport-6.1/790-30-v6.9-net-dsa-mt7530-empty-default-case-on-mt7530_setup_po.patch b/lede/target/linux/generic/backport-6.1/790-30-v6.9-net-dsa-mt7530-empty-default-case-on-mt7530_setup_po.patch new file mode 100644 index 0000000000..89527e2b39 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-30-v6.9-net-dsa-mt7530-empty-default-case-on-mt7530_setup_po.patch @@ -0,0 +1,58 @@ +From 959f4ac4940bebb84bdd25ac61470b3965e1e475 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Tue, 6 Feb 2024 01:08:02 +0300 +Subject: [PATCH 30/48] net: dsa: mt7530: empty default case on + mt7530_setup_port5() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There're two code paths for setting up port 5: + +mt7530_setup() +-> mt7530_setup_port5() + +mt753x_phylink_mac_config() +-> mt753x_mac_config() + -> mt7530_mac_config() + -> mt7530_setup_port5() + +On the first code path, priv->p5_intf_sel is either set to +P5_INTF_SEL_PHY_P0 or P5_INTF_SEL_PHY_P4 when mt7530_setup_port5() is run. + +On the second code path, priv->p5_intf_sel is set to P5_INTF_SEL_GMAC5 when +mt7530_setup_port5() is run. + +Empty the default case which will never run but is needed nonetheless to +handle all the remaining enumeration values. + +Reviewed-by: Vladimir Oltean +Reviewed-by: Russell King (Oracle) +Signed-off-by: Arınç ÜNAL +Link: https://lore.kernel.org/r/20240206-for-netnext-mt7530-improvements-2-v5-1-d7d92a185cb1@arinc9.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -950,9 +950,7 @@ static void mt7530_setup_port5(struct ds + val &= ~MHWTRAP_P5_DIS; + break; + default: +- dev_err(ds->dev, "Unsupported p5_intf_sel %d\n", +- priv->p5_intf_sel); +- goto unlock_exit; ++ break; + } + + /* Setup RGMII settings */ +@@ -982,7 +980,6 @@ static void mt7530_setup_port5(struct ds + dev_dbg(ds->dev, "Setup P5, HWTRAP=0x%x, intf_sel=%s, phy-mode=%s\n", + val, p5_intf_modes(priv->p5_intf_sel), phy_modes(interface)); + +-unlock_exit: + mutex_unlock(&priv->reg_mutex); + } + diff --git a/lede/target/linux/generic/backport-6.1/790-31-v6.9-net-dsa-mt7530-move-XTAL-check-to-mt7530_setup.patch b/lede/target/linux/generic/backport-6.1/790-31-v6.9-net-dsa-mt7530-move-XTAL-check-to-mt7530_setup.patch new file mode 100644 index 0000000000..0dc4baf0c7 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-31-v6.9-net-dsa-mt7530-move-XTAL-check-to-mt7530_setup.patch @@ -0,0 +1,53 @@ +From 9ec0a800c8e0850e1358b7402d6af557af81cb38 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Tue, 6 Feb 2024 01:08:03 +0300 +Subject: [PATCH 31/48] net: dsa: mt7530: move XTAL check to mt7530_setup() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The crystal frequency concerns the switch core. The frequency should be +checked when the switch is being set up so the driver can reject the +unsupported hardware earlier and without requiring port 6 to be used. + +Move it to mt7530_setup(). Drop the unnecessary function printing. + +Reviewed-by: Andrew Lunn +Reviewed-by: Vladimir Oltean +Reviewed-by: Russell King (Oracle) +Signed-off-by: Arınç ÜNAL +Link: https://lore.kernel.org/r/20240206-for-netnext-mt7530-improvements-2-v5-2-d7d92a185cb1@arinc9.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -422,13 +422,6 @@ mt7530_pad_clk_setup(struct dsa_switch * + + xtal = mt7530_read(priv, MT7530_MHWTRAP) & HWTRAP_XTAL_MASK; + +- if (xtal == HWTRAP_XTAL_20MHZ) { +- dev_err(priv->dev, +- "%s: MT7530 with a 20MHz XTAL is not supported!\n", +- __func__); +- return -EINVAL; +- } +- + switch (interface) { + case PHY_INTERFACE_MODE_RGMII: + trgint = 0; +@@ -2461,6 +2454,12 @@ mt7530_setup(struct dsa_switch *ds) + return -ENODEV; + } + ++ if ((val & HWTRAP_XTAL_MASK) == HWTRAP_XTAL_20MHZ) { ++ dev_err(priv->dev, ++ "MT7530 with a 20MHz XTAL is not supported!\n"); ++ return -EINVAL; ++ } ++ + /* Reset the switch through internal reset */ + mt7530_write(priv, MT7530_SYS_CTRL, + SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | diff --git a/lede/target/linux/generic/backport-6.1/790-32-v6.9-net-dsa-mt7530-simplify-mt7530_pad_clk_setup.patch b/lede/target/linux/generic/backport-6.1/790-32-v6.9-net-dsa-mt7530-simplify-mt7530_pad_clk_setup.patch new file mode 100644 index 0000000000..46e1b50f24 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-32-v6.9-net-dsa-mt7530-simplify-mt7530_pad_clk_setup.patch @@ -0,0 +1,146 @@ +From 7199c736aa8cd9c69ae681a9c733408372c2ce76 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Tue, 6 Feb 2024 01:08:04 +0300 +Subject: [PATCH 32/48] net: dsa: mt7530: simplify mt7530_pad_clk_setup() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This code is from before this driver was converted to phylink API. Phylink +deals with the unsupported interface cases before mt7530_pad_clk_setup() is +run. Therefore, the default case would never run. However, it must be +defined nonetheless to handle all the remaining enumeration values, the +phy-modes. + +Switch to if statement for RGMII and return which simplifies the code and +saves an indent. + +Set P6_INTF_MODE, which is the three least significant bits of the +MT7530_P6ECR register, to 0 for RGMII even though it will already be 0 +after reset. This is to keep supporting dynamic reconfiguration of the port +in the case the interface changes from TRGMII to RGMII. + +Disable the TRGMII clocks for all cases. They will be enabled if TRGMII is +being used. + +Read XTAL after checking for RGMII as it's only needed for the TRGMII +interface mode. + +Reviewed-by: Daniel Golle +Reviewed-by: Russell King (Oracle) +Signed-off-by: Arınç ÜNAL +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20240206-for-netnext-mt7530-improvements-2-v5-3-d7d92a185cb1@arinc9.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 91 ++++++++++++++++++---------------------- + 1 file changed, 40 insertions(+), 51 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -418,65 +418,54 @@ static int + mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) + { + struct mt7530_priv *priv = ds->priv; +- u32 ncpo1, ssc_delta, trgint, xtal; ++ u32 ncpo1, ssc_delta, xtal; + +- xtal = mt7530_read(priv, MT7530_MHWTRAP) & HWTRAP_XTAL_MASK; ++ /* Disable the MT7530 TRGMII clocks */ ++ core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN); + +- switch (interface) { +- case PHY_INTERFACE_MODE_RGMII: +- trgint = 0; +- break; +- case PHY_INTERFACE_MODE_TRGMII: +- trgint = 1; +- if (xtal == HWTRAP_XTAL_25MHZ) +- ssc_delta = 0x57; +- else +- ssc_delta = 0x87; +- if (priv->id == ID_MT7621) { +- /* PLL frequency: 125MHz: 1.0GBit */ +- if (xtal == HWTRAP_XTAL_40MHZ) +- ncpo1 = 0x0640; +- if (xtal == HWTRAP_XTAL_25MHZ) +- ncpo1 = 0x0a00; +- } else { /* PLL frequency: 250MHz: 2.0Gbit */ +- if (xtal == HWTRAP_XTAL_40MHZ) +- ncpo1 = 0x0c80; +- if (xtal == HWTRAP_XTAL_25MHZ) +- ncpo1 = 0x1400; +- } +- break; +- default: +- dev_err(priv->dev, "xMII interface %d not supported\n", +- interface); +- return -EINVAL; ++ if (interface == PHY_INTERFACE_MODE_RGMII) { ++ mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK, ++ P6_INTF_MODE(0)); ++ return 0; + } + +- mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK, +- P6_INTF_MODE(trgint)); ++ mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK, P6_INTF_MODE(1)); + +- if (trgint) { +- /* Disable the MT7530 TRGMII clocks */ +- core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN); +- +- /* Setup the MT7530 TRGMII Tx Clock */ +- core_write(priv, CORE_PLL_GROUP5, RG_LCDDS_PCW_NCPO1(ncpo1)); +- core_write(priv, CORE_PLL_GROUP6, RG_LCDDS_PCW_NCPO0(0)); +- core_write(priv, CORE_PLL_GROUP10, RG_LCDDS_SSC_DELTA(ssc_delta)); +- core_write(priv, CORE_PLL_GROUP11, RG_LCDDS_SSC_DELTA1(ssc_delta)); +- core_write(priv, CORE_PLL_GROUP4, +- RG_SYSPLL_DDSFBK_EN | RG_SYSPLL_BIAS_EN | +- RG_SYSPLL_BIAS_LPF_EN); +- core_write(priv, CORE_PLL_GROUP2, +- RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN | +- RG_SYSPLL_POSDIV(1)); +- core_write(priv, CORE_PLL_GROUP7, +- RG_LCDDS_PCW_NCPO_CHG | RG_LCCDS_C(3) | +- RG_LCDDS_PWDB | RG_LCDDS_ISO_EN); ++ xtal = mt7530_read(priv, MT7530_MHWTRAP) & HWTRAP_XTAL_MASK; + +- /* Enable the MT7530 TRGMII clocks */ +- core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN); ++ if (xtal == HWTRAP_XTAL_25MHZ) ++ ssc_delta = 0x57; ++ else ++ ssc_delta = 0x87; ++ ++ if (priv->id == ID_MT7621) { ++ /* PLL frequency: 125MHz: 1.0GBit */ ++ if (xtal == HWTRAP_XTAL_40MHZ) ++ ncpo1 = 0x0640; ++ if (xtal == HWTRAP_XTAL_25MHZ) ++ ncpo1 = 0x0a00; ++ } else { /* PLL frequency: 250MHz: 2.0Gbit */ ++ if (xtal == HWTRAP_XTAL_40MHZ) ++ ncpo1 = 0x0c80; ++ if (xtal == HWTRAP_XTAL_25MHZ) ++ ncpo1 = 0x1400; + } + ++ /* Setup the MT7530 TRGMII Tx Clock */ ++ core_write(priv, CORE_PLL_GROUP5, RG_LCDDS_PCW_NCPO1(ncpo1)); ++ core_write(priv, CORE_PLL_GROUP6, RG_LCDDS_PCW_NCPO0(0)); ++ core_write(priv, CORE_PLL_GROUP10, RG_LCDDS_SSC_DELTA(ssc_delta)); ++ core_write(priv, CORE_PLL_GROUP11, RG_LCDDS_SSC_DELTA1(ssc_delta)); ++ core_write(priv, CORE_PLL_GROUP4, RG_SYSPLL_DDSFBK_EN | ++ RG_SYSPLL_BIAS_EN | RG_SYSPLL_BIAS_LPF_EN); ++ core_write(priv, CORE_PLL_GROUP2, RG_SYSPLL_EN_NORMAL | ++ RG_SYSPLL_VODEN | RG_SYSPLL_POSDIV(1)); ++ core_write(priv, CORE_PLL_GROUP7, RG_LCDDS_PCW_NCPO_CHG | ++ RG_LCCDS_C(3) | RG_LCDDS_PWDB | RG_LCDDS_ISO_EN); ++ ++ /* Enable the MT7530 TRGMII clocks */ ++ core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN); ++ + return 0; + } + diff --git a/lede/target/linux/generic/backport-6.1/790-33-v6.9-net-dsa-mt7530-call-port-6-setup-from-mt7530_mac_con.patch b/lede/target/linux/generic/backport-6.1/790-33-v6.9-net-dsa-mt7530-call-port-6-setup-from-mt7530_mac_con.patch new file mode 100644 index 0000000000..7d78b7df70 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-33-v6.9-net-dsa-mt7530-call-port-6-setup-from-mt7530_mac_con.patch @@ -0,0 +1,97 @@ +From 921a7deee767aa157b5372863a4c1cac53e5c53a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Tue, 6 Feb 2024 01:08:05 +0300 +Subject: [PATCH 33/48] net: dsa: mt7530: call port 6 setup from + mt7530_mac_config() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mt7530_pad_clk_setup() is called if port 6 is enabled. It used to do more +things than setting up port 6. That part was moved to more appropriate +locations, mt7530_setup() and mt7530_pll_setup(). + +Now that all it does is set up port 6, rename it to mt7530_setup_port6(), +and move it to a more appropriate location, under mt7530_mac_config(). + +Change mt7530_setup_port6() to void as there're no error cases. + +Leave an empty mt7530_pad_clk_setup() to satisfy the pad_setup function +pointer. + +This is the code path for setting up the ports before: + +dsa_switch_ops :: phylink_mac_config() -> mt753x_phylink_mac_config() +-> mt753x_mac_config() + -> mt753x_info :: mac_port_config() -> mt7530_mac_config() + -> mt7530_setup_port5() +-> mt753x_pad_setup() + -> mt753x_info :: pad_setup() -> mt7530_pad_clk_setup() + +This is after: + +dsa_switch_ops :: phylink_mac_config() -> mt753x_phylink_mac_config() +-> mt753x_mac_config() + -> mt753x_info :: mac_port_config() -> mt7530_mac_config() + -> mt7530_setup_port5() + -> mt7530_setup_port6() + +Reviewed-by: Vladimir Oltean +Reviewed-by: Russell King (Oracle) +Signed-off-by: Arınç ÜNAL +Link: https://lore.kernel.org/r/20240206-for-netnext-mt7530-improvements-2-v5-4-d7d92a185cb1@arinc9.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -414,8 +414,8 @@ mt753x_preferred_default_local_cpu_port( + } + + /* Setup port 6 interface mode and TRGMII TX circuit */ +-static int +-mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) ++static void ++mt7530_setup_port6(struct dsa_switch *ds, phy_interface_t interface) + { + struct mt7530_priv *priv = ds->priv; + u32 ncpo1, ssc_delta, xtal; +@@ -426,7 +426,7 @@ mt7530_pad_clk_setup(struct dsa_switch * + if (interface == PHY_INTERFACE_MODE_RGMII) { + mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK, + P6_INTF_MODE(0)); +- return 0; ++ return; + } + + mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK, P6_INTF_MODE(1)); +@@ -465,7 +465,11 @@ mt7530_pad_clk_setup(struct dsa_switch * + + /* Enable the MT7530 TRGMII clocks */ + core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN); ++} + ++static int ++mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) ++{ + return 0; + } + +@@ -2829,11 +2833,10 @@ mt7530_mac_config(struct dsa_switch *ds, + { + struct mt7530_priv *priv = ds->priv; + +- /* Only need to setup port5. */ +- if (port != 5) +- return 0; +- +- mt7530_setup_port5(priv->ds, interface); ++ if (port == 5) ++ mt7530_setup_port5(priv->ds, interface); ++ else if (port == 6) ++ mt7530_setup_port6(priv->ds, interface); + + return 0; + } diff --git a/lede/target/linux/generic/backport-6.1/790-34-v6.9-net-dsa-mt7530-remove-pad_setup-function-pointer.patch b/lede/target/linux/generic/backport-6.1/790-34-v6.9-net-dsa-mt7530-remove-pad_setup-function-pointer.patch new file mode 100644 index 0000000000..725830e769 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-34-v6.9-net-dsa-mt7530-remove-pad_setup-function-pointer.patch @@ -0,0 +1,148 @@ +From fcbc5d900fa53f79963fe4626069739ee5567b4b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Tue, 6 Feb 2024 01:08:06 +0300 +Subject: [PATCH 34/48] net: dsa: mt7530: remove pad_setup function pointer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The pad_setup function pointer was introduced with 88bdef8be9f6 ("net: dsa: +mt7530: Extend device data ready for adding a new hardware"). It was being +used to set up the core clock and port 6 of the MT7530 switch, and pll of +the MT7531 switch. + +All of these were moved to more appropriate locations, and it was never +used for the switch on the MT7988 SoC. Therefore, this function pointer +hasn't got a use anymore. Remove it. + +Acked-by: Daniel Golle +Reviewed-by: Vladimir Oltean +Reviewed-by: Russell King (Oracle) +Signed-off-by: Arınç ÜNAL +Link: https://lore.kernel.org/r/20240206-for-netnext-mt7530-improvements-2-v5-5-d7d92a185cb1@arinc9.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 36 ++---------------------------------- + drivers/net/dsa/mt7530.h | 3 --- + 2 files changed, 2 insertions(+), 37 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -467,18 +467,6 @@ mt7530_setup_port6(struct dsa_switch *ds + core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN); + } + +-static int +-mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) +-{ +- return 0; +-} +- +-static int +-mt7531_pad_setup(struct dsa_switch *ds, phy_interface_t interface) +-{ +- return 0; +-} +- + static void + mt7531_pll_setup(struct mt7530_priv *priv) + { +@@ -2820,14 +2808,6 @@ static void mt7988_mac_port_get_caps(str + } + + static int +-mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state) +-{ +- struct mt7530_priv *priv = ds->priv; +- +- return priv->info->pad_setup(ds, state->interface); +-} +- +-static int + mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + phy_interface_t interface) + { +@@ -2992,8 +2972,6 @@ mt753x_phylink_mac_config(struct dsa_swi + if (priv->p6_interface == state->interface) + break; + +- mt753x_pad_setup(ds, state); +- + if (mt753x_mac_config(ds, port, mode, state) < 0) + goto unsupported; + +@@ -3316,11 +3294,6 @@ mt753x_conduit_state_change(struct dsa_s + mt7530_rmw(priv, MT7530_MFC, CPU_EN | CPU_PORT_MASK, val); + } + +-static int mt7988_pad_setup(struct dsa_switch *ds, phy_interface_t interface) +-{ +- return 0; +-} +- + static int mt7988_setup(struct dsa_switch *ds) + { + struct mt7530_priv *priv = ds->priv; +@@ -3382,7 +3355,6 @@ const struct mt753x_info mt753x_table[] + .sw_setup = mt7530_setup, + .phy_read = mt7530_phy_read, + .phy_write = mt7530_phy_write, +- .pad_setup = mt7530_pad_clk_setup, + .mac_port_get_caps = mt7530_mac_port_get_caps, + .mac_port_config = mt7530_mac_config, + }, +@@ -3392,7 +3364,6 @@ const struct mt753x_info mt753x_table[] + .sw_setup = mt7530_setup, + .phy_read = mt7530_phy_read, + .phy_write = mt7530_phy_write, +- .pad_setup = mt7530_pad_clk_setup, + .mac_port_get_caps = mt7530_mac_port_get_caps, + .mac_port_config = mt7530_mac_config, + }, +@@ -3402,7 +3373,6 @@ const struct mt753x_info mt753x_table[] + .sw_setup = mt7531_setup, + .phy_read = mt7531_ind_phy_read, + .phy_write = mt7531_ind_phy_write, +- .pad_setup = mt7531_pad_setup, + .cpu_port_config = mt7531_cpu_port_config, + .mac_port_get_caps = mt7531_mac_port_get_caps, + .mac_port_config = mt7531_mac_config, +@@ -3413,7 +3383,6 @@ const struct mt753x_info mt753x_table[] + .sw_setup = mt7988_setup, + .phy_read = mt7531_ind_phy_read, + .phy_write = mt7531_ind_phy_write, +- .pad_setup = mt7988_pad_setup, + .cpu_port_config = mt7988_cpu_port_config, + .mac_port_get_caps = mt7988_mac_port_get_caps, + .mac_port_config = mt7988_mac_config, +@@ -3443,9 +3412,8 @@ mt7530_probe_common(struct mt7530_priv * + /* Sanity check if these required device operations are filled + * properly. + */ +- if (!priv->info->sw_setup || !priv->info->pad_setup || +- !priv->info->phy_read || !priv->info->phy_write || +- !priv->info->mac_port_get_caps || ++ if (!priv->info->sw_setup || !priv->info->phy_read || ++ !priv->info->phy_write || !priv->info->mac_port_get_caps || + !priv->info->mac_port_config) + return -EINVAL; + +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -732,8 +732,6 @@ struct mt753x_pcs { + * @sw_setup: Holding the handler to a device initialization + * @phy_read: Holding the way reading PHY port + * @phy_write: Holding the way writing PHY port +- * @pad_setup: Holding the way setting up the bus pad for a certain +- * MAC port + * @phy_mode_supported: Check if the PHY type is being supported on a certain + * port + * @mac_port_validate: Holding the way to set addition validate type for a +@@ -749,7 +747,6 @@ struct mt753x_info { + int (*sw_setup)(struct dsa_switch *ds); + int (*phy_read)(struct mt7530_priv *priv, int port, int regnum); + int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val); +- int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface); + int (*cpu_port_config)(struct dsa_switch *ds, int port); + void (*mac_port_get_caps)(struct dsa_switch *ds, int port, + struct phylink_config *config); diff --git a/lede/target/linux/generic/backport-6.1/790-35-v6.9-net-dsa-mt7530-correct-port-capabilities-of-MT7988.patch b/lede/target/linux/generic/backport-6.1/790-35-v6.9-net-dsa-mt7530-correct-port-capabilities-of-MT7988.patch new file mode 100644 index 0000000000..606c48234c --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-35-v6.9-net-dsa-mt7530-correct-port-capabilities-of-MT7988.patch @@ -0,0 +1,36 @@ +From 58a94eb63233bb2ede13b183b6a6a03aa0a2dfc3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Tue, 6 Feb 2024 01:08:07 +0300 +Subject: [PATCH 35/48] net: dsa: mt7530: correct port capabilities of MT7988 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +On the switch on the MT7988 SoC, as shown in Block Diagram 8.1.1.3 on page +125 of "MT7988A Wi-Fi 7 Generation Router Platform: Datasheet (Open +Version) v0.1", there are only 4 PHYs. That's port 0 to 3. Set the case for +ports which connect to switch PHYs to '0 ... 3'. + +Port 4 and 5 are not used at all in this design. + +Link: https://wiki.banana-pi.org/Banana_Pi_BPI-R4#Documents [1] +Acked-by: Daniel Golle +Reviewed-by: Vladimir Oltean +Signed-off-by: Arınç ÜNAL +Link: https://lore.kernel.org/r/20240206-for-netnext-mt7530-improvements-2-v5-6-d7d92a185cb1@arinc9.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2793,7 +2793,7 @@ static void mt7988_mac_port_get_caps(str + + switch (port) { + /* Ports which are connected to switch PHYs. There is no MII pinout. */ +- case 0 ... 4: ++ case 0 ... 3: + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + config->supported_interfaces); + break; diff --git a/lede/target/linux/generic/backport-6.1/790-36-v6.9-net-dsa-mt7530-do-not-clear-config-supported_interfa.patch b/lede/target/linux/generic/backport-6.1/790-36-v6.9-net-dsa-mt7530-do-not-clear-config-supported_interfa.patch new file mode 100644 index 0000000000..e2f1f23435 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-36-v6.9-net-dsa-mt7530-do-not-clear-config-supported_interfa.patch @@ -0,0 +1,38 @@ +From 4440ce33074be6bd55d1a0c8b5f4b6d433ae2c74 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Tue, 6 Feb 2024 01:08:08 +0300 +Subject: [PATCH 36/48] net: dsa: mt7530: do not clear + config->supported_interfaces +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There's no need to clear the config->supported_interfaces bitmap before +reporting the supported interfaces as all bits in the bitmap will already +be initialized to zero when the phylink_config structure is allocated. The +"config" pointer points to &dp->phylink_config, and "dp" is allocated by +dsa_port_touch() with kzalloc(), so all its fields are filled with zeroes. + +There's no code that would change the bitmap beforehand. Remove it. + +Acked-by: Daniel Golle +Reviewed-by: Vladimir Oltean +Reviewed-by: Russell King (Oracle) +Signed-off-by: Arınç ÜNAL +Link: https://lore.kernel.org/r/20240206-for-netnext-mt7530-improvements-2-v5-7-d7d92a185cb1@arinc9.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2789,8 +2789,6 @@ static void mt7531_mac_port_get_caps(str + static void mt7988_mac_port_get_caps(struct dsa_switch *ds, int port, + struct phylink_config *config) + { +- phy_interface_zero(config->supported_interfaces); +- + switch (port) { + /* Ports which are connected to switch PHYs. There is no MII pinout. */ + case 0 ... 3: diff --git a/lede/target/linux/generic/backport-6.1/790-37-v6.9-net-dsa-mt7530-remove-.mac_port_config-for-MT7988-an.patch b/lede/target/linux/generic/backport-6.1/790-37-v6.9-net-dsa-mt7530-remove-.mac_port_config-for-MT7988-an.patch new file mode 100644 index 0000000000..be6fe39f38 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-37-v6.9-net-dsa-mt7530-remove-.mac_port_config-for-MT7988-an.patch @@ -0,0 +1,81 @@ +From 2f507aaeb1a12044f2376a255c2afff1f7432b0b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Fri, 1 Mar 2024 12:42:57 +0200 +Subject: [PATCH 37/48] net: dsa: mt7530: remove .mac_port_config for MT7988 + and make it optional +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For the switch on the MT7988 SoC, the mac_port_config member for ID_MT7988 +in mt753x_table is not needed as the interfaces of all MACs are already +handled on mt7988_mac_port_get_caps(). + +Therefore, remove the mac_port_config member from ID_MT7988 in +mt753x_table. Before calling priv->info->mac_port_config(), if there's no +mac_port_config member in mt753x_table, exit mt753x_mac_config() +successfully. + +Remove calling priv->info->mac_port_config() from the sanity check as the +sanity check requires a pointer to a mac_port_config function to be +non-NULL. This will fail for MT7988 as mac_port_config won't be a member of +its info table. + +Co-developed-by: Daniel Golle +Signed-off-by: Daniel Golle +Signed-off-by: Arınç ÜNAL +Reviewed-by: Vladimir Oltean +Reviewed-by: Russell King (Oracle) +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 18 ++++-------------- + 1 file changed, 4 insertions(+), 14 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2872,17 +2872,6 @@ static bool mt753x_is_mac_port(u32 port) + } + + static int +-mt7988_mac_config(struct dsa_switch *ds, int port, unsigned int mode, +- phy_interface_t interface) +-{ +- if (dsa_is_cpu_port(ds, port) && +- interface == PHY_INTERFACE_MODE_INTERNAL) +- return 0; +- +- return -EINVAL; +-} +- +-static int + mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + phy_interface_t interface) + { +@@ -2922,6 +2911,9 @@ mt753x_mac_config(struct dsa_switch *ds, + { + struct mt7530_priv *priv = ds->priv; + ++ if (!priv->info->mac_port_config) ++ return 0; ++ + return priv->info->mac_port_config(ds, port, mode, state->interface); + } + +@@ -3383,7 +3375,6 @@ const struct mt753x_info mt753x_table[] + .phy_write = mt7531_ind_phy_write, + .cpu_port_config = mt7988_cpu_port_config, + .mac_port_get_caps = mt7988_mac_port_get_caps, +- .mac_port_config = mt7988_mac_config, + }, + }; + EXPORT_SYMBOL_GPL(mt753x_table); +@@ -3411,8 +3402,7 @@ mt7530_probe_common(struct mt7530_priv * + * properly. + */ + if (!priv->info->sw_setup || !priv->info->phy_read || +- !priv->info->phy_write || !priv->info->mac_port_get_caps || +- !priv->info->mac_port_config) ++ !priv->info->phy_write || !priv->info->mac_port_get_caps) + return -EINVAL; + + priv->id = priv->info->id; diff --git a/lede/target/linux/generic/backport-6.1/790-38-v6.9-net-dsa-mt7530-set-interrupt-register-only-for-MT753.patch b/lede/target/linux/generic/backport-6.1/790-38-v6.9-net-dsa-mt7530-set-interrupt-register-only-for-MT753.patch new file mode 100644 index 0000000000..b8473ed128 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-38-v6.9-net-dsa-mt7530-set-interrupt-register-only-for-MT753.patch @@ -0,0 +1,31 @@ +From 0e297b1c662825f7dcd97272323c81f502987e0f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Fri, 1 Mar 2024 12:42:58 +0200 +Subject: [PATCH 38/48] net: dsa: mt7530: set interrupt register only for + MT7530 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Setting this register related to interrupts is only needed for the MT7530 +switch. Make an exclusive check to ensure this. + +Signed-off-by: Arınç ÜNAL +Acked-by: Daniel Golle +Tested-by: Daniel Golle +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2259,7 +2259,7 @@ mt7530_setup_irq(struct mt7530_priv *pri + } + + /* This register must be set for MT7530 to properly fire interrupts */ +- if (priv->id != ID_MT7531) ++ if (priv->id == ID_MT7530 || priv->id == ID_MT7621) + mt7530_set(priv, MT7530_TOP_SIG_CTRL, TOP_SIG_CTRL_NORMAL); + + ret = request_threaded_irq(priv->irq, NULL, mt7530_irq_thread_fn, diff --git a/lede/target/linux/generic/backport-6.1/790-39-v6.9-net-dsa-mt7530-do-not-use-SW_PHY_RST-to-reset-MT7531.patch b/lede/target/linux/generic/backport-6.1/790-39-v6.9-net-dsa-mt7530-do-not-use-SW_PHY_RST-to-reset-MT7531.patch new file mode 100644 index 0000000000..216a781087 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-39-v6.9-net-dsa-mt7530-do-not-use-SW_PHY_RST-to-reset-MT7531.patch @@ -0,0 +1,41 @@ +From 0eb6bc551371070325b6606cc3bed6734ecad87d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Fri, 1 Mar 2024 12:42:59 +0200 +Subject: [PATCH 39/48] net: dsa: mt7530: do not use SW_PHY_RST to reset MT7531 + switch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +According to the document MT7531 Reference Manual for Development Board +v1.0, the SW_PHY_RST bit on the SYS_CTRL register doesn't exist for +MT7531. This is likely why forcing link down on all ports is necessary for +MT7531. + +Therefore, do not set SW_PHY_RST on mt7531_setup(). + +Signed-off-by: Arınç ÜNAL +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2660,14 +2660,12 @@ mt7531_setup(struct dsa_switch *ds) + val = mt7530_read(priv, MT7531_TOP_SIG_SR); + priv->p5_sgmii = !!(val & PAD_DUAL_SGMII_EN); + +- /* all MACs must be forced link-down before sw reset */ ++ /* Force link down on all ports before internal reset */ + for (i = 0; i < MT7530_NUM_PORTS; i++) + mt7530_write(priv, MT7530_PMCR_P(i), MT7531_FORCE_LNK); + + /* Reset the switch through internal reset */ +- mt7530_write(priv, MT7530_SYS_CTRL, +- SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | +- SYS_CTRL_REG_RST); ++ mt7530_write(priv, MT7530_SYS_CTRL, SYS_CTRL_SW_RST | SYS_CTRL_REG_RST); + + if (!priv->p5_sgmii) { + mt7531_pll_setup(priv); diff --git a/lede/target/linux/generic/backport-6.1/790-40-v6.9-net-dsa-mt7530-get-rid-of-useless-error-returns-on-p.patch b/lede/target/linux/generic/backport-6.1/790-40-v6.9-net-dsa-mt7530-get-rid-of-useless-error-returns-on-p.patch new file mode 100644 index 0000000000..f920a6604d --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-40-v6.9-net-dsa-mt7530-get-rid-of-useless-error-returns-on-p.patch @@ -0,0 +1,217 @@ +From bb20b1b4d832de4eb98ec7c22906db7c04e3f7c5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Fri, 1 Mar 2024 12:43:00 +0200 +Subject: [PATCH 40/48] net: dsa: mt7530: get rid of useless error returns on + phylink code path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Remove error returns on the cases where they are already handled with the +function the mac_port_get_caps member in mt753x_table points to. + +mt7531_mac_config() is also called from mt7531_cpu_port_config() outside of +phylink but the port and interface modes are already handled there. + +Change the functions and the mac_port_config function pointer to void now +that there're no error returns anymore. + +Remove mt753x_is_mac_port() that used to help the said error returns. + +On mt7531_mac_config(), switch to if statements to simplify the code. + +Remove internal phy cases from mt753x_phylink_mac_config(), there is no +need to check the interface mode as that's already handled with the +function the mac_port_get_caps member in mt753x_table points to. + +Acked-by: Daniel Golle +Tested-by: Daniel Golle +Signed-off-by: Arınç ÜNAL +Reviewed-by: Russell King (Oracle) +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 81 ++++++++-------------------------------- + drivers/net/dsa/mt7530.h | 6 +-- + 2 files changed, 19 insertions(+), 68 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2803,7 +2803,7 @@ static void mt7988_mac_port_get_caps(str + } + } + +-static int ++static void + mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + phy_interface_t interface) + { +@@ -2813,22 +2813,14 @@ mt7530_mac_config(struct dsa_switch *ds, + mt7530_setup_port5(priv->ds, interface); + else if (port == 6) + mt7530_setup_port6(priv->ds, interface); +- +- return 0; + } + +-static int mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port, +- phy_interface_t interface, +- struct phy_device *phydev) ++static void mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port, ++ phy_interface_t interface, ++ struct phy_device *phydev) + { + u32 val; + +- if (priv->p5_sgmii) { +- dev_err(priv->dev, "RGMII mode is not available for port %d\n", +- port); +- return -EINVAL; +- } +- + val = mt7530_read(priv, MT7531_CLKGEN_CTRL); + val |= GP_CLK_EN; + val &= ~GP_MODE_MASK; +@@ -2856,20 +2848,14 @@ static int mt7531_rgmii_setup(struct mt7 + case PHY_INTERFACE_MODE_RGMII_ID: + break; + default: +- return -EINVAL; ++ break; + } + } +- mt7530_write(priv, MT7531_CLKGEN_CTRL, val); + +- return 0; +-} +- +-static bool mt753x_is_mac_port(u32 port) +-{ +- return (port == 5 || port == 6); ++ mt7530_write(priv, MT7531_CLKGEN_CTRL, val); + } + +-static int ++static void + mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + phy_interface_t interface) + { +@@ -2877,42 +2863,21 @@ mt7531_mac_config(struct dsa_switch *ds, + struct phy_device *phydev; + struct dsa_port *dp; + +- if (!mt753x_is_mac_port(port)) { +- dev_err(priv->dev, "port %d is not a MAC port\n", port); +- return -EINVAL; +- } +- +- switch (interface) { +- case PHY_INTERFACE_MODE_RGMII: +- case PHY_INTERFACE_MODE_RGMII_ID: +- case PHY_INTERFACE_MODE_RGMII_RXID: +- case PHY_INTERFACE_MODE_RGMII_TXID: ++ if (phy_interface_mode_is_rgmii(interface)) { + dp = dsa_to_port(ds, port); + phydev = dp->slave->phydev; +- return mt7531_rgmii_setup(priv, port, interface, phydev); +- case PHY_INTERFACE_MODE_SGMII: +- case PHY_INTERFACE_MODE_NA: +- case PHY_INTERFACE_MODE_1000BASEX: +- case PHY_INTERFACE_MODE_2500BASEX: +- /* handled in SGMII PCS driver */ +- return 0; +- default: +- return -EINVAL; ++ mt7531_rgmii_setup(priv, port, interface, phydev); + } +- +- return -EINVAL; + } + +-static int ++static void + mt753x_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + const struct phylink_link_state *state) + { + struct mt7530_priv *priv = ds->priv; + +- if (!priv->info->mac_port_config) +- return 0; +- +- return priv->info->mac_port_config(ds, port, mode, state->interface); ++ if (priv->info->mac_port_config) ++ priv->info->mac_port_config(ds, port, mode, state->interface); + } + + static struct phylink_pcs * +@@ -2941,17 +2906,11 @@ mt753x_phylink_mac_config(struct dsa_swi + u32 mcr_cur, mcr_new; + + switch (port) { +- case 0 ... 4: +- if (state->interface != PHY_INTERFACE_MODE_GMII && +- state->interface != PHY_INTERFACE_MODE_INTERNAL) +- goto unsupported; +- break; + case 5: + if (priv->p5_interface == state->interface) + break; + +- if (mt753x_mac_config(ds, port, mode, state) < 0) +- goto unsupported; ++ mt753x_mac_config(ds, port, mode, state); + + if (priv->p5_intf_sel != P5_DISABLED) + priv->p5_interface = state->interface; +@@ -2960,16 +2919,10 @@ mt753x_phylink_mac_config(struct dsa_swi + if (priv->p6_interface == state->interface) + break; + +- if (mt753x_mac_config(ds, port, mode, state) < 0) +- goto unsupported; ++ mt753x_mac_config(ds, port, mode, state); + + priv->p6_interface = state->interface; + break; +- default: +-unsupported: +- dev_err(ds->dev, "%s: unsupported %s port: %i\n", +- __func__, phy_modes(state->interface), port); +- return; + } + + mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port)); +@@ -3052,7 +3005,6 @@ mt7531_cpu_port_config(struct dsa_switch + struct mt7530_priv *priv = ds->priv; + phy_interface_t interface; + int speed; +- int ret; + + switch (port) { + case 5: +@@ -3077,9 +3029,8 @@ mt7531_cpu_port_config(struct dsa_switch + else + speed = SPEED_1000; + +- ret = mt7531_mac_config(ds, port, MLO_AN_FIXED, interface); +- if (ret) +- return ret; ++ mt7531_mac_config(ds, port, MLO_AN_FIXED, interface); ++ + mt7530_write(priv, MT7530_PMCR_P(port), + PMCR_CPU_PORT_SETTING(priv->id)); + mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL, +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -753,9 +753,9 @@ struct mt753x_info { + void (*mac_port_validate)(struct dsa_switch *ds, int port, + phy_interface_t interface, + unsigned long *supported); +- int (*mac_port_config)(struct dsa_switch *ds, int port, +- unsigned int mode, +- phy_interface_t interface); ++ void (*mac_port_config)(struct dsa_switch *ds, int port, ++ unsigned int mode, ++ phy_interface_t interface); + }; + + /* struct mt7530_priv - This is the main data structure for holding the state diff --git a/lede/target/linux/generic/backport-6.1/790-41-v6.9-net-dsa-mt7530-get-rid-of-priv-info-cpu_port_config.patch b/lede/target/linux/generic/backport-6.1/790-41-v6.9-net-dsa-mt7530-get-rid-of-priv-info-cpu_port_config.patch new file mode 100644 index 0000000000..eb0a5706ec --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-41-v6.9-net-dsa-mt7530-get-rid-of-priv-info-cpu_port_config.patch @@ -0,0 +1,305 @@ +From 8554f6a7914d28b179671540f527897d85c88809 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Fri, 1 Mar 2024 12:43:01 +0200 +Subject: [PATCH 41/48] net: dsa: mt7530: get rid of + priv->info->cpu_port_config() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +priv->info->cpu_port_config() is used for MT7531 and the switch on the +MT7988 SoC. It sets up the ports described as a CPU port earlier than the +phylink code path would do. + +This function is useless as: +- Configuring the MACs can be done from the phylink_mac_config code path + instead. +- All the link configuration it does on the CPU ports are later undone with + the port_enable, phylink_mac_config, and then phylink_mac_link_up code + path [1]. + +priv->p5_interface and priv->p6_interface were being used to prevent +configuring the MACs from the phylink_mac_config code path. Remove them now +that they hold no purpose. + +Remove priv->info->cpu_port_config(). On mt753x_phylink_mac_config, switch +to if statements to simplify the code. + +Remove the overwriting of the speed and duplex interfaces for certain +interface modes. Phylink already provides the speed and duplex variables +with proper values. Phylink already sets the max speed of TRGMII to +SPEED_1000. Add SPEED_2500 for PHY_INTERFACE_MODE_2500BASEX to where the +speed and EEE bits are set instead. + +On the switch on the MT7988 SoC, PHY_INTERFACE_MODE_INTERNAL is being used +to describe the interface mode of the 10G MAC, which is of port 6. On +mt7988_cpu_port_config() PMCR_FORCE_SPEED_1000 was set via the +PMCR_CPU_PORT_SETTING() mask. Add SPEED_10000 case to where the speed bits +are set to cover this. No need to add it to where the EEE bits are set as +the "MT7988A Wi-Fi 7 Generation Router Platform: Datasheet (Open Version) +v0.1" document shows that these bits don't exist on the MT7530_PMCR_P(6) +register. + +Remove the definition of PMCR_CPU_PORT_SETTING() now that it holds no +purpose. + +Change mt753x_cpu_port_enable() to void now that there're no error cases +left. + +Link: https://lore.kernel.org/netdev/ZHy2jQLesdYFMQtO@shell.armlinux.org.uk/ [1] +Suggested-by: Russell King (Oracle) +Signed-off-by: Arınç ÜNAL +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 114 +++------------------------------------ + drivers/net/dsa/mt7530.h | 11 ---- + 2 files changed, 7 insertions(+), 118 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1170,18 +1170,10 @@ mt753x_trap_frames(struct mt7530_priv *p + MT753X_BPDU_CPU_ONLY); + } + +-static int ++static void + mt753x_cpu_port_enable(struct dsa_switch *ds, int port) + { + struct mt7530_priv *priv = ds->priv; +- int ret; +- +- /* Setup max capability of CPU port at first */ +- if (priv->info->cpu_port_config) { +- ret = priv->info->cpu_port_config(ds, port); +- if (ret) +- return ret; +- } + + /* Enable Mediatek header mode on the cpu port */ + mt7530_write(priv, MT7530_PVC_P(port), +@@ -1207,8 +1199,6 @@ mt753x_cpu_port_enable(struct dsa_switch + /* Set to fallback mode for independent VLAN learning */ + mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, + MT7530_PORT_FALLBACK_MODE); +- +- return 0; + } + + static int +@@ -2461,8 +2451,6 @@ mt7530_setup(struct dsa_switch *ds) + val |= MHWTRAP_MANUAL; + mt7530_write(priv, MT7530_MHWTRAP, val); + +- priv->p6_interface = PHY_INTERFACE_MODE_NA; +- + if ((val & HWTRAP_XTAL_MASK) == HWTRAP_XTAL_40MHZ) + mt7530_pll_setup(priv); + +@@ -2480,9 +2468,7 @@ mt7530_setup(struct dsa_switch *ds) + mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); + + if (dsa_is_cpu_port(ds, i)) { +- ret = mt753x_cpu_port_enable(ds, i); +- if (ret) +- return ret; ++ mt753x_cpu_port_enable(ds, i); + } else { + mt7530_port_disable(ds, i); + +@@ -2589,9 +2575,7 @@ mt7531_setup_common(struct dsa_switch *d + mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR); + + if (dsa_is_cpu_port(ds, i)) { +- ret = mt753x_cpu_port_enable(ds, i); +- if (ret) +- return ret; ++ mt753x_cpu_port_enable(ds, i); + } else { + mt7530_port_disable(ds, i); + +@@ -2683,10 +2667,6 @@ mt7531_setup(struct dsa_switch *ds) + mt7530_rmw(priv, MT7531_GPIO_MODE0, MT7531_GPIO0_MASK, + MT7531_GPIO0_INTERRUPT); + +- /* Let phylink decide the interface later. */ +- priv->p5_interface = PHY_INTERFACE_MODE_NA; +- priv->p6_interface = PHY_INTERFACE_MODE_NA; +- + /* Enable Energy-Efficient Ethernet (EEE) and PHY core PLL, since + * phy_device has not yet been created provided for + * phy_[read,write]_mmd_indirect is called, we provide our own +@@ -2905,26 +2885,9 @@ mt753x_phylink_mac_config(struct dsa_swi + struct mt7530_priv *priv = ds->priv; + u32 mcr_cur, mcr_new; + +- switch (port) { +- case 5: +- if (priv->p5_interface == state->interface) +- break; +- ++ if (port == 5 || port == 6) + mt753x_mac_config(ds, port, mode, state); + +- if (priv->p5_intf_sel != P5_DISABLED) +- priv->p5_interface = state->interface; +- break; +- case 6: +- if (priv->p6_interface == state->interface) +- break; +- +- mt753x_mac_config(ds, port, mode, state); +- +- priv->p6_interface = state->interface; +- break; +- } +- + mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port)); + mcr_new = mcr_cur; + mcr_new &= ~PMCR_LINK_SETTINGS_MASK; +@@ -2960,17 +2923,10 @@ static void mt753x_phylink_mac_link_up(s + + mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK; + +- /* MT753x MAC works in 1G full duplex mode for all up-clocked +- * variants. +- */ +- if (interface == PHY_INTERFACE_MODE_TRGMII || +- (phy_interface_mode_is_8023z(interface))) { +- speed = SPEED_1000; +- duplex = DUPLEX_FULL; +- } +- + switch (speed) { + case SPEED_1000: ++ case SPEED_2500: ++ case SPEED_10000: + mcr |= PMCR_FORCE_SPEED_1000; + break; + case SPEED_100: +@@ -2988,6 +2944,7 @@ static void mt753x_phylink_mac_link_up(s + if (mode == MLO_AN_PHY && phydev && phy_init_eee(phydev, false) >= 0) { + switch (speed) { + case SPEED_1000: ++ case SPEED_2500: + mcr |= PMCR_FORCE_EEE1G; + break; + case SPEED_100: +@@ -2999,61 +2956,6 @@ static void mt753x_phylink_mac_link_up(s + mt7530_set(priv, MT7530_PMCR_P(port), mcr); + } + +-static int +-mt7531_cpu_port_config(struct dsa_switch *ds, int port) +-{ +- struct mt7530_priv *priv = ds->priv; +- phy_interface_t interface; +- int speed; +- +- switch (port) { +- case 5: +- if (!priv->p5_sgmii) +- interface = PHY_INTERFACE_MODE_RGMII; +- else +- interface = PHY_INTERFACE_MODE_2500BASEX; +- +- priv->p5_interface = interface; +- break; +- case 6: +- interface = PHY_INTERFACE_MODE_2500BASEX; +- +- priv->p6_interface = interface; +- break; +- default: +- return -EINVAL; +- } +- +- if (interface == PHY_INTERFACE_MODE_2500BASEX) +- speed = SPEED_2500; +- else +- speed = SPEED_1000; +- +- mt7531_mac_config(ds, port, MLO_AN_FIXED, interface); +- +- mt7530_write(priv, MT7530_PMCR_P(port), +- PMCR_CPU_PORT_SETTING(priv->id)); +- mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL, +- speed, DUPLEX_FULL, true, true); +- +- return 0; +-} +- +-static int +-mt7988_cpu_port_config(struct dsa_switch *ds, int port) +-{ +- struct mt7530_priv *priv = ds->priv; +- +- mt7530_write(priv, MT7530_PMCR_P(port), +- PMCR_CPU_PORT_SETTING(priv->id)); +- +- mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, +- PHY_INTERFACE_MODE_INTERNAL, NULL, +- SPEED_10000, DUPLEX_FULL, true, true); +- +- return 0; +-} +- + static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port, + struct phylink_config *config) + { +@@ -3312,7 +3214,6 @@ const struct mt753x_info mt753x_table[] + .sw_setup = mt7531_setup, + .phy_read = mt7531_ind_phy_read, + .phy_write = mt7531_ind_phy_write, +- .cpu_port_config = mt7531_cpu_port_config, + .mac_port_get_caps = mt7531_mac_port_get_caps, + .mac_port_config = mt7531_mac_config, + }, +@@ -3322,7 +3223,6 @@ const struct mt753x_info mt753x_table[] + .sw_setup = mt7988_setup, + .phy_read = mt7531_ind_phy_read, + .phy_write = mt7531_ind_phy_write, +- .cpu_port_config = mt7988_cpu_port_config, + .mac_port_get_caps = mt7988_mac_port_get_caps, + }, + }; +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -340,13 +340,6 @@ enum mt7530_vlan_port_acc_frm { + PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ + PMCR_FORCE_FDX | PMCR_FORCE_LNK | \ + PMCR_FORCE_EEE1G | PMCR_FORCE_EEE100) +-#define PMCR_CPU_PORT_SETTING(id) (PMCR_FORCE_MODE_ID((id)) | \ +- PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \ +- PMCR_BACKOFF_EN | PMCR_BACKPR_EN | \ +- PMCR_TX_EN | PMCR_RX_EN | \ +- PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ +- PMCR_FORCE_SPEED_1000 | \ +- PMCR_FORCE_FDX | PMCR_FORCE_LNK) + + #define MT7530_PMEEECR_P(x) (0x3004 + (x) * 0x100) + #define WAKEUP_TIME_1000(x) (((x) & 0xFF) << 24) +@@ -747,7 +740,6 @@ struct mt753x_info { + int (*sw_setup)(struct dsa_switch *ds); + int (*phy_read)(struct mt7530_priv *priv, int port, int regnum); + int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val); +- int (*cpu_port_config)(struct dsa_switch *ds, int port); + void (*mac_port_get_caps)(struct dsa_switch *ds, int port, + struct phylink_config *config); + void (*mac_port_validate)(struct dsa_switch *ds, int port, +@@ -773,7 +765,6 @@ struct mt753x_info { + * @ports: Holding the state among ports + * @reg_mutex: The lock for protecting among process accessing + * registers +- * @p6_interface Holding the current port 6 interface + * @p5_intf_sel: Holding the current port 5 interface select + * @p5_sgmii: Flag for distinguishing if port 5 of the MT7531 switch + * has got SGMII +@@ -795,8 +786,6 @@ struct mt7530_priv { + const struct mt753x_info *info; + unsigned int id; + bool mcm; +- phy_interface_t p6_interface; +- phy_interface_t p5_interface; + enum p5_interface_select p5_intf_sel; + bool p5_sgmii; + u8 mirror_rx; diff --git a/lede/target/linux/generic/backport-6.1/790-42-v6.9-net-dsa-mt7530-get-rid-of-mt753x_mac_config.patch b/lede/target/linux/generic/backport-6.1/790-42-v6.9-net-dsa-mt7530-get-rid-of-mt753x_mac_config.patch new file mode 100644 index 0000000000..c83a627808 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-42-v6.9-net-dsa-mt7530-get-rid-of-mt753x_mac_config.patch @@ -0,0 +1,48 @@ +From 0c282205ef8c6dd6d2c145fac1fb6aba3e65c02d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Fri, 1 Mar 2024 12:43:02 +0200 +Subject: [PATCH 42/48] net: dsa: mt7530: get rid of mt753x_mac_config() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There is no need for a separate function to call +priv->info->mac_port_config(). Call it from mt753x_phylink_mac_config() +instead and remove mt753x_mac_config(). + +Signed-off-by: Arınç ÜNAL +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 14 ++------------ + 1 file changed, 2 insertions(+), 12 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2850,16 +2850,6 @@ mt7531_mac_config(struct dsa_switch *ds, + } + } + +-static void +-mt753x_mac_config(struct dsa_switch *ds, int port, unsigned int mode, +- const struct phylink_link_state *state) +-{ +- struct mt7530_priv *priv = ds->priv; +- +- if (priv->info->mac_port_config) +- priv->info->mac_port_config(ds, port, mode, state->interface); +-} +- + static struct phylink_pcs * + mt753x_phylink_mac_select_pcs(struct dsa_switch *ds, int port, + phy_interface_t interface) +@@ -2885,8 +2875,8 @@ mt753x_phylink_mac_config(struct dsa_swi + struct mt7530_priv *priv = ds->priv; + u32 mcr_cur, mcr_new; + +- if (port == 5 || port == 6) +- mt753x_mac_config(ds, port, mode, state); ++ if ((port == 5 || port == 6) && priv->info->mac_port_config) ++ priv->info->mac_port_config(ds, port, mode, state->interface); + + mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port)); + mcr_new = mcr_cur; diff --git a/lede/target/linux/generic/backport-6.1/790-43-v6.9-net-dsa-mt7530-put-initialising-PCS-devices-code-bac.patch b/lede/target/linux/generic/backport-6.1/790-43-v6.9-net-dsa-mt7530-put-initialising-PCS-devices-code-bac.patch new file mode 100644 index 0000000000..84ee7416bf --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-43-v6.9-net-dsa-mt7530-put-initialising-PCS-devices-code-bac.patch @@ -0,0 +1,57 @@ +From d55c300aa1fe240aa3eba18550ba6c4e2c4bd157 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Fri, 1 Mar 2024 12:43:03 +0200 +Subject: [PATCH 43/48] net: dsa: mt7530: put initialising PCS devices code + back to original order +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The commit fae463084032 ("net: dsa: mt753x: fix pcs conversion regression") +fixes regression caused by cpu_port_config manually calling phylink +operations. cpu_port_config was deemed useless and was removed. Therefore, +put initialising PCS devices code back to its original order. + +Signed-off-by: Arınç ÜNAL +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -3034,17 +3034,9 @@ static int + mt753x_setup(struct dsa_switch *ds) + { + struct mt7530_priv *priv = ds->priv; +- int i, ret; ++ int ret = priv->info->sw_setup(ds); ++ int i; + +- /* Initialise the PCS devices */ +- for (i = 0; i < priv->ds->num_ports; i++) { +- priv->pcs[i].pcs.ops = priv->info->pcs_ops; +- priv->pcs[i].pcs.neg_mode = true; +- priv->pcs[i].priv = priv; +- priv->pcs[i].port = i; +- } +- +- ret = priv->info->sw_setup(ds); + if (ret) + return ret; + +@@ -3056,6 +3048,14 @@ mt753x_setup(struct dsa_switch *ds) + if (ret && priv->irq) + mt7530_free_irq_common(priv); + ++ /* Initialise the PCS devices */ ++ for (i = 0; i < priv->ds->num_ports; i++) { ++ priv->pcs[i].pcs.ops = priv->info->pcs_ops; ++ priv->pcs[i].pcs.neg_mode = true; ++ priv->pcs[i].priv = priv; ++ priv->pcs[i].port = i; ++ } ++ + if (priv->create_sgmii) { + ret = priv->create_sgmii(priv); + if (ret && priv->irq) diff --git a/lede/target/linux/generic/backport-6.1/790-44-v6.9-net-dsa-mt7530-sort-link-settings-ops-and-force-link.patch b/lede/target/linux/generic/backport-6.1/790-44-v6.9-net-dsa-mt7530-sort-link-settings-ops-and-force-link.patch new file mode 100644 index 0000000000..814a9d06e7 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-44-v6.9-net-dsa-mt7530-sort-link-settings-ops-and-force-link.patch @@ -0,0 +1,68 @@ +From a9544caa482a7ed215117a902f04185216997831 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Fri, 1 Mar 2024 12:43:04 +0200 +Subject: [PATCH 44/48] net: dsa: mt7530: sort link settings ops and force link + down on all ports +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +port_enable and port_disable clears the link settings. Move that to +mt7530_setup() and mt7531_setup_common() which set up the switches. This +way, the link settings are cleared on all ports at setup, and then only +once with phylink_mac_link_down() when a link goes down. + +Enable force mode at setup to apply the force part of the link settings. +This ensures that disabled ports will have their link down. + +Suggested-by: Vladimir Oltean +Signed-off-by: Arınç ÜNAL +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1222,7 +1222,6 @@ mt7530_port_enable(struct dsa_switch *ds + priv->ports[port].enable = true; + mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, + priv->ports[port].pm); +- mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); + + mutex_unlock(&priv->reg_mutex); + +@@ -1242,7 +1241,6 @@ mt7530_port_disable(struct dsa_switch *d + priv->ports[port].enable = false; + mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, + PCR_MATRIX_CLR); +- mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); + + mutex_unlock(&priv->reg_mutex); + } +@@ -2460,6 +2458,12 @@ mt7530_setup(struct dsa_switch *ds) + mt7530_mib_reset(ds); + + for (i = 0; i < MT7530_NUM_PORTS; i++) { ++ /* Clear link settings and enable force mode to force link down ++ * on all ports until they're enabled later. ++ */ ++ mt7530_rmw(priv, MT7530_PMCR_P(i), PMCR_LINK_SETTINGS_MASK | ++ PMCR_FORCE_MODE, PMCR_FORCE_MODE); ++ + /* Disable forwarding by default on all ports */ + mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, + PCR_MATRIX_CLR); +@@ -2565,6 +2569,12 @@ mt7531_setup_common(struct dsa_switch *d + UNU_FFP_MASK); + + for (i = 0; i < MT7530_NUM_PORTS; i++) { ++ /* Clear link settings and enable force mode to force link down ++ * on all ports until they're enabled later. ++ */ ++ mt7530_rmw(priv, MT7530_PMCR_P(i), PMCR_LINK_SETTINGS_MASK | ++ MT7531_FORCE_MODE, MT7531_FORCE_MODE); ++ + /* Disable forwarding by default on all ports */ + mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, + PCR_MATRIX_CLR); diff --git a/lede/target/linux/generic/backport-6.1/790-45-v6.9-net-dsa-mt7530-simplify-link-operations.patch b/lede/target/linux/generic/backport-6.1/790-45-v6.9-net-dsa-mt7530-simplify-link-operations.patch new file mode 100644 index 0000000000..d9f91a932a --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-45-v6.9-net-dsa-mt7530-simplify-link-operations.patch @@ -0,0 +1,83 @@ +From 89017cac5f6fbaab23955818c31b3c7f1eb26f4a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Fri, 1 Mar 2024 12:43:05 +0200 +Subject: [PATCH 45/48] net: dsa: mt7530: simplify link operations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The "MT7621 Giga Switch Programming Guide v0.3", "MT7531 Reference Manual +for Development Board v1.0", and "MT7988A Wi-Fi 7 Generation Router +Platform: Datasheet (Open Version) v0.1" documents show that these bits are +enabled at reset: + +PMCR_IFG_XMIT(1) (not part of PMCR_LINK_SETTINGS_MASK) +PMCR_MAC_MODE (not part of PMCR_LINK_SETTINGS_MASK) +PMCR_TX_EN +PMCR_RX_EN +PMCR_BACKOFF_EN (not part of PMCR_LINK_SETTINGS_MASK) +PMCR_BACKPR_EN (not part of PMCR_LINK_SETTINGS_MASK) +PMCR_TX_FC_EN +PMCR_RX_FC_EN + +These bits also don't exist on the MT7530_PMCR_P(6) register of the switch +on the MT7988 SoC: + +PMCR_IFG_XMIT() +PMCR_MAC_MODE +PMCR_BACKOFF_EN +PMCR_BACKPR_EN + +Remove the setting of the bits not part of PMCR_LINK_SETTINGS_MASK on +phylink_mac_config as they're already set. + +The bit for setting the port on force mode is already done on +mt7530_setup() and mt7531_setup_common(). So get rid of +PMCR_FORCE_MODE_ID() which helped determine which bit to use for the switch +model. + +Signed-off-by: Arınç ÜNAL +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 12 +----------- + drivers/net/dsa/mt7530.h | 2 -- + 2 files changed, 1 insertion(+), 13 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2883,23 +2883,13 @@ mt753x_phylink_mac_config(struct dsa_swi + const struct phylink_link_state *state) + { + struct mt7530_priv *priv = ds->priv; +- u32 mcr_cur, mcr_new; + + if ((port == 5 || port == 6) && priv->info->mac_port_config) + priv->info->mac_port_config(ds, port, mode, state->interface); + +- mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port)); +- mcr_new = mcr_cur; +- mcr_new &= ~PMCR_LINK_SETTINGS_MASK; +- mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN | +- PMCR_BACKPR_EN | PMCR_FORCE_MODE_ID(priv->id); +- + /* Are we connected to external phy */ + if (port == 5 && dsa_is_user_port(ds, 5)) +- mcr_new |= PMCR_EXT_PHY; +- +- if (mcr_new != mcr_cur) +- mt7530_write(priv, MT7530_PMCR_P(port), mcr_new); ++ mt7530_set(priv, MT7530_PMCR_P(port), PMCR_EXT_PHY); + } + + static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port, +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -333,8 +333,6 @@ enum mt7530_vlan_port_acc_frm { + MT7531_FORCE_DPX | \ + MT7531_FORCE_RX_FC | \ + MT7531_FORCE_TX_FC) +-#define PMCR_FORCE_MODE_ID(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ +- MT7531_FORCE_MODE : PMCR_FORCE_MODE) + #define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \ + PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \ + PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ diff --git a/lede/target/linux/generic/backport-6.1/790-49-v6.10-net-dsa-mt7530-provide-own-phylink-MAC-operations.patch b/lede/target/linux/generic/backport-6.1/790-49-v6.10-net-dsa-mt7530-provide-own-phylink-MAC-operations.patch new file mode 100644 index 0000000000..8962e560f7 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-49-v6.10-net-dsa-mt7530-provide-own-phylink-MAC-operations.patch @@ -0,0 +1,135 @@ +From 5754b3bdcd872aa229881b8f07f84a8404c7d72a Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 12 Apr 2024 16:15:34 +0100 +Subject: [PATCH 1/5] net: dsa: mt7530: provide own phylink MAC operations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Convert mt753x to provide its own phylink MAC operations, thus avoiding +the shim layer in DSA's port.c + +Signed-off-by: Russell King (Oracle) +Tested-by: Arınç ÜNAL +Link: https://lore.kernel.org/r/E1rvIco-006bQu-Fq@rmk-PC.armlinux.org.uk +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 46 +++++++++++++++++++++++++--------------- + 1 file changed, 29 insertions(+), 17 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2861,28 +2861,34 @@ mt7531_mac_config(struct dsa_switch *ds, + } + + static struct phylink_pcs * +-mt753x_phylink_mac_select_pcs(struct dsa_switch *ds, int port, ++mt753x_phylink_mac_select_pcs(struct phylink_config *config, + phy_interface_t interface) + { +- struct mt7530_priv *priv = ds->priv; ++ struct dsa_port *dp = dsa_phylink_to_port(config); ++ struct mt7530_priv *priv = dp->ds->priv; + + switch (interface) { + case PHY_INTERFACE_MODE_TRGMII: +- return &priv->pcs[port].pcs; ++ return &priv->pcs[dp->index].pcs; + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: +- return priv->ports[port].sgmii_pcs; ++ return priv->ports[dp->index].sgmii_pcs; + default: + return NULL; + } + } + + static void +-mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ++mt753x_phylink_mac_config(struct phylink_config *config, unsigned int mode, + const struct phylink_link_state *state) + { +- struct mt7530_priv *priv = ds->priv; ++ struct dsa_port *dp = dsa_phylink_to_port(config); ++ struct dsa_switch *ds = dp->ds; ++ struct mt7530_priv *priv; ++ int port = dp->index; ++ ++ priv = ds->priv; + + if ((port == 5 || port == 6) && priv->info->mac_port_config) + priv->info->mac_port_config(ds, port, mode, state->interface); +@@ -2892,23 +2898,25 @@ mt753x_phylink_mac_config(struct dsa_swi + mt7530_set(priv, MT7530_PMCR_P(port), PMCR_EXT_PHY); + } + +-static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port, ++static void mt753x_phylink_mac_link_down(struct phylink_config *config, + unsigned int mode, + phy_interface_t interface) + { +- struct mt7530_priv *priv = ds->priv; ++ struct dsa_port *dp = dsa_phylink_to_port(config); ++ struct mt7530_priv *priv = dp->ds->priv; + +- mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); ++ mt7530_clear(priv, MT7530_PMCR_P(dp->index), PMCR_LINK_SETTINGS_MASK); + } + +-static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port, ++static void mt753x_phylink_mac_link_up(struct phylink_config *config, ++ struct phy_device *phydev, + unsigned int mode, + phy_interface_t interface, +- struct phy_device *phydev, + int speed, int duplex, + bool tx_pause, bool rx_pause) + { +- struct mt7530_priv *priv = ds->priv; ++ struct dsa_port *dp = dsa_phylink_to_port(config); ++ struct mt7530_priv *priv = dp->ds->priv; + u32 mcr; + + mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK; +@@ -2943,7 +2951,7 @@ static void mt753x_phylink_mac_link_up(s + } + } + +- mt7530_set(priv, MT7530_PMCR_P(port), mcr); ++ mt7530_set(priv, MT7530_PMCR_P(dp->index), mcr); + } + + static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port, +@@ -3169,16 +3177,19 @@ const struct dsa_switch_ops mt7530_switc + .port_mirror_add = mt753x_port_mirror_add, + .port_mirror_del = mt753x_port_mirror_del, + .phylink_get_caps = mt753x_phylink_get_caps, +- .phylink_mac_select_pcs = mt753x_phylink_mac_select_pcs, +- .phylink_mac_config = mt753x_phylink_mac_config, +- .phylink_mac_link_down = mt753x_phylink_mac_link_down, +- .phylink_mac_link_up = mt753x_phylink_mac_link_up, + .get_mac_eee = mt753x_get_mac_eee, + .set_mac_eee = mt753x_set_mac_eee, + .master_state_change = mt753x_conduit_state_change, + }; + EXPORT_SYMBOL_GPL(mt7530_switch_ops); + ++static const struct phylink_mac_ops mt753x_phylink_mac_ops = { ++ .mac_select_pcs = mt753x_phylink_mac_select_pcs, ++ .mac_config = mt753x_phylink_mac_config, ++ .mac_link_down = mt753x_phylink_mac_link_down, ++ .mac_link_up = mt753x_phylink_mac_link_up, ++}; ++ + const struct mt753x_info mt753x_table[] = { + [ID_MT7621] = { + .id = ID_MT7621, +@@ -3248,6 +3259,7 @@ mt7530_probe_common(struct mt7530_priv * + priv->dev = dev; + priv->ds->priv = priv; + priv->ds->ops = &mt7530_switch_ops; ++ priv->ds->phylink_mac_ops = &mt753x_phylink_mac_ops; + mutex_init(&priv->reg_mutex); + dev_set_drvdata(dev, priv); + diff --git a/lede/target/linux/generic/backport-6.1/790-51-v6.10-net-dsa-mt7530-fix-port-mirroring-for-MT7988-SoC-swi.patch b/lede/target/linux/generic/backport-6.1/790-51-v6.10-net-dsa-mt7530-fix-port-mirroring-for-MT7988-SoC-swi.patch new file mode 100644 index 0000000000..cd5b7b287d --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-51-v6.10-net-dsa-mt7530-fix-port-mirroring-for-MT7988-SoC-swi.patch @@ -0,0 +1,49 @@ +From 019a17a5e76940ea86114838d1d638d4dc8d3750 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Sat, 13 Apr 2024 16:01:40 +0300 +Subject: [PATCH 3/5] net: dsa: mt7530: fix port mirroring for MT7988 SoC + switch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The "MT7988A Wi-Fi 7 Generation Router Platform: Datasheet (Open Version) +v0.1" document shows bits 16 to 18 as the MIRROR_PORT field of the CPU +forward control register. Currently, the MT7530 DSA subdriver configures +bits 0 to 2 of the CPU forward control register which breaks the port +mirroring feature for the MT7988 SoC switch. + +Fix this by using the MT7531_MIRROR_PORT_GET() and MT7531_MIRROR_PORT_SET() +macros which utilise the correct bits. + +Fixes: 110c18bfed41 ("net: dsa: mt7530: introduce driver for MT7988 built-in switch") +Signed-off-by: Arınç ÜNAL +Acked-by: Daniel Golle +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1890,14 +1890,16 @@ mt7530_port_vlan_del(struct dsa_switch * + + static int mt753x_mirror_port_get(unsigned int id, u32 val) + { +- return (id == ID_MT7531) ? MT7531_MIRROR_PORT_GET(val) : +- MIRROR_PORT(val); ++ return (id == ID_MT7531 || id == ID_MT7988) ? ++ MT7531_MIRROR_PORT_GET(val) : ++ MIRROR_PORT(val); + } + + static int mt753x_mirror_port_set(unsigned int id, u32 val) + { +- return (id == ID_MT7531) ? MT7531_MIRROR_PORT_SET(val) : +- MIRROR_PORT(val); ++ return (id == ID_MT7531 || id == ID_MT7988) ? ++ MT7531_MIRROR_PORT_SET(val) : ++ MIRROR_PORT(val); + } + + static int mt753x_port_mirror_add(struct dsa_switch *ds, int port, diff --git a/lede/target/linux/generic/backport-6.1/790-52-v6.10-net-dsa-mt7530-mdio-read-PHY-address-of-switch-from-.patch b/lede/target/linux/generic/backport-6.1/790-52-v6.10-net-dsa-mt7530-mdio-read-PHY-address-of-switch-from-.patch new file mode 100644 index 0000000000..e9c8f955c9 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-52-v6.10-net-dsa-mt7530-mdio-read-PHY-address-of-switch-from-.patch @@ -0,0 +1,238 @@ +From 5053a6cf1d50d785078562470d2a63695a9f3bf2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Thu, 18 Apr 2024 08:35:30 +0300 +Subject: [PATCH 4/5] net: dsa: mt7530-mdio: read PHY address of switch from + device tree +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Read the PHY address the switch listens on from the reg property of the +switch node on the device tree. This change brings support for MT7530 +switches on boards with such bootstrapping configuration where the switch +listens on a different PHY address than the hardcoded PHY address on the +driver, 31. + +As described on the "MT7621 Programming Guide v0.4" document, the MT7530 +switch and its PHYs can be configured to listen on the range of 7-12, +15-20, 23-28, and 31 and 0-4 PHY addresses. + +There are operations where the switch PHY registers are used. For the PHY +address of the control PHY, transform the MT753X_CTRL_PHY_ADDR constant +into a macro and use it. The PHY address for the control PHY is 0 when the +switch listens on 31. In any other case, it is one greater than the PHY +address the switch listens on. + +Reviewed-by: Daniel Golle +Tested-by: Daniel Golle +Reviewed-by: Florian Fainelli +Signed-off-by: Arınç ÜNAL +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530-mdio.c | 28 +++++++++++++------------- + drivers/net/dsa/mt7530.c | 37 +++++++++++++++++++++++------------ + drivers/net/dsa/mt7530.h | 4 +++- + 3 files changed, 41 insertions(+), 28 deletions(-) + +--- a/drivers/net/dsa/mt7530-mdio.c ++++ b/drivers/net/dsa/mt7530-mdio.c +@@ -18,7 +18,8 @@ + static int + mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) + { +- struct mii_bus *bus = context; ++ struct mt7530_priv *priv = context; ++ struct mii_bus *bus = priv->bus; + u16 page, r, lo, hi; + int ret; + +@@ -27,36 +28,35 @@ mt7530_regmap_write(void *context, unsig + lo = val & 0xffff; + hi = val >> 16; + +- /* MT7530 uses 31 as the pseudo port */ +- ret = bus->write(bus, 0x1f, 0x1f, page); ++ ret = bus->write(bus, priv->mdiodev->addr, 0x1f, page); + if (ret < 0) + return ret; + +- ret = bus->write(bus, 0x1f, r, lo); ++ ret = bus->write(bus, priv->mdiodev->addr, r, lo); + if (ret < 0) + return ret; + +- ret = bus->write(bus, 0x1f, 0x10, hi); ++ ret = bus->write(bus, priv->mdiodev->addr, 0x10, hi); + return ret; + } + + static int + mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) + { +- struct mii_bus *bus = context; ++ struct mt7530_priv *priv = context; ++ struct mii_bus *bus = priv->bus; + u16 page, r, lo, hi; + int ret; + + page = (reg >> 6) & 0x3ff; + r = (reg >> 2) & 0xf; + +- /* MT7530 uses 31 as the pseudo port */ +- ret = bus->write(bus, 0x1f, 0x1f, page); ++ ret = bus->write(bus, priv->mdiodev->addr, 0x1f, page); + if (ret < 0) + return ret; + +- lo = bus->read(bus, 0x1f, r); +- hi = bus->read(bus, 0x1f, 0x10); ++ lo = bus->read(bus, priv->mdiodev->addr, r); ++ hi = bus->read(bus, priv->mdiodev->addr, 0x10); + + *val = (hi << 16) | (lo & 0xffff); + +@@ -107,8 +107,7 @@ mt7531_create_sgmii(struct mt7530_priv * + mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock; + mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock; + +- regmap = devm_regmap_init(priv->dev, +- &mt7530_regmap_bus, priv->bus, ++ regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, priv, + mt7531_pcs_config[i]); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); +@@ -153,6 +152,7 @@ mt7530_probe(struct mdio_device *mdiodev + + priv->bus = mdiodev->bus; + priv->dev = &mdiodev->dev; ++ priv->mdiodev = mdiodev; + + ret = mt7530_probe_common(priv); + if (ret) +@@ -203,8 +203,8 @@ mt7530_probe(struct mdio_device *mdiodev + regmap_config->reg_stride = 4; + regmap_config->max_register = MT7530_CREV; + regmap_config->disable_locking = true; +- priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, +- priv->bus, regmap_config); ++ priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, priv, ++ regmap_config); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -86,22 +86,26 @@ core_read_mmd_indirect(struct mt7530_pri + int value, ret; + + /* Write the desired MMD Devad */ +- ret = bus->write(bus, 0, MII_MMD_CTRL, devad); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_CTRL, devad); + if (ret < 0) + goto err; + + /* Write the desired MMD register address */ +- ret = bus->write(bus, 0, MII_MMD_DATA, prtad); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA, prtad); + if (ret < 0) + goto err; + + /* Select the Function : DATA with no post increment */ +- ret = bus->write(bus, 0, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR)); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_CTRL, devad | MII_MMD_CTRL_NOINCR); + if (ret < 0) + goto err; + + /* Read the content of the MMD's selected register */ +- value = bus->read(bus, 0, MII_MMD_DATA); ++ value = bus->read(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA); + + return value; + err: +@@ -118,22 +122,26 @@ core_write_mmd_indirect(struct mt7530_pr + int ret; + + /* Write the desired MMD Devad */ +- ret = bus->write(bus, 0, MII_MMD_CTRL, devad); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_CTRL, devad); + if (ret < 0) + goto err; + + /* Write the desired MMD register address */ +- ret = bus->write(bus, 0, MII_MMD_DATA, prtad); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA, prtad); + if (ret < 0) + goto err; + + /* Select the Function : DATA with no post increment */ +- ret = bus->write(bus, 0, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR)); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_CTRL, devad | MII_MMD_CTRL_NOINCR); + if (ret < 0) + goto err; + + /* Write the data into MMD's selected register */ +- ret = bus->write(bus, 0, MII_MMD_DATA, data); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA, data); + err: + if (ret < 0) + dev_err(&bus->dev, +@@ -2684,16 +2692,19 @@ mt7531_setup(struct dsa_switch *ds) + * phy_[read,write]_mmd_indirect is called, we provide our own + * mt7531_ind_mmd_phy_[read,write] to complete this function. + */ +- val = mt7531_ind_c45_phy_read(priv, MT753X_CTRL_PHY_ADDR, ++ val = mt7531_ind_c45_phy_read(priv, ++ MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), + MDIO_MMD_VEND2, CORE_PLL_GROUP4); + val |= MT7531_RG_SYSPLL_DMY2 | MT7531_PHY_PLL_BYPASS_MODE; + val &= ~MT7531_PHY_PLL_OFF; +- mt7531_ind_c45_phy_write(priv, MT753X_CTRL_PHY_ADDR, MDIO_MMD_VEND2, +- CORE_PLL_GROUP4, val); ++ mt7531_ind_c45_phy_write(priv, ++ MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MDIO_MMD_VEND2, CORE_PLL_GROUP4, val); + + /* Disable EEE advertisement on the switch PHYs. */ +- for (i = MT753X_CTRL_PHY_ADDR; +- i < MT753X_CTRL_PHY_ADDR + MT7530_NUM_PHYS; i++) { ++ for (i = MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr); ++ i < MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr) + MT7530_NUM_PHYS; ++ i++) { + mt7531_ind_c45_phy_write(priv, i, MDIO_MMD_AN, MDIO_AN_EEE_ADV, + 0); + } +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -629,7 +629,7 @@ enum mt7531_clk_skew { + #define MT7531_PHY_PLL_OFF BIT(5) + #define MT7531_PHY_PLL_BYPASS_MODE BIT(4) + +-#define MT753X_CTRL_PHY_ADDR 0 ++#define MT753X_CTRL_PHY_ADDR(addr) ((addr + 1) & 0x1f) + + #define CORE_PLL_GROUP5 0x404 + #define RG_LCDDS_PCW_NCPO1(x) ((x) & 0xffff) +@@ -771,6 +771,7 @@ struct mt753x_info { + * @irq_enable: IRQ enable bits, synced to SYS_INT_EN + * @create_sgmii: Pointer to function creating SGMII PCS instance(s) + * @active_cpu_ports: Holding the active CPU ports ++ * @mdiodev: The pointer to the MDIO device structure + */ + struct mt7530_priv { + struct device *dev; +@@ -797,6 +798,7 @@ struct mt7530_priv { + u32 irq_enable; + int (*create_sgmii)(struct mt7530_priv *priv); + u8 active_cpu_ports; ++ struct mdio_device *mdiodev; + }; + + struct mt7530_hw_vlan_entry { diff --git a/lede/target/linux/generic/backport-6.1/790-53-v6.10-net-dsa-mt7530-simplify-core-operations.patch b/lede/target/linux/generic/backport-6.1/790-53-v6.10-net-dsa-mt7530-simplify-core-operations.patch new file mode 100644 index 0000000000..d9d70f1d4d --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-53-v6.10-net-dsa-mt7530-simplify-core-operations.patch @@ -0,0 +1,186 @@ +From 9764a08b3d260f4e7799d34bbfe64463db940d74 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Thu, 18 Apr 2024 08:35:31 +0300 +Subject: [PATCH 5/5] net: dsa: mt7530: simplify core operations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The core_rmw() function calls core_read_mmd_indirect() to read the +requested register, and then calls core_write_mmd_indirect() to write the +requested value to the register. Because Clause 22 is used to access Clause +45 registers, some operations on core_write_mmd_indirect() are +unnecessarily run. Get rid of core_read_mmd_indirect() and +core_write_mmd_indirect(), and run only the necessary operations on +core_write() and core_rmw(). + +Reviewed-by: Daniel Golle +Tested-by: Daniel Golle +Signed-off-by: Arınç ÜNAL +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 108 ++++++++++++++++----------------------- + 1 file changed, 43 insertions(+), 65 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -74,116 +74,94 @@ static const struct mt7530_mib_desc mt75 + MIB_DESC(1, 0xb8, "RxArlDrop"), + }; + +-/* Since phy_device has not yet been created and +- * phy_{read,write}_mmd_indirect is not available, we provide our own +- * core_{read,write}_mmd_indirect with core_{clear,write,set} wrappers +- * to complete this function. +- */ +-static int +-core_read_mmd_indirect(struct mt7530_priv *priv, int prtad, int devad) ++static void ++mt7530_mutex_lock(struct mt7530_priv *priv) ++{ ++ if (priv->bus) ++ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++} ++ ++static void ++mt7530_mutex_unlock(struct mt7530_priv *priv) ++{ ++ if (priv->bus) ++ mutex_unlock(&priv->bus->mdio_lock); ++} ++ ++static void ++core_write(struct mt7530_priv *priv, u32 reg, u32 val) + { + struct mii_bus *bus = priv->bus; +- int value, ret; ++ int ret; ++ ++ mt7530_mutex_lock(priv); + + /* Write the desired MMD Devad */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_CTRL, devad); ++ MII_MMD_CTRL, MDIO_MMD_VEND2); + if (ret < 0) + goto err; + + /* Write the desired MMD register address */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_DATA, prtad); ++ MII_MMD_DATA, reg); + if (ret < 0) + goto err; + + /* Select the Function : DATA with no post increment */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_CTRL, devad | MII_MMD_CTRL_NOINCR); ++ MII_MMD_CTRL, MDIO_MMD_VEND2 | MII_MMD_CTRL_NOINCR); + if (ret < 0) + goto err; + +- /* Read the content of the MMD's selected register */ +- value = bus->read(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_DATA); +- +- return value; ++ /* Write the data into MMD's selected register */ ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA, val); + err: +- dev_err(&bus->dev, "failed to read mmd register\n"); ++ if (ret < 0) ++ dev_err(&bus->dev, "failed to write mmd register\n"); + +- return ret; ++ mt7530_mutex_unlock(priv); + } + +-static int +-core_write_mmd_indirect(struct mt7530_priv *priv, int prtad, +- int devad, u32 data) ++static void ++core_rmw(struct mt7530_priv *priv, u32 reg, u32 mask, u32 set) + { + struct mii_bus *bus = priv->bus; ++ u32 val; + int ret; + ++ mt7530_mutex_lock(priv); ++ + /* Write the desired MMD Devad */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_CTRL, devad); ++ MII_MMD_CTRL, MDIO_MMD_VEND2); + if (ret < 0) + goto err; + + /* Write the desired MMD register address */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_DATA, prtad); ++ MII_MMD_DATA, reg); + if (ret < 0) + goto err; + + /* Select the Function : DATA with no post increment */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_CTRL, devad | MII_MMD_CTRL_NOINCR); ++ MII_MMD_CTRL, MDIO_MMD_VEND2 | MII_MMD_CTRL_NOINCR); + if (ret < 0) + goto err; + ++ /* Read the content of the MMD's selected register */ ++ val = bus->read(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA); ++ val &= ~mask; ++ val |= set; + /* Write the data into MMD's selected register */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_DATA, data); ++ MII_MMD_DATA, val); + err: + if (ret < 0) +- dev_err(&bus->dev, +- "failed to write mmd register\n"); +- return ret; +-} +- +-static void +-mt7530_mutex_lock(struct mt7530_priv *priv) +-{ +- if (priv->bus) +- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); +-} +- +-static void +-mt7530_mutex_unlock(struct mt7530_priv *priv) +-{ +- if (priv->bus) +- mutex_unlock(&priv->bus->mdio_lock); +-} +- +-static void +-core_write(struct mt7530_priv *priv, u32 reg, u32 val) +-{ +- mt7530_mutex_lock(priv); +- +- core_write_mmd_indirect(priv, reg, MDIO_MMD_VEND2, val); +- +- mt7530_mutex_unlock(priv); +-} +- +-static void +-core_rmw(struct mt7530_priv *priv, u32 reg, u32 mask, u32 set) +-{ +- u32 val; +- +- mt7530_mutex_lock(priv); +- +- val = core_read_mmd_indirect(priv, reg, MDIO_MMD_VEND2); +- val &= ~mask; +- val |= set; +- core_write_mmd_indirect(priv, reg, MDIO_MMD_VEND2, val); ++ dev_err(&bus->dev, "failed to write mmd register\n"); + + mt7530_mutex_unlock(priv); + } diff --git a/lede/target/linux/generic/backport-6.1/790-54-v6.10-net-dsa-mt7530-disable-EEE-abilities-on-failure-on-M.patch b/lede/target/linux/generic/backport-6.1/790-54-v6.10-net-dsa-mt7530-disable-EEE-abilities-on-failure-on-M.patch new file mode 100644 index 0000000000..44cf60cf14 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-54-v6.10-net-dsa-mt7530-disable-EEE-abilities-on-failure-on-M.patch @@ -0,0 +1,88 @@ +From 856e8954a0a88d1a4d2b43e9002b9249131a156f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:08 +0300 +Subject: [PATCH 01/15] net: dsa: mt7530: disable EEE abilities on failure on + MT7531 and MT7988 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The MT7531_FORCE_EEE1G and MT7531_FORCE_EEE100 bits let the +PMCR_FORCE_EEE1G and PMCR_FORCE_EEE100 bits determine the 1G/100 EEE +abilities of the MAC. If MT7531_FORCE_EEE1G and MT7531_FORCE_EEE100 are +unset, the abilities are left to be determined by PHY auto polling. + +The commit 40b5d2f15c09 ("net: dsa: mt7530: Add support for EEE features") +made it so that the PMCR_FORCE_EEE1G and PMCR_FORCE_EEE100 bits are set on +mt753x_phylink_mac_link_up(). But it did not set the MT7531_FORCE_EEE1G and +MT7531_FORCE_EEE100 bits. Because of this, the EEE abilities will be +determined by PHY auto polling, regardless of the result of phy_init_eee(). + +Define these bits and add them to the MT7531_FORCE_MODE mask which is set +in mt7531_setup_common(). With this, there won't be any EEE abilities set +when phy_init_eee() returns a negative value. + +Thanks to Russell for explaining when phy_init_eee() could return a +negative value below. + +Looking at phy_init_eee(), it could return a negative value when: + +1. phydev->drv is NULL +2. if genphy_c45_eee_is_active() returns negative +3. if genphy_c45_eee_is_active() returns zero, it returns -EPROTONOSUPPORT +4. if phy_set_bits_mmd() fails (e.g. communication error with the PHY) + +If we then look at genphy_c45_eee_is_active(), then: + +genphy_c45_read_eee_adv() and genphy_c45_read_eee_lpa() propagate their +non-zero return values, otherwise this function returns zero or positive +integer. + +If we then look at genphy_c45_read_eee_adv(), then a failure of +phy_read_mmd() would cause a negative value to be returned. + +Looking at genphy_c45_read_eee_lpa(), the same is true. + +So, it can be summarised as: + +- phydev->drv is NULL +- there is a communication error accessing the PHY +- EEE is not active + +otherwise, it returns zero on success. + +If one wishes to determine whether an error occurred vs EEE not being +supported through negotiation for the negotiated speed, if it returns +-EPROTONOSUPPORT in the latter case. Other error codes mean either the +driver has been unloaded or communication error. + +In conclusion, determining the EEE abilities by PHY auto polling shouldn't +result in having any EEE abilities enabled, when one of the last two +situations in the summary happens. And it seems that if phydev->drv is +NULL, there would be bigger problems with the device than a broken link. So +this is not a bugfix. + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -328,11 +328,15 @@ enum mt7530_vlan_port_acc_frm { + #define MT7531_FORCE_DPX BIT(29) + #define MT7531_FORCE_RX_FC BIT(28) + #define MT7531_FORCE_TX_FC BIT(27) ++#define MT7531_FORCE_EEE100 BIT(26) ++#define MT7531_FORCE_EEE1G BIT(25) + #define MT7531_FORCE_MODE (MT7531_FORCE_LNK | \ + MT7531_FORCE_SPD | \ + MT7531_FORCE_DPX | \ + MT7531_FORCE_RX_FC | \ +- MT7531_FORCE_TX_FC) ++ MT7531_FORCE_TX_FC | \ ++ MT7531_FORCE_EEE100 | \ ++ MT7531_FORCE_EEE1G) + #define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \ + PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \ + PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ diff --git a/lede/target/linux/generic/backport-6.1/790-55-v6.10-net-dsa-mt7530-refactor-MT7530_PMCR_P.patch b/lede/target/linux/generic/backport-6.1/790-55-v6.10-net-dsa-mt7530-refactor-MT7530_PMCR_P.patch new file mode 100644 index 0000000000..158e5f8c00 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-55-v6.10-net-dsa-mt7530-refactor-MT7530_PMCR_P.patch @@ -0,0 +1,200 @@ +From 712ad00d2f43814c81a7abfcbc339690a05fb6a0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:09 +0300 +Subject: [PATCH 02/15] net: dsa: mt7530: refactor MT7530_PMCR_P() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The MT7530_PMCR_P() registers are on MT7530, MT7531, and the switch on the +MT7988 SoC. Rename the definition for them to MT753X_PMCR_P(). Bit 15 is +for MT7530 only. Add MT7530 prefix to the definition for bit 15. + +Use GENMASK and FIELD_PREP for PMCR_IFG_XMIT(). + +Rename PMCR_TX_EN and PMCR_RX_EN to PMCR_MAC_TX_EN and PMCR_MAC_TX_EN to +follow the naming on the "MT7621 Giga Switch Programming Guide v0.3", +"MT7531 Reference Manual for Development Board v1.0", and "MT7988A Wi-Fi 7 +Generation Router Platform: Datasheet (Open Version) v0.1" documents. + +These documents show that PMCR_RX_FC_EN is at bit 5. Correct this along +with renaming it to PMCR_FORCE_RX_FC_EN, and the same for PMCR_TX_FC_EN. + +Remove PMCR_SPEED_MASK which doesn't have a use. + +Rename the force mode definitions for MT7531 to FORCE_MODE. Add MASK at the +end for the mask that includes all force mode definitions. + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.c | 24 ++++++++--------- + drivers/net/dsa/mt7530.h | 58 +++++++++++++++++++++------------------- + 2 files changed, 42 insertions(+), 40 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -903,7 +903,7 @@ static void mt7530_setup_port5(struct ds + val &= ~MHWTRAP_P5_MAC_SEL & ~MHWTRAP_P5_DIS; + + /* Setup the MAC by default for the cpu port */ +- mt7530_write(priv, MT7530_PMCR_P(5), 0x56300); ++ mt7530_write(priv, MT753X_PMCR_P(5), 0x56300); + break; + case P5_INTF_SEL_GMAC5: + /* MT7530_P5_MODE_GMAC: P5 -> External phy or 2nd GMAC */ +@@ -2449,8 +2449,8 @@ mt7530_setup(struct dsa_switch *ds) + /* Clear link settings and enable force mode to force link down + * on all ports until they're enabled later. + */ +- mt7530_rmw(priv, MT7530_PMCR_P(i), PMCR_LINK_SETTINGS_MASK | +- PMCR_FORCE_MODE, PMCR_FORCE_MODE); ++ mt7530_rmw(priv, MT753X_PMCR_P(i), PMCR_LINK_SETTINGS_MASK | ++ MT7530_FORCE_MODE, MT7530_FORCE_MODE); + + /* Disable forwarding by default on all ports */ + mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, +@@ -2560,8 +2560,8 @@ mt7531_setup_common(struct dsa_switch *d + /* Clear link settings and enable force mode to force link down + * on all ports until they're enabled later. + */ +- mt7530_rmw(priv, MT7530_PMCR_P(i), PMCR_LINK_SETTINGS_MASK | +- MT7531_FORCE_MODE, MT7531_FORCE_MODE); ++ mt7530_rmw(priv, MT753X_PMCR_P(i), PMCR_LINK_SETTINGS_MASK | ++ MT7531_FORCE_MODE_MASK, MT7531_FORCE_MODE_MASK); + + /* Disable forwarding by default on all ports */ + mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, +@@ -2644,7 +2644,7 @@ mt7531_setup(struct dsa_switch *ds) + + /* Force link down on all ports before internal reset */ + for (i = 0; i < MT7530_NUM_PORTS; i++) +- mt7530_write(priv, MT7530_PMCR_P(i), MT7531_FORCE_LNK); ++ mt7530_write(priv, MT753X_PMCR_P(i), MT7531_FORCE_MODE_LNK); + + /* Reset the switch through internal reset */ + mt7530_write(priv, MT7530_SYS_CTRL, SYS_CTRL_SW_RST | SYS_CTRL_REG_RST); +@@ -2886,7 +2886,7 @@ mt753x_phylink_mac_config(struct phylink + + /* Are we connected to external phy */ + if (port == 5 && dsa_is_user_port(ds, 5)) +- mt7530_set(priv, MT7530_PMCR_P(port), PMCR_EXT_PHY); ++ mt7530_set(priv, MT753X_PMCR_P(port), PMCR_EXT_PHY); + } + + static void mt753x_phylink_mac_link_down(struct phylink_config *config, +@@ -2896,7 +2896,7 @@ static void mt753x_phylink_mac_link_down + struct dsa_port *dp = dsa_phylink_to_port(config); + struct mt7530_priv *priv = dp->ds->priv; + +- mt7530_clear(priv, MT7530_PMCR_P(dp->index), PMCR_LINK_SETTINGS_MASK); ++ mt7530_clear(priv, MT753X_PMCR_P(dp->index), PMCR_LINK_SETTINGS_MASK); + } + + static void mt753x_phylink_mac_link_up(struct phylink_config *config, +@@ -2910,7 +2910,7 @@ static void mt753x_phylink_mac_link_up(s + struct mt7530_priv *priv = dp->ds->priv; + u32 mcr; + +- mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK; ++ mcr = PMCR_MAC_RX_EN | PMCR_MAC_TX_EN | PMCR_FORCE_LNK; + + switch (speed) { + case SPEED_1000: +@@ -2925,9 +2925,9 @@ static void mt753x_phylink_mac_link_up(s + if (duplex == DUPLEX_FULL) { + mcr |= PMCR_FORCE_FDX; + if (tx_pause) +- mcr |= PMCR_TX_FC_EN; ++ mcr |= PMCR_FORCE_TX_FC_EN; + if (rx_pause) +- mcr |= PMCR_RX_FC_EN; ++ mcr |= PMCR_FORCE_RX_FC_EN; + } + + if (mode == MLO_AN_PHY && phydev && phy_init_eee(phydev, false) >= 0) { +@@ -2942,7 +2942,7 @@ static void mt753x_phylink_mac_link_up(s + } + } + +- mt7530_set(priv, MT7530_PMCR_P(dp->index), mcr); ++ mt7530_set(priv, MT753X_PMCR_P(dp->index), mcr); + } + + static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port, +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -304,44 +304,46 @@ enum mt7530_vlan_port_acc_frm { + #define G0_PORT_VID_DEF G0_PORT_VID(0) + + /* Register for port MAC control register */ +-#define MT7530_PMCR_P(x) (0x3000 + ((x) * 0x100)) +-#define PMCR_IFG_XMIT(x) (((x) & 0x3) << 18) ++#define MT753X_PMCR_P(x) (0x3000 + ((x) * 0x100)) ++#define PMCR_IFG_XMIT_MASK GENMASK(19, 18) ++#define PMCR_IFG_XMIT(x) FIELD_PREP(PMCR_IFG_XMIT_MASK, x) + #define PMCR_EXT_PHY BIT(17) + #define PMCR_MAC_MODE BIT(16) +-#define PMCR_FORCE_MODE BIT(15) +-#define PMCR_TX_EN BIT(14) +-#define PMCR_RX_EN BIT(13) ++#define MT7530_FORCE_MODE BIT(15) ++#define PMCR_MAC_TX_EN BIT(14) ++#define PMCR_MAC_RX_EN BIT(13) + #define PMCR_BACKOFF_EN BIT(9) + #define PMCR_BACKPR_EN BIT(8) + #define PMCR_FORCE_EEE1G BIT(7) + #define PMCR_FORCE_EEE100 BIT(6) +-#define PMCR_TX_FC_EN BIT(5) +-#define PMCR_RX_FC_EN BIT(4) ++#define PMCR_FORCE_RX_FC_EN BIT(5) ++#define PMCR_FORCE_TX_FC_EN BIT(4) + #define PMCR_FORCE_SPEED_1000 BIT(3) + #define PMCR_FORCE_SPEED_100 BIT(2) + #define PMCR_FORCE_FDX BIT(1) + #define PMCR_FORCE_LNK BIT(0) +-#define PMCR_SPEED_MASK (PMCR_FORCE_SPEED_100 | \ +- PMCR_FORCE_SPEED_1000) +-#define MT7531_FORCE_LNK BIT(31) +-#define MT7531_FORCE_SPD BIT(30) +-#define MT7531_FORCE_DPX BIT(29) +-#define MT7531_FORCE_RX_FC BIT(28) +-#define MT7531_FORCE_TX_FC BIT(27) +-#define MT7531_FORCE_EEE100 BIT(26) +-#define MT7531_FORCE_EEE1G BIT(25) +-#define MT7531_FORCE_MODE (MT7531_FORCE_LNK | \ +- MT7531_FORCE_SPD | \ +- MT7531_FORCE_DPX | \ +- MT7531_FORCE_RX_FC | \ +- MT7531_FORCE_TX_FC | \ +- MT7531_FORCE_EEE100 | \ +- MT7531_FORCE_EEE1G) +-#define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \ +- PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \ +- PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ +- PMCR_FORCE_FDX | PMCR_FORCE_LNK | \ +- PMCR_FORCE_EEE1G | PMCR_FORCE_EEE100) ++#define MT7531_FORCE_MODE_LNK BIT(31) ++#define MT7531_FORCE_MODE_SPD BIT(30) ++#define MT7531_FORCE_MODE_DPX BIT(29) ++#define MT7531_FORCE_MODE_RX_FC BIT(28) ++#define MT7531_FORCE_MODE_TX_FC BIT(27) ++#define MT7531_FORCE_MODE_EEE100 BIT(26) ++#define MT7531_FORCE_MODE_EEE1G BIT(25) ++#define MT7531_FORCE_MODE_MASK (MT7531_FORCE_MODE_LNK | \ ++ MT7531_FORCE_MODE_SPD | \ ++ MT7531_FORCE_MODE_DPX | \ ++ MT7531_FORCE_MODE_RX_FC | \ ++ MT7531_FORCE_MODE_TX_FC | \ ++ MT7531_FORCE_MODE_EEE100 | \ ++ MT7531_FORCE_MODE_EEE1G) ++#define PMCR_LINK_SETTINGS_MASK (PMCR_MAC_TX_EN | PMCR_MAC_RX_EN | \ ++ PMCR_FORCE_EEE1G | \ ++ PMCR_FORCE_EEE100 | \ ++ PMCR_FORCE_RX_FC_EN | \ ++ PMCR_FORCE_TX_FC_EN | \ ++ PMCR_FORCE_SPEED_1000 | \ ++ PMCR_FORCE_SPEED_100 | \ ++ PMCR_FORCE_FDX | PMCR_FORCE_LNK) + + #define MT7530_PMEEECR_P(x) (0x3004 + (x) * 0x100) + #define WAKEUP_TIME_1000(x) (((x) & 0xFF) << 24) diff --git a/lede/target/linux/generic/backport-6.1/790-56-v6.10-net-dsa-mt7530-rename-p5_intf_sel-and-use-only-for-M.patch b/lede/target/linux/generic/backport-6.1/790-56-v6.10-net-dsa-mt7530-rename-p5_intf_sel-and-use-only-for-M.patch new file mode 100644 index 0000000000..9a0ce7c36c --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-56-v6.10-net-dsa-mt7530-rename-p5_intf_sel-and-use-only-for-M.patch @@ -0,0 +1,185 @@ +From 875ec5b67ab88e969b171e6e9ea803e3ed759614 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:10 +0300 +Subject: [PATCH 03/15] net: dsa: mt7530: rename p5_intf_sel and use only for + MT7530 switch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The p5_intf_sel pointer is used to store the information of whether PHY +muxing is used or not. PHY muxing is a feature specific to port 5 of the +MT7530 switch. Do not use it for other switch models. + +Rename the pointer to p5_mode to store the mode the port is being used in. +Rename the p5_interface_select enum to mt7530_p5_mode, the string +representation to mt7530_p5_mode_str, and the enum elements. + +If PHY muxing is not detected, the default mode, GMAC5, will be used. + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.c | 62 +++++++++++++++++----------------------- + drivers/net/dsa/mt7530.h | 15 +++++----- + 2 files changed, 33 insertions(+), 44 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -864,19 +864,15 @@ mt7530_set_ageing_time(struct dsa_switch + return 0; + } + +-static const char *p5_intf_modes(unsigned int p5_interface) ++static const char *mt7530_p5_mode_str(unsigned int mode) + { +- switch (p5_interface) { +- case P5_DISABLED: +- return "DISABLED"; +- case P5_INTF_SEL_PHY_P0: +- return "PHY P0"; +- case P5_INTF_SEL_PHY_P4: +- return "PHY P4"; +- case P5_INTF_SEL_GMAC5: +- return "GMAC5"; ++ switch (mode) { ++ case MUX_PHY_P0: ++ return "MUX PHY P0"; ++ case MUX_PHY_P4: ++ return "MUX PHY P4"; + default: +- return "unknown"; ++ return "GMAC5"; + } + } + +@@ -893,23 +889,23 @@ static void mt7530_setup_port5(struct ds + val |= MHWTRAP_MANUAL | MHWTRAP_P5_MAC_SEL | MHWTRAP_P5_DIS; + val &= ~MHWTRAP_P5_RGMII_MODE & ~MHWTRAP_PHY0_SEL; + +- switch (priv->p5_intf_sel) { +- case P5_INTF_SEL_PHY_P0: +- /* MT7530_P5_MODE_GPHY_P0: 2nd GMAC -> P5 -> P0 */ ++ switch (priv->p5_mode) { ++ /* MUX_PHY_P0: P0 -> P5 -> SoC MAC */ ++ case MUX_PHY_P0: + val |= MHWTRAP_PHY0_SEL; + fallthrough; +- case P5_INTF_SEL_PHY_P4: +- /* MT7530_P5_MODE_GPHY_P4: 2nd GMAC -> P5 -> P4 */ ++ ++ /* MUX_PHY_P4: P4 -> P5 -> SoC MAC */ ++ case MUX_PHY_P4: + val &= ~MHWTRAP_P5_MAC_SEL & ~MHWTRAP_P5_DIS; + + /* Setup the MAC by default for the cpu port */ + mt7530_write(priv, MT753X_PMCR_P(5), 0x56300); + break; +- case P5_INTF_SEL_GMAC5: +- /* MT7530_P5_MODE_GMAC: P5 -> External phy or 2nd GMAC */ +- val &= ~MHWTRAP_P5_DIS; +- break; ++ ++ /* GMAC5: P5 -> SoC MAC or external PHY */ + default: ++ val &= ~MHWTRAP_P5_DIS; + break; + } + +@@ -937,8 +933,8 @@ static void mt7530_setup_port5(struct ds + + mt7530_write(priv, MT7530_MHWTRAP, val); + +- dev_dbg(ds->dev, "Setup P5, HWTRAP=0x%x, intf_sel=%s, phy-mode=%s\n", +- val, p5_intf_modes(priv->p5_intf_sel), phy_modes(interface)); ++ dev_dbg(ds->dev, "Setup P5, HWTRAP=0x%x, mode=%s, phy-mode=%s\n", val, ++ mt7530_p5_mode_str(priv->p5_mode), phy_modes(interface)); + + mutex_unlock(&priv->reg_mutex); + } +@@ -2481,13 +2477,11 @@ mt7530_setup(struct dsa_switch *ds) + if (ret) + return ret; + +- /* Setup port 5 */ +- if (!dsa_is_unused_port(ds, 5)) { +- priv->p5_intf_sel = P5_INTF_SEL_GMAC5; +- } else { ++ /* Check for PHY muxing on port 5 */ ++ if (dsa_is_unused_port(ds, 5)) { + /* Scan the ethernet nodes. Look for GMAC1, lookup the used PHY. +- * Set priv->p5_intf_sel to the appropriate value if PHY muxing +- * is detected. ++ * Set priv->p5_mode to the appropriate value if PHY muxing is ++ * detected. + */ + for_each_child_of_node(dn, mac_np) { + if (!of_device_is_compatible(mac_np, +@@ -2511,17 +2505,16 @@ mt7530_setup(struct dsa_switch *ds) + } + id = of_mdio_parse_addr(ds->dev, phy_node); + if (id == 0) +- priv->p5_intf_sel = P5_INTF_SEL_PHY_P0; ++ priv->p5_mode = MUX_PHY_P0; + if (id == 4) +- priv->p5_intf_sel = P5_INTF_SEL_PHY_P4; ++ priv->p5_mode = MUX_PHY_P4; + } + of_node_put(mac_np); + of_node_put(phy_node); + break; + } + +- if (priv->p5_intf_sel == P5_INTF_SEL_PHY_P0 || +- priv->p5_intf_sel == P5_INTF_SEL_PHY_P4) ++ if (priv->p5_mode == MUX_PHY_P0 || priv->p5_mode == MUX_PHY_P4) + mt7530_setup_port5(ds, interface); + } + +@@ -2659,9 +2652,6 @@ mt7531_setup(struct dsa_switch *ds) + MT7531_EXT_P_MDIO_12); + } + +- if (!dsa_is_unused_port(ds, 5)) +- priv->p5_intf_sel = P5_INTF_SEL_GMAC5; +- + mt7530_rmw(priv, MT7531_GPIO_MODE0, MT7531_GPIO0_MASK, + MT7531_GPIO0_INTERRUPT); + +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -708,12 +708,11 @@ struct mt7530_port { + struct phylink_pcs *sgmii_pcs; + }; + +-/* Port 5 interface select definitions */ +-enum p5_interface_select { +- P5_DISABLED, +- P5_INTF_SEL_PHY_P0, +- P5_INTF_SEL_PHY_P4, +- P5_INTF_SEL_GMAC5, ++/* Port 5 mode definitions of the MT7530 switch */ ++enum mt7530_p5_mode { ++ GMAC5, ++ MUX_PHY_P0, ++ MUX_PHY_P4, + }; + + struct mt7530_priv; +@@ -769,7 +768,7 @@ struct mt753x_info { + * @ports: Holding the state among ports + * @reg_mutex: The lock for protecting among process accessing + * registers +- * @p5_intf_sel: Holding the current port 5 interface select ++ * @p5_mode: Holding the current mode of port 5 of the MT7530 switch + * @p5_sgmii: Flag for distinguishing if port 5 of the MT7531 switch + * has got SGMII + * @irq: IRQ number of the switch +@@ -791,7 +790,7 @@ struct mt7530_priv { + const struct mt753x_info *info; + unsigned int id; + bool mcm; +- enum p5_interface_select p5_intf_sel; ++ enum mt7530_p5_mode p5_mode; + bool p5_sgmii; + u8 mirror_rx; + u8 mirror_tx; diff --git a/lede/target/linux/generic/backport-6.1/790-57-v6.10-net-dsa-mt7530-rename-mt753x_bpdu_port_fw-enum-to-mt.patch b/lede/target/linux/generic/backport-6.1/790-57-v6.10-net-dsa-mt7530-rename-mt753x_bpdu_port_fw-enum-to-mt.patch new file mode 100644 index 0000000000..c8ffd5f07c --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-57-v6.10-net-dsa-mt7530-rename-mt753x_bpdu_port_fw-enum-to-mt.patch @@ -0,0 +1,169 @@ +From 83fe3df057e641cd0e88425e579d7a5a370ca430 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:11 +0300 +Subject: [PATCH 04/15] net: dsa: mt7530: rename mt753x_bpdu_port_fw enum to + mt753x_to_cpu_fw +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The mt753x_bpdu_port_fw enum is globally used for manipulating the process +of deciding the forwardable ports, specifically concerning the CPU port(s). +Therefore, rename it and the values in it to mt753x_to_cpu_fw. + +Change FOLLOW_MFC to SYSTEM_DEFAULT to be on par with the switch documents. + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.c | 44 ++++++++++------------- + drivers/net/dsa/mt7530.h | 76 ++++++++++++++++++++-------------------- + 2 files changed, 56 insertions(+), 64 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1114,42 +1114,34 @@ mt753x_trap_frames(struct mt7530_priv *p + * VLAN-untagged. + */ + mt7530_rmw(priv, MT753X_BPC, +- MT753X_PAE_BPDU_FR | MT753X_PAE_EG_TAG_MASK | +- MT753X_PAE_PORT_FW_MASK | MT753X_BPDU_EG_TAG_MASK | +- MT753X_BPDU_PORT_FW_MASK, +- MT753X_PAE_BPDU_FR | +- MT753X_PAE_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | +- MT753X_PAE_PORT_FW(MT753X_BPDU_CPU_ONLY) | +- MT753X_BPDU_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | +- MT753X_BPDU_CPU_ONLY); ++ PAE_BPDU_FR | PAE_EG_TAG_MASK | PAE_PORT_FW_MASK | ++ BPDU_EG_TAG_MASK | BPDU_PORT_FW_MASK, ++ PAE_BPDU_FR | PAE_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | ++ PAE_PORT_FW(TO_CPU_FW_CPU_ONLY) | ++ BPDU_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | ++ TO_CPU_FW_CPU_ONLY); + + /* Trap frames with :01 and :02 MAC DAs to the CPU port(s) and egress + * them VLAN-untagged. + */ + mt7530_rmw(priv, MT753X_RGAC1, +- MT753X_R02_BPDU_FR | MT753X_R02_EG_TAG_MASK | +- MT753X_R02_PORT_FW_MASK | MT753X_R01_BPDU_FR | +- MT753X_R01_EG_TAG_MASK | MT753X_R01_PORT_FW_MASK, +- MT753X_R02_BPDU_FR | +- MT753X_R02_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | +- MT753X_R02_PORT_FW(MT753X_BPDU_CPU_ONLY) | +- MT753X_R01_BPDU_FR | +- MT753X_R01_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | +- MT753X_BPDU_CPU_ONLY); ++ R02_BPDU_FR | R02_EG_TAG_MASK | R02_PORT_FW_MASK | ++ R01_BPDU_FR | R01_EG_TAG_MASK | R01_PORT_FW_MASK, ++ R02_BPDU_FR | R02_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | ++ R02_PORT_FW(TO_CPU_FW_CPU_ONLY) | R01_BPDU_FR | ++ R01_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | ++ TO_CPU_FW_CPU_ONLY); + + /* Trap frames with :03 and :0E MAC DAs to the CPU port(s) and egress + * them VLAN-untagged. + */ + mt7530_rmw(priv, MT753X_RGAC2, +- MT753X_R0E_BPDU_FR | MT753X_R0E_EG_TAG_MASK | +- MT753X_R0E_PORT_FW_MASK | MT753X_R03_BPDU_FR | +- MT753X_R03_EG_TAG_MASK | MT753X_R03_PORT_FW_MASK, +- MT753X_R0E_BPDU_FR | +- MT753X_R0E_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | +- MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY) | +- MT753X_R03_BPDU_FR | +- MT753X_R03_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | +- MT753X_BPDU_CPU_ONLY); ++ R0E_BPDU_FR | R0E_EG_TAG_MASK | R0E_PORT_FW_MASK | ++ R03_BPDU_FR | R03_EG_TAG_MASK | R03_PORT_FW_MASK, ++ R0E_BPDU_FR | R0E_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | ++ R0E_PORT_FW(TO_CPU_FW_CPU_ONLY) | R03_BPDU_FR | ++ R03_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | ++ TO_CPU_FW_CPU_ONLY); + } + + static void +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -67,47 +67,47 @@ enum mt753x_id { + #define MT753X_MIRROR_MASK(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ + MT7531_MIRROR_MASK : MIRROR_MASK) + +-/* Registers for BPDU and PAE frame control*/ ++/* Register for BPDU and PAE frame control */ + #define MT753X_BPC 0x24 +-#define MT753X_PAE_BPDU_FR BIT(25) +-#define MT753X_PAE_EG_TAG_MASK GENMASK(24, 22) +-#define MT753X_PAE_EG_TAG(x) FIELD_PREP(MT753X_PAE_EG_TAG_MASK, x) +-#define MT753X_PAE_PORT_FW_MASK GENMASK(18, 16) +-#define MT753X_PAE_PORT_FW(x) FIELD_PREP(MT753X_PAE_PORT_FW_MASK, x) +-#define MT753X_BPDU_EG_TAG_MASK GENMASK(8, 6) +-#define MT753X_BPDU_EG_TAG(x) FIELD_PREP(MT753X_BPDU_EG_TAG_MASK, x) +-#define MT753X_BPDU_PORT_FW_MASK GENMASK(2, 0) ++#define PAE_BPDU_FR BIT(25) ++#define PAE_EG_TAG_MASK GENMASK(24, 22) ++#define PAE_EG_TAG(x) FIELD_PREP(PAE_EG_TAG_MASK, x) ++#define PAE_PORT_FW_MASK GENMASK(18, 16) ++#define PAE_PORT_FW(x) FIELD_PREP(PAE_PORT_FW_MASK, x) ++#define BPDU_EG_TAG_MASK GENMASK(8, 6) ++#define BPDU_EG_TAG(x) FIELD_PREP(BPDU_EG_TAG_MASK, x) ++#define BPDU_PORT_FW_MASK GENMASK(2, 0) + +-/* Register for :01 and :02 MAC DA frame control */ ++/* Register for 01-80-C2-00-00-[01,02] MAC DA frame control */ + #define MT753X_RGAC1 0x28 +-#define MT753X_R02_BPDU_FR BIT(25) +-#define MT753X_R02_EG_TAG_MASK GENMASK(24, 22) +-#define MT753X_R02_EG_TAG(x) FIELD_PREP(MT753X_R02_EG_TAG_MASK, x) +-#define MT753X_R02_PORT_FW_MASK GENMASK(18, 16) +-#define MT753X_R02_PORT_FW(x) FIELD_PREP(MT753X_R02_PORT_FW_MASK, x) +-#define MT753X_R01_BPDU_FR BIT(9) +-#define MT753X_R01_EG_TAG_MASK GENMASK(8, 6) +-#define MT753X_R01_EG_TAG(x) FIELD_PREP(MT753X_R01_EG_TAG_MASK, x) +-#define MT753X_R01_PORT_FW_MASK GENMASK(2, 0) ++#define R02_BPDU_FR BIT(25) ++#define R02_EG_TAG_MASK GENMASK(24, 22) ++#define R02_EG_TAG(x) FIELD_PREP(R02_EG_TAG_MASK, x) ++#define R02_PORT_FW_MASK GENMASK(18, 16) ++#define R02_PORT_FW(x) FIELD_PREP(R02_PORT_FW_MASK, x) ++#define R01_BPDU_FR BIT(9) ++#define R01_EG_TAG_MASK GENMASK(8, 6) ++#define R01_EG_TAG(x) FIELD_PREP(R01_EG_TAG_MASK, x) ++#define R01_PORT_FW_MASK GENMASK(2, 0) + +-/* Register for :03 and :0E MAC DA frame control */ ++/* Register for 01-80-C2-00-00-[03,0E] MAC DA frame control */ + #define MT753X_RGAC2 0x2c +-#define MT753X_R0E_BPDU_FR BIT(25) +-#define MT753X_R0E_EG_TAG_MASK GENMASK(24, 22) +-#define MT753X_R0E_EG_TAG(x) FIELD_PREP(MT753X_R0E_EG_TAG_MASK, x) +-#define MT753X_R0E_PORT_FW_MASK GENMASK(18, 16) +-#define MT753X_R0E_PORT_FW(x) FIELD_PREP(MT753X_R0E_PORT_FW_MASK, x) +-#define MT753X_R03_BPDU_FR BIT(9) +-#define MT753X_R03_EG_TAG_MASK GENMASK(8, 6) +-#define MT753X_R03_EG_TAG(x) FIELD_PREP(MT753X_R03_EG_TAG_MASK, x) +-#define MT753X_R03_PORT_FW_MASK GENMASK(2, 0) ++#define R0E_BPDU_FR BIT(25) ++#define R0E_EG_TAG_MASK GENMASK(24, 22) ++#define R0E_EG_TAG(x) FIELD_PREP(R0E_EG_TAG_MASK, x) ++#define R0E_PORT_FW_MASK GENMASK(18, 16) ++#define R0E_PORT_FW(x) FIELD_PREP(R0E_PORT_FW_MASK, x) ++#define R03_BPDU_FR BIT(9) ++#define R03_EG_TAG_MASK GENMASK(8, 6) ++#define R03_EG_TAG(x) FIELD_PREP(R03_EG_TAG_MASK, x) ++#define R03_PORT_FW_MASK GENMASK(2, 0) + +-enum mt753x_bpdu_port_fw { +- MT753X_BPDU_FOLLOW_MFC, +- MT753X_BPDU_CPU_EXCLUDE = 4, +- MT753X_BPDU_CPU_INCLUDE = 5, +- MT753X_BPDU_CPU_ONLY = 6, +- MT753X_BPDU_DROP = 7, ++enum mt753x_to_cpu_fw { ++ TO_CPU_FW_SYSTEM_DEFAULT, ++ TO_CPU_FW_CPU_EXCLUDE = 4, ++ TO_CPU_FW_CPU_INCLUDE = 5, ++ TO_CPU_FW_CPU_ONLY = 6, ++ TO_CPU_FW_DROP = 7, + }; + + /* Registers for address table access */ diff --git a/lede/target/linux/generic/backport-6.1/790-58-v6.10-net-dsa-mt7530-refactor-MT7530_MFC-and-MT7531_CFC-ad.patch b/lede/target/linux/generic/backport-6.1/790-58-v6.10-net-dsa-mt7530-refactor-MT7530_MFC-and-MT7531_CFC-ad.patch new file mode 100644 index 0000000000..c977fe46cd --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-58-v6.10-net-dsa-mt7530-refactor-MT7530_MFC-and-MT7531_CFC-ad.patch @@ -0,0 +1,201 @@ +From 1dbc1bdc2869e6d2929235c70d64e393aa5a5fa2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:12 +0300 +Subject: [PATCH 05/15] net: dsa: mt7530: refactor MT7530_MFC and MT7531_CFC, + add MT7531_QRY_FFP +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The MT7530_MFC register is on MT7530, MT7531, and the switch on the MT7988 +SoC. Rename it to MT753X_MFC. Bit 7 to 0 differs between MT7530 and +MT7531/MT7988. Add MT7530 prefix to these definitions, and define the +IGMP/MLD Query Frame Flooding Ports mask for MT7531. + +Rename the cases of MIRROR_MASK to MIRROR_PORT_MASK. + +Move mt753x_mirror_port_get() and mt753x_port_mirror_set() to mt7530.h as +macros. + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.c | 38 ++++++++-------------- + drivers/net/dsa/mt7530.h | 69 +++++++++++++++++++++++++--------------- + 2 files changed, 57 insertions(+), 50 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1154,7 +1154,7 @@ mt753x_cpu_port_enable(struct dsa_switch + PORT_SPEC_TAG); + + /* Enable flooding on the CPU port */ +- mt7530_set(priv, MT7530_MFC, BC_FFP(BIT(port)) | UNM_FFP(BIT(port)) | ++ mt7530_set(priv, MT753X_MFC, BC_FFP(BIT(port)) | UNM_FFP(BIT(port)) | + UNU_FFP(BIT(port))); + + /* Add the CPU port to the CPU port bitmap for MT7531. Trapped frames +@@ -1318,15 +1318,15 @@ mt7530_port_bridge_flags(struct dsa_swit + flags.val & BR_LEARNING ? 0 : SA_DIS); + + if (flags.mask & BR_FLOOD) +- mt7530_rmw(priv, MT7530_MFC, UNU_FFP(BIT(port)), ++ mt7530_rmw(priv, MT753X_MFC, UNU_FFP(BIT(port)), + flags.val & BR_FLOOD ? UNU_FFP(BIT(port)) : 0); + + if (flags.mask & BR_MCAST_FLOOD) +- mt7530_rmw(priv, MT7530_MFC, UNM_FFP(BIT(port)), ++ mt7530_rmw(priv, MT753X_MFC, UNM_FFP(BIT(port)), + flags.val & BR_MCAST_FLOOD ? UNM_FFP(BIT(port)) : 0); + + if (flags.mask & BR_BCAST_FLOOD) +- mt7530_rmw(priv, MT7530_MFC, BC_FFP(BIT(port)), ++ mt7530_rmw(priv, MT753X_MFC, BC_FFP(BIT(port)), + flags.val & BR_BCAST_FLOOD ? BC_FFP(BIT(port)) : 0); + + return 0; +@@ -1862,20 +1862,6 @@ mt7530_port_vlan_del(struct dsa_switch * + return 0; + } + +-static int mt753x_mirror_port_get(unsigned int id, u32 val) +-{ +- return (id == ID_MT7531 || id == ID_MT7988) ? +- MT7531_MIRROR_PORT_GET(val) : +- MIRROR_PORT(val); +-} +- +-static int mt753x_mirror_port_set(unsigned int id, u32 val) +-{ +- return (id == ID_MT7531 || id == ID_MT7988) ? +- MT7531_MIRROR_PORT_SET(val) : +- MIRROR_PORT(val); +-} +- + static int mt753x_port_mirror_add(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress, struct netlink_ext_ack *extack) +@@ -1891,14 +1877,14 @@ static int mt753x_port_mirror_add(struct + val = mt7530_read(priv, MT753X_MIRROR_REG(priv->id)); + + /* MT7530 only supports one monitor port */ +- monitor_port = mt753x_mirror_port_get(priv->id, val); ++ monitor_port = MT753X_MIRROR_PORT_GET(priv->id, val); + if (val & MT753X_MIRROR_EN(priv->id) && + monitor_port != mirror->to_local_port) + return -EEXIST; + + val |= MT753X_MIRROR_EN(priv->id); +- val &= ~MT753X_MIRROR_MASK(priv->id); +- val |= mt753x_mirror_port_set(priv->id, mirror->to_local_port); ++ val &= ~MT753X_MIRROR_PORT_MASK(priv->id); ++ val |= MT753X_MIRROR_PORT_SET(priv->id, mirror->to_local_port); + mt7530_write(priv, MT753X_MIRROR_REG(priv->id), val); + + val = mt7530_read(priv, MT7530_PCR_P(port)); +@@ -2538,7 +2524,7 @@ mt7531_setup_common(struct dsa_switch *d + mt7530_mib_reset(ds); + + /* Disable flooding on all ports */ +- mt7530_clear(priv, MT7530_MFC, BC_FFP_MASK | UNM_FFP_MASK | ++ mt7530_clear(priv, MT753X_MFC, BC_FFP_MASK | UNM_FFP_MASK | + UNU_FFP_MASK); + + for (i = 0; i < MT7530_NUM_PORTS; i++) { +@@ -3100,10 +3086,12 @@ mt753x_conduit_state_change(struct dsa_s + else + priv->active_cpu_ports &= ~mask; + +- if (priv->active_cpu_ports) +- val = CPU_EN | CPU_PORT(__ffs(priv->active_cpu_ports)); ++ if (priv->active_cpu_ports) { ++ val = MT7530_CPU_EN | ++ MT7530_CPU_PORT(__ffs(priv->active_cpu_ports)); ++ } + +- mt7530_rmw(priv, MT7530_MFC, CPU_EN | CPU_PORT_MASK, val); ++ mt7530_rmw(priv, MT753X_MFC, MT7530_CPU_EN | MT7530_CPU_PORT_MASK, val); + } + + static int mt7988_setup(struct dsa_switch *ds) +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -36,36 +36,55 @@ enum mt753x_id { + #define MT753X_AGC 0xc + #define LOCAL_EN BIT(7) + +-/* Registers to mac forward control for unknown frames */ +-#define MT7530_MFC 0x10 +-#define BC_FFP(x) (((x) & 0xff) << 24) +-#define BC_FFP_MASK BC_FFP(~0) +-#define UNM_FFP(x) (((x) & 0xff) << 16) +-#define UNM_FFP_MASK UNM_FFP(~0) +-#define UNU_FFP(x) (((x) & 0xff) << 8) +-#define UNU_FFP_MASK UNU_FFP(~0) +-#define CPU_EN BIT(7) +-#define CPU_PORT_MASK GENMASK(6, 4) +-#define CPU_PORT(x) FIELD_PREP(CPU_PORT_MASK, x) +-#define MIRROR_EN BIT(3) +-#define MIRROR_PORT(x) ((x) & 0x7) +-#define MIRROR_MASK 0x7 ++/* Register for MAC forward control */ ++#define MT753X_MFC 0x10 ++#define BC_FFP_MASK GENMASK(31, 24) ++#define BC_FFP(x) FIELD_PREP(BC_FFP_MASK, x) ++#define UNM_FFP_MASK GENMASK(23, 16) ++#define UNM_FFP(x) FIELD_PREP(UNM_FFP_MASK, x) ++#define UNU_FFP_MASK GENMASK(15, 8) ++#define UNU_FFP(x) FIELD_PREP(UNU_FFP_MASK, x) ++#define MT7530_CPU_EN BIT(7) ++#define MT7530_CPU_PORT_MASK GENMASK(6, 4) ++#define MT7530_CPU_PORT(x) FIELD_PREP(MT7530_CPU_PORT_MASK, x) ++#define MT7530_MIRROR_EN BIT(3) ++#define MT7530_MIRROR_PORT_MASK GENMASK(2, 0) ++#define MT7530_MIRROR_PORT_GET(x) FIELD_GET(MT7530_MIRROR_PORT_MASK, x) ++#define MT7530_MIRROR_PORT_SET(x) FIELD_PREP(MT7530_MIRROR_PORT_MASK, x) ++#define MT7531_QRY_FFP_MASK GENMASK(7, 0) ++#define MT7531_QRY_FFP(x) FIELD_PREP(MT7531_QRY_FFP_MASK, x) + +-/* Registers for CPU forward control */ ++/* Register for CPU forward control */ + #define MT7531_CFC 0x4 + #define MT7531_MIRROR_EN BIT(19) +-#define MT7531_MIRROR_MASK (MIRROR_MASK << 16) +-#define MT7531_MIRROR_PORT_GET(x) (((x) >> 16) & MIRROR_MASK) +-#define MT7531_MIRROR_PORT_SET(x) (((x) & MIRROR_MASK) << 16) ++#define MT7531_MIRROR_PORT_MASK GENMASK(18, 16) ++#define MT7531_MIRROR_PORT_GET(x) FIELD_GET(MT7531_MIRROR_PORT_MASK, x) ++#define MT7531_MIRROR_PORT_SET(x) FIELD_PREP(MT7531_MIRROR_PORT_MASK, x) + #define MT7531_CPU_PMAP_MASK GENMASK(7, 0) + #define MT7531_CPU_PMAP(x) FIELD_PREP(MT7531_CPU_PMAP_MASK, x) + +-#define MT753X_MIRROR_REG(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ +- MT7531_CFC : MT7530_MFC) +-#define MT753X_MIRROR_EN(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ +- MT7531_MIRROR_EN : MIRROR_EN) +-#define MT753X_MIRROR_MASK(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ +- MT7531_MIRROR_MASK : MIRROR_MASK) ++#define MT753X_MIRROR_REG(id) ((id == ID_MT7531 || \ ++ id == ID_MT7988) ? \ ++ MT7531_CFC : MT753X_MFC) ++ ++#define MT753X_MIRROR_EN(id) ((id == ID_MT7531 || \ ++ id == ID_MT7988) ? \ ++ MT7531_MIRROR_EN : MT7530_MIRROR_EN) ++ ++#define MT753X_MIRROR_PORT_MASK(id) ((id == ID_MT7531 || \ ++ id == ID_MT7988) ? \ ++ MT7531_MIRROR_PORT_MASK : \ ++ MT7530_MIRROR_PORT_MASK) ++ ++#define MT753X_MIRROR_PORT_GET(id, val) ((id == ID_MT7531 || \ ++ id == ID_MT7988) ? \ ++ MT7531_MIRROR_PORT_GET(val) : \ ++ MT7530_MIRROR_PORT_GET(val)) ++ ++#define MT753X_MIRROR_PORT_SET(id, val) ((id == ID_MT7531 || \ ++ id == ID_MT7988) ? \ ++ MT7531_MIRROR_PORT_SET(val) : \ ++ MT7530_MIRROR_PORT_SET(val)) + + /* Register for BPDU and PAE frame control */ + #define MT753X_BPC 0x24 diff --git a/lede/target/linux/generic/backport-6.1/790-59-v6.10-net-dsa-mt7530-refactor-MT7530_HWTRAP-and-MT7530_MHW.patch b/lede/target/linux/generic/backport-6.1/790-59-v6.10-net-dsa-mt7530-refactor-MT7530_HWTRAP-and-MT7530_MHW.patch new file mode 100644 index 0000000000..3c487d21f6 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-59-v6.10-net-dsa-mt7530-refactor-MT7530_HWTRAP-and-MT7530_MHW.patch @@ -0,0 +1,257 @@ +From 3ccf67597d35c06a7319e407b1c42f78a7966779 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:13 +0300 +Subject: [PATCH 06/15] net: dsa: mt7530: refactor MT7530_HWTRAP and + MT7530_MHWTRAP +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The MT7530_HWTRAP and MT7530_MHWTRAP registers are on MT7530 and MT7531. +It's called hardware trap on MT7530, software trap on MT7531. That's +because some bits of the trap on MT7530 cannot be modified by software +whilst all bits of the trap on MT7531 can. Rename the definitions for them +to MT753X_TRAP and MT753X_MTRAP. Add MT7530 and MT7531 prefixes to the +definitions specific to the switch model. + +Remove the extra parentheses from MT7530_XTAL_40MHZ and MT7530_XTAL_20MHZ. + +Rename MHWTRAP_PHY0_SEL, MHWTRAP_MANUAL, and MHWTRAP_PHY_ACCESS to be on +par with the "MT7621 Giga Switch Programming Guide v0.3" document. + +Make an enumaration for the XTAL frequency. Set the data type of the xtal +variable on mt7531_pll_setup() to it. + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.c | 59 ++++++++++++++++++++-------------------- + drivers/net/dsa/mt7530.h | 50 ++++++++++++++++------------------ + 2 files changed, 54 insertions(+), 55 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -417,23 +417,23 @@ mt7530_setup_port6(struct dsa_switch *ds + + mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK, P6_INTF_MODE(1)); + +- xtal = mt7530_read(priv, MT7530_MHWTRAP) & HWTRAP_XTAL_MASK; ++ xtal = mt7530_read(priv, MT753X_MTRAP) & MT7530_XTAL_MASK; + +- if (xtal == HWTRAP_XTAL_25MHZ) ++ if (xtal == MT7530_XTAL_25MHZ) + ssc_delta = 0x57; + else + ssc_delta = 0x87; + + if (priv->id == ID_MT7621) { + /* PLL frequency: 125MHz: 1.0GBit */ +- if (xtal == HWTRAP_XTAL_40MHZ) ++ if (xtal == MT7530_XTAL_40MHZ) + ncpo1 = 0x0640; +- if (xtal == HWTRAP_XTAL_25MHZ) ++ if (xtal == MT7530_XTAL_25MHZ) + ncpo1 = 0x0a00; + } else { /* PLL frequency: 250MHz: 2.0Gbit */ +- if (xtal == HWTRAP_XTAL_40MHZ) ++ if (xtal == MT7530_XTAL_40MHZ) + ncpo1 = 0x0c80; +- if (xtal == HWTRAP_XTAL_25MHZ) ++ if (xtal == MT7530_XTAL_25MHZ) + ncpo1 = 0x1400; + } + +@@ -456,19 +456,20 @@ mt7530_setup_port6(struct dsa_switch *ds + static void + mt7531_pll_setup(struct mt7530_priv *priv) + { ++ enum mt7531_xtal_fsel xtal; + u32 top_sig; + u32 hwstrap; +- u32 xtal; + u32 val; + + val = mt7530_read(priv, MT7531_CREV); + top_sig = mt7530_read(priv, MT7531_TOP_SIG_SR); +- hwstrap = mt7530_read(priv, MT7531_HWTRAP); ++ hwstrap = mt7530_read(priv, MT753X_TRAP); + if ((val & CHIP_REV_M) > 0) +- xtal = (top_sig & PAD_MCM_SMI_EN) ? HWTRAP_XTAL_FSEL_40MHZ : +- HWTRAP_XTAL_FSEL_25MHZ; ++ xtal = (top_sig & PAD_MCM_SMI_EN) ? MT7531_XTAL_FSEL_40MHZ : ++ MT7531_XTAL_FSEL_25MHZ; + else +- xtal = hwstrap & HWTRAP_XTAL_FSEL_MASK; ++ xtal = (hwstrap & MT7531_XTAL25) ? MT7531_XTAL_FSEL_25MHZ : ++ MT7531_XTAL_FSEL_40MHZ; + + /* Step 1 : Disable MT7531 COREPLL */ + val = mt7530_read(priv, MT7531_PLLGP_EN); +@@ -497,13 +498,13 @@ mt7531_pll_setup(struct mt7530_priv *pri + usleep_range(25, 35); + + switch (xtal) { +- case HWTRAP_XTAL_FSEL_25MHZ: ++ case MT7531_XTAL_FSEL_25MHZ: + val = mt7530_read(priv, MT7531_PLLGP_CR0); + val &= ~RG_COREPLL_SDM_PCW_M; + val |= 0x140000 << RG_COREPLL_SDM_PCW_S; + mt7530_write(priv, MT7531_PLLGP_CR0, val); + break; +- case HWTRAP_XTAL_FSEL_40MHZ: ++ case MT7531_XTAL_FSEL_40MHZ: + val = mt7530_read(priv, MT7531_PLLGP_CR0); + val &= ~RG_COREPLL_SDM_PCW_M; + val |= 0x190000 << RG_COREPLL_SDM_PCW_S; +@@ -884,20 +885,20 @@ static void mt7530_setup_port5(struct ds + + mutex_lock(&priv->reg_mutex); + +- val = mt7530_read(priv, MT7530_MHWTRAP); ++ val = mt7530_read(priv, MT753X_MTRAP); + +- val |= MHWTRAP_MANUAL | MHWTRAP_P5_MAC_SEL | MHWTRAP_P5_DIS; +- val &= ~MHWTRAP_P5_RGMII_MODE & ~MHWTRAP_PHY0_SEL; ++ val |= MT7530_CHG_TRAP | MT7530_P5_MAC_SEL | MT7530_P5_DIS; ++ val &= ~MT7530_P5_RGMII_MODE & ~MT7530_P5_PHY0_SEL; + + switch (priv->p5_mode) { + /* MUX_PHY_P0: P0 -> P5 -> SoC MAC */ + case MUX_PHY_P0: +- val |= MHWTRAP_PHY0_SEL; ++ val |= MT7530_P5_PHY0_SEL; + fallthrough; + + /* MUX_PHY_P4: P4 -> P5 -> SoC MAC */ + case MUX_PHY_P4: +- val &= ~MHWTRAP_P5_MAC_SEL & ~MHWTRAP_P5_DIS; ++ val &= ~MT7530_P5_MAC_SEL & ~MT7530_P5_DIS; + + /* Setup the MAC by default for the cpu port */ + mt7530_write(priv, MT753X_PMCR_P(5), 0x56300); +@@ -905,13 +906,13 @@ static void mt7530_setup_port5(struct ds + + /* GMAC5: P5 -> SoC MAC or external PHY */ + default: +- val &= ~MHWTRAP_P5_DIS; ++ val &= ~MT7530_P5_DIS; + break; + } + + /* Setup RGMII settings */ + if (phy_interface_mode_is_rgmii(interface)) { +- val |= MHWTRAP_P5_RGMII_MODE; ++ val |= MT7530_P5_RGMII_MODE; + + /* P5 RGMII RX Clock Control: delay setting for 1000M */ + mt7530_write(priv, MT7530_P5RGMIIRXCR, CSR_RGMII_EDGE_ALIGN); +@@ -931,7 +932,7 @@ static void mt7530_setup_port5(struct ds + P5_IO_CLK_DRV(1) | P5_IO_DATA_DRV(1)); + } + +- mt7530_write(priv, MT7530_MHWTRAP, val); ++ mt7530_write(priv, MT753X_MTRAP, val); + + dev_dbg(ds->dev, "Setup P5, HWTRAP=0x%x, mode=%s, phy-mode=%s\n", val, + mt7530_p5_mode_str(priv->p5_mode), phy_modes(interface)); +@@ -2370,7 +2371,7 @@ mt7530_setup(struct dsa_switch *ds) + } + + /* Waiting for MT7530 got to stable */ +- INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_HWTRAP); ++ INIT_MT7530_DUMMY_POLL(&p, priv, MT753X_TRAP); + ret = readx_poll_timeout(_mt7530_read, &p, val, val != 0, + 20, 1000000); + if (ret < 0) { +@@ -2385,7 +2386,7 @@ mt7530_setup(struct dsa_switch *ds) + return -ENODEV; + } + +- if ((val & HWTRAP_XTAL_MASK) == HWTRAP_XTAL_20MHZ) { ++ if ((val & MT7530_XTAL_MASK) == MT7530_XTAL_20MHZ) { + dev_err(priv->dev, + "MT7530 with a 20MHz XTAL is not supported!\n"); + return -EINVAL; +@@ -2406,12 +2407,12 @@ mt7530_setup(struct dsa_switch *ds) + RD_TAP_MASK, RD_TAP(16)); + + /* Enable port 6 */ +- val = mt7530_read(priv, MT7530_MHWTRAP); +- val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; +- val |= MHWTRAP_MANUAL; +- mt7530_write(priv, MT7530_MHWTRAP, val); ++ val = mt7530_read(priv, MT753X_MTRAP); ++ val &= ~MT7530_P6_DIS & ~MT7530_PHY_INDIRECT_ACCESS; ++ val |= MT7530_CHG_TRAP; ++ mt7530_write(priv, MT753X_MTRAP, val); + +- if ((val & HWTRAP_XTAL_MASK) == HWTRAP_XTAL_40MHZ) ++ if ((val & MT7530_XTAL_MASK) == MT7530_XTAL_40MHZ) + mt7530_pll_setup(priv); + + mt753x_trap_frames(priv); +@@ -2591,7 +2592,7 @@ mt7531_setup(struct dsa_switch *ds) + } + + /* Waiting for MT7530 got to stable */ +- INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_HWTRAP); ++ INIT_MT7530_DUMMY_POLL(&p, priv, MT753X_TRAP); + ret = readx_poll_timeout(_mt7530_read, &p, val, val != 0, + 20, 1000000); + if (ret < 0) { +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -495,32 +495,30 @@ enum mt7531_clk_skew { + MT7531_CLK_SKEW_REVERSE = 3, + }; + +-/* Register for hw trap status */ +-#define MT7530_HWTRAP 0x7800 +-#define HWTRAP_XTAL_MASK (BIT(10) | BIT(9)) +-#define HWTRAP_XTAL_25MHZ (BIT(10) | BIT(9)) +-#define HWTRAP_XTAL_40MHZ (BIT(10)) +-#define HWTRAP_XTAL_20MHZ (BIT(9)) ++/* Register for trap status */ ++#define MT753X_TRAP 0x7800 ++#define MT7530_XTAL_MASK (BIT(10) | BIT(9)) ++#define MT7530_XTAL_25MHZ (BIT(10) | BIT(9)) ++#define MT7530_XTAL_40MHZ BIT(10) ++#define MT7530_XTAL_20MHZ BIT(9) ++#define MT7531_XTAL25 BIT(7) + +-#define MT7531_HWTRAP 0x7800 +-#define HWTRAP_XTAL_FSEL_MASK BIT(7) +-#define HWTRAP_XTAL_FSEL_25MHZ BIT(7) +-#define HWTRAP_XTAL_FSEL_40MHZ 0 +-/* Unique fields of (M)HWSTRAP for MT7531 */ +-#define XTAL_FSEL_S 7 +-#define XTAL_FSEL_M BIT(7) +-#define PHY_EN BIT(6) +-#define CHG_STRAP BIT(8) ++/* Register for trap modification */ ++#define MT753X_MTRAP 0x7804 ++#define MT7530_P5_PHY0_SEL BIT(20) ++#define MT7530_CHG_TRAP BIT(16) ++#define MT7530_P5_MAC_SEL BIT(13) ++#define MT7530_P6_DIS BIT(8) ++#define MT7530_P5_RGMII_MODE BIT(7) ++#define MT7530_P5_DIS BIT(6) ++#define MT7530_PHY_INDIRECT_ACCESS BIT(5) ++#define MT7531_CHG_STRAP BIT(8) ++#define MT7531_PHY_EN BIT(6) + +-/* Register for hw trap modification */ +-#define MT7530_MHWTRAP 0x7804 +-#define MHWTRAP_PHY0_SEL BIT(20) +-#define MHWTRAP_MANUAL BIT(16) +-#define MHWTRAP_P5_MAC_SEL BIT(13) +-#define MHWTRAP_P6_DIS BIT(8) +-#define MHWTRAP_P5_RGMII_MODE BIT(7) +-#define MHWTRAP_P5_DIS BIT(6) +-#define MHWTRAP_PHY_ACCESS BIT(5) ++enum mt7531_xtal_fsel { ++ MT7531_XTAL_FSEL_25MHZ, ++ MT7531_XTAL_FSEL_40MHZ, ++}; + + /* Register for TOP signal control */ + #define MT7530_TOP_SIG_CTRL 0x7808 diff --git a/lede/target/linux/generic/backport-6.1/790-60-v6.10-net-dsa-mt7530-move-MT753X_MTRAP-operations-for-MT75.patch b/lede/target/linux/generic/backport-6.1/790-60-v6.10-net-dsa-mt7530-move-MT753X_MTRAP-operations-for-MT75.patch new file mode 100644 index 0000000000..cfc38f81d0 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-60-v6.10-net-dsa-mt7530-move-MT753X_MTRAP-operations-for-MT75.patch @@ -0,0 +1,117 @@ +From 2982f395c9a513b168f1e685588f70013cba2f5f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:14 +0300 +Subject: [PATCH 07/15] net: dsa: mt7530: move MT753X_MTRAP operations for + MT7530 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +On MT7530, the media-independent interfaces of port 5 and 6 are controlled +by the MT7530_P5_DIS and MT7530_P6_DIS bits of the hardware trap. Deal with +these bits only when the relevant port is being enabled or disabled. This +ensures that these ports will be disabled when they are not in use. + +Do not set MT7530_CHG_TRAP on mt7530_setup_port5() as that's already being +done on mt7530_setup(). + +Instead of globally setting MT7530_P5_MAC_SEL, clear it, then set it only +on the appropriate case. + +If PHY muxing is detected, clear MT7530_P5_DIS before calling +mt7530_setup_port5(). + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.c | 38 +++++++++++++++++++++++++++----------- + 1 file changed, 27 insertions(+), 11 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -887,8 +887,7 @@ static void mt7530_setup_port5(struct ds + + val = mt7530_read(priv, MT753X_MTRAP); + +- val |= MT7530_CHG_TRAP | MT7530_P5_MAC_SEL | MT7530_P5_DIS; +- val &= ~MT7530_P5_RGMII_MODE & ~MT7530_P5_PHY0_SEL; ++ val &= ~MT7530_P5_PHY0_SEL & ~MT7530_P5_MAC_SEL & ~MT7530_P5_RGMII_MODE; + + switch (priv->p5_mode) { + /* MUX_PHY_P0: P0 -> P5 -> SoC MAC */ +@@ -898,15 +897,13 @@ static void mt7530_setup_port5(struct ds + + /* MUX_PHY_P4: P4 -> P5 -> SoC MAC */ + case MUX_PHY_P4: +- val &= ~MT7530_P5_MAC_SEL & ~MT7530_P5_DIS; +- + /* Setup the MAC by default for the cpu port */ + mt7530_write(priv, MT753X_PMCR_P(5), 0x56300); + break; + + /* GMAC5: P5 -> SoC MAC or external PHY */ + default: +- val &= ~MT7530_P5_DIS; ++ val |= MT7530_P5_MAC_SEL; + break; + } + +@@ -1200,6 +1197,14 @@ mt7530_port_enable(struct dsa_switch *ds + + mutex_unlock(&priv->reg_mutex); + ++ if (priv->id != ID_MT7530 && priv->id != ID_MT7621) ++ return 0; ++ ++ if (port == 5) ++ mt7530_clear(priv, MT753X_MTRAP, MT7530_P5_DIS); ++ else if (port == 6) ++ mt7530_clear(priv, MT753X_MTRAP, MT7530_P6_DIS); ++ + return 0; + } + +@@ -1218,6 +1223,14 @@ mt7530_port_disable(struct dsa_switch *d + PCR_MATRIX_CLR); + + mutex_unlock(&priv->reg_mutex); ++ ++ if (priv->id != ID_MT7530 && priv->id != ID_MT7621) ++ return; ++ ++ if (port == 5) ++ mt7530_set(priv, MT753X_MTRAP, MT7530_P5_DIS); ++ else if (port == 6) ++ mt7530_set(priv, MT753X_MTRAP, MT7530_P6_DIS); + } + + static int +@@ -2406,11 +2419,11 @@ mt7530_setup(struct dsa_switch *ds) + mt7530_rmw(priv, MT7530_TRGMII_RD(i), + RD_TAP_MASK, RD_TAP(16)); + +- /* Enable port 6 */ +- val = mt7530_read(priv, MT753X_MTRAP); +- val &= ~MT7530_P6_DIS & ~MT7530_PHY_INDIRECT_ACCESS; +- val |= MT7530_CHG_TRAP; +- mt7530_write(priv, MT753X_MTRAP, val); ++ /* Allow modifying the trap and directly access PHY registers via the ++ * MDIO bus the switch is on. ++ */ ++ mt7530_rmw(priv, MT753X_MTRAP, MT7530_CHG_TRAP | ++ MT7530_PHY_INDIRECT_ACCESS, MT7530_CHG_TRAP); + + if ((val & MT7530_XTAL_MASK) == MT7530_XTAL_40MHZ) + mt7530_pll_setup(priv); +@@ -2493,8 +2506,11 @@ mt7530_setup(struct dsa_switch *ds) + break; + } + +- if (priv->p5_mode == MUX_PHY_P0 || priv->p5_mode == MUX_PHY_P4) ++ if (priv->p5_mode == MUX_PHY_P0 || ++ priv->p5_mode == MUX_PHY_P4) { ++ mt7530_clear(priv, MT753X_MTRAP, MT7530_P5_DIS); + mt7530_setup_port5(ds, interface); ++ } + } + + #ifdef CONFIG_GPIOLIB diff --git a/lede/target/linux/generic/backport-6.1/790-61-v6.10-net-dsa-mt7530-return-mt7530_setup_mdio-mt7531_setup.patch b/lede/target/linux/generic/backport-6.1/790-61-v6.10-net-dsa-mt7530-return-mt7530_setup_mdio-mt7531_setup.patch new file mode 100644 index 0000000000..178ac8022f --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-61-v6.10-net-dsa-mt7530-return-mt7530_setup_mdio-mt7531_setup.patch @@ -0,0 +1,39 @@ +From 1f5669efca65564c7533704917f79003c6b36c9c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:15 +0300 +Subject: [PATCH 08/15] net: dsa: mt7530: return mt7530_setup_mdio & + mt7531_setup_common on error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The mt7530_setup_mdio() and mt7531_setup_common() functions should be +checked for errors. Return if the functions return a non-zero value. + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2672,7 +2672,9 @@ mt7531_setup(struct dsa_switch *ds) + 0); + } + +- mt7531_setup_common(ds); ++ ret = mt7531_setup_common(ds); ++ if (ret) ++ return ret; + + /* Setup VLAN ID 0 for VLAN-unaware bridges */ + ret = mt7530_setup_vlan0(priv); +@@ -3031,6 +3033,8 @@ mt753x_setup(struct dsa_switch *ds) + ret = mt7530_setup_mdio(priv); + if (ret && priv->irq) + mt7530_free_irq_common(priv); ++ if (ret) ++ return ret; + + /* Initialise the PCS devices */ + for (i = 0; i < priv->ds->num_ports; i++) { diff --git a/lede/target/linux/generic/backport-6.1/790-62-v6.10-net-dsa-mt7530-define-MAC-speed-capabilities-per-swi.patch b/lede/target/linux/generic/backport-6.1/790-62-v6.10-net-dsa-mt7530-define-MAC-speed-capabilities-per-swi.patch new file mode 100644 index 0000000000..af8edf5a42 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-62-v6.10-net-dsa-mt7530-define-MAC-speed-capabilities-per-swi.patch @@ -0,0 +1,75 @@ +From 6cc2d4ccd77509df74b7b8ef46bbc6ba0a571318 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:16 +0300 +Subject: [PATCH 09/15] net: dsa: mt7530: define MAC speed capabilities per + switch model +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +With the support of the MT7988 SoC switch, the MAC speed capabilities +defined on mt753x_phylink_get_caps() won't apply to all switch models +anymore. Move them to more appropriate locations instead of overwriting +config->mac_capabilities. + +Remove the comment on mt753x_phylink_get_caps() as it's become invalid with +the support of MT7531 and MT7988 SoC switch. + +Add break to case 6 of mt7988_mac_port_get_caps() to be explicit. + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2690,6 +2690,8 @@ mt7531_setup(struct dsa_switch *ds) + static void mt7530_mac_port_get_caps(struct dsa_switch *ds, int port, + struct phylink_config *config) + { ++ config->mac_capabilities |= MAC_10 | MAC_100 | MAC_1000FD; ++ + switch (port) { + /* Ports which are connected to switch PHYs. There is no MII pinout. */ + case 0 ... 4: +@@ -2721,6 +2723,8 @@ static void mt7531_mac_port_get_caps(str + { + struct mt7530_priv *priv = ds->priv; + ++ config->mac_capabilities |= MAC_10 | MAC_100 | MAC_1000FD; ++ + switch (port) { + /* Ports which are connected to switch PHYs. There is no MII pinout. */ + case 0 ... 4: +@@ -2760,14 +2764,17 @@ static void mt7988_mac_port_get_caps(str + case 0 ... 3: + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + config->supported_interfaces); ++ ++ config->mac_capabilities |= MAC_10 | MAC_100 | MAC_1000FD; + break; + + /* Port 6 is connected to SoC's XGMII MAC. There is no MII pinout. */ + case 6: + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + config->supported_interfaces); +- config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | +- MAC_10000FD; ++ ++ config->mac_capabilities |= MAC_10000FD; ++ break; + } + } + +@@ -2937,9 +2944,7 @@ static void mt753x_phylink_get_caps(stru + { + struct mt7530_priv *priv = ds->priv; + +- /* This switch only supports full-duplex at 1Gbps */ +- config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | +- MAC_10 | MAC_100 | MAC_1000FD; ++ config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE; + + /* This driver does not make use of the speed, duplex, pause or the + * advertisement in its mac_config, so it is safe to mark this driver diff --git a/lede/target/linux/generic/backport-6.1/790-63-v6.10-net-dsa-mt7530-get-rid-of-function-sanity-check.patch b/lede/target/linux/generic/backport-6.1/790-63-v6.10-net-dsa-mt7530-get-rid-of-function-sanity-check.patch new file mode 100644 index 0000000000..3825952dc3 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-63-v6.10-net-dsa-mt7530-get-rid-of-function-sanity-check.patch @@ -0,0 +1,33 @@ +From dd0f15fc877c10567699190bce0f55e96f4ad6b5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:17 +0300 +Subject: [PATCH 10/15] net: dsa: mt7530: get rid of function sanity check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Get rid of checking whether functions are filled properly. priv->info which +is an mt753x_info structure is filled and checked for before this check. +It's unnecessary checking whether it's filled properly. + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.c | 7 ------- + 1 file changed, 7 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -3235,13 +3235,6 @@ mt7530_probe_common(struct mt7530_priv * + if (!priv->info) + return -EINVAL; + +- /* Sanity check if these required device operations are filled +- * properly. +- */ +- if (!priv->info->sw_setup || !priv->info->phy_read || +- !priv->info->phy_write || !priv->info->mac_port_get_caps) +- return -EINVAL; +- + priv->id = priv->info->id; + priv->dev = dev; + priv->ds->priv = priv; diff --git a/lede/target/linux/generic/backport-6.1/790-64-v6.10-net-dsa-mt7530-refactor-MT7530_PMEEECR_P.patch b/lede/target/linux/generic/backport-6.1/790-64-v6.10-net-dsa-mt7530-refactor-MT7530_PMEEECR_P.patch new file mode 100644 index 0000000000..df47458014 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-64-v6.10-net-dsa-mt7530-refactor-MT7530_PMEEECR_P.patch @@ -0,0 +1,71 @@ +From 2dff9759602b069f97ccc939e15a47ca051b2983 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:18 +0300 +Subject: [PATCH 11/15] net: dsa: mt7530: refactor MT7530_PMEEECR_P() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The MT7530_PMEEECR_P() register is on MT7530, MT7531, and the switch on the +MT7988 SoC. Rename the definition for them to MT753X_PMEEECR_P(). Use the +FIELD_PREP and FIELD_GET macros. Rename GET_LPI_THRESH() and +SET_LPI_THRESH() to LPI_THRESH_GET() and LPI_THRESH_SET(). + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.c | 8 ++++---- + drivers/net/dsa/mt7530.h | 13 +++++++------ + 2 files changed, 11 insertions(+), 10 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -3062,10 +3062,10 @@ static int mt753x_get_mac_eee(struct dsa + struct ethtool_eee *e) + { + struct mt7530_priv *priv = ds->priv; +- u32 eeecr = mt7530_read(priv, MT7530_PMEEECR_P(port)); ++ u32 eeecr = mt7530_read(priv, MT753X_PMEEECR_P(port)); + + e->tx_lpi_enabled = !(eeecr & LPI_MODE_EN); +- e->tx_lpi_timer = GET_LPI_THRESH(eeecr); ++ e->tx_lpi_timer = LPI_THRESH_GET(eeecr); + + return 0; + } +@@ -3079,11 +3079,11 @@ static int mt753x_set_mac_eee(struct dsa + if (e->tx_lpi_timer > 0xFFF) + return -EINVAL; + +- set = SET_LPI_THRESH(e->tx_lpi_timer); ++ set = LPI_THRESH_SET(e->tx_lpi_timer); + if (!e->tx_lpi_enabled) + /* Force LPI Mode without a delay */ + set |= LPI_MODE_EN; +- mt7530_rmw(priv, MT7530_PMEEECR_P(port), mask, set); ++ mt7530_rmw(priv, MT753X_PMEEECR_P(port), mask, set); + + return 0; + } +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -364,13 +364,14 @@ enum mt7530_vlan_port_acc_frm { + PMCR_FORCE_SPEED_100 | \ + PMCR_FORCE_FDX | PMCR_FORCE_LNK) + +-#define MT7530_PMEEECR_P(x) (0x3004 + (x) * 0x100) +-#define WAKEUP_TIME_1000(x) (((x) & 0xFF) << 24) +-#define WAKEUP_TIME_100(x) (((x) & 0xFF) << 16) ++#define MT753X_PMEEECR_P(x) (0x3004 + (x) * 0x100) ++#define WAKEUP_TIME_1000_MASK GENMASK(31, 24) ++#define WAKEUP_TIME_1000(x) FIELD_PREP(WAKEUP_TIME_1000_MASK, x) ++#define WAKEUP_TIME_100_MASK GENMASK(23, 16) ++#define WAKEUP_TIME_100(x) FIELD_PREP(WAKEUP_TIME_100_MASK, x) + #define LPI_THRESH_MASK GENMASK(15, 4) +-#define LPI_THRESH_SHT 4 +-#define SET_LPI_THRESH(x) (((x) << LPI_THRESH_SHT) & LPI_THRESH_MASK) +-#define GET_LPI_THRESH(x) (((x) & LPI_THRESH_MASK) >> LPI_THRESH_SHT) ++#define LPI_THRESH_GET(x) FIELD_GET(LPI_THRESH_MASK, x) ++#define LPI_THRESH_SET(x) FIELD_PREP(LPI_THRESH_MASK, x) + #define LPI_MODE_EN BIT(0) + + #define MT7530_PMSR_P(x) (0x3008 + (x) * 0x100) diff --git a/lede/target/linux/generic/backport-6.1/790-65-v6.10-net-dsa-mt7530-get-rid-of-mac_port_validate-member-o.patch b/lede/target/linux/generic/backport-6.1/790-65-v6.10-net-dsa-mt7530-get-rid-of-mac_port_validate-member-o.patch new file mode 100644 index 0000000000..7ce2d4c04e --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-65-v6.10-net-dsa-mt7530-get-rid-of-mac_port_validate-member-o.patch @@ -0,0 +1,46 @@ +From 21d67c2fabfe40baf33202d3287b67b6c16f8382 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:19 +0300 +Subject: [PATCH 12/15] net: dsa: mt7530: get rid of mac_port_validate member + of mt753x_info +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The mac_port_validate member of the mt753x_info structure is not being +used, remove it. Improve the member description section in the process. + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.h | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -743,13 +743,12 @@ struct mt753x_pcs { + + /* struct mt753x_info - This is the main data structure for holding the specific + * part for each supported device ++ * @id: Holding the identifier to a switch model ++ * @pcs_ops: Holding the pointer to the MAC PCS operations structure + * @sw_setup: Holding the handler to a device initialization + * @phy_read: Holding the way reading PHY port + * @phy_write: Holding the way writing PHY port +- * @phy_mode_supported: Check if the PHY type is being supported on a certain +- * port +- * @mac_port_validate: Holding the way to set addition validate type for a +- * certan MAC port ++ * @mac_port_get_caps: Holding the handler that provides MAC capabilities + * @mac_port_config: Holding the way setting up the PHY attribute to a + * certain MAC port + */ +@@ -763,9 +762,6 @@ struct mt753x_info { + int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val); + void (*mac_port_get_caps)(struct dsa_switch *ds, int port, + struct phylink_config *config); +- void (*mac_port_validate)(struct dsa_switch *ds, int port, +- phy_interface_t interface, +- unsigned long *supported); + void (*mac_port_config)(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface); diff --git a/lede/target/linux/generic/backport-6.1/790-66-v6.10-net-dsa-mt7530-use-priv-ds-num_ports-instead-of-MT75.patch b/lede/target/linux/generic/backport-6.1/790-66-v6.10-net-dsa-mt7530-use-priv-ds-num_ports-instead-of-MT75.patch new file mode 100644 index 0000000000..e9512421c2 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-66-v6.10-net-dsa-mt7530-use-priv-ds-num_ports-instead-of-MT75.patch @@ -0,0 +1,57 @@ +From 6efc8ae3eb0363328f479191a0cf0dc12a16e090 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:20 +0300 +Subject: [PATCH 13/15] net: dsa: mt7530: use priv->ds->num_ports instead of + MT7530_NUM_PORTS +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use priv->ds->num_ports on all for loops which configure the switch +registers. In the future, the value of MT7530_NUM_PORTS will depend on +priv->id. Therefore, this change prepares the subdriver for a simpler +implementation. + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1418,7 +1418,7 @@ mt7530_port_set_vlan_unaware(struct dsa_ + mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, + G0_PORT_VID_DEF); + +- for (i = 0; i < MT7530_NUM_PORTS; i++) { ++ for (i = 0; i < priv->ds->num_ports; i++) { + if (dsa_is_user_port(ds, i) && + dsa_port_is_vlan_filtering(dsa_to_port(ds, i))) { + all_user_ports_removed = false; +@@ -2433,7 +2433,7 @@ mt7530_setup(struct dsa_switch *ds) + /* Enable and reset MIB counters */ + mt7530_mib_reset(ds); + +- for (i = 0; i < MT7530_NUM_PORTS; i++) { ++ for (i = 0; i < priv->ds->num_ports; i++) { + /* Clear link settings and enable force mode to force link down + * on all ports until they're enabled later. + */ +@@ -2544,7 +2544,7 @@ mt7531_setup_common(struct dsa_switch *d + mt7530_clear(priv, MT753X_MFC, BC_FFP_MASK | UNM_FFP_MASK | + UNU_FFP_MASK); + +- for (i = 0; i < MT7530_NUM_PORTS; i++) { ++ for (i = 0; i < priv->ds->num_ports; i++) { + /* Clear link settings and enable force mode to force link down + * on all ports until they're enabled later. + */ +@@ -2631,7 +2631,7 @@ mt7531_setup(struct dsa_switch *ds) + priv->p5_sgmii = !!(val & PAD_DUAL_SGMII_EN); + + /* Force link down on all ports before internal reset */ +- for (i = 0; i < MT7530_NUM_PORTS; i++) ++ for (i = 0; i < priv->ds->num_ports; i++) + mt7530_write(priv, MT753X_PMCR_P(i), MT7531_FORCE_MODE_LNK); + + /* Reset the switch through internal reset */ diff --git a/lede/target/linux/generic/backport-6.1/790-67-v6.10-net-dsa-mt7530-do-not-pass-port-variable-to-mt7531_r.patch b/lede/target/linux/generic/backport-6.1/790-67-v6.10-net-dsa-mt7530-do-not-pass-port-variable-to-mt7531_r.patch new file mode 100644 index 0000000000..3b3330bdce --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-67-v6.10-net-dsa-mt7530-do-not-pass-port-variable-to-mt7531_r.patch @@ -0,0 +1,37 @@ +From 4794c12e3aefe05dd0063c2b6b0101854b143bac Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:21 +0300 +Subject: [PATCH 14/15] net: dsa: mt7530: do not pass port variable to + mt7531_rgmii_setup() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The mt7531_rgmii_setup() function does not use the port variable, do not +pass the variable to it. + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2790,7 +2790,7 @@ mt7530_mac_config(struct dsa_switch *ds, + mt7530_setup_port6(priv->ds, interface); + } + +-static void mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port, ++static void mt7531_rgmii_setup(struct mt7530_priv *priv, + phy_interface_t interface, + struct phy_device *phydev) + { +@@ -2841,7 +2841,7 @@ mt7531_mac_config(struct dsa_switch *ds, + if (phy_interface_mode_is_rgmii(interface)) { + dp = dsa_to_port(ds, port); + phydev = dp->slave->phydev; +- mt7531_rgmii_setup(priv, port, interface, phydev); ++ mt7531_rgmii_setup(priv, interface, phydev); + } + } + diff --git a/lede/target/linux/generic/backport-6.1/790-68-v6.10-net-dsa-mt7530-explain-exposing-MDIO-bus-of-MT7531AE.patch b/lede/target/linux/generic/backport-6.1/790-68-v6.10-net-dsa-mt7530-explain-exposing-MDIO-bus-of-MT7531AE.patch new file mode 100644 index 0000000000..6d28e5b5f9 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-68-v6.10-net-dsa-mt7530-explain-exposing-MDIO-bus-of-MT7531AE.patch @@ -0,0 +1,33 @@ +From c45832fe783f468aaaace09ae95a30cbf0acf724 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Mon, 22 Apr 2024 10:15:22 +0300 +Subject: [PATCH 15/15] net: dsa: mt7530: explain exposing MDIO bus of MT7531AE + better +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Unlike MT7531BE, the GPIO 6-12 pins are not used for RGMII on MT7531AE. +Therefore, the GPIO 11-12 pins are set to function as MDC and MDIO to +expose the MDIO bus of the switch. Replace the comment with a better +explanation. + +Signed-off-by: Arınç ÜNAL +--- + drivers/net/dsa/mt7530.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2640,7 +2640,10 @@ mt7531_setup(struct dsa_switch *ds) + if (!priv->p5_sgmii) { + mt7531_pll_setup(priv); + } else { +- /* Let ds->slave_mii_bus be able to access external phy. */ ++ /* Unlike MT7531BE, the GPIO 6-12 pins are not used for RGMII on ++ * MT7531AE. Set the GPIO 11-12 pins to function as MDC and MDIO ++ * to expose the MDIO bus of the switch. ++ */ + mt7530_rmw(priv, MT7531_GPIO_MODE1, MT7531_GPIO11_RG_RXD2_MASK, + MT7531_EXT_P_MDC_11); + mt7530_rmw(priv, MT7531_GPIO_MODE1, MT7531_GPIO12_RG_RXD3_MASK, diff --git a/lede/target/linux/generic/backport-6.1/790-69-v6.10-net-dsa-mt7530-do-not-set-MT7530_P5_DIS-when-PHY-.patch b/lede/target/linux/generic/backport-6.1/790-69-v6.10-net-dsa-mt7530-do-not-set-MT7530_P5_DIS-when-PHY-.patch new file mode 100644 index 0000000000..29079e03c5 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-69-v6.10-net-dsa-mt7530-do-not-set-MT7530_P5_DIS-when-PHY-.patch @@ -0,0 +1,45 @@ +From 16e6592cd5c5bd74d8890973489f60176c692614 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Sun, 28 Apr 2024 12:19:58 +0300 +Subject: [PATCH] net: dsa: mt7530: do not set MT7530_P5_DIS when PHY muxing is + being used +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +DSA initalises the ds->num_ports amount of ports in +dsa_switch_touch_ports(). When the PHY muxing feature is in use, port 5 +won't be defined in the device tree. Because of this, the type member of +the dsa_port structure for this port will be assigned DSA_PORT_TYPE_UNUSED. +The dsa_port_setup() function calls ds->ops->port_disable() when the port +type is DSA_PORT_TYPE_UNUSED. + +The MT7530_P5_DIS bit is unset in mt7530_setup() when PHY muxing is being +used. mt7530_port_disable() which is assigned to ds->ops->port_disable() is +called afterwards. Currently, mt7530_port_disable() sets MT7530_P5_DIS +which breaks network connectivity when PHY muxing is being used. + +Therefore, do not set MT7530_P5_DIS when PHY muxing is being used. + +Fixes: 377174c5760c ("net: dsa: mt7530: move MT753X_MTRAP operations for MT7530") +Reported-by: Daniel Golle +Signed-off-by: Arınç ÜNAL +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240428-for-netnext-mt7530-do-not-disable-port5-when-phy-muxing-v2-1-bb7c37d293f8@arinc9.com +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1227,7 +1227,8 @@ mt7530_port_disable(struct dsa_switch *d + if (priv->id != ID_MT7530 && priv->id != ID_MT7621) + return; + +- if (port == 5) ++ /* Do not set MT7530_P5_DIS when port 5 is being used for PHY muxing. */ ++ if (port == 5 && priv->p5_mode == GMAC5) + mt7530_set(priv, MT753X_MTRAP, MT7530_P5_DIS); + else if (port == 6) + mt7530_set(priv, MT753X_MTRAP, MT7530_P6_DIS); diff --git a/lede/target/linux/generic/backport-6.1/790-70-v6.10-796-net-dsa-mt7530-detect-PHY-muxing-when-PHY-is-defined.patch b/lede/target/linux/generic/backport-6.1/790-70-v6.10-796-net-dsa-mt7530-detect-PHY-muxing-when-PHY-is-defined.patch new file mode 100644 index 0000000000..69bbb8e229 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/790-70-v6.10-796-net-dsa-mt7530-detect-PHY-muxing-when-PHY-is-defined.patch @@ -0,0 +1,45 @@ +From d8dcf5bd6d0eace9f7c1daa14b63b3925b09d033 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Tue, 30 Apr 2024 08:01:33 +0300 +Subject: [PATCH] net: dsa: mt7530: detect PHY muxing when PHY is defined on + switch MDIO bus +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently, the MT7530 DSA subdriver configures the MT7530 switch to provide +direct access to switch PHYs, meaning, the switch PHYs listen on the MDIO +bus the switch listens on. The PHY muxing feature makes use of this. + +This is problematic as the PHY may be attached before the switch is +initialised, in which case, the PHY will fail to be attached. + +Since commit 91374ba537bd ("net: dsa: mt7530: support OF-based registration +of switch MDIO bus"), we can describe the switch PHYs on the MDIO bus of +the switch on the device tree. Extend the check to detect PHY muxing when +the PHY is defined on the MDIO bus of the switch on the device tree. + +When the PHY is described this way, the switch will be initialised first, +then the switch MDIO bus will be registered. Only after these steps, the +PHY will be attached. + +Signed-off-by: Arınç ÜNAL +Reviewed-by: Daniel Golle +Link: https://lore.kernel.org/r/20240430-b4-for-netnext-mt7530-use-switch-mdio-bus-for-phy-muxing-v2-1-9104d886d0db@arinc9.com +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2489,7 +2489,8 @@ mt7530_setup(struct dsa_switch *ds) + if (!phy_node) + continue; + +- if (phy_node->parent == priv->dev->of_node->parent) { ++ if (phy_node->parent == priv->dev->of_node->parent || ++ phy_node->parent->parent == priv->dev->of_node) { + ret = of_get_phy_mode(mac_np, &interface); + if (ret && ret != -ENODEV) { + of_node_put(mac_np); diff --git a/lede/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch b/lede/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch index e366def8fb..3cf98acc85 100644 --- a/lede/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch +++ b/lede/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch @@ -31,7 +31,7 @@ Signed-off-by: David S. Miller F: drivers/net/phy/motorcomm.c --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -260,7 +260,7 @@ config MOTORCOMM_PHY +@@ -257,7 +257,7 @@ config MOTORCOMM_PHY tristate "Motorcomm PHYs" help Enables support for Motorcomm network PHYs. diff --git a/lede/target/linux/generic/backport-6.1/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch b/lede/target/linux/generic/backport-6.1/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch index a2f22ee99b..d22cc69425 100644 --- a/lede/target/linux/generic/backport-6.1/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch +++ b/lede/target/linux/generic/backport-6.1/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch @@ -22,7 +22,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -260,7 +260,7 @@ config MOTORCOMM_PHY +@@ -257,7 +257,7 @@ config MOTORCOMM_PHY tristate "Motorcomm PHYs" help Enables support for Motorcomm network PHYs. diff --git a/lede/target/linux/generic/backport-6.1/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch b/lede/target/linux/generic/backport-6.1/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch index 35495978ef..60eea4fa47 100644 --- a/lede/target/linux/generic/backport-6.1/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch +++ b/lede/target/linux/generic/backport-6.1/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch @@ -19,7 +19,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -260,7 +260,7 @@ config MOTORCOMM_PHY +@@ -257,7 +257,7 @@ config MOTORCOMM_PHY tristate "Motorcomm PHYs" help Enables support for Motorcomm network PHYs. diff --git a/lede/target/linux/generic/backport-6.1/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch b/lede/target/linux/generic/backport-6.1/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch index eac8966a48..f82c8fc622 100644 --- a/lede/target/linux/generic/backport-6.1/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch +++ b/lede/target/linux/generic/backport-6.1/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch @@ -27,15 +27,15 @@ Signed-off-by: David S. Miller }; /** -@@ -71,6 +75,7 @@ struct phylink { - struct mutex state_mutex; +@@ -72,6 +76,7 @@ struct phylink { struct phylink_link_state phy_state; struct work_struct resolve; + unsigned int pcs_neg_mode; + unsigned int pcs_state; bool mac_link_dropped; bool using_mac_select_pcs; -@@ -987,6 +992,22 @@ static void phylink_mac_pcs_an_restart(s +@@ -992,6 +997,22 @@ static void phylink_resolve_an_pause(str } } @@ -55,16 +55,17 @@ Signed-off-by: David S. Miller + return err; +} + - static void phylink_major_config(struct phylink *pl, bool restart, - const struct phylink_link_state *state) - { -@@ -1023,11 +1044,16 @@ static void phylink_major_config(struct + static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, + const struct phylink_link_state *state, + bool permit_pause_to_mac) +@@ -1094,11 +1115,17 @@ static void phylink_major_config(struct /* If we have a new PCS, switch to the new PCS after preparing the MAC * for the change. */ - if (pcs_changed) + if (pcs_changed) { + phylink_pcs_disable(pl->pcs); ++ pl->pcs = pcs; + } @@ -73,18 +74,18 @@ Signed-off-by: David S. Miller + if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed) + phylink_pcs_enable(pl->pcs); + - if (pl->pcs) { - err = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, - state->interface, -@@ -1499,6 +1525,7 @@ struct phylink *phylink_create(struct ph + neg_mode = pl->cur_link_an_mode; + if (pl->pcs && pl->pcs->neg_mode) + neg_mode = pl->pcs_neg_mode; +@@ -1586,6 +1613,7 @@ struct phylink *phylink_create(struct ph + pl->link_config.pause = MLO_PAUSE_AN; pl->link_config.speed = SPEED_UNKNOWN; pl->link_config.duplex = DUPLEX_UNKNOWN; - pl->link_config.an_enabled = true; + pl->pcs_state = PCS_STATE_DOWN; pl->mac_ops = mac_ops; __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); timer_setup(&pl->link_poll, phylink_fixed_poll, 0); -@@ -1900,6 +1927,8 @@ void phylink_start(struct phylink *pl) +@@ -1987,6 +2015,8 @@ void phylink_start(struct phylink *pl) if (pl->netdev) netif_carrier_off(pl->netdev); @@ -93,7 +94,7 @@ Signed-off-by: David S. Miller /* Apply the link configuration to the MAC when starting. This allows * a fixed-link to start with the correct parameters, and also * ensures that we set the appropriate advertisement for Serdes links. -@@ -1910,6 +1939,8 @@ void phylink_start(struct phylink *pl) +@@ -1997,6 +2027,8 @@ void phylink_start(struct phylink *pl) */ phylink_mac_initial_config(pl, true); @@ -102,7 +103,7 @@ Signed-off-by: David S. Miller phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED); if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) { -@@ -1928,15 +1959,9 @@ void phylink_start(struct phylink *pl) +@@ -2015,15 +2047,9 @@ void phylink_start(struct phylink *pl) poll = true; } @@ -120,7 +121,7 @@ Signed-off-by: David S. Miller if (poll) mod_timer(&pl->link_poll, jiffies + HZ); if (pl->phydev) -@@ -1973,6 +1998,10 @@ void phylink_stop(struct phylink *pl) +@@ -2060,6 +2086,10 @@ void phylink_stop(struct phylink *pl) } phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED); @@ -133,7 +134,7 @@ Signed-off-by: David S. Miller --- a/include/linux/phylink.h +++ b/include/linux/phylink.h -@@ -446,6 +446,8 @@ struct phylink_pcs { +@@ -533,6 +533,8 @@ struct phylink_pcs { /** * struct phylink_pcs_ops - MAC PCS operations structure. * @pcs_validate: validate the link configuration. @@ -142,7 +143,7 @@ Signed-off-by: David S. Miller * @pcs_get_state: read the current MAC PCS link state from the hardware. * @pcs_config: configure the MAC PCS for the selected mode and state. * @pcs_an_restart: restart 802.3z BaseX autonegotiation. -@@ -455,6 +457,8 @@ struct phylink_pcs { +@@ -542,6 +544,8 @@ struct phylink_pcs { struct phylink_pcs_ops { int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported, const struct phylink_link_state *state); @@ -150,8 +151,8 @@ Signed-off-by: David S. Miller + void (*pcs_disable)(struct phylink_pcs *pcs); void (*pcs_get_state)(struct phylink_pcs *pcs, struct phylink_link_state *state); - int (*pcs_config)(struct phylink_pcs *pcs, unsigned int mode, -@@ -485,6 +489,18 @@ int pcs_validate(struct phylink_pcs *pcs + int (*pcs_config)(struct phylink_pcs *pcs, unsigned int neg_mode, +@@ -572,6 +576,18 @@ int pcs_validate(struct phylink_pcs *pcs const struct phylink_link_state *state); /** diff --git a/lede/target/linux/generic/backport-6.1/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch b/lede/target/linux/generic/backport-6.1/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch index eb9b4b7c09..6b6369761a 100644 --- a/lede/target/linux/generic/backport-6.1/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch +++ b/lede/target/linux/generic/backport-6.1/793-v6.6-net-pcs-lynxi-implement-pcs_disable-op.patch @@ -22,7 +22,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/pcs/pcs-mtk-lynxi.c +++ b/drivers/net/pcs/pcs-mtk-lynxi.c -@@ -241,11 +241,19 @@ static void mtk_pcs_lynxi_link_up(struct +@@ -234,11 +234,19 @@ static void mtk_pcs_lynxi_link_up(struct } } diff --git a/lede/target/linux/generic/backport-6.1/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch b/lede/target/linux/generic/backport-6.1/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch new file mode 100644 index 0000000000..c4141eee93 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch @@ -0,0 +1,136 @@ +From: Andy Ren +Date: Mon, 7 Nov 2022 09:42:42 -0800 +Subject: [PATCH] net/core: Allow live renaming when an interface is up + +Allow a network interface to be renamed when the interface +is up. + +As described in the netconsole documentation [1], when netconsole is +used as a built-in, it will bring up the specified interface as soon as +possible. As a result, user space will not be able to rename the +interface since the kernel disallows renaming of interfaces that are +administratively up unless the 'IFF_LIVE_RENAME_OK' private flag was set +by the kernel. + +The original solution [2] to this problem was to add a new parameter to +the netconsole configuration parameters that allows renaming of +the interface used by netconsole while it is administratively up. +However, during the discussion that followed, it became apparent that we +have no reason to keep the current restriction and instead we should +allow user space to rename interfaces regardless of their administrative +state: + +1. The restriction was put in place over 20 years ago when renaming was +only possible via IOCTL and before rtnetlink started notifying user +space about such changes like it does today. + +2. The 'IFF_LIVE_RENAME_OK' flag was added over 3 years ago in version +5.2 and no regressions were reported. + +3. In-kernel listeners to 'NETDEV_CHANGENAME' do not seem to care about +the administrative state of interface. + +Therefore, allow user space to rename running interfaces by removing the +restriction and the associated 'IFF_LIVE_RENAME_OK' flag. Help in +possible triage by emitting a message to the kernel log that an +interface was renamed while UP. + +[1] https://www.kernel.org/doc/Documentation/networking/netconsole.rst +[2] https://lore.kernel.org/netdev/20221102002420.2613004-1-andy.ren@getcruise.com/ + +Signed-off-by: Andy Ren +Reviewed-by: Ido Schimmel +Reviewed-by: David Ahern +Signed-off-by: David S. Miller +--- + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1691,7 +1691,6 @@ struct net_device_ops { + * @IFF_FAILOVER: device is a failover master device + * @IFF_FAILOVER_SLAVE: device is lower dev of a failover master device + * @IFF_L3MDEV_RX_HANDLER: only invoke the rx handler of L3 master device +- * @IFF_LIVE_RENAME_OK: rename is allowed while device is up and running + * @IFF_TX_SKB_NO_LINEAR: device/driver is capable of xmitting frames with + * skb_headlen(skb) == 0 (data starts from frag0) + * @IFF_CHANGE_PROTO_DOWN: device supports setting carrier via IFLA_PROTO_DOWN +@@ -1727,7 +1726,7 @@ enum netdev_priv_flags { + IFF_FAILOVER = 1<<27, + IFF_FAILOVER_SLAVE = 1<<28, + IFF_L3MDEV_RX_HANDLER = 1<<29, +- IFF_LIVE_RENAME_OK = 1<<30, ++ /* was IFF_LIVE_RENAME_OK */ + IFF_TX_SKB_NO_LINEAR = BIT_ULL(31), + IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), + }; +@@ -1762,7 +1761,6 @@ enum netdev_priv_flags { + #define IFF_FAILOVER IFF_FAILOVER + #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE + #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER +-#define IFF_LIVE_RENAME_OK IFF_LIVE_RENAME_OK + #define IFF_TX_SKB_NO_LINEAR IFF_TX_SKB_NO_LINEAR + + /* Specifies the type of the struct net_device::ml_priv pointer */ +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1188,22 +1188,6 @@ int dev_change_name(struct net_device *d + + net = dev_net(dev); + +- /* Some auto-enslaved devices e.g. failover slaves are +- * special, as userspace might rename the device after +- * the interface had been brought up and running since +- * the point kernel initiated auto-enslavement. Allow +- * live name change even when these slave devices are +- * up and running. +- * +- * Typically, users of these auto-enslaving devices +- * don't actually care about slave name change, as +- * they are supposed to operate on master interface +- * directly. +- */ +- if (dev->flags & IFF_UP && +- likely(!(dev->priv_flags & IFF_LIVE_RENAME_OK))) +- return -EBUSY; +- + down_write(&devnet_rename_sem); + + if (strncmp(newname, dev->name, IFNAMSIZ) == 0) { +@@ -1220,7 +1204,8 @@ int dev_change_name(struct net_device *d + } + + if (oldname[0] && !strchr(oldname, '%')) +- netdev_info(dev, "renamed from %s\n", oldname); ++ netdev_info(dev, "renamed from %s%s\n", oldname, ++ dev->flags & IFF_UP ? " (while UP)" : ""); + + old_assign_type = dev->name_assign_type; + dev->name_assign_type = NET_NAME_RENAMED; +--- a/net/core/failover.c ++++ b/net/core/failover.c +@@ -80,14 +80,14 @@ static int failover_slave_register(struc + goto err_upper_link; + } + +- slave_dev->priv_flags |= (IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); ++ slave_dev->priv_flags |= IFF_FAILOVER_SLAVE; + + if (fops && fops->slave_register && + !fops->slave_register(slave_dev, failover_dev)) + return NOTIFY_OK; + + netdev_upper_dev_unlink(slave_dev, failover_dev); +- slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); ++ slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE; + err_upper_link: + netdev_rx_handler_unregister(slave_dev); + done: +@@ -121,7 +121,7 @@ int failover_slave_unregister(struct net + + netdev_rx_handler_unregister(slave_dev); + netdev_upper_dev_unlink(slave_dev, failover_dev); +- slave_dev->priv_flags &= ~(IFF_FAILOVER_SLAVE | IFF_LIVE_RENAME_OK); ++ slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE; + + if (fops && fops->slave_unregister && + !fops->slave_unregister(slave_dev, failover_dev)) diff --git a/lede/target/linux/generic/backport-6.1/796-v6.5-01-usbnet-ipheth-fix-risk-of-NULL-pointer-deallocation.patch b/lede/target/linux/generic/backport-6.1/796-v6.5-01-usbnet-ipheth-fix-risk-of-NULL-pointer-deallocation.patch new file mode 100644 index 0000000000..d9d6f36fce --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/796-v6.5-01-usbnet-ipheth-fix-risk-of-NULL-pointer-deallocation.patch @@ -0,0 +1,30 @@ +From 2203718c2f59ffdd6c78d54e5add594aebb4461e Mon Sep 17 00:00:00 2001 +From: Georgi Valkov +Date: Wed, 7 Jun 2023 15:56:59 +0200 +Subject: [PATCH 1/4] usbnet: ipheth: fix risk of NULL pointer deallocation + +The cleanup precedure in ipheth_probe will attempt to free a +NULL pointer in dev->ctrl_buf if the memory allocation for +this buffer is not successful. While kfree ignores NULL pointers, +and the existing code is safe, it is a better design to rearrange +the goto labels and avoid this. + +Signed-off-by: Georgi Valkov +Signed-off-by: Foster Snowhill +Signed-off-by: David S. Miller +--- + drivers/net/usb/ipheth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/usb/ipheth.c ++++ b/drivers/net/usb/ipheth.c +@@ -510,8 +510,8 @@ err_register_netdev: + ipheth_free_urbs(dev); + err_alloc_urbs: + err_get_macaddr: +-err_alloc_ctrl_buf: + kfree(dev->ctrl_buf); ++err_alloc_ctrl_buf: + err_endpoints: + free_netdev(netdev); + return retval; diff --git a/lede/target/linux/generic/backport-6.1/796-v6.5-02-usbnet-ipheth-transmit-URBs-without-trailing-padding.patch b/lede/target/linux/generic/backport-6.1/796-v6.5-02-usbnet-ipheth-transmit-URBs-without-trailing-padding.patch new file mode 100644 index 0000000000..adfec356d9 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/796-v6.5-02-usbnet-ipheth-transmit-URBs-without-trailing-padding.patch @@ -0,0 +1,35 @@ +From 3e65efcca87a9bb5f3b864e0a43d167bc0a8688c Mon Sep 17 00:00:00 2001 +From: Foster Snowhill +Date: Wed, 7 Jun 2023 15:57:00 +0200 +Subject: [PATCH 2/4] usbnet: ipheth: transmit URBs without trailing padding + +The behaviour of the official iOS tethering driver on macOS is to not +transmit any trailing padding at the end of URBs. This is applicable +to both NCM and legacy modes, including older devices. + +Adapt the driver to not include trailing padding in TX URBs, matching +the behaviour of the official macOS driver. + +Signed-off-by: Foster Snowhill +Tested-by: Georgi Valkov +Signed-off-by: David S. Miller +--- + drivers/net/usb/ipheth.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/net/usb/ipheth.c ++++ b/drivers/net/usb/ipheth.c +@@ -373,12 +373,10 @@ static netdev_tx_t ipheth_tx(struct sk_b + } + + memcpy(dev->tx_buf, skb->data, skb->len); +- if (skb->len < IPHETH_BUF_SIZE) +- memset(dev->tx_buf + skb->len, 0, IPHETH_BUF_SIZE - skb->len); + + usb_fill_bulk_urb(dev->tx_urb, udev, + usb_sndbulkpipe(udev, dev->bulk_out), +- dev->tx_buf, IPHETH_BUF_SIZE, ++ dev->tx_buf, skb->len, + ipheth_sndbulk_callback, + dev); + dev->tx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; diff --git a/lede/target/linux/generic/backport-6.1/796-v6.5-03-usbnet-ipheth-add-CDC-NCM-support.patch b/lede/target/linux/generic/backport-6.1/796-v6.5-03-usbnet-ipheth-add-CDC-NCM-support.patch new file mode 100644 index 0000000000..e3f2b9c331 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/796-v6.5-03-usbnet-ipheth-add-CDC-NCM-support.patch @@ -0,0 +1,326 @@ +From a2d274c62e44b1995c170595db3865c6fe701226 Mon Sep 17 00:00:00 2001 +From: Foster Snowhill +Date: Wed, 7 Jun 2023 15:57:01 +0200 +Subject: [PATCH 3/4] usbnet: ipheth: add CDC NCM support + +Recent iOS releases support CDC NCM encapsulation on RX. This mode is +the default on macOS and Windows. In this mode, an iOS device may include +one or more Ethernet frames inside a single URB. + +Freshly booted iOS devices start in legacy mode, but are put into +NCM mode by the official Apple driver. When reconnecting such a device +from a macOS/Windows machine to a Linux host, the device stays in +NCM mode, making it unusable with the legacy ipheth driver code. + +To correctly support such a device, the driver has to either support +the NCM mode too, or put the device back into legacy mode. + +To match the behaviour of the macOS/Windows driver, and since there +is no documented control command to revert to legacy mode, implement +NCM support. The device is attempted to be put into NCM mode by default, +and falls back to legacy mode if the attempt fails. + +Signed-off-by: Foster Snowhill +Tested-by: Georgi Valkov +Signed-off-by: David S. Miller +--- + drivers/net/usb/ipheth.c | 180 +++++++++++++++++++++++++++++++++------ + 1 file changed, 155 insertions(+), 25 deletions(-) + +--- a/drivers/net/usb/ipheth.c ++++ b/drivers/net/usb/ipheth.c +@@ -52,6 +52,7 @@ + #include + #include + #include ++#include + + #define USB_VENDOR_APPLE 0x05ac + +@@ -59,8 +60,12 @@ + #define IPHETH_USBINTF_SUBCLASS 253 + #define IPHETH_USBINTF_PROTO 1 + +-#define IPHETH_BUF_SIZE 1514 + #define IPHETH_IP_ALIGN 2 /* padding at front of URB */ ++#define IPHETH_NCM_HEADER_SIZE (12 + 96) /* NCMH + NCM0 */ ++#define IPHETH_TX_BUF_SIZE ETH_FRAME_LEN ++#define IPHETH_RX_BUF_SIZE_LEGACY (IPHETH_IP_ALIGN + ETH_FRAME_LEN) ++#define IPHETH_RX_BUF_SIZE_NCM 65536 ++ + #define IPHETH_TX_TIMEOUT (5 * HZ) + + #define IPHETH_INTFNUM 2 +@@ -71,6 +76,7 @@ + #define IPHETH_CTRL_TIMEOUT (5 * HZ) + + #define IPHETH_CMD_GET_MACADDR 0x00 ++#define IPHETH_CMD_ENABLE_NCM 0x04 + #define IPHETH_CMD_CARRIER_CHECK 0x45 + + #define IPHETH_CARRIER_CHECK_TIMEOUT round_jiffies_relative(1 * HZ) +@@ -97,6 +103,8 @@ struct ipheth_device { + u8 bulk_out; + struct delayed_work carrier_work; + bool confirmed_pairing; ++ int (*rcvbulk_callback)(struct urb *urb); ++ size_t rx_buf_len; + }; + + static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags); +@@ -116,12 +124,12 @@ static int ipheth_alloc_urbs(struct iphe + if (rx_urb == NULL) + goto free_tx_urb; + +- tx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE, ++ tx_buf = usb_alloc_coherent(iphone->udev, IPHETH_TX_BUF_SIZE, + GFP_KERNEL, &tx_urb->transfer_dma); + if (tx_buf == NULL) + goto free_rx_urb; + +- rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, ++ rx_buf = usb_alloc_coherent(iphone->udev, iphone->rx_buf_len, + GFP_KERNEL, &rx_urb->transfer_dma); + if (rx_buf == NULL) + goto free_tx_buf; +@@ -134,7 +142,7 @@ static int ipheth_alloc_urbs(struct iphe + return 0; + + free_tx_buf: +- usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, tx_buf, ++ usb_free_coherent(iphone->udev, IPHETH_TX_BUF_SIZE, tx_buf, + tx_urb->transfer_dma); + free_rx_urb: + usb_free_urb(rx_urb); +@@ -146,9 +154,9 @@ error_nomem: + + static void ipheth_free_urbs(struct ipheth_device *iphone) + { +- usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, iphone->rx_buf, ++ usb_free_coherent(iphone->udev, iphone->rx_buf_len, iphone->rx_buf, + iphone->rx_urb->transfer_dma); +- usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf, ++ usb_free_coherent(iphone->udev, IPHETH_TX_BUF_SIZE, iphone->tx_buf, + iphone->tx_urb->transfer_dma); + usb_free_urb(iphone->rx_urb); + usb_free_urb(iphone->tx_urb); +@@ -160,15 +168,106 @@ static void ipheth_kill_urbs(struct iphe + usb_kill_urb(dev->rx_urb); + } + +-static void ipheth_rcvbulk_callback(struct urb *urb) ++static int ipheth_consume_skb(char *buf, int len, struct ipheth_device *dev) + { +- struct ipheth_device *dev; + struct sk_buff *skb; +- int status; ++ ++ skb = dev_alloc_skb(len); ++ if (!skb) { ++ dev->net->stats.rx_dropped++; ++ return -ENOMEM; ++ } ++ ++ skb_put_data(skb, buf, len); ++ skb->dev = dev->net; ++ skb->protocol = eth_type_trans(skb, dev->net); ++ ++ dev->net->stats.rx_packets++; ++ dev->net->stats.rx_bytes += len; ++ netif_rx(skb); ++ ++ return 0; ++} ++ ++static int ipheth_rcvbulk_callback_legacy(struct urb *urb) ++{ ++ struct ipheth_device *dev; ++ char *buf; ++ int len; ++ ++ dev = urb->context; ++ ++ if (urb->actual_length <= IPHETH_IP_ALIGN) { ++ dev->net->stats.rx_length_errors++; ++ return -EINVAL; ++ } ++ len = urb->actual_length - IPHETH_IP_ALIGN; ++ buf = urb->transfer_buffer + IPHETH_IP_ALIGN; ++ ++ return ipheth_consume_skb(buf, len, dev); ++} ++ ++static int ipheth_rcvbulk_callback_ncm(struct urb *urb) ++{ ++ struct usb_cdc_ncm_nth16 *ncmh; ++ struct usb_cdc_ncm_ndp16 *ncm0; ++ struct usb_cdc_ncm_dpe16 *dpe; ++ struct ipheth_device *dev; ++ int retval = -EINVAL; + char *buf; + int len; + + dev = urb->context; ++ ++ if (urb->actual_length < IPHETH_NCM_HEADER_SIZE) { ++ dev->net->stats.rx_length_errors++; ++ return retval; ++ } ++ ++ ncmh = urb->transfer_buffer; ++ if (ncmh->dwSignature != cpu_to_le32(USB_CDC_NCM_NTH16_SIGN) || ++ le16_to_cpu(ncmh->wNdpIndex) >= urb->actual_length) { ++ dev->net->stats.rx_errors++; ++ return retval; ++ } ++ ++ ncm0 = urb->transfer_buffer + le16_to_cpu(ncmh->wNdpIndex); ++ if (ncm0->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN) || ++ le16_to_cpu(ncmh->wHeaderLength) + le16_to_cpu(ncm0->wLength) >= ++ urb->actual_length) { ++ dev->net->stats.rx_errors++; ++ return retval; ++ } ++ ++ dpe = ncm0->dpe16; ++ while (le16_to_cpu(dpe->wDatagramIndex) != 0 && ++ le16_to_cpu(dpe->wDatagramLength) != 0) { ++ if (le16_to_cpu(dpe->wDatagramIndex) >= urb->actual_length || ++ le16_to_cpu(dpe->wDatagramIndex) + ++ le16_to_cpu(dpe->wDatagramLength) > urb->actual_length) { ++ dev->net->stats.rx_length_errors++; ++ return retval; ++ } ++ ++ buf = urb->transfer_buffer + le16_to_cpu(dpe->wDatagramIndex); ++ len = le16_to_cpu(dpe->wDatagramLength); ++ ++ retval = ipheth_consume_skb(buf, len, dev); ++ if (retval != 0) ++ return retval; ++ ++ dpe++; ++ } ++ ++ return 0; ++} ++ ++static void ipheth_rcvbulk_callback(struct urb *urb) ++{ ++ struct ipheth_device *dev; ++ int retval, status; ++ ++ dev = urb->context; + if (dev == NULL) + return; + +@@ -191,25 +290,27 @@ static void ipheth_rcvbulk_callback(stru + dev->net->stats.rx_length_errors++; + return; + } +- len = urb->actual_length - IPHETH_IP_ALIGN; +- buf = urb->transfer_buffer + IPHETH_IP_ALIGN; + +- skb = dev_alloc_skb(len); +- if (!skb) { +- dev_err(&dev->intf->dev, "%s: dev_alloc_skb: -ENOMEM\n", +- __func__); +- dev->net->stats.rx_dropped++; ++ /* RX URBs starting with 0x00 0x01 do not encapsulate Ethernet frames, ++ * but rather are control frames. Their purpose is not documented, and ++ * they don't affect driver functionality, okay to drop them. ++ * There is usually just one 4-byte control frame as the very first ++ * URB received from the bulk IN endpoint. ++ */ ++ if (unlikely ++ (((char *)urb->transfer_buffer)[0] == 0 && ++ ((char *)urb->transfer_buffer)[1] == 1)) ++ goto rx_submit; ++ ++ retval = dev->rcvbulk_callback(urb); ++ if (retval != 0) { ++ dev_err(&dev->intf->dev, "%s: callback retval: %d\n", ++ __func__, retval); + return; + } + +- skb_put_data(skb, buf, len); +- skb->dev = dev->net; +- skb->protocol = eth_type_trans(skb, dev->net); +- +- dev->net->stats.rx_packets++; +- dev->net->stats.rx_bytes += len; ++rx_submit: + dev->confirmed_pairing = true; +- netif_rx(skb); + ipheth_rx_submit(dev, GFP_ATOMIC); + } + +@@ -310,6 +411,27 @@ static int ipheth_get_macaddr(struct iph + return retval; + } + ++static int ipheth_enable_ncm(struct ipheth_device *dev) ++{ ++ struct usb_device *udev = dev->udev; ++ int retval; ++ ++ retval = usb_control_msg(udev, ++ usb_sndctrlpipe(udev, IPHETH_CTRL_ENDP), ++ IPHETH_CMD_ENABLE_NCM, /* request */ ++ 0x41, /* request type */ ++ 0x00, /* value */ ++ 0x02, /* index */ ++ NULL, ++ 0, ++ IPHETH_CTRL_TIMEOUT); ++ ++ dev_info(&dev->intf->dev, "%s: usb_control_msg: %d\n", ++ __func__, retval); ++ ++ return retval; ++} ++ + static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags) + { + struct usb_device *udev = dev->udev; +@@ -317,7 +439,7 @@ static int ipheth_rx_submit(struct iphet + + usb_fill_bulk_urb(dev->rx_urb, udev, + usb_rcvbulkpipe(udev, dev->bulk_in), +- dev->rx_buf, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, ++ dev->rx_buf, dev->rx_buf_len, + ipheth_rcvbulk_callback, + dev); + dev->rx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +@@ -365,7 +487,7 @@ static netdev_tx_t ipheth_tx(struct sk_b + int retval; + + /* Paranoid */ +- if (skb->len > IPHETH_BUF_SIZE) { ++ if (skb->len > IPHETH_TX_BUF_SIZE) { + WARN(1, "%s: skb too large: %d bytes\n", __func__, skb->len); + dev->net->stats.tx_dropped++; + dev_kfree_skb_any(skb); +@@ -448,6 +570,8 @@ static int ipheth_probe(struct usb_inter + dev->net = netdev; + dev->intf = intf; + dev->confirmed_pairing = false; ++ dev->rx_buf_len = IPHETH_RX_BUF_SIZE_LEGACY; ++ dev->rcvbulk_callback = ipheth_rcvbulk_callback_legacy; + /* Set up endpoints */ + hintf = usb_altnum_to_altsetting(intf, IPHETH_ALT_INTFNUM); + if (hintf == NULL) { +@@ -479,6 +603,12 @@ static int ipheth_probe(struct usb_inter + if (retval) + goto err_get_macaddr; + ++ retval = ipheth_enable_ncm(dev); ++ if (!retval) { ++ dev->rx_buf_len = IPHETH_RX_BUF_SIZE_NCM; ++ dev->rcvbulk_callback = ipheth_rcvbulk_callback_ncm; ++ } ++ + INIT_DELAYED_WORK(&dev->carrier_work, ipheth_carrier_check_work); + + retval = ipheth_alloc_urbs(dev); diff --git a/lede/target/linux/generic/backport-6.1/796-v6.5-04-usbnet-ipheth-update-Kconfig-description.patch b/lede/target/linux/generic/backport-6.1/796-v6.5-04-usbnet-ipheth-update-Kconfig-description.patch new file mode 100644 index 0000000000..9089c4d8c3 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/796-v6.5-04-usbnet-ipheth-update-Kconfig-description.patch @@ -0,0 +1,36 @@ +From 0c6e9d32ef0ccfcf2d875cbcff23bf345a54d585 Mon Sep 17 00:00:00 2001 +From: Foster Snowhill +Date: Wed, 7 Jun 2023 15:57:02 +0200 +Subject: [PATCH 4/4] usbnet: ipheth: update Kconfig description + +This module has for a long time not been limited to iPhone <= 3GS. +Update description to match the actual state of the driver. + +Remove dead link from 2010, instead reference an existing userspace +iOS device pairing implementation as part of libimobiledevice. + +Signed-off-by: Foster Snowhill +Signed-off-by: David S. Miller +--- + drivers/net/usb/Kconfig | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/net/usb/Kconfig ++++ b/drivers/net/usb/Kconfig +@@ -583,12 +583,10 @@ config USB_IPHETH + default n + help + Module used to share Internet connection (tethering) from your +- iPhone (Original, 3G and 3GS) to your system. +- Note that you need userspace libraries and programs that are needed +- to pair your device with your system and that understand the iPhone +- protocol. +- +- For more information: http://giagio.com/wiki/moin.cgi/iPhoneEthernetDriver ++ iPhone to your system. ++ Note that you need a corresponding userspace library/program ++ to pair your device with your system, for example usbmuxd ++ . + + config USB_SIERRA_NET + tristate "USB-to-WWAN Driver for Sierra Wireless modems" diff --git a/lede/target/linux/generic/backport-6.1/797-6.7-net-dsa-mv88e6xxx-fix-marvell-6350-switch-probing.patch b/lede/target/linux/generic/backport-6.1/797-6.7-net-dsa-mv88e6xxx-fix-marvell-6350-switch-probing.patch new file mode 100644 index 0000000000..36083bbaf5 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/797-6.7-net-dsa-mv88e6xxx-fix-marvell-6350-switch-probing.patch @@ -0,0 +1,89 @@ +From b3f1a164c7f742503dc7159011f7ad6b092b660e Mon Sep 17 00:00:00 2001 +From: Greg Ungerer +Date: Fri, 24 Nov 2023 14:15:28 +1000 +Subject: [PATCH] net: dsa: mv88e6xxx: fix marvell 6350 switch probing + +As of commit de5c9bf40c45 ("net: phylink: require supported_interfaces to +be filled") Marvell 88e6350 switches fail to be probed: + + ... + mv88e6085 d0072004.mdio-mii:11: switch 0x3710 detected: Marvell 88E6350, revision 2 + mv88e6085 d0072004.mdio-mii:11: phylink: error: empty supported_interfaces + error creating PHYLINK: -22 + mv88e6085: probe of d0072004.mdio-mii:11 failed with error -22 + ... + +The problem stems from the use of mv88e6185_phylink_get_caps() to get +the device capabilities. Create a new dedicated phylink_get_caps for the +6351 family (which the 6350 is one of) to properly support their set of +capabilities. + +According to chip.h the 6351 switch family includes the 6171, 6175, 6350 +and 6351 switches, so update each of these to use the correct +phylink_get_caps. + +Fixes: de5c9bf40c45 ("net: phylink: require supported_interfaces to be filled") +Signed-off-by: Greg Ungerer +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mv88e6xxx/chip.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -652,6 +652,18 @@ static void mv88e6250_phylink_get_caps(s + config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100; + } + ++static void mv88e6351_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, ++ struct phylink_config *config) ++{ ++ unsigned long *supported = config->supported_interfaces; ++ ++ /* Translate the default cmode */ ++ mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported); ++ ++ config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | ++ MAC_1000FD; ++} ++ + static int mv88e6352_get_port4_serdes_cmode(struct mv88e6xxx_chip *chip) + { + u16 reg, val; +@@ -4501,7 +4513,7 @@ static const struct mv88e6xxx_ops mv88e6 + .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, + .stu_getnext = mv88e6352_g1_stu_getnext, + .stu_loadpurge = mv88e6352_g1_stu_loadpurge, +- .phylink_get_caps = mv88e6185_phylink_get_caps, ++ .phylink_get_caps = mv88e6351_phylink_get_caps, + }; + + static const struct mv88e6xxx_ops mv88e6172_ops = { +@@ -4604,7 +4616,7 @@ static const struct mv88e6xxx_ops mv88e6 + .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, + .stu_getnext = mv88e6352_g1_stu_getnext, + .stu_loadpurge = mv88e6352_g1_stu_loadpurge, +- .phylink_get_caps = mv88e6185_phylink_get_caps, ++ .phylink_get_caps = mv88e6351_phylink_get_caps, + }; + + static const struct mv88e6xxx_ops mv88e6176_ops = { +@@ -5281,7 +5293,7 @@ static const struct mv88e6xxx_ops mv88e6 + .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, + .stu_getnext = mv88e6352_g1_stu_getnext, + .stu_loadpurge = mv88e6352_g1_stu_loadpurge, +- .phylink_get_caps = mv88e6185_phylink_get_caps, ++ .phylink_get_caps = mv88e6351_phylink_get_caps, + }; + + static const struct mv88e6xxx_ops mv88e6351_ops = { +@@ -5327,7 +5339,7 @@ static const struct mv88e6xxx_ops mv88e6 + .stu_loadpurge = mv88e6352_g1_stu_loadpurge, + .avb_ops = &mv88e6352_avb_ops, + .ptp_ops = &mv88e6352_ptp_ops, +- .phylink_get_caps = mv88e6185_phylink_get_caps, ++ .phylink_get_caps = mv88e6351_phylink_get_caps, + }; + + static const struct mv88e6xxx_ops mv88e6352_ops = { diff --git a/lede/target/linux/generic/backport-6.1/798-v6.10-net-phy-air_en8811h-Add-the-Airoha-EN8811H-PHY-drive.patch b/lede/target/linux/generic/backport-6.1/798-v6.10-net-phy-air_en8811h-Add-the-Airoha-EN8811H-PHY-drive.patch new file mode 100644 index 0000000000..7f963b3cf6 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/798-v6.10-net-phy-air_en8811h-Add-the-Airoha-EN8811H-PHY-drive.patch @@ -0,0 +1,1140 @@ +From 71e79430117d56c409c5ea485a263bc0d8083390 Mon Sep 17 00:00:00 2001 +From: Eric Woudstra +Date: Tue, 26 Mar 2024 17:23:05 +0100 +Subject: [PATCH] net: phy: air_en8811h: Add the Airoha EN8811H PHY driver + +Add the driver for the Airoha EN8811H 2.5 Gigabit PHY. The phy supports +100/1000/2500 Mbps with auto negotiation only. + +The driver uses two firmware files, for which updated versions are added to +linux-firmware already. + +Note: At phy-address + 8 there is another device on the mdio bus, that +belongs to the EN881H. While the original driver writes to it, Airoha +has confirmed this is not needed. Therefore, communication with this +device is not included in this driver. + +Signed-off-by: Eric Woudstra +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240326162305.303598-3-ericwouds@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/Kconfig | 5 + + drivers/net/phy/Makefile | 1 + + drivers/net/phy/air_en8811h.c | 1086 +++++++++++++++++++++++++++++++++ + 3 files changed, 1092 insertions(+) + create mode 100644 drivers/net/phy/air_en8811h.c + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -63,6 +63,11 @@ config SFP + + comment "MII PHY device drivers" + ++config AIR_EN8811H_PHY ++ tristate "Airoha EN8811H 2.5 Gigabit PHY" ++ help ++ Currently supports the Airoha EN8811H PHY. ++ + config AMD_PHY + tristate "AMD PHYs" + help +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -32,6 +32,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m) + + obj-$(CONFIG_ADIN_PHY) += adin.o + obj-$(CONFIG_ADIN1100_PHY) += adin1100.o ++obj-$(CONFIG_AIR_EN8811H_PHY) += air_en8811h.o + obj-$(CONFIG_AMD_PHY) += amd.o + obj-$(CONFIG_AQUANTIA_PHY) += aquantia/ + obj-$(CONFIG_AX88796B_PHY) += ax88796b.o +--- /dev/null ++++ b/drivers/net/phy/air_en8811h.c +@@ -0,0 +1,1086 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Driver for the Airoha EN8811H 2.5 Gigabit PHY. ++ * ++ * Limitations of the EN8811H: ++ * - Only full duplex supported ++ * - Forced speed (AN off) is not supported by hardware (100Mbps) ++ * ++ * Source originated from airoha's en8811h.c and en8811h.h v1.2.1 ++ * ++ * Copyright (C) 2023 Airoha Technology Corp. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define EN8811H_PHY_ID 0x03a2a411 ++ ++#define EN8811H_MD32_DM "airoha/EthMD32.dm.bin" ++#define EN8811H_MD32_DSP "airoha/EthMD32.DSP.bin" ++ ++#define AIR_FW_ADDR_DM 0x00000000 ++#define AIR_FW_ADDR_DSP 0x00100000 ++ ++/* MII Registers */ ++#define AIR_AUX_CTRL_STATUS 0x1d ++#define AIR_AUX_CTRL_STATUS_SPEED_MASK GENMASK(4, 2) ++#define AIR_AUX_CTRL_STATUS_SPEED_100 0x4 ++#define AIR_AUX_CTRL_STATUS_SPEED_1000 0x8 ++#define AIR_AUX_CTRL_STATUS_SPEED_2500 0xc ++ ++#define AIR_EXT_PAGE_ACCESS 0x1f ++#define AIR_PHY_PAGE_STANDARD 0x0000 ++#define AIR_PHY_PAGE_EXTENDED_4 0x0004 ++ ++/* MII Registers Page 4*/ ++#define AIR_BPBUS_MODE 0x10 ++#define AIR_BPBUS_MODE_ADDR_FIXED 0x0000 ++#define AIR_BPBUS_MODE_ADDR_INCR BIT(15) ++#define AIR_BPBUS_WR_ADDR_HIGH 0x11 ++#define AIR_BPBUS_WR_ADDR_LOW 0x12 ++#define AIR_BPBUS_WR_DATA_HIGH 0x13 ++#define AIR_BPBUS_WR_DATA_LOW 0x14 ++#define AIR_BPBUS_RD_ADDR_HIGH 0x15 ++#define AIR_BPBUS_RD_ADDR_LOW 0x16 ++#define AIR_BPBUS_RD_DATA_HIGH 0x17 ++#define AIR_BPBUS_RD_DATA_LOW 0x18 ++ ++/* Registers on MDIO_MMD_VEND1 */ ++#define EN8811H_PHY_FW_STATUS 0x8009 ++#define EN8811H_PHY_READY 0x02 ++ ++#define AIR_PHY_MCU_CMD_1 0x800c ++#define AIR_PHY_MCU_CMD_1_MODE1 0x0 ++#define AIR_PHY_MCU_CMD_2 0x800d ++#define AIR_PHY_MCU_CMD_2_MODE1 0x0 ++#define AIR_PHY_MCU_CMD_3 0x800e ++#define AIR_PHY_MCU_CMD_3_MODE1 0x1101 ++#define AIR_PHY_MCU_CMD_3_DOCMD 0x1100 ++#define AIR_PHY_MCU_CMD_4 0x800f ++#define AIR_PHY_MCU_CMD_4_MODE1 0x0002 ++#define AIR_PHY_MCU_CMD_4_INTCLR 0x00e4 ++ ++/* Registers on MDIO_MMD_VEND2 */ ++#define AIR_PHY_LED_BCR 0x021 ++#define AIR_PHY_LED_BCR_MODE_MASK GENMASK(1, 0) ++#define AIR_PHY_LED_BCR_TIME_TEST BIT(2) ++#define AIR_PHY_LED_BCR_CLK_EN BIT(3) ++#define AIR_PHY_LED_BCR_EXT_CTRL BIT(15) ++ ++#define AIR_PHY_LED_DUR_ON 0x022 ++ ++#define AIR_PHY_LED_DUR_BLINK 0x023 ++ ++#define AIR_PHY_LED_ON(i) (0x024 + ((i) * 2)) ++#define AIR_PHY_LED_ON_MASK (GENMASK(6, 0) | BIT(8)) ++#define AIR_PHY_LED_ON_LINK1000 BIT(0) ++#define AIR_PHY_LED_ON_LINK100 BIT(1) ++#define AIR_PHY_LED_ON_LINK10 BIT(2) ++#define AIR_PHY_LED_ON_LINKDOWN BIT(3) ++#define AIR_PHY_LED_ON_FDX BIT(4) /* Full duplex */ ++#define AIR_PHY_LED_ON_HDX BIT(5) /* Half duplex */ ++#define AIR_PHY_LED_ON_FORCE_ON BIT(6) ++#define AIR_PHY_LED_ON_LINK2500 BIT(8) ++#define AIR_PHY_LED_ON_POLARITY BIT(14) ++#define AIR_PHY_LED_ON_ENABLE BIT(15) ++ ++#define AIR_PHY_LED_BLINK(i) (0x025 + ((i) * 2)) ++#define AIR_PHY_LED_BLINK_1000TX BIT(0) ++#define AIR_PHY_LED_BLINK_1000RX BIT(1) ++#define AIR_PHY_LED_BLINK_100TX BIT(2) ++#define AIR_PHY_LED_BLINK_100RX BIT(3) ++#define AIR_PHY_LED_BLINK_10TX BIT(4) ++#define AIR_PHY_LED_BLINK_10RX BIT(5) ++#define AIR_PHY_LED_BLINK_COLLISION BIT(6) ++#define AIR_PHY_LED_BLINK_RX_CRC_ERR BIT(7) ++#define AIR_PHY_LED_BLINK_RX_IDLE_ERR BIT(8) ++#define AIR_PHY_LED_BLINK_FORCE_BLINK BIT(9) ++#define AIR_PHY_LED_BLINK_2500TX BIT(10) ++#define AIR_PHY_LED_BLINK_2500RX BIT(11) ++ ++/* Registers on BUCKPBUS */ ++#define EN8811H_2P5G_LPA 0x3b30 ++#define EN8811H_2P5G_LPA_2P5G BIT(0) ++ ++#define EN8811H_FW_VERSION 0x3b3c ++ ++#define EN8811H_POLARITY 0xca0f8 ++#define EN8811H_POLARITY_TX_NORMAL BIT(0) ++#define EN8811H_POLARITY_RX_REVERSE BIT(1) ++ ++#define EN8811H_GPIO_OUTPUT 0xcf8b8 ++#define EN8811H_GPIO_OUTPUT_345 (BIT(3) | BIT(4) | BIT(5)) ++ ++#define EN8811H_FW_CTRL_1 0x0f0018 ++#define EN8811H_FW_CTRL_1_START 0x0 ++#define EN8811H_FW_CTRL_1_FINISH 0x1 ++#define EN8811H_FW_CTRL_2 0x800000 ++#define EN8811H_FW_CTRL_2_LOADING BIT(11) ++ ++/* Led definitions */ ++#define EN8811H_LED_COUNT 3 ++ ++/* Default LED setup: ++ * GPIO5 <-> LED0 On: Link detected, blink Rx/Tx ++ * GPIO4 <-> LED1 On: Link detected at 2500 or 1000 Mbps ++ * GPIO3 <-> LED2 On: Link detected at 2500 or 100 Mbps ++ */ ++#define AIR_DEFAULT_TRIGGER_LED0 (BIT(TRIGGER_NETDEV_LINK) | \ ++ BIT(TRIGGER_NETDEV_RX) | \ ++ BIT(TRIGGER_NETDEV_TX)) ++#define AIR_DEFAULT_TRIGGER_LED1 (BIT(TRIGGER_NETDEV_LINK_2500) | \ ++ BIT(TRIGGER_NETDEV_LINK_1000)) ++#define AIR_DEFAULT_TRIGGER_LED2 (BIT(TRIGGER_NETDEV_LINK_2500) | \ ++ BIT(TRIGGER_NETDEV_LINK_100)) ++ ++struct led { ++ unsigned long rules; ++ unsigned long state; ++}; ++ ++struct en8811h_priv { ++ u32 firmware_version; ++ bool mcu_needs_restart; ++ struct led led[EN8811H_LED_COUNT]; ++}; ++ ++enum { ++ AIR_PHY_LED_STATE_FORCE_ON, ++ AIR_PHY_LED_STATE_FORCE_BLINK, ++}; ++ ++enum { ++ AIR_PHY_LED_DUR_BLINK_32MS, ++ AIR_PHY_LED_DUR_BLINK_64MS, ++ AIR_PHY_LED_DUR_BLINK_128MS, ++ AIR_PHY_LED_DUR_BLINK_256MS, ++ AIR_PHY_LED_DUR_BLINK_512MS, ++ AIR_PHY_LED_DUR_BLINK_1024MS, ++}; ++ ++enum { ++ AIR_LED_DISABLE, ++ AIR_LED_ENABLE, ++}; ++ ++enum { ++ AIR_ACTIVE_LOW, ++ AIR_ACTIVE_HIGH, ++}; ++ ++enum { ++ AIR_LED_MODE_DISABLE, ++ AIR_LED_MODE_USER_DEFINE, ++}; ++ ++#define AIR_PHY_LED_DUR_UNIT 1024 ++#define AIR_PHY_LED_DUR (AIR_PHY_LED_DUR_UNIT << AIR_PHY_LED_DUR_BLINK_64MS) ++ ++static const unsigned long en8811h_led_trig = BIT(TRIGGER_NETDEV_FULL_DUPLEX) | ++ BIT(TRIGGER_NETDEV_LINK) | ++ BIT(TRIGGER_NETDEV_LINK_10) | ++ BIT(TRIGGER_NETDEV_LINK_100) | ++ BIT(TRIGGER_NETDEV_LINK_1000) | ++ BIT(TRIGGER_NETDEV_LINK_2500) | ++ BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX); ++ ++static int air_phy_read_page(struct phy_device *phydev) ++{ ++ return __phy_read(phydev, AIR_EXT_PAGE_ACCESS); ++} ++ ++static int air_phy_write_page(struct phy_device *phydev, int page) ++{ ++ return __phy_write(phydev, AIR_EXT_PAGE_ACCESS, page); ++} ++ ++static int __air_buckpbus_reg_write(struct phy_device *phydev, ++ u32 pbus_address, u32 pbus_data) ++{ ++ int ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_HIGH, ++ upper_16_bits(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_LOW, ++ lower_16_bits(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_HIGH, ++ upper_16_bits(pbus_data)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_LOW, ++ lower_16_bits(pbus_data)); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int air_buckpbus_reg_write(struct phy_device *phydev, ++ u32 pbus_address, u32 pbus_data) ++{ ++ int saved_page; ++ int ret = 0; ++ ++ saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); ++ ++ if (saved_page >= 0) { ++ ret = __air_buckpbus_reg_write(phydev, pbus_address, ++ pbus_data); ++ if (ret < 0) ++ phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, ++ pbus_address, ret); ++ } ++ ++ return phy_restore_page(phydev, saved_page, ret); ++} ++ ++static int __air_buckpbus_reg_read(struct phy_device *phydev, ++ u32 pbus_address, u32 *pbus_data) ++{ ++ int pbus_data_low, pbus_data_high; ++ int ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_HIGH, ++ upper_16_bits(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_LOW, ++ lower_16_bits(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ pbus_data_high = __phy_read(phydev, AIR_BPBUS_RD_DATA_HIGH); ++ if (pbus_data_high < 0) ++ return ret; ++ ++ pbus_data_low = __phy_read(phydev, AIR_BPBUS_RD_DATA_LOW); ++ if (pbus_data_low < 0) ++ return ret; ++ ++ *pbus_data = pbus_data_low | (pbus_data_high << 16); ++ return 0; ++} ++ ++static int air_buckpbus_reg_read(struct phy_device *phydev, ++ u32 pbus_address, u32 *pbus_data) ++{ ++ int saved_page; ++ int ret = 0; ++ ++ saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); ++ ++ if (saved_page >= 0) { ++ ret = __air_buckpbus_reg_read(phydev, pbus_address, pbus_data); ++ if (ret < 0) ++ phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, ++ pbus_address, ret); ++ } ++ ++ return phy_restore_page(phydev, saved_page, ret); ++} ++ ++static int __air_buckpbus_reg_modify(struct phy_device *phydev, ++ u32 pbus_address, u32 mask, u32 set) ++{ ++ int pbus_data_low, pbus_data_high; ++ u32 pbus_data_old, pbus_data_new; ++ int ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_HIGH, ++ upper_16_bits(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_LOW, ++ lower_16_bits(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ pbus_data_high = __phy_read(phydev, AIR_BPBUS_RD_DATA_HIGH); ++ if (pbus_data_high < 0) ++ return ret; ++ ++ pbus_data_low = __phy_read(phydev, AIR_BPBUS_RD_DATA_LOW); ++ if (pbus_data_low < 0) ++ return ret; ++ ++ pbus_data_old = pbus_data_low | (pbus_data_high << 16); ++ pbus_data_new = (pbus_data_old & ~mask) | set; ++ if (pbus_data_new == pbus_data_old) ++ return 0; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_HIGH, ++ upper_16_bits(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_LOW, ++ lower_16_bits(pbus_address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_HIGH, ++ upper_16_bits(pbus_data_new)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_LOW, ++ lower_16_bits(pbus_data_new)); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int air_buckpbus_reg_modify(struct phy_device *phydev, ++ u32 pbus_address, u32 mask, u32 set) ++{ ++ int saved_page; ++ int ret = 0; ++ ++ saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); ++ ++ if (saved_page >= 0) { ++ ret = __air_buckpbus_reg_modify(phydev, pbus_address, mask, ++ set); ++ if (ret < 0) ++ phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, ++ pbus_address, ret); ++ } ++ ++ return phy_restore_page(phydev, saved_page, ret); ++} ++ ++static int __air_write_buf(struct phy_device *phydev, u32 address, ++ const struct firmware *fw) ++{ ++ unsigned int offset; ++ int ret; ++ u16 val; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_INCR); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_HIGH, ++ upper_16_bits(address)); ++ if (ret < 0) ++ return ret; ++ ++ ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_LOW, ++ lower_16_bits(address)); ++ if (ret < 0) ++ return ret; ++ ++ for (offset = 0; offset < fw->size; offset += 4) { ++ val = get_unaligned_le16(&fw->data[offset + 2]); ++ ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_HIGH, val); ++ if (ret < 0) ++ return ret; ++ ++ val = get_unaligned_le16(&fw->data[offset]); ++ ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_LOW, val); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int air_write_buf(struct phy_device *phydev, u32 address, ++ const struct firmware *fw) ++{ ++ int saved_page; ++ int ret = 0; ++ ++ saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); ++ ++ if (saved_page >= 0) { ++ ret = __air_write_buf(phydev, address, fw); ++ if (ret < 0) ++ phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__, ++ address, ret); ++ } ++ ++ return phy_restore_page(phydev, saved_page, ret); ++} ++ ++static int en8811h_wait_mcu_ready(struct phy_device *phydev) ++{ ++ int ret, reg_value; ++ ++ /* Because of mdio-lock, may have to wait for multiple loads */ ++ ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ++ EN8811H_PHY_FW_STATUS, reg_value, ++ reg_value == EN8811H_PHY_READY, ++ 20000, 7500000, true); ++ if (ret) { ++ phydev_err(phydev, "MCU not ready: 0x%x\n", reg_value); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static int en8811h_load_firmware(struct phy_device *phydev) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ struct device *dev = &phydev->mdio.dev; ++ const struct firmware *fw1, *fw2; ++ int ret; ++ ++ ret = request_firmware_direct(&fw1, EN8811H_MD32_DM, dev); ++ if (ret < 0) ++ return ret; ++ ++ ret = request_firmware_direct(&fw2, EN8811H_MD32_DSP, dev); ++ if (ret < 0) ++ goto en8811h_load_firmware_rel1; ++ ++ ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, ++ EN8811H_FW_CTRL_1_START); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2, ++ EN8811H_FW_CTRL_2_LOADING, ++ EN8811H_FW_CTRL_2_LOADING); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_write_buf(phydev, AIR_FW_ADDR_DM, fw1); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_write_buf(phydev, AIR_FW_ADDR_DSP, fw2); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2, ++ EN8811H_FW_CTRL_2_LOADING, 0); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, ++ EN8811H_FW_CTRL_1_FINISH); ++ if (ret < 0) ++ goto en8811h_load_firmware_out; ++ ++ ret = en8811h_wait_mcu_ready(phydev); ++ ++ air_buckpbus_reg_read(phydev, EN8811H_FW_VERSION, ++ &priv->firmware_version); ++ phydev_info(phydev, "MD32 firmware version: %08x\n", ++ priv->firmware_version); ++ ++en8811h_load_firmware_out: ++ release_firmware(fw2); ++ ++en8811h_load_firmware_rel1: ++ release_firmware(fw1); ++ ++ if (ret < 0) ++ phydev_err(phydev, "Load firmware failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int en8811h_restart_mcu(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, ++ EN8811H_FW_CTRL_1_START); ++ if (ret < 0) ++ return ret; ++ ++ ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, ++ EN8811H_FW_CTRL_1_FINISH); ++ if (ret < 0) ++ return ret; ++ ++ return en8811h_wait_mcu_ready(phydev); ++} ++ ++static int air_hw_led_on_set(struct phy_device *phydev, u8 index, bool on) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ bool changed; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ if (on) ++ changed = !test_and_set_bit(AIR_PHY_LED_STATE_FORCE_ON, ++ &priv->led[index].state); ++ else ++ changed = !!test_and_clear_bit(AIR_PHY_LED_STATE_FORCE_ON, ++ &priv->led[index].state); ++ ++ changed |= (priv->led[index].rules != 0); ++ ++ if (changed) ++ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, ++ AIR_PHY_LED_ON(index), ++ AIR_PHY_LED_ON_MASK, ++ on ? AIR_PHY_LED_ON_FORCE_ON : 0); ++ ++ return 0; ++} ++ ++static int air_hw_led_blink_set(struct phy_device *phydev, u8 index, ++ bool blinking) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ bool changed; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ if (blinking) ++ changed = !test_and_set_bit(AIR_PHY_LED_STATE_FORCE_BLINK, ++ &priv->led[index].state); ++ else ++ changed = !!test_and_clear_bit(AIR_PHY_LED_STATE_FORCE_BLINK, ++ &priv->led[index].state); ++ ++ changed |= (priv->led[index].rules != 0); ++ ++ if (changed) ++ return phy_write_mmd(phydev, MDIO_MMD_VEND2, ++ AIR_PHY_LED_BLINK(index), ++ blinking ? ++ AIR_PHY_LED_BLINK_FORCE_BLINK : 0); ++ else ++ return 0; ++} ++ ++static int air_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ bool blinking = false; ++ int err; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) { ++ blinking = true; ++ *delay_on = 50; ++ *delay_off = 50; ++ } ++ ++ err = air_hw_led_blink_set(phydev, index, blinking); ++ if (err) ++ return err; ++ ++ /* led-blink set, so switch led-on off */ ++ err = air_hw_led_on_set(phydev, index, false); ++ if (err) ++ return err; ++ ++ /* hw-control is off*/ ++ if (!!test_bit(AIR_PHY_LED_STATE_FORCE_BLINK, &priv->led[index].state)) ++ priv->led[index].rules = 0; ++ ++ return 0; ++} ++ ++static int air_led_brightness_set(struct phy_device *phydev, u8 index, ++ enum led_brightness value) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ int err; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ /* led-on set, so switch led-blink off */ ++ err = air_hw_led_blink_set(phydev, index, false); ++ if (err) ++ return err; ++ ++ err = air_hw_led_on_set(phydev, index, (value != LED_OFF)); ++ if (err) ++ return err; ++ ++ /* hw-control is off */ ++ if (!!test_bit(AIR_PHY_LED_STATE_FORCE_ON, &priv->led[index].state)) ++ priv->led[index].rules = 0; ++ ++ return 0; ++} ++ ++static int air_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ *rules = priv->led[index].rules; ++ ++ return 0; ++}; ++ ++static int air_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ u16 on = 0, blink = 0; ++ int ret; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ priv->led[index].rules = rules; ++ ++ if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX)) ++ on |= AIR_PHY_LED_ON_FDX; ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK))) ++ on |= AIR_PHY_LED_ON_LINK10; ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK))) ++ on |= AIR_PHY_LED_ON_LINK100; ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK))) ++ on |= AIR_PHY_LED_ON_LINK1000; ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK))) ++ on |= AIR_PHY_LED_ON_LINK2500; ++ ++ if (rules & BIT(TRIGGER_NETDEV_RX)) { ++ blink |= AIR_PHY_LED_BLINK_10RX | ++ AIR_PHY_LED_BLINK_100RX | ++ AIR_PHY_LED_BLINK_1000RX | ++ AIR_PHY_LED_BLINK_2500RX; ++ } ++ ++ if (rules & BIT(TRIGGER_NETDEV_TX)) { ++ blink |= AIR_PHY_LED_BLINK_10TX | ++ AIR_PHY_LED_BLINK_100TX | ++ AIR_PHY_LED_BLINK_1000TX | ++ AIR_PHY_LED_BLINK_2500TX; ++ } ++ ++ if (blink || on) { ++ /* switch hw-control on, so led-on and led-blink are off */ ++ clear_bit(AIR_PHY_LED_STATE_FORCE_ON, ++ &priv->led[index].state); ++ clear_bit(AIR_PHY_LED_STATE_FORCE_BLINK, ++ &priv->led[index].state); ++ } else { ++ priv->led[index].rules = 0; ++ } ++ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_ON(index), ++ AIR_PHY_LED_ON_MASK, on); ++ ++ if (ret < 0) ++ return ret; ++ ++ return phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_BLINK(index), ++ blink); ++}; ++ ++static int air_led_init(struct phy_device *phydev, u8 index, u8 state, u8 pol) ++{ ++ int val = 0; ++ int err; ++ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ if (state == AIR_LED_ENABLE) ++ val |= AIR_PHY_LED_ON_ENABLE; ++ else ++ val &= ~AIR_PHY_LED_ON_ENABLE; ++ ++ if (pol == AIR_ACTIVE_HIGH) ++ val |= AIR_PHY_LED_ON_POLARITY; ++ else ++ val &= ~AIR_PHY_LED_ON_POLARITY; ++ ++ err = phy_modify_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_ON(index), ++ AIR_PHY_LED_ON_ENABLE | ++ AIR_PHY_LED_ON_POLARITY, val); ++ ++ if (err < 0) ++ return err; ++ ++ return 0; ++} ++ ++static int air_leds_init(struct phy_device *phydev, int num, int dur, int mode) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ int ret, i; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_DUR_BLINK, ++ dur); ++ if (ret < 0) ++ return ret; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_DUR_ON, ++ dur >> 1); ++ if (ret < 0) ++ return ret; ++ ++ switch (mode) { ++ case AIR_LED_MODE_DISABLE: ++ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_BCR, ++ AIR_PHY_LED_BCR_EXT_CTRL | ++ AIR_PHY_LED_BCR_MODE_MASK, 0); ++ if (ret < 0) ++ return ret; ++ break; ++ case AIR_LED_MODE_USER_DEFINE: ++ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_BCR, ++ AIR_PHY_LED_BCR_EXT_CTRL | ++ AIR_PHY_LED_BCR_CLK_EN, ++ AIR_PHY_LED_BCR_EXT_CTRL | ++ AIR_PHY_LED_BCR_CLK_EN); ++ if (ret < 0) ++ return ret; ++ break; ++ default: ++ phydev_err(phydev, "LED mode %d is not supported\n", mode); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < num; ++i) { ++ ret = air_led_init(phydev, i, AIR_LED_ENABLE, AIR_ACTIVE_HIGH); ++ if (ret < 0) { ++ phydev_err(phydev, "LED%d init failed: %d\n", i, ret); ++ return ret; ++ } ++ air_led_hw_control_set(phydev, i, priv->led[i].rules); ++ } ++ ++ return 0; ++} ++ ++static int en8811h_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ if (index >= EN8811H_LED_COUNT) ++ return -EINVAL; ++ ++ /* All combinations of the supported triggers are allowed */ ++ if (rules & ~en8811h_led_trig) ++ return -EOPNOTSUPP; ++ ++ return 0; ++}; ++ ++static int en8811h_probe(struct phy_device *phydev) ++{ ++ struct en8811h_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct en8811h_priv), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ phydev->priv = priv; ++ ++ ret = en8811h_load_firmware(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* mcu has just restarted after firmware load */ ++ priv->mcu_needs_restart = false; ++ ++ priv->led[0].rules = AIR_DEFAULT_TRIGGER_LED0; ++ priv->led[1].rules = AIR_DEFAULT_TRIGGER_LED1; ++ priv->led[2].rules = AIR_DEFAULT_TRIGGER_LED2; ++ ++ /* MDIO_DEVS1/2 empty, so set mmds_present bits here */ ++ phydev->c45_ids.mmds_present |= MDIO_DEVS_PMAPMD | MDIO_DEVS_AN; ++ ++ ret = air_leds_init(phydev, EN8811H_LED_COUNT, AIR_PHY_LED_DUR, ++ AIR_LED_MODE_DISABLE); ++ if (ret < 0) { ++ phydev_err(phydev, "Failed to disable leds: %d\n", ret); ++ return ret; ++ } ++ ++ /* Configure led gpio pins as output */ ++ ret = air_buckpbus_reg_modify(phydev, EN8811H_GPIO_OUTPUT, ++ EN8811H_GPIO_OUTPUT_345, ++ EN8811H_GPIO_OUTPUT_345); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int en8811h_config_init(struct phy_device *phydev) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ struct device *dev = &phydev->mdio.dev; ++ u32 pbus_value; ++ int ret; ++ ++ /* If restart happened in .probe(), no need to restart now */ ++ if (priv->mcu_needs_restart) { ++ ret = en8811h_restart_mcu(phydev); ++ if (ret < 0) ++ return ret; ++ } else { ++ /* Next calls to .config_init() mcu needs to restart */ ++ priv->mcu_needs_restart = true; ++ } ++ ++ /* Select mode 1, the only mode supported. ++ * Configures the SerDes for 2500Base-X with rate adaptation ++ */ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_MCU_CMD_1, ++ AIR_PHY_MCU_CMD_1_MODE1); ++ if (ret < 0) ++ return ret; ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_MCU_CMD_2, ++ AIR_PHY_MCU_CMD_2_MODE1); ++ if (ret < 0) ++ return ret; ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_MCU_CMD_3, ++ AIR_PHY_MCU_CMD_3_MODE1); ++ if (ret < 0) ++ return ret; ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_MCU_CMD_4, ++ AIR_PHY_MCU_CMD_4_MODE1); ++ if (ret < 0) ++ return ret; ++ ++ /* Serdes polarity */ ++ pbus_value = 0; ++ if (device_property_read_bool(dev, "airoha,pnswap-rx")) ++ pbus_value |= EN8811H_POLARITY_RX_REVERSE; ++ else ++ pbus_value &= ~EN8811H_POLARITY_RX_REVERSE; ++ if (device_property_read_bool(dev, "airoha,pnswap-tx")) ++ pbus_value &= ~EN8811H_POLARITY_TX_NORMAL; ++ else ++ pbus_value |= EN8811H_POLARITY_TX_NORMAL; ++ ret = air_buckpbus_reg_modify(phydev, EN8811H_POLARITY, ++ EN8811H_POLARITY_RX_REVERSE | ++ EN8811H_POLARITY_TX_NORMAL, pbus_value); ++ if (ret < 0) ++ return ret; ++ ++ ret = air_leds_init(phydev, EN8811H_LED_COUNT, AIR_PHY_LED_DUR, ++ AIR_LED_MODE_USER_DEFINE); ++ if (ret < 0) { ++ phydev_err(phydev, "Failed to initialize leds: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int en8811h_get_features(struct phy_device *phydev) ++{ ++ linkmode_set_bit_array(phy_basic_ports_array, ++ ARRAY_SIZE(phy_basic_ports_array), ++ phydev->supported); ++ ++ return genphy_c45_pma_read_abilities(phydev); ++} ++ ++static int en8811h_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface) ++{ ++ return RATE_MATCH_PAUSE; ++} ++ ++static int en8811h_config_aneg(struct phy_device *phydev) ++{ ++ bool changed = false; ++ int ret; ++ u32 adv; ++ ++ if (phydev->autoneg == AUTONEG_DISABLE) { ++ phydev_warn(phydev, "Disabling autoneg is not supported\n"); ++ return -EINVAL; ++ } ++ ++ adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising); ++ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, ++ MDIO_AN_10GBT_CTRL_ADV2_5G, adv); ++ if (ret < 0) ++ return ret; ++ if (ret > 0) ++ changed = true; ++ ++ return __genphy_config_aneg(phydev, changed); ++} ++ ++static int en8811h_read_status(struct phy_device *phydev) ++{ ++ struct en8811h_priv *priv = phydev->priv; ++ u32 pbus_value; ++ int ret, val; ++ ++ ret = genphy_update_link(phydev); ++ if (ret) ++ return ret; ++ ++ phydev->master_slave_get = MASTER_SLAVE_CFG_UNSUPPORTED; ++ phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; ++ phydev->speed = SPEED_UNKNOWN; ++ phydev->duplex = DUPLEX_UNKNOWN; ++ phydev->pause = 0; ++ phydev->asym_pause = 0; ++ phydev->rate_matching = RATE_MATCH_PAUSE; ++ ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = genphy_read_lpa(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* Get link partner 2.5GBASE-T ability from vendor register */ ++ ret = air_buckpbus_reg_read(phydev, EN8811H_2P5G_LPA, &pbus_value); ++ if (ret < 0) ++ return ret; ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ phydev->lp_advertising, ++ pbus_value & EN8811H_2P5G_LPA_2P5G); ++ ++ if (phydev->autoneg_complete) ++ phy_resolve_aneg_pause(phydev); ++ ++ if (!phydev->link) ++ return 0; ++ ++ /* Get real speed from vendor register */ ++ val = phy_read(phydev, AIR_AUX_CTRL_STATUS); ++ if (val < 0) ++ return val; ++ switch (val & AIR_AUX_CTRL_STATUS_SPEED_MASK) { ++ case AIR_AUX_CTRL_STATUS_SPEED_2500: ++ phydev->speed = SPEED_2500; ++ break; ++ case AIR_AUX_CTRL_STATUS_SPEED_1000: ++ phydev->speed = SPEED_1000; ++ break; ++ case AIR_AUX_CTRL_STATUS_SPEED_100: ++ phydev->speed = SPEED_100; ++ break; ++ } ++ ++ /* Firmware before version 24011202 has no vendor register 2P5G_LPA. ++ * Assume link partner advertised it if connected at 2500Mbps. ++ */ ++ if (priv->firmware_version < 0x24011202) { ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ phydev->lp_advertising, ++ phydev->speed == SPEED_2500); ++ } ++ ++ /* Only supports full duplex */ ++ phydev->duplex = DUPLEX_FULL; ++ ++ return 0; ++} ++ ++static int en8811h_clear_intr(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_MCU_CMD_3, ++ AIR_PHY_MCU_CMD_3_DOCMD); ++ if (ret < 0) ++ return ret; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_MCU_CMD_4, ++ AIR_PHY_MCU_CMD_4_INTCLR); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static irqreturn_t en8811h_handle_interrupt(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = en8811h_clear_intr(phydev); ++ if (ret < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct phy_driver en8811h_driver[] = { ++{ ++ PHY_ID_MATCH_MODEL(EN8811H_PHY_ID), ++ .name = "Airoha EN8811H", ++ .probe = en8811h_probe, ++ .get_features = en8811h_get_features, ++ .config_init = en8811h_config_init, ++ .get_rate_matching = en8811h_get_rate_matching, ++ .config_aneg = en8811h_config_aneg, ++ .read_status = en8811h_read_status, ++ .config_intr = en8811h_clear_intr, ++ .handle_interrupt = en8811h_handle_interrupt, ++ .led_hw_is_supported = en8811h_led_hw_is_supported, ++ .read_page = air_phy_read_page, ++ .write_page = air_phy_write_page, ++ .led_blink_set = air_led_blink_set, ++ .led_brightness_set = air_led_brightness_set, ++ .led_hw_control_set = air_led_hw_control_set, ++ .led_hw_control_get = air_led_hw_control_get, ++} }; ++ ++module_phy_driver(en8811h_driver); ++ ++static struct mdio_device_id __maybe_unused en8811h_tbl[] = { ++ { PHY_ID_MATCH_MODEL(EN8811H_PHY_ID) }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, en8811h_tbl); ++MODULE_FIRMWARE(EN8811H_MD32_DM); ++MODULE_FIRMWARE(EN8811H_MD32_DSP); ++ ++MODULE_DESCRIPTION("Airoha EN8811H PHY drivers"); ++MODULE_AUTHOR("Airoha"); ++MODULE_AUTHOR("Eric Woudstra "); ++MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/generic/backport-6.1/799-v6.10-net-phy-air_en8811h-fix-some-error-codes.patch b/lede/target/linux/generic/backport-6.1/799-v6.10-net-phy-air_en8811h-fix-some-error-codes.patch new file mode 100644 index 0000000000..1bd0eefe77 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/799-v6.10-net-phy-air_en8811h-fix-some-error-codes.patch @@ -0,0 +1,47 @@ +From 87c33315af380ca12a2e59ac94edad4fe0481b4c Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Fri, 5 Apr 2024 13:08:59 +0300 +Subject: [PATCH] net: phy: air_en8811h: fix some error codes + +These error paths accidentally return "ret" which is zero/success +instead of the correct error code. + +Fixes: 71e79430117d ("net: phy: air_en8811h: Add the Airoha EN8811H PHY driver") +Signed-off-by: Dan Carpenter +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/7ef2e230-dfb7-4a77-8973-9e5be1a99fc2@moroto.mountain +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/air_en8811h.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/phy/air_en8811h.c ++++ b/drivers/net/phy/air_en8811h.c +@@ -272,11 +272,11 @@ static int __air_buckpbus_reg_read(struc + + pbus_data_high = __phy_read(phydev, AIR_BPBUS_RD_DATA_HIGH); + if (pbus_data_high < 0) +- return ret; ++ return pbus_data_high; + + pbus_data_low = __phy_read(phydev, AIR_BPBUS_RD_DATA_LOW); + if (pbus_data_low < 0) +- return ret; ++ return pbus_data_low; + + *pbus_data = pbus_data_low | (pbus_data_high << 16); + return 0; +@@ -323,11 +323,11 @@ static int __air_buckpbus_reg_modify(str + + pbus_data_high = __phy_read(phydev, AIR_BPBUS_RD_DATA_HIGH); + if (pbus_data_high < 0) +- return ret; ++ return pbus_data_high; + + pbus_data_low = __phy_read(phydev, AIR_BPBUS_RD_DATA_LOW); + if (pbus_data_low < 0) +- return ret; ++ return pbus_data_low; + + pbus_data_old = pbus_data_low | (pbus_data_high << 16); + pbus_data_new = (pbus_data_old & ~mask) | set; diff --git a/lede/target/linux/generic/backport-6.1/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch b/lede/target/linux/generic/backport-6.1/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch index 07becafbeb..f6a025fa12 100644 --- a/lede/target/linux/generic/backport-6.1/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch +++ b/lede/target/linux/generic/backport-6.1/801-v6.4-01-net-dsa-qca8k-move-qca8k_port_to_phy-to-header.patch @@ -20,7 +20,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/dsa/qca/qca8k-8xxx.c +++ b/drivers/net/dsa/qca/qca8k-8xxx.c -@@ -730,21 +730,6 @@ err_clear_skb: +@@ -789,21 +789,6 @@ err_clear_skb: return ret; } @@ -44,7 +44,7 @@ Signed-off-by: David S. Miller { --- a/drivers/net/dsa/qca/qca8k.h +++ b/drivers/net/dsa/qca/qca8k.h -@@ -422,6 +422,20 @@ struct qca8k_fdb { +@@ -421,6 +421,20 @@ struct qca8k_fdb { u8 mac[6]; }; diff --git a/lede/target/linux/generic/backport-6.1/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch b/lede/target/linux/generic/backport-6.1/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch index 414ba97e9c..409fe9c7a1 100644 --- a/lede/target/linux/generic/backport-6.1/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch +++ b/lede/target/linux/generic/backport-6.1/801-v6.4-02-net-dsa-qca8k-add-LEDs-basic-support.patch @@ -71,7 +71,7 @@ Signed-off-by: David S. Miller static void qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) -@@ -1751,6 +1752,10 @@ qca8k_setup(struct dsa_switch *ds) +@@ -1851,6 +1852,10 @@ qca8k_setup(struct dsa_switch *ds) if (ret) return ret; @@ -386,7 +386,7 @@ Signed-off-by: David S. Miller #define QCA8K_GOL_MAC_ADDR0 0x60 #define QCA8K_GOL_MAC_ADDR1 0x64 #define QCA8K_MAX_FRAME_SIZE 0x78 -@@ -383,6 +429,19 @@ struct qca8k_pcs { +@@ -382,6 +428,19 @@ struct qca8k_pcs { int port; }; @@ -406,7 +406,7 @@ Signed-off-by: David S. Miller struct qca8k_priv { u8 switch_id; u8 switch_revision; -@@ -407,6 +466,7 @@ struct qca8k_priv { +@@ -406,6 +465,7 @@ struct qca8k_priv { struct qca8k_pcs pcs_port_0; struct qca8k_pcs pcs_port_6; const struct qca8k_match_data *info; diff --git a/lede/target/linux/generic/backport-6.1/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch b/lede/target/linux/generic/backport-6.1/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch index a3184513ee..0d2c0bcd83 100644 --- a/lede/target/linux/generic/backport-6.1/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch +++ b/lede/target/linux/generic/backport-6.1/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch @@ -48,7 +48,7 @@ Signed-off-by: David S. Miller #include #include #include -@@ -644,6 +646,7 @@ struct phy_device *phy_device_create(str +@@ -642,6 +644,7 @@ struct phy_device *phy_device_create(str device_initialize(&mdiodev->dev); dev->state = PHY_DOWN; @@ -56,7 +56,7 @@ Signed-off-by: David S. Miller mutex_init(&dev->lock); INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); -@@ -2931,6 +2934,74 @@ static bool phy_drv_supports_irq(struct +@@ -3035,6 +3038,74 @@ static bool phy_drv_supports_irq(struct return phydrv->config_intr && phydrv->handle_interrupt; } @@ -131,7 +131,7 @@ Signed-off-by: David S. Miller /** * fwnode_mdio_find_device - Given a fwnode, find the mdio_device * @fwnode: pointer to the mdio_device's fwnode -@@ -3109,6 +3180,11 @@ static int phy_probe(struct device *dev) +@@ -3213,6 +3284,11 @@ static int phy_probe(struct device *dev) /* Set the state to READY by default */ phydev->state = PHY_READY; @@ -153,7 +153,7 @@ Signed-off-by: David S. Miller #include #include #include -@@ -593,6 +594,7 @@ struct macsec_ops; +@@ -606,6 +607,7 @@ struct macsec_ops; * @phy_num_led_triggers: Number of triggers in @phy_led_triggers * @led_link_trigger: LED trigger for link up/down * @last_triggered: last LED trigger for link speed @@ -161,7 +161,7 @@ Signed-off-by: David S. Miller * @master_slave_set: User requested master/slave configuration * @master_slave_get: Current master/slave advertisement * @master_slave_state: Current master/slave configuration -@@ -685,6 +687,7 @@ struct phy_device { +@@ -698,6 +700,7 @@ struct phy_device { struct phy_led_trigger *led_link_trigger; #endif @@ -169,7 +169,7 @@ Signed-off-by: David S. Miller /* * Interrupt number for this PHY -@@ -759,6 +762,19 @@ struct phy_tdr_config { +@@ -772,6 +775,19 @@ struct phy_tdr_config { #define PHY_PAIR_ALL -1 /** diff --git a/lede/target/linux/generic/backport-6.1/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/lede/target/linux/generic/backport-6.1/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch index 57db12ed4a..4873c40a77 100644 --- a/lede/target/linux/generic/backport-6.1/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ b/lede/target/linux/generic/backport-6.1/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -20,7 +20,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -2934,11 +2934,18 @@ static bool phy_drv_supports_irq(struct +@@ -3038,11 +3038,18 @@ static bool phy_drv_supports_irq(struct return phydrv->config_intr && phydrv->handle_interrupt; } @@ -41,7 +41,7 @@ Signed-off-by: David S. Miller } static int of_phy_led(struct phy_device *phydev, -@@ -2955,12 +2962,14 @@ static int of_phy_led(struct phy_device +@@ -3059,12 +3066,14 @@ static int of_phy_led(struct phy_device return -ENOMEM; cdev = &phyled->led_cdev; @@ -59,7 +59,7 @@ Signed-off-by: David S. Miller init_data.fwnode = of_fwnode_handle(led); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -765,15 +765,19 @@ struct phy_tdr_config { +@@ -778,15 +778,19 @@ struct phy_tdr_config { * struct phy_led: An LED driven by the PHY * * @list: List of LEDs @@ -79,7 +79,7 @@ Signed-off-by: David S. Miller /** * struct phy_driver - Driver structure for a particular PHY type * -@@ -988,6 +992,15 @@ struct phy_driver { +@@ -1001,6 +1005,15 @@ struct phy_driver { int (*get_sqi)(struct phy_device *dev); /** @get_sqi_max: Get the maximum signal quality indication */ int (*get_sqi_max)(struct phy_device *dev); diff --git a/lede/target/linux/generic/backport-6.1/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/lede/target/linux/generic/backport-6.1/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch index e868722afa..00bdcc5468 100644 --- a/lede/target/linux/generic/backport-6.1/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ b/lede/target/linux/generic/backport-6.1/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -18,7 +18,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -2948,6 +2948,22 @@ static int phy_led_set_brightness(struct +@@ -3052,6 +3052,22 @@ static int phy_led_set_brightness(struct return err; } @@ -41,7 +41,7 @@ Signed-off-by: David S. Miller static int of_phy_led(struct phy_device *phydev, struct device_node *led) { -@@ -2970,6 +2986,8 @@ static int of_phy_led(struct phy_device +@@ -3074,6 +3090,8 @@ static int of_phy_led(struct phy_device if (phydev->drv->led_brightness_set) cdev->brightness_set_blocking = phy_led_set_brightness; @@ -52,7 +52,7 @@ Signed-off-by: David S. Miller init_data.fwnode = of_fwnode_handle(led); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -1001,6 +1001,18 @@ struct phy_driver { +@@ -1014,6 +1014,18 @@ struct phy_driver { */ int (*led_brightness_set)(struct phy_device *dev, u8 index, enum led_brightness value); diff --git a/lede/target/linux/generic/backport-6.1/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch b/lede/target/linux/generic/backport-6.1/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch new file mode 100644 index 0000000000..ac322e1939 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/806-v6.5-net-dsa-qca8k-add-support-for-additional-modes-for-n.patch @@ -0,0 +1,64 @@ +From 2555f35a4f428a9bfdf09aa0459dbfdf59a24a9a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 21 Jun 2023 11:54:09 +0200 +Subject: [PATCH] net: dsa: qca8k: add support for additional modes for netdev + trigger + +The QCA8K switch supports additional modes that can be handled in +hardware for the LED netdev trigger. + +Add these additional modes to further support the Switch LEDs and +offload more blink modes. + +Add additional modes: +- link_10 +- link_100 +- link_1000 +- half_duplex +- full_duplex + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20230621095409.25859-1-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/qca/qca8k-leds.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/drivers/net/dsa/qca/qca8k-leds.c ++++ b/drivers/net/dsa/qca/qca8k-leds.c +@@ -68,6 +68,16 @@ qca8k_parse_netdev(unsigned long rules, + *offload_trigger |= QCA8K_LED_TX_BLINK_MASK; + if (test_bit(TRIGGER_NETDEV_RX, &rules)) + *offload_trigger |= QCA8K_LED_RX_BLINK_MASK; ++ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) ++ *offload_trigger |= QCA8K_LED_LINK_10M_EN_MASK; ++ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ *offload_trigger |= QCA8K_LED_LINK_100M_EN_MASK; ++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ *offload_trigger |= QCA8K_LED_LINK_1000M_EN_MASK; ++ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) ++ *offload_trigger |= QCA8K_LED_HALF_DUPLEX_MASK; ++ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) ++ *offload_trigger |= QCA8K_LED_FULL_DUPLEX_MASK; + + if (rules && !*offload_trigger) + return -EOPNOTSUPP; +@@ -322,6 +332,16 @@ qca8k_cled_hw_control_get(struct led_cla + set_bit(TRIGGER_NETDEV_TX, rules); + if (val & QCA8K_LED_RX_BLINK_MASK) + set_bit(TRIGGER_NETDEV_RX, rules); ++ if (val & QCA8K_LED_LINK_10M_EN_MASK) ++ set_bit(TRIGGER_NETDEV_LINK_10, rules); ++ if (val & QCA8K_LED_LINK_100M_EN_MASK) ++ set_bit(TRIGGER_NETDEV_LINK_100, rules); ++ if (val & QCA8K_LED_LINK_1000M_EN_MASK) ++ set_bit(TRIGGER_NETDEV_LINK_1000, rules); ++ if (val & QCA8K_LED_HALF_DUPLEX_MASK) ++ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); ++ if (val & QCA8K_LED_FULL_DUPLEX_MASK) ++ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); + + return 0; + } diff --git a/lede/target/linux/generic/backport-6.1/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch b/lede/target/linux/generic/backport-6.1/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch new file mode 100644 index 0000000000..8c062dc3b4 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/807-v6.5-01-net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch @@ -0,0 +1,64 @@ +From 4f86eb098e18fd0f032877dfa1a7e8c1503ca409 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= +Date: Mon, 29 May 2023 10:02:41 +0200 +Subject: [PATCH 1/6] net: dsa: mv88e6xxx: pass directly chip structure to + mv88e6xxx_phy_is_internal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since this function is a simple helper, we do not need to pass a full +dsa_switch structure, we can directly pass the mv88e6xxx_chip structure. +Doing so will allow to share this function with any other function +not manipulating dsa_switch structure but needing info about number of +internal phys + +Signed-off-by: Alexis Lothoré +Reviewed-by: Russell King (Oracle) +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/chip.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -470,10 +470,8 @@ restore_link: + return err; + } + +-static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port) ++static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port) + { +- struct mv88e6xxx_chip *chip = ds->priv; +- + return port < chip->info->num_internal_phys; + } + +@@ -591,7 +589,7 @@ static void mv88e6095_phylink_get_caps(s + + config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100; + +- if (mv88e6xxx_phy_is_internal(chip->ds, port)) { ++ if (mv88e6xxx_phy_is_internal(chip, port)) { + __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces); + } else { + if (cmode < ARRAY_SIZE(mv88e6185_phy_interface_modes) && +@@ -851,7 +849,7 @@ static void mv88e6xxx_get_caps(struct ds + chip->info->ops->phylink_get_caps(chip, port, config); + mv88e6xxx_reg_unlock(chip); + +- if (mv88e6xxx_phy_is_internal(ds, port)) { ++ if (mv88e6xxx_phy_is_internal(chip, port)) { + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + config->supported_interfaces); + /* Internal ports with no phy-mode need GMII for PHYLIB */ +@@ -872,7 +870,7 @@ static void mv88e6xxx_mac_config(struct + + mv88e6xxx_reg_lock(chip); + +- if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(ds, port)) { ++ if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(chip, port)) { + /* In inband mode, the link may come up at any time while the + * link is not forced down. Force the link down while we + * reconfigure the interface mode. diff --git a/lede/target/linux/generic/backport-6.1/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch b/lede/target/linux/generic/backport-6.1/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch new file mode 100644 index 0000000000..75a21a931d --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/807-v6.5-02-net-dsa-mv88e6xxx-use-mv88e6xxx_phy_is_internal-in-m.patch @@ -0,0 +1,31 @@ +From 73cbfad9296eed004992806e056db5b48583ca41 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= +Date: Mon, 29 May 2023 10:02:42 +0200 +Subject: [PATCH 2/6] net: dsa: mv88e6xxx: use mv88e6xxx_phy_is_internal in + mv88e6xxx_port_ppu_updates +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Make sure to use existing helper to get internal PHYs count instead of +redoing it manually + +Signed-off-by: Alexis Lothoré +Reviewed-by: Russell King (Oracle) +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/chip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -484,7 +484,7 @@ static int mv88e6xxx_port_ppu_updates(st + * report whether the port is internal. + */ + if (chip->info->family == MV88E6XXX_FAMILY_6250) +- return port < chip->info->num_internal_phys; ++ return mv88e6xxx_phy_is_internal(chip, port); + + err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®); + if (err) { diff --git a/lede/target/linux/generic/backport-6.1/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch b/lede/target/linux/generic/backport-6.1/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch new file mode 100644 index 0000000000..e24dca819b --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/807-v6.5-03-net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch @@ -0,0 +1,69 @@ +From 1414d30660d201f515a9d877571ceea9ca190b6a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= +Date: Mon, 29 May 2023 10:02:43 +0200 +Subject: [PATCH 3/6] net: dsa: mv88e6xxx: add field to specify internal phys + layout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mv88e6xxx currently assumes that switch equipped with internal phys have +those phys mapped contiguously starting from port 0 (see +mv88e6xxx_phy_is_internal). However, some switches have internal PHYs but +NOT starting from port 0. For example 88e6393X, 88E6193X and 88E6191X have +integrated PHYs available on ports 1 to 8 +To properly support this offset, add a new field to allow specifying an +internal PHYs layout. If field is not set, default layout is assumed (start +at port 0) + +Signed-off-by: Alexis Lothoré +Reviewed-by: Andrew Lunn +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/chip.c | 4 +++- + drivers/net/dsa/mv88e6xxx/chip.h | 5 +++++ + drivers/net/dsa/mv88e6xxx/global2.c | 5 ++++- + 3 files changed, 12 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -472,7 +472,9 @@ restore_link: + + static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port) + { +- return port < chip->info->num_internal_phys; ++ return port >= chip->info->internal_phys_offset && ++ port < chip->info->num_internal_phys + ++ chip->info->internal_phys_offset; + } + + static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port) +--- a/drivers/net/dsa/mv88e6xxx/chip.h ++++ b/drivers/net/dsa/mv88e6xxx/chip.h +@@ -167,6 +167,11 @@ struct mv88e6xxx_info { + + /* Supports PTP */ + bool ptp_support; ++ ++ /* Internal PHY start index. 0 means that internal PHYs range starts at ++ * port 0, 1 means internal PHYs range starts at port 1, etc ++ */ ++ unsigned int internal_phys_offset; + }; + + struct mv88e6xxx_atu_entry { +--- a/drivers/net/dsa/mv88e6xxx/global2.c ++++ b/drivers/net/dsa/mv88e6xxx/global2.c +@@ -1185,8 +1185,11 @@ int mv88e6xxx_g2_irq_mdio_setup(struct m + struct mii_bus *bus) + { + int phy, irq, err, err_phy; ++ int phy_start = chip->info->internal_phys_offset; ++ int phy_end = chip->info->internal_phys_offset + ++ chip->info->num_internal_phys; + +- for (phy = 0; phy < chip->info->num_internal_phys; phy++) { ++ for (phy = phy_start; phy < phy_end; phy++) { + irq = irq_find_mapping(chip->g2_irq.domain, phy); + if (irq < 0) { + err = irq; diff --git a/lede/target/linux/generic/backport-6.1/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch b/lede/target/linux/generic/backport-6.1/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch new file mode 100644 index 0000000000..cadc70fd73 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/807-v6.5-04-net-dsa-mv88e6xxx-fix-88E6393X-family-internal-phys-.patch @@ -0,0 +1,52 @@ +From eb8c75f82a6711387f3b9e03e28923f3e75a761b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= +Date: Mon, 29 May 2023 10:02:44 +0200 +Subject: [PATCH 4/6] net: dsa: mv88e6xxx: fix 88E6393X family internal phys + layout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +88E6393X/88E6193X/88E6191X switches have in fact 8 internal PHYs, but those +are not present starting at port 0: supported ports go from 1 to 8 + +Signed-off-by: Alexis Lothoré +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/chip.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -5998,7 +5998,8 @@ static const struct mv88e6xxx_info mv88e + .name = "Marvell 88E6191X", + .num_databases = 4096, + .num_ports = 11, /* 10 + Z80 */ +- .num_internal_phys = 9, ++ .num_internal_phys = 8, ++ .internal_phys_offset = 1, + .max_vid = 8191, + .max_sid = 63, + .port_base_addr = 0x0, +@@ -6021,7 +6022,8 @@ static const struct mv88e6xxx_info mv88e + .name = "Marvell 88E6193X", + .num_databases = 4096, + .num_ports = 11, /* 10 + Z80 */ +- .num_internal_phys = 9, ++ .num_internal_phys = 8, ++ .internal_phys_offset = 1, + .max_vid = 8191, + .max_sid = 63, + .port_base_addr = 0x0, +@@ -6340,7 +6342,8 @@ static const struct mv88e6xxx_info mv88e + .name = "Marvell 88E6393X", + .num_databases = 4096, + .num_ports = 11, /* 10 + Z80 */ +- .num_internal_phys = 9, ++ .num_internal_phys = 8, ++ .internal_phys_offset = 1, + .max_vid = 8191, + .max_sid = 63, + .port_base_addr = 0x0, diff --git a/lede/target/linux/generic/backport-6.1/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch b/lede/target/linux/generic/backport-6.1/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch new file mode 100644 index 0000000000..e2d3b57ccc --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/807-v6.5-05-net-dsa-mv88e6xxx-pass-mv88e6xxx_chip-structure-to-p.patch @@ -0,0 +1,110 @@ +From cef945452c8468efce75ba0dc8420510a5b84af9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= +Date: Mon, 29 May 2023 10:02:45 +0200 +Subject: [PATCH 5/6] net: dsa: mv88e6xxx: pass mv88e6xxx_chip structure to + port_max_speed_mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some switches families have minor differences on supported link speed for +ports. Instead of redefining a new port_max_speed_mode for each different +configuration, allow to pass mv88e6xxx_chip structure to allow +differentiating those chips by known chip id + +Signed-off-by: Alexis Lothoré +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/chip.c | 2 +- + drivers/net/dsa/mv88e6xxx/chip.h | 3 ++- + drivers/net/dsa/mv88e6xxx/port.c | 12 ++++++++---- + drivers/net/dsa/mv88e6xxx/port.h | 12 ++++++++---- + 4 files changed, 19 insertions(+), 10 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -3350,7 +3350,7 @@ static int mv88e6xxx_setup_port(struct m + caps = pl_config.mac_capabilities; + + if (chip->info->ops->port_max_speed_mode) +- mode = chip->info->ops->port_max_speed_mode(port); ++ mode = chip->info->ops->port_max_speed_mode(chip, port); + else + mode = PHY_INTERFACE_MODE_NA; + +--- a/drivers/net/dsa/mv88e6xxx/chip.h ++++ b/drivers/net/dsa/mv88e6xxx/chip.h +@@ -514,7 +514,8 @@ struct mv88e6xxx_ops { + int speed, int duplex); + + /* What interface mode should be used for maximum speed? */ +- phy_interface_t (*port_max_speed_mode)(int port); ++ phy_interface_t (*port_max_speed_mode)(struct mv88e6xxx_chip *chip, ++ int port); + + int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port); + +--- a/drivers/net/dsa/mv88e6xxx/port.c ++++ b/drivers/net/dsa/mv88e6xxx/port.c +@@ -342,7 +342,8 @@ int mv88e6341_port_set_speed_duplex(stru + duplex); + } + +-phy_interface_t mv88e6341_port_max_speed_mode(int port) ++phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port) + { + if (port == 5) + return PHY_INTERFACE_MODE_2500BASEX; +@@ -381,7 +382,8 @@ int mv88e6390_port_set_speed_duplex(stru + duplex); + } + +-phy_interface_t mv88e6390_port_max_speed_mode(int port) ++phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port) + { + if (port == 9 || port == 10) + return PHY_INTERFACE_MODE_2500BASEX; +@@ -403,7 +405,8 @@ int mv88e6390x_port_set_speed_duplex(str + duplex); + } + +-phy_interface_t mv88e6390x_port_max_speed_mode(int port) ++phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port) + { + if (port == 9 || port == 10) + return PHY_INTERFACE_MODE_XAUI; +@@ -500,7 +503,8 @@ int mv88e6393x_port_set_speed_duplex(str + return 0; + } + +-phy_interface_t mv88e6393x_port_max_speed_mode(int port) ++phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port) + { + if (port == 0 || port == 9 || port == 10) + return PHY_INTERFACE_MODE_10GBASER; +--- a/drivers/net/dsa/mv88e6xxx/port.h ++++ b/drivers/net/dsa/mv88e6xxx/port.h +@@ -359,10 +359,14 @@ int mv88e6390x_port_set_speed_duplex(str + int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, + int speed, int duplex); + +-phy_interface_t mv88e6341_port_max_speed_mode(int port); +-phy_interface_t mv88e6390_port_max_speed_mode(int port); +-phy_interface_t mv88e6390x_port_max_speed_mode(int port); +-phy_interface_t mv88e6393x_port_max_speed_mode(int port); ++phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port); ++phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port); ++phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port); ++phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, ++ int port); + + int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); + diff --git a/lede/target/linux/generic/backport-6.1/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch b/lede/target/linux/generic/backport-6.1/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch new file mode 100644 index 0000000000..471e6a3903 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/807-v6.5-06-net-dsa-mv88e6xxx-enable-support-for-88E6361-switch.patch @@ -0,0 +1,153 @@ +From 23680321789863bab2d60af507858ce50ff9f56a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= +Date: Mon, 29 May 2023 10:02:46 +0200 +Subject: [PATCH 6/6] net: dsa: mv88e6xxx: enable support for 88E6361 switch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Marvell 88E6361 is an 8-port switch derived from the +88E6393X/88E9193X/88E6191X switches family. It can benefit from the +existing mv88e6xxx driver by simply adding the proper switch description in +the driver. Main differences with other switches from this +family are: +- 8 ports exposed (instead of 11): ports 1, 2 and 8 not available +- No 5GBase-x nor SFI/USXGMII support + +Signed-off-by: Alexis Lothoré +Reviewed-by: Andrew Lunn +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/chip.c | 42 ++++++++++++++++++++++++++++---- + drivers/net/dsa/mv88e6xxx/chip.h | 3 ++- + drivers/net/dsa/mv88e6xxx/port.c | 14 ++++++++--- + drivers/net/dsa/mv88e6xxx/port.h | 1 + + 4 files changed, 51 insertions(+), 9 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -809,6 +809,8 @@ static void mv88e6393x_phylink_get_caps( + unsigned long *supported = config->supported_interfaces; + bool is_6191x = + chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6191X; ++ bool is_6361 = ++ chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361; + + mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported); + +@@ -823,13 +825,17 @@ static void mv88e6393x_phylink_get_caps( + /* 6191X supports >1G modes only on port 10 */ + if (!is_6191x || port == 10) { + __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); +- __set_bit(PHY_INTERFACE_MODE_5GBASER, supported); +- __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); ++ config->mac_capabilities |= MAC_2500FD; ++ ++ /* 6361 only supports up to 2500BaseX */ ++ if (!is_6361) { ++ __set_bit(PHY_INTERFACE_MODE_5GBASER, supported); ++ __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); ++ config->mac_capabilities |= MAC_5000FD | ++ MAC_10000FD; ++ } + /* FIXME: USXGMII is not supported yet */ + /* __set_bit(PHY_INTERFACE_MODE_USXGMII, supported); */ +- +- config->mac_capabilities |= MAC_2500FD | MAC_5000FD | +- MAC_10000FD; + } + } + +@@ -6285,6 +6291,32 @@ static const struct mv88e6xxx_info mv88e + .ptp_support = true, + .ops = &mv88e6352_ops, + }, ++ [MV88E6361] = { ++ .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6361, ++ .family = MV88E6XXX_FAMILY_6393, ++ .name = "Marvell 88E6361", ++ .num_databases = 4096, ++ .num_macs = 16384, ++ .num_ports = 11, ++ /* Ports 1, 2 and 8 are not routed */ ++ .invalid_port_mask = BIT(1) | BIT(2) | BIT(8), ++ .num_internal_phys = 5, ++ .internal_phys_offset = 3, ++ .max_vid = 4095, ++ .max_sid = 63, ++ .port_base_addr = 0x0, ++ .phy_base_addr = 0x0, ++ .global1_addr = 0x1b, ++ .global2_addr = 0x1c, ++ .age_time_coeff = 3750, ++ .g1_irqs = 10, ++ .g2_irqs = 14, ++ .atu_move_port_mask = 0x1f, ++ .pvt = true, ++ .multi_chip = true, ++ .ptp_support = true, ++ .ops = &mv88e6393x_ops, ++ }, + [MV88E6390] = { + .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390, + .family = MV88E6XXX_FAMILY_6390, +--- a/drivers/net/dsa/mv88e6xxx/chip.h ++++ b/drivers/net/dsa/mv88e6xxx/chip.h +@@ -82,6 +82,7 @@ enum mv88e6xxx_model { + MV88E6350, + MV88E6351, + MV88E6352, ++ MV88E6361, + MV88E6390, + MV88E6390X, + MV88E6393X, +@@ -100,7 +101,7 @@ enum mv88e6xxx_family { + MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ + MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */ + MV88E6XXX_FAMILY_6390, /* 6190 6190X 6191 6290 6390 6390X */ +- MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6393X */ ++ MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6361 6393X */ + }; + + /** +--- a/drivers/net/dsa/mv88e6xxx/port.c ++++ b/drivers/net/dsa/mv88e6xxx/port.c +@@ -424,6 +424,10 @@ int mv88e6393x_port_set_speed_duplex(str + u16 reg, ctrl; + int err; + ++ if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361 && ++ speed > 2500) ++ return -EOPNOTSUPP; ++ + if (speed == 200 && port != 0) + return -EOPNOTSUPP; + +@@ -506,10 +510,14 @@ int mv88e6393x_port_set_speed_duplex(str + phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port) + { +- if (port == 0 || port == 9 || port == 10) +- return PHY_INTERFACE_MODE_10GBASER; + +- return PHY_INTERFACE_MODE_NA; ++ if (port != 0 && port != 9 && port != 10) ++ return PHY_INTERFACE_MODE_NA; ++ ++ if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361) ++ return PHY_INTERFACE_MODE_2500BASEX; ++ ++ return PHY_INTERFACE_MODE_10GBASER; + } + + static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port, +--- a/drivers/net/dsa/mv88e6xxx/port.h ++++ b/drivers/net/dsa/mv88e6xxx/port.h +@@ -133,6 +133,7 @@ + #define MV88E6XXX_PORT_SWITCH_ID_PROD_6220 0x2200 + #define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400 + #define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500 ++#define MV88E6XXX_PORT_SWITCH_ID_PROD_6361 0x2610 + #define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900 + #define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100 + #define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400 diff --git a/lede/target/linux/generic/backport-6.1/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch b/lede/target/linux/generic/backport-6.1/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch new file mode 100644 index 0000000000..5c4206da14 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/810-v6.3-i915-Move-list_count-to-list.h-as-list_count_nodes-f.patch @@ -0,0 +1,75 @@ +From 4d70c74659d9746502b23d055dba03d1d28ec388 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Wed, 30 Nov 2022 15:48:35 +0200 +Subject: [PATCH] i915: Move list_count() to list.h as list_count_nodes() for + broader use + +Some of the existing users, and definitely will be new ones, want to +count existing nodes in the list. Provide a generic API for that by +moving code from i915 to list.h. + +Reviewed-by: Lucas De Marchi +Acked-by: Jani Nikula +Signed-off-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20221130134838.23805-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/gt/intel_engine_cs.c | 15 ++------------- + include/linux/list.h | 15 +++++++++++++++ + 2 files changed, 17 insertions(+), 13 deletions(-) + +--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c ++++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +@@ -4157,17 +4157,6 @@ void intel_execlists_show_requests(struc + spin_unlock_irqrestore(&sched_engine->lock, flags); + } + +-static unsigned long list_count(struct list_head *list) +-{ +- struct list_head *pos; +- unsigned long count = 0; +- +- list_for_each(pos, list) +- count++; +- +- return count; +-} +- + void intel_execlists_dump_active_requests(struct intel_engine_cs *engine, + struct i915_request *hung_rq, + struct drm_printer *m) +@@ -4178,8 +4167,8 @@ void intel_execlists_dump_active_request + + intel_engine_dump_active_requests(&engine->sched_engine->requests, hung_rq, m); + +- drm_printf(m, "\tOn hold?: %lu\n", +- list_count(&engine->sched_engine->hold)); ++ drm_printf(m, "\tOn hold?: %zu\n", ++ list_count_nodes(&engine->sched_engine->hold)); + + spin_unlock_irqrestore(&engine->sched_engine->lock, flags); + } +--- a/include/linux/list.h ++++ b/include/linux/list.h +@@ -656,6 +656,21 @@ static inline void list_splice_tail_init + pos = n, n = pos->prev) + + /** ++ * list_count_nodes - count nodes in the list ++ * @head: the head for your list. ++ */ ++static inline size_t list_count_nodes(struct list_head *head) ++{ ++ struct list_head *pos; ++ size_t count = 0; ++ ++ list_for_each(pos, head) ++ count++; ++ ++ return count; ++} ++ ++/** + * list_entry_is_head - test if the entry points to the head of the list + * @pos: the type * to cursor + * @head: the head for your list. diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch new file mode 100644 index 0000000000..bf7a816bb2 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0001-nvmem-sunxi_sid-Convert-to-devm_platform_ioremap_res.patch @@ -0,0 +1,36 @@ +From 9ccfcbeb8f32ff89e99b36cb9cdebaa0d1b44ed1 Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:24 +0100 +Subject: [PATCH] nvmem: sunxi_sid: Convert to devm_platform_ioremap_resource() + +Use devm_platform_ioremap_resource() to simplify code. + +Signed-off-by: Yangtao Li +Acked-by: Jernej Skrabec +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/sunxi_sid.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/nvmem/sunxi_sid.c ++++ b/drivers/nvmem/sunxi_sid.c +@@ -125,7 +125,6 @@ static int sun8i_sid_read_by_reg(void *c + static int sunxi_sid_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- struct resource *res; + struct nvmem_config *nvmem_cfg; + struct nvmem_device *nvmem; + struct sunxi_sid *sid; +@@ -142,8 +141,7 @@ static int sunxi_sid_probe(struct platfo + return -EINVAL; + sid->value_offset = cfg->value_offset; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- sid->base = devm_ioremap_resource(dev, res); ++ sid->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(sid->base)) + return PTR_ERR(sid->base); + diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch new file mode 100644 index 0000000000..f142d735de --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0002-nvmem-brcm_nvram-Use-devm_platform_get_and_ioremap_r.patch @@ -0,0 +1,30 @@ +From cfadd0e7d9225566f320bc4dc716682be910be6c Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:25 +0100 +Subject: [PATCH] nvmem: brcm_nvram: Use + devm_platform_get_and_ioremap_resource() + +Convert platform_get_resource(), devm_ioremap_resource() to a single +call to devm_platform_get_and_ioremap_resource(), as this is exactly +what this function does. + +Signed-off-by: Yangtao Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-4-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/brcm_nvram.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/nvmem/brcm_nvram.c ++++ b/drivers/nvmem/brcm_nvram.c +@@ -159,8 +159,7 @@ static int brcm_nvram_probe(struct platf + return -ENOMEM; + priv->dev = dev; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- priv->base = devm_ioremap_resource(dev, res); ++ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch new file mode 100644 index 0000000000..0395bbf8bc --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0003-nvmem-lpc18xx_otp-Convert-to-devm_platform_ioremap_r.patch @@ -0,0 +1,34 @@ +From 0b49178e2b6b4aac3c7fa3ce8d8c02208a13b988 Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:26 +0100 +Subject: [PATCH] nvmem: lpc18xx_otp: Convert to + devm_platform_ioremap_resource() + +Use devm_platform_ioremap_resource() to simplify code. + +Signed-off-by: Yangtao Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-5-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/lpc18xx_otp.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/nvmem/lpc18xx_otp.c ++++ b/drivers/nvmem/lpc18xx_otp.c +@@ -68,14 +68,12 @@ static int lpc18xx_otp_probe(struct plat + { + struct nvmem_device *nvmem; + struct lpc18xx_otp *otp; +- struct resource *res; + + otp = devm_kzalloc(&pdev->dev, sizeof(*otp), GFP_KERNEL); + if (!otp) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- otp->base = devm_ioremap_resource(&pdev->dev, res); ++ otp->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(otp->base)) + return PTR_ERR(otp->base); + diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch new file mode 100644 index 0000000000..da077eb4b7 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0004-nvmem-meson-mx-efuse-Convert-to-devm_platform_iorema.patch @@ -0,0 +1,36 @@ +From 0a223a097709b99a0ba738d6be5b4f52c04ffb64 Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:27 +0100 +Subject: [PATCH] nvmem: meson-mx-efuse: Convert to + devm_platform_ioremap_resource() + +Use devm_platform_ioremap_resource() to simplify code. + +Signed-off-by: Yangtao Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-6-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/meson-mx-efuse.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/nvmem/meson-mx-efuse.c ++++ b/drivers/nvmem/meson-mx-efuse.c +@@ -194,7 +194,6 @@ static int meson_mx_efuse_probe(struct p + { + const struct meson_mx_efuse_platform_data *drvdata; + struct meson_mx_efuse *efuse; +- struct resource *res; + + drvdata = of_device_get_match_data(&pdev->dev); + if (!drvdata) +@@ -204,8 +203,7 @@ static int meson_mx_efuse_probe(struct p + if (!efuse) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- efuse->base = devm_ioremap_resource(&pdev->dev, res); ++ efuse->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(efuse->base)) + return PTR_ERR(efuse->base); + diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch new file mode 100644 index 0000000000..dc144ddfbd --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0005-nvmem-rockchip-efuse-Use-devm_platform_get_and_iorem.patch @@ -0,0 +1,31 @@ +From 94904db28db49ac8fbb2a273d25156db26a3a985 Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:28 +0100 +Subject: [PATCH] nvmem: rockchip-efuse: Use + devm_platform_get_and_ioremap_resource() + +Convert platform_get_resource(), devm_ioremap_resource() to a single +call to devm_platform_get_and_ioremap_resource(), as this is exactly +what this function does. + +Signed-off-by: Yangtao Li +Reviewed-by: Heiko Stuebner +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-7-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/rockchip-efuse.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/nvmem/rockchip-efuse.c ++++ b/drivers/nvmem/rockchip-efuse.c +@@ -267,8 +267,7 @@ static int rockchip_efuse_probe(struct p + if (!efuse) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- efuse->base = devm_ioremap_resource(dev, res); ++ efuse->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(efuse->base)) + return PTR_ERR(efuse->base); + diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch new file mode 100644 index 0000000000..99e20939cc --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0006-nvmem-stm32-romem-Use-devm_platform_get_and_ioremap_.patch @@ -0,0 +1,30 @@ +From 0a4a8c0d238fec1fa4b85591524ef42ad261cb97 Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:29 +0100 +Subject: [PATCH] nvmem: stm32-romem: Use + devm_platform_get_and_ioremap_resource() + +Convert platform_get_resource(), devm_ioremap_resource() to a single +call to devm_platform_get_and_ioremap_resource(), as this is exactly +what this function does. + +Signed-off-by: Yangtao Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-8-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/stm32-romem.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -196,8 +196,7 @@ static int stm32_romem_probe(struct plat + if (!priv) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- priv->base = devm_ioremap_resource(dev, res); ++ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch new file mode 100644 index 0000000000..6d93752e27 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0007-nvmem-qfprom-do-some-cleanup.patch @@ -0,0 +1,59 @@ +From 0bc0d6dc2a9a05ae6729b4622f09782d9f230815 Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:30 +0100 +Subject: [PATCH] nvmem: qfprom: do some cleanup + +Use devm_platform_ioremap_resource() and +devm_platform_get_and_ioremap_resource() to simplify code. +BTW convert to use dev_err_probe() instead of open it. + +Signed-off-by: Yangtao Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-9-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/qfprom.c | 17 +++++------------ + 1 file changed, 5 insertions(+), 12 deletions(-) + +--- a/drivers/nvmem/qfprom.c ++++ b/drivers/nvmem/qfprom.c +@@ -374,8 +374,7 @@ static int qfprom_probe(struct platform_ + return -ENOMEM; + + /* The corrected section is always provided */ +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- priv->qfpcorrected = devm_ioremap_resource(dev, res); ++ priv->qfpcorrected = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(priv->qfpcorrected)) + return PTR_ERR(priv->qfpcorrected); + +@@ -402,12 +401,10 @@ static int qfprom_probe(struct platform_ + priv->qfpraw = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->qfpraw)) + return PTR_ERR(priv->qfpraw); +- res = platform_get_resource(pdev, IORESOURCE_MEM, 2); +- priv->qfpconf = devm_ioremap_resource(dev, res); ++ priv->qfpconf = devm_platform_ioremap_resource(pdev, 2); + if (IS_ERR(priv->qfpconf)) + return PTR_ERR(priv->qfpconf); +- res = platform_get_resource(pdev, IORESOURCE_MEM, 3); +- priv->qfpsecurity = devm_ioremap_resource(dev, res); ++ priv->qfpsecurity = devm_platform_ioremap_resource(pdev, 3); + if (IS_ERR(priv->qfpsecurity)) + return PTR_ERR(priv->qfpsecurity); + +@@ -427,12 +424,8 @@ static int qfprom_probe(struct platform_ + return PTR_ERR(priv->vcc); + + priv->secclk = devm_clk_get(dev, "core"); +- if (IS_ERR(priv->secclk)) { +- ret = PTR_ERR(priv->secclk); +- if (ret != -EPROBE_DEFER) +- dev_err(dev, "Error getting clock: %d\n", ret); +- return ret; +- } ++ if (IS_ERR(priv->secclk)) ++ return dev_err_probe(dev, PTR_ERR(priv->secclk), "Error getting clock\n"); + + /* Only enable writing if we have SoC data. */ + if (priv->soc_data) diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch new file mode 100644 index 0000000000..3e328a4c99 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0008-nvmem-uniphier-Use-devm_platform_get_and_ioremap_res.patch @@ -0,0 +1,29 @@ +From 6ac41c556e22a0d7d267c9b9d48681d73af4b368 Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Wed, 23 Aug 2023 14:27:31 +0100 +Subject: [PATCH] nvmem: uniphier: Use devm_platform_get_and_ioremap_resource() + +Convert platform_get_resource(), devm_ioremap_resource() to a single +call to devm_platform_get_and_ioremap_resource(), as this is exactly +what this function does. + +Signed-off-by: Yangtao Li +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20230823132744.350618-10-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/uniphier-efuse.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/nvmem/uniphier-efuse.c ++++ b/drivers/nvmem/uniphier-efuse.c +@@ -41,8 +41,7 @@ static int uniphier_efuse_probe(struct p + if (!priv) + return -ENOMEM; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- priv->base = devm_ioremap_resource(dev, res); ++ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch new file mode 100644 index 0000000000..acbe18e270 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0009-nvmem-add-new-NXP-QorIQ-eFuse-driver.patch @@ -0,0 +1,133 @@ +From c8efcf7a86ebf2ff48584d270b3070a7075bc345 Mon Sep 17 00:00:00 2001 +From: Richard Alpe +Date: Mon, 10 Apr 2023 10:20:51 +0200 +Subject: [PATCH] nvmem: add new NXP QorIQ eFuse driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add SFP (Security Fuse Processor) read support for NXP (Freescale) +QorIQ series SOC's. + +This patch adds support for the T1023 SOC using the SFP offset from +the existing T1023 device tree. In theory this should also work for +T1024, T1014 and T1013 which uses the same SFP base offset. + +Signed-off-by: Richard Alpe +Reviewed-by: Niklas Söderlund +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/Kconfig | 12 ++++++ + drivers/nvmem/Makefile | 2 + + drivers/nvmem/qoriq-efuse.c | 78 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 92 insertions(+) + create mode 100644 drivers/nvmem/qoriq-efuse.c + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -392,4 +392,16 @@ config NVMEM_ZYNQMP + + If sure, say yes. If unsure, say no. + ++config NVMEM_QORIQ_EFUSE ++ tristate "NXP QorIQ eFuse support" ++ depends on PPC_85xx || COMPILE_TEST ++ depends on HAS_IOMEM ++ help ++ This driver provides read support for the eFuses (SFP) on NXP QorIQ ++ series SoC's. This includes secure boot settings, the globally unique ++ NXP ID 'FUIDR' and the OEM unique ID 'OUIDR'. ++ ++ This driver can also be built as a module. If so, the module ++ will be called nvmem_qoriq_efuse. ++ + endif +--- a/drivers/nvmem/Makefile ++++ b/drivers/nvmem/Makefile +@@ -77,3 +77,5 @@ obj-$(CONFIG_NVMEM_VF610_OCOTP) += nvme + nvmem-vf610-ocotp-y := vf610-ocotp.o + obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynqmp_nvmem.o + nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o ++obj-$(CONFIG_NVMEM_QORIQ_EFUSE) += nvmem-qoriq-efuse.o ++nvmem-qoriq-efuse-y := qoriq-efuse.o +--- /dev/null ++++ b/drivers/nvmem/qoriq-efuse.c +@@ -0,0 +1,78 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2023 Westermo Network Technologies AB ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct qoriq_efuse_priv { ++ void __iomem *base; ++}; ++ ++static int qoriq_efuse_read(void *context, unsigned int offset, void *val, ++ size_t bytes) ++{ ++ struct qoriq_efuse_priv *priv = context; ++ ++ /* .stride = 4 so offset is guaranteed to be aligned */ ++ __ioread32_copy(val, priv->base + offset, bytes / 4); ++ ++ /* Ignore trailing bytes (there shouldn't be any) */ ++ ++ return 0; ++} ++ ++static int qoriq_efuse_probe(struct platform_device *pdev) ++{ ++ struct nvmem_config config = { ++ .dev = &pdev->dev, ++ .read_only = true, ++ .reg_read = qoriq_efuse_read, ++ .stride = sizeof(u32), ++ .word_size = sizeof(u32), ++ .name = "qoriq_efuse_read", ++ .id = NVMEM_DEVID_AUTO, ++ .root_only = true, ++ }; ++ struct qoriq_efuse_priv *priv; ++ struct nvmem_device *nvmem; ++ struct resource *res; ++ ++ priv = devm_kzalloc(config.dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ config.size = resource_size(res); ++ config.priv = priv; ++ nvmem = devm_nvmem_register(config.dev, &config); ++ ++ return PTR_ERR_OR_ZERO(nvmem); ++} ++ ++static const struct of_device_id qoriq_efuse_of_match[] = { ++ { .compatible = "fsl,t1023-sfp", }, ++ {/* sentinel */}, ++}; ++MODULE_DEVICE_TABLE(of, qoriq_efuse_of_match); ++ ++static struct platform_driver qoriq_efuse_driver = { ++ .probe = qoriq_efuse_probe, ++ .driver = { ++ .name = "qoriq-efuse", ++ .of_match_table = qoriq_efuse_of_match, ++ }, ++}; ++module_platform_driver(qoriq_efuse_driver); ++ ++MODULE_AUTHOR("Richard Alpe "); ++MODULE_DESCRIPTION("NXP QorIQ Security Fuse Processor (SFP) Reader"); ++MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch new file mode 100644 index 0000000000..67f30e34a2 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0011-nvmem-Kconfig-Fix-typo-drive-driver.patch @@ -0,0 +1,37 @@ +From 9d53d595f688c9837e88a919229cc61a165c7b9e Mon Sep 17 00:00:00 2001 +From: Diederik de Haas +Date: Mon, 24 Jul 2023 13:36:22 +0200 +Subject: [PATCH] nvmem: Kconfig: Fix typo "drive" -> "driver" + +Fix typo where "driver" was meant instead of "drive". +While at it, also capitalize "OTP". + +Signed-off-by: Diederik de Haas +Reviewed-by: Heiko Stuebner +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/Kconfig | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -247,7 +247,7 @@ config NVMEM_ROCKCHIP_EFUSE + depends on ARCH_ROCKCHIP || COMPILE_TEST + depends on HAS_IOMEM + help +- This is a simple drive to dump specified values of Rockchip SoC ++ This is a simple driver to dump specified values of Rockchip SoC + from eFuse, such as cpu-leakage. + + This driver can also be built as a module. If so, the module +@@ -258,8 +258,8 @@ config NVMEM_ROCKCHIP_OTP + depends on ARCH_ROCKCHIP || COMPILE_TEST + depends on HAS_IOMEM + help +- This is a simple drive to dump specified values of Rockchip SoC +- from otp, such as cpu-leakage. ++ This is a simple driver to dump specified values of Rockchip SoC ++ from OTP, such as cpu-leakage. + + This driver can also be built as a module. If so, the module + will be called nvmem_rockchip_otp. diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch new file mode 100644 index 0000000000..af4a2926dc --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch @@ -0,0 +1,152 @@ +From 0a9ec38c47c1ca4528aa058e2b9ea61901a7e632 Mon Sep 17 00:00:00 2001 +From: Komal Bajaj +Date: Tue, 1 Aug 2023 12:10:25 +0530 +Subject: [PATCH] nvmem: sec-qfprom: Add Qualcomm secure QFPROM support + +For some of the Qualcomm SoC's, it is possible that +some of the fuse regions or entire qfprom region is +protected from non-secure access. In such situations, +the OS will have to use secure calls to read the region. +With that motivation, add secure qfprom driver. + +Signed-off-by: Komal Bajaj +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/Kconfig | 13 ++++++ + drivers/nvmem/Makefile | 2 + + drivers/nvmem/sec-qfprom.c | 96 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 111 insertions(+) + create mode 100644 drivers/nvmem/sec-qfprom.c + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -226,6 +226,19 @@ config NVMEM_QCOM_QFPROM + This driver can also be built as a module. If so, the module + will be called nvmem_qfprom. + ++config NVMEM_QCOM_SEC_QFPROM ++ tristate "QCOM SECURE QFPROM Support" ++ depends on ARCH_QCOM || COMPILE_TEST ++ depends on HAS_IOMEM ++ depends on OF ++ select QCOM_SCM ++ help ++ Say y here to enable secure QFPROM support. The secure QFPROM provides access ++ functions for QFPROM data to rest of the drivers via nvmem interface. ++ ++ This driver can also be built as a module. If so, the module will be called ++ nvmem_sec_qfprom. ++ + config NVMEM_RAVE_SP_EEPROM + tristate "Rave SP EEPROM Support" + depends on RAVE_SP_CORE +--- a/drivers/nvmem/Makefile ++++ b/drivers/nvmem/Makefile +@@ -46,6 +46,8 @@ obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvme + nvmem-nintendo-otp-y := nintendo-otp.o + obj-$(CONFIG_NVMEM_QCOM_QFPROM) += nvmem_qfprom.o + nvmem_qfprom-y := qfprom.o ++obj-$(CONFIG_NVMEM_QCOM_SEC_QFPROM) += nvmem_sec_qfprom.o ++nvmem_sec_qfprom-y := sec-qfprom.o + obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o + nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o + obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o +--- /dev/null ++++ b/drivers/nvmem/sec-qfprom.c +@@ -0,0 +1,96 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/** ++ * struct sec_qfprom - structure holding secure qfprom attributes ++ * ++ * @base: starting physical address for secure qfprom corrected address space. ++ * @dev: qfprom device structure. ++ */ ++struct sec_qfprom { ++ phys_addr_t base; ++ struct device *dev; ++}; ++ ++static int sec_qfprom_reg_read(void *context, unsigned int reg, void *_val, size_t bytes) ++{ ++ struct sec_qfprom *priv = context; ++ unsigned int i; ++ u8 *val = _val; ++ u32 read_val; ++ u8 *tmp; ++ ++ for (i = 0; i < bytes; i++, reg++) { ++ if (i == 0 || reg % 4 == 0) { ++ if (qcom_scm_io_readl(priv->base + (reg & ~3), &read_val)) { ++ dev_err(priv->dev, "Couldn't access fuse register\n"); ++ return -EINVAL; ++ } ++ tmp = (u8 *)&read_val; ++ } ++ ++ val[i] = tmp[reg & 3]; ++ } ++ ++ return 0; ++} ++ ++static int sec_qfprom_probe(struct platform_device *pdev) ++{ ++ struct nvmem_config econfig = { ++ .name = "sec-qfprom", ++ .stride = 1, ++ .word_size = 1, ++ .id = NVMEM_DEVID_AUTO, ++ .reg_read = sec_qfprom_reg_read, ++ }; ++ struct device *dev = &pdev->dev; ++ struct nvmem_device *nvmem; ++ struct sec_qfprom *priv; ++ struct resource *res; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ return -EINVAL; ++ ++ priv->base = res->start; ++ ++ econfig.size = resource_size(res); ++ econfig.dev = dev; ++ econfig.priv = priv; ++ ++ priv->dev = dev; ++ ++ nvmem = devm_nvmem_register(dev, &econfig); ++ ++ return PTR_ERR_OR_ZERO(nvmem); ++} ++ ++static const struct of_device_id sec_qfprom_of_match[] = { ++ { .compatible = "qcom,sec-qfprom" }, ++ {/* sentinel */}, ++}; ++MODULE_DEVICE_TABLE(of, sec_qfprom_of_match); ++ ++static struct platform_driver qfprom_driver = { ++ .probe = sec_qfprom_probe, ++ .driver = { ++ .name = "qcom_sec_qfprom", ++ .of_match_table = sec_qfprom_of_match, ++ }, ++}; ++module_platform_driver(qfprom_driver); ++MODULE_DESCRIPTION("Qualcomm Secure QFPROM driver"); ++MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch new file mode 100644 index 0000000000..dab8ec2c24 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0013-nvmem-u-boot-env-Replace-zero-length-array-with-DECL.patch @@ -0,0 +1,30 @@ +From c32f2186acc9abb4d766361255d7ddf07d15eeb2 Mon Sep 17 00:00:00 2001 +From: Atul Raut +Date: Sun, 30 Jul 2023 15:39:15 -0700 +Subject: [PATCH] nvmem: u-boot-env:: Replace zero-length array with + DECLARE_FLEX_ARRAY() helper + +We are moving toward replacing zero-length arrays with C99 flexible-array +members since they are deprecated. Therefore, the new DECLARE_FLEX_ARRAY() +helper macro should be used to replace the zero-length array declaration. + +This fixes warnings such as: +./drivers/nvmem/u-boot-env.c:50:9-13: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays) + +Signed-off-by: Atul Raut +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/u-boot-env.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -47,7 +47,7 @@ struct u_boot_env_image_broadcom { + __le32 magic; + __le32 len; + __le32 crc32; +- uint8_t data[0]; ++ DECLARE_FLEX_ARRAY(uint8_t, data); + } __packed; + + static int u_boot_env_read(void *context, unsigned int offset, void *val, diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch new file mode 100644 index 0000000000..f9532f39c3 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0014-nvmem-core-Create-all-cells-before-adding-the-nvmem-.patch @@ -0,0 +1,40 @@ +From 104af6a5b199eb4dc7970d1304aef38ac5a6ed54 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 8 Aug 2023 08:29:26 +0200 +Subject: [PATCH] nvmem: core: Create all cells before adding the nvmem device + +Let's pack all the cells creation in one place, so they are all created +before we add the nvmem device. + +Signed-off-by: Miquel Raynal +Reviewed-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/core.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -998,17 +998,17 @@ struct nvmem_device *nvmem_register(cons + if (rval) + goto err_remove_cells; + +- dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); +- +- rval = device_add(&nvmem->dev); ++ rval = nvmem_add_cells_from_fixed_layout(nvmem); + if (rval) + goto err_remove_cells; + +- rval = nvmem_add_cells_from_fixed_layout(nvmem); ++ rval = nvmem_add_cells_from_layout(nvmem); + if (rval) + goto err_remove_cells; + +- rval = nvmem_add_cells_from_layout(nvmem); ++ dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); ++ ++ rval = device_add(&nvmem->dev); + if (rval) + goto err_remove_cells; + diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch new file mode 100644 index 0000000000..8f64d0c28b --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0015-nvmem-core-Return-NULL-when-no-nvmem-layout-is-found.patch @@ -0,0 +1,35 @@ +From 6c7f48ea2e663b679aa8e60d8d8e1e6306a644f9 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 8 Aug 2023 08:29:27 +0200 +Subject: [PATCH] nvmem: core: Return NULL when no nvmem layout is found + +Currently, of_nvmem_layout_get_container() returns NULL on error, or an +error pointer if either CONFIG_NVMEM or CONFIG_OF is turned off. We +should likely avoid this kind of mix for two reasons: to clarify the +intend and anyway fix the !CONFIG_OF which will likely always if we use +this helper somewhere else. Let's just return NULL when no layout is +found, we don't need an error value here. + +Link: https://staticthinking.wordpress.com/2022/08/01/mixing-error-pointers-and-null/ +Fixes: 266570f496b9 ("nvmem: core: introduce NVMEM layouts") +Reported-by: kernel test robot +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/r/202308030002.DnSFOrMB-lkp@intel.com/ +Signed-off-by: Miquel Raynal +Reviewed-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +--- + include/linux/nvmem-consumer.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -256,7 +256,7 @@ static inline struct nvmem_device *of_nv + static inline struct device_node * + of_nvmem_layout_get_container(struct nvmem_device *nvmem) + { +- return ERR_PTR(-EOPNOTSUPP); ++ return NULL; + } + #endif /* CONFIG_NVMEM && CONFIG_OF */ + diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch new file mode 100644 index 0000000000..28d8bba194 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0016-nvmem-core-Do-not-open-code-existing-functions.patch @@ -0,0 +1,29 @@ +From b8257f61b4ddac6d7d0e19a5a4e8b07afb3b4ed3 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 8 Aug 2023 08:29:28 +0200 +Subject: [PATCH] nvmem: core: Do not open-code existing functions + +Use of_nvmem_layout_get_container() instead of hardcoding it. + +Signed-off-by: Miquel Raynal +Reviewed-by: Michael Walle +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -786,10 +786,10 @@ EXPORT_SYMBOL_GPL(nvmem_layout_unregiste + + static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem) + { +- struct device_node *layout_np, *np = nvmem->dev.of_node; ++ struct device_node *layout_np; + struct nvmem_layout *l, *layout = ERR_PTR(-EPROBE_DEFER); + +- layout_np = of_get_child_by_name(np, "nvmem-layout"); ++ layout_np = of_nvmem_layout_get_container(nvmem); + if (!layout_np) + return NULL; + diff --git a/lede/target/linux/generic/backport-6.1/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch b/lede/target/linux/generic/backport-6.1/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch new file mode 100644 index 0000000000..b62a0e18da --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/814-v6.6-0017-nvmem-core-Notify-when-a-new-layout-is-registered.patch @@ -0,0 +1,44 @@ +From 0991afbe4b1805e7f0113ef10d7c5f0698a739e4 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 8 Aug 2023 08:29:29 +0200 +Subject: [PATCH] nvmem: core: Notify when a new layout is registered + +Tell listeners a new layout was introduced and is now available. + +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +--- + drivers/nvmem/core.c | 4 ++++ + include/linux/nvmem-consumer.h | 2 ++ + 2 files changed, 6 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -772,12 +772,16 @@ int __nvmem_layout_register(struct nvmem + list_add(&layout->node, &nvmem_layouts); + spin_unlock(&nvmem_layout_lock); + ++ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_LAYOUT_ADD, layout); ++ + return 0; + } + EXPORT_SYMBOL_GPL(__nvmem_layout_register); + + void nvmem_layout_unregister(struct nvmem_layout *layout) + { ++ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_LAYOUT_REMOVE, layout); ++ + spin_lock(&nvmem_layout_lock); + list_del(&layout->node); + spin_unlock(&nvmem_layout_lock); +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -43,6 +43,8 @@ enum { + NVMEM_REMOVE, + NVMEM_CELL_ADD, + NVMEM_CELL_REMOVE, ++ NVMEM_LAYOUT_ADD, ++ NVMEM_LAYOUT_REMOVE, + }; + + #if IS_ENABLED(CONFIG_NVMEM) diff --git a/lede/target/linux/generic/backport-6.1/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch b/lede/target/linux/generic/backport-6.1/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch new file mode 100644 index 0000000000..e17be439b2 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/815-v6.6-1-leds-turris-omnia-Use-sysfs_emit-instead-of-sprintf.patch @@ -0,0 +1,29 @@ +From a75b58a46423cfd9b1f73581f4bd2ac2ae743996 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Wed, 2 Aug 2023 18:07:45 +0200 +Subject: [PATCH 1/6] leds: turris-omnia: Use sysfs_emit() instead of sprintf() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use the dedicated sysfs_emit() function instead of sprintf() in sysfs +attribute accessor brightness_show(). + +Signed-off-by: Marek Behún +Link: https://lore.kernel.org/r/20230802160748.11208-4-kabel@kernel.org +Signed-off-by: Lee Jones +--- + drivers/leds/leds-turris-omnia.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/leds/leds-turris-omnia.c ++++ b/drivers/leds/leds-turris-omnia.c +@@ -194,7 +194,7 @@ static ssize_t brightness_show(struct de + if (ret < 0) + return ret; + +- return sprintf(buf, "%d\n", ret); ++ return sysfs_emit(buf, "%d\n", ret); + } + + static ssize_t brightness_store(struct device *dev, struct device_attribute *a, diff --git a/lede/target/linux/generic/backport-6.1/815-v6.7-2-leds-turris-omnia-Make-set_brightness-more-efficient.patch b/lede/target/linux/generic/backport-6.1/815-v6.7-2-leds-turris-omnia-Make-set_brightness-more-efficient.patch new file mode 100644 index 0000000000..d84ad67125 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/815-v6.7-2-leds-turris-omnia-Make-set_brightness-more-efficient.patch @@ -0,0 +1,207 @@ +From a64c3c1357275b1fd61bc9734f638cdb5d8a8bbb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 18 Sep 2023 18:11:02 +0200 +Subject: [PATCH 4/6] leds: turris-omnia: Make set_brightness() more efficient +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Implement caching of the LED color and state values that are sent to MCU +in order to make the set_brightness() operation more efficient by +avoiding I2C transactions which are not needed. + +On Turris Omnia's MCU, which acts as the RGB LED controller, each LED +has a RGB color, and a ON/OFF state, which are configurable via I2C +commands CMD_LED_COLOR and CMD_LED_STATE. + +The CMD_LED_COLOR command sends 5 bytes and the CMD_LED_STATE command 2 +bytes over the I2C bus, which operates at 100 kHz. With I2C overhead +this allows ~1670 color changing commands and ~3200 state changing +commands per second (or around 1000 color + state changes per second). +This may seem more than enough, but the issue is that the I2C bus is +shared with another peripheral, the MCU. The MCU exposes an interrupt +interface, and it can trigger hundreds of interrupts per second. Each +time, we need to read the interrupt state register over this I2C bus. +Whenever we are sending a LED color/state changing command, the +interrupt reading is waiting. + +Currently, every time LED brightness or LED multi intensity is changed, +we send a CMD_LED_STATE command, and if the computed color (brightness +adjusted multi_intensity) is non-zero, we also send a CMD_LED_COLOR +command. + +Consider for example the situation when we have a netdev trigger enabled +for a LED. The netdev trigger does not change the LED color, only the +brightness (either to 0 or to currently configured brightness), and so +there is no need to send the CMD_LED_COLOR command. But each change of +brightness to 0 sends one CMD_LED_STATE command, and each change of +brightness to max_brightness sends one CMD_LED_STATE command and one +CMD_LED_COLOR command: + set_brightness(0) -> CMD_LED_STATE + set_brightness(255) -> CMD_LED_STATE + CMD_LED_COLOR + (unnecessary) + +We can avoid the unnecessary I2C transactions if we cache the values of +state and color that are sent to the controller. If the color does not +change from the one previously sent, there is no need to do the +CMD_LED_COLOR I2C transaction, and if the state does not change, there +is no need to do the CMD_LED_STATE transaction. + +Because we need to make sure that our cached values are consistent with +the controller state, add explicit setting of the LED color to white at +probe time (this is the default setting when MCU resets, but does not +necessarily need to be the case, for example if U-Boot played with the +LED colors). + +Signed-off-by: Marek Behún +Link: https://lore.kernel.org/r/20230918161104.20860-3-kabel@kernel.org +Signed-off-by: Lee Jones +--- + drivers/leds/leds-turris-omnia.c | 96 ++++++++++++++++++++++++++------ + 1 file changed, 78 insertions(+), 18 deletions(-) + +--- a/drivers/leds/leds-turris-omnia.c ++++ b/drivers/leds/leds-turris-omnia.c +@@ -30,6 +30,8 @@ + struct omnia_led { + struct led_classdev_mc mc_cdev; + struct mc_subled subled_info[OMNIA_LED_NUM_CHANNELS]; ++ u8 cached_channels[OMNIA_LED_NUM_CHANNELS]; ++ bool on; + int reg; + }; + +@@ -72,36 +74,82 @@ static int omnia_cmd_read_u8(const struc + return -EIO; + } + ++static int omnia_led_send_color_cmd(const struct i2c_client *client, ++ struct omnia_led *led) ++{ ++ char cmd[5]; ++ int ret; ++ ++ cmd[0] = CMD_LED_COLOR; ++ cmd[1] = led->reg; ++ cmd[2] = led->subled_info[0].brightness; ++ cmd[3] = led->subled_info[1].brightness; ++ cmd[4] = led->subled_info[2].brightness; ++ ++ /* Send the color change command */ ++ ret = i2c_master_send(client, cmd, 5); ++ if (ret < 0) ++ return ret; ++ ++ /* Cache the RGB channel brightnesses */ ++ for (int i = 0; i < OMNIA_LED_NUM_CHANNELS; ++i) ++ led->cached_channels[i] = led->subled_info[i].brightness; ++ ++ return 0; ++} ++ ++/* Determine if the computed RGB channels are different from the cached ones */ ++static bool omnia_led_channels_changed(struct omnia_led *led) ++{ ++ for (int i = 0; i < OMNIA_LED_NUM_CHANNELS; ++i) ++ if (led->subled_info[i].brightness != led->cached_channels[i]) ++ return true; ++ ++ return false; ++} ++ + static int omnia_led_brightness_set_blocking(struct led_classdev *cdev, + enum led_brightness brightness) + { + struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev); + struct omnia_leds *leds = dev_get_drvdata(cdev->dev->parent); + struct omnia_led *led = to_omnia_led(mc_cdev); +- u8 buf[5], state; +- int ret; ++ int err = 0; + + mutex_lock(&leds->lock); + +- led_mc_calc_color_components(&led->mc_cdev, brightness); ++ /* ++ * Only recalculate RGB brightnesses from intensities if brightness is ++ * non-zero. Otherwise we won't be using them and we can save ourselves ++ * some software divisions (Omnia's CPU does not implement the division ++ * instruction). ++ */ ++ if (brightness) { ++ led_mc_calc_color_components(mc_cdev, brightness); ++ ++ /* ++ * Send color command only if brightness is non-zero and the RGB ++ * channel brightnesses changed. ++ */ ++ if (omnia_led_channels_changed(led)) ++ err = omnia_led_send_color_cmd(leds->client, led); ++ } + +- buf[0] = CMD_LED_COLOR; +- buf[1] = led->reg; +- buf[2] = mc_cdev->subled_info[0].brightness; +- buf[3] = mc_cdev->subled_info[1].brightness; +- buf[4] = mc_cdev->subled_info[2].brightness; +- +- state = CMD_LED_STATE_LED(led->reg); +- if (buf[2] || buf[3] || buf[4]) +- state |= CMD_LED_STATE_ON; +- +- ret = omnia_cmd_write_u8(leds->client, CMD_LED_STATE, state); +- if (ret >= 0 && (state & CMD_LED_STATE_ON)) +- ret = i2c_master_send(leds->client, buf, 5); ++ /* Send on/off state change only if (bool)brightness changed */ ++ if (!err && !brightness != !led->on) { ++ u8 state = CMD_LED_STATE_LED(led->reg); ++ ++ if (brightness) ++ state |= CMD_LED_STATE_ON; ++ ++ err = omnia_cmd_write_u8(leds->client, CMD_LED_STATE, state); ++ if (!err) ++ led->on = !!brightness; ++ } + + mutex_unlock(&leds->lock); + +- return ret; ++ return err; + } + + static int omnia_led_register(struct i2c_client *client, struct omnia_led *led, +@@ -129,11 +177,15 @@ static int omnia_led_register(struct i2c + } + + led->subled_info[0].color_index = LED_COLOR_ID_RED; +- led->subled_info[0].channel = 0; + led->subled_info[1].color_index = LED_COLOR_ID_GREEN; +- led->subled_info[1].channel = 1; + led->subled_info[2].color_index = LED_COLOR_ID_BLUE; +- led->subled_info[2].channel = 2; ++ ++ /* Initial color is white */ ++ for (int i = 0; i < OMNIA_LED_NUM_CHANNELS; ++i) { ++ led->subled_info[i].intensity = 255; ++ led->subled_info[i].brightness = 255; ++ led->subled_info[i].channel = i; ++ } + + led->mc_cdev.subled_info = led->subled_info; + led->mc_cdev.num_colors = OMNIA_LED_NUM_CHANNELS; +@@ -162,6 +214,14 @@ static int omnia_led_register(struct i2c + return ret; + } + ++ /* Set initial color and cache it */ ++ ret = omnia_led_send_color_cmd(client, led); ++ if (ret < 0) { ++ dev_err(dev, "Cannot set LED %pOF initial color: %i\n", np, ++ ret); ++ return ret; ++ } ++ + ret = devm_led_classdev_multicolor_register_ext(dev, &led->mc_cdev, + &init_data); + if (ret < 0) { diff --git a/lede/target/linux/generic/backport-6.1/815-v6.7-3-leds-turris-omnia-Support-HW-controlled-mode-via-pri.patch b/lede/target/linux/generic/backport-6.1/815-v6.7-3-leds-turris-omnia-Support-HW-controlled-mode-via-pri.patch new file mode 100644 index 0000000000..00773ab0f6 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/815-v6.7-3-leds-turris-omnia-Support-HW-controlled-mode-via-pri.patch @@ -0,0 +1,202 @@ +From e965e0f6de60874fc0a0caed9a9e0122999e0c7b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 18 Sep 2023 18:11:03 +0200 +Subject: [PATCH 5/6] leds: turris-omnia: Support HW controlled mode via + private trigger +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for enabling MCU controlled mode of the Turris Omnia LEDs +via a LED private trigger called "omnia-mcu". Recall that private LED +triggers will only be listed in the sysfs trigger file for LEDs that +support them (currently there is no user of this mechanism). + +When in MCU controlled mode, the user can still set LED color, but the +blinking is done by MCU, which does different things for different LEDs: +- WAN LED is blinked according to the LED[0] pin of the WAN PHY +- LAN LEDs are blinked according to the LED[0] output of the + corresponding port of the LAN switch +- PCIe LEDs are blinked according to the logical OR of the MiniPCIe port + LED pins + +In the future I want to make the netdev trigger to transparently offload +the blinking to the HW if user sets compatible settings for the netdev +trigger (for LEDs associated with network devices). +There was some work on this already, and hopefully we will be able to +complete it sometime, but for now there are still multiple blockers for +this, and even if there weren't, we still would not be able to configure +HW controlled mode for the LEDs associated with MiniPCIe ports. + +In the meantime let's support HW controlled mode via the private LED +trigger mechanism. If, in the future, we manage to complete the netdev +trigger offloading, we can still keep this private trigger for backwards +compatibility, if needed. + +We also set "omnia-mcu" to cdev->default_trigger, so that the MCU keeps +control until the user first wants to take over it. If a different +default trigger is specified in device-tree via the +'linux,default-trigger' property, LED class will overwrite +cdev->default_trigger, and so the DT property will be respected. + +Signed-off-by: Marek Behún +Link: https://lore.kernel.org/r/20230918161104.20860-4-kabel@kernel.org +Signed-off-by: Lee Jones +--- + drivers/leds/Kconfig | 1 + + drivers/leds/leds-turris-omnia.c | 98 +++++++++++++++++++++++++++++--- + 2 files changed, 91 insertions(+), 8 deletions(-) + +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -164,6 +164,7 @@ config LEDS_TURRIS_OMNIA + depends on I2C + depends on MACH_ARMADA_38X || COMPILE_TEST + depends on OF ++ select LEDS_TRIGGERS + help + This option enables basic support for the LEDs found on the front + side of CZ.NIC's Turris Omnia router. There are 12 RGB LEDs on the +--- a/drivers/leds/leds-turris-omnia.c ++++ b/drivers/leds/leds-turris-omnia.c +@@ -31,7 +31,7 @@ struct omnia_led { + struct led_classdev_mc mc_cdev; + struct mc_subled subled_info[OMNIA_LED_NUM_CHANNELS]; + u8 cached_channels[OMNIA_LED_NUM_CHANNELS]; +- bool on; ++ bool on, hwtrig; + int reg; + }; + +@@ -120,12 +120,14 @@ static int omnia_led_brightness_set_bloc + + /* + * Only recalculate RGB brightnesses from intensities if brightness is +- * non-zero. Otherwise we won't be using them and we can save ourselves +- * some software divisions (Omnia's CPU does not implement the division +- * instruction). ++ * non-zero (if it is zero and the LED is in HW blinking mode, we use ++ * max_brightness as brightness). Otherwise we won't be using them and ++ * we can save ourselves some software divisions (Omnia's CPU does not ++ * implement the division instruction). + */ +- if (brightness) { +- led_mc_calc_color_components(mc_cdev, brightness); ++ if (brightness || led->hwtrig) { ++ led_mc_calc_color_components(mc_cdev, brightness ?: ++ cdev->max_brightness); + + /* + * Send color command only if brightness is non-zero and the RGB +@@ -135,8 +137,11 @@ static int omnia_led_brightness_set_bloc + err = omnia_led_send_color_cmd(leds->client, led); + } + +- /* Send on/off state change only if (bool)brightness changed */ +- if (!err && !brightness != !led->on) { ++ /* ++ * Send on/off state change only if (bool)brightness changed and the LED ++ * is not being blinked by HW. ++ */ ++ if (!err && !led->hwtrig && !brightness != !led->on) { + u8 state = CMD_LED_STATE_LED(led->reg); + + if (brightness) +@@ -152,6 +157,71 @@ static int omnia_led_brightness_set_bloc + return err; + } + ++static struct led_hw_trigger_type omnia_hw_trigger_type; ++ ++static int omnia_hwtrig_activate(struct led_classdev *cdev) ++{ ++ struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev); ++ struct omnia_leds *leds = dev_get_drvdata(cdev->dev->parent); ++ struct omnia_led *led = to_omnia_led(mc_cdev); ++ int err = 0; ++ ++ mutex_lock(&leds->lock); ++ ++ if (!led->on) { ++ /* ++ * If the LED is off (brightness was set to 0), the last ++ * configured color was not necessarily sent to the MCU. ++ * Recompute with max_brightness and send if needed. ++ */ ++ led_mc_calc_color_components(mc_cdev, cdev->max_brightness); ++ ++ if (omnia_led_channels_changed(led)) ++ err = omnia_led_send_color_cmd(leds->client, led); ++ } ++ ++ if (!err) { ++ /* Put the LED into MCU controlled mode */ ++ err = omnia_cmd_write_u8(leds->client, CMD_LED_MODE, ++ CMD_LED_MODE_LED(led->reg)); ++ if (!err) ++ led->hwtrig = true; ++ } ++ ++ mutex_unlock(&leds->lock); ++ ++ return err; ++} ++ ++static void omnia_hwtrig_deactivate(struct led_classdev *cdev) ++{ ++ struct omnia_leds *leds = dev_get_drvdata(cdev->dev->parent); ++ struct omnia_led *led = to_omnia_led(lcdev_to_mccdev(cdev)); ++ int err; ++ ++ mutex_lock(&leds->lock); ++ ++ led->hwtrig = false; ++ ++ /* Put the LED into software mode */ ++ err = omnia_cmd_write_u8(leds->client, CMD_LED_MODE, ++ CMD_LED_MODE_LED(led->reg) | ++ CMD_LED_MODE_USER); ++ ++ mutex_unlock(&leds->lock); ++ ++ if (err < 0) ++ dev_err(cdev->dev, "Cannot put LED to software mode: %i\n", ++ err); ++} ++ ++static struct led_trigger omnia_hw_trigger = { ++ .name = "omnia-mcu", ++ .activate = omnia_hwtrig_activate, ++ .deactivate = omnia_hwtrig_deactivate, ++ .trigger_type = &omnia_hw_trigger_type, ++}; ++ + static int omnia_led_register(struct i2c_client *client, struct omnia_led *led, + struct device_node *np) + { +@@ -195,6 +265,12 @@ static int omnia_led_register(struct i2c + cdev = &led->mc_cdev.led_cdev; + cdev->max_brightness = 255; + cdev->brightness_set_blocking = omnia_led_brightness_set_blocking; ++ cdev->trigger_type = &omnia_hw_trigger_type; ++ /* ++ * Use the omnia-mcu trigger as the default trigger. It may be rewritten ++ * by LED class from the linux,default-trigger property. ++ */ ++ cdev->default_trigger = omnia_hw_trigger.name; + + /* put the LED into software mode */ + ret = omnia_cmd_write_u8(client, CMD_LED_MODE, +@@ -309,6 +385,12 @@ static int omnia_leds_probe(struct i2c_c + + mutex_init(&leds->lock); + ++ ret = devm_led_trigger_register(dev, &omnia_hw_trigger); ++ if (ret < 0) { ++ dev_err(dev, "Cannot register private LED trigger: %d\n", ret); ++ return ret; ++ } ++ + led = &leds->leds[0]; + for_each_available_child_of_node(np, child) { + ret = omnia_led_register(client, led, child); diff --git a/lede/target/linux/generic/backport-6.1/815-v6.7-4-leds-turris-omnia-Add-support-for-enabling-disabling.patch b/lede/target/linux/generic/backport-6.1/815-v6.7-4-leds-turris-omnia-Add-support-for-enabling-disabling.patch new file mode 100644 index 0000000000..e98397922d --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/815-v6.7-4-leds-turris-omnia-Add-support-for-enabling-disabling.patch @@ -0,0 +1,244 @@ +From 0efb3f9609d3de5a7d8c31e3835d7eb3e6adce79 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 18 Sep 2023 18:11:04 +0200 +Subject: [PATCH 6/6] leds: turris-omnia: Add support for enabling/disabling HW + gamma correction +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If the MCU on Turris Omnia is running newer firmware versions, the LED +controller supports RGB gamma correction (and enables it by default for +newer boards). + +Determine whether the gamma correction setting feature is supported and +add the ability to set it via sysfs attribute file. + +Signed-off-by: Marek Behún +Link: https://lore.kernel.org/r/20230918161104.20860-5-kabel@kernel.org +Signed-off-by: Lee Jones +--- + .../sysfs-class-led-driver-turris-omnia | 14 ++ + drivers/leds/leds-turris-omnia.c | 137 +++++++++++++++--- + 2 files changed, 134 insertions(+), 17 deletions(-) + +--- a/Documentation/ABI/testing/sysfs-class-led-driver-turris-omnia ++++ b/Documentation/ABI/testing/sysfs-class-led-driver-turris-omnia +@@ -12,3 +12,17 @@ Description: (RW) On the front panel of + able to change this setting from software. + + Format: %i ++ ++What: /sys/class/leds//device/gamma_correction ++Date: August 2023 ++KernelVersion: 6.6 ++Contact: Marek Behún ++Description: (RW) Newer versions of the microcontroller firmware of the ++ Turris Omnia router support gamma correction for the RGB LEDs. ++ This feature can be enabled/disabled by writing to this file. ++ ++ If the feature is not supported because the MCU firmware is too ++ old, the file always reads as 0, and writing to the file results ++ in the EOPNOTSUPP error. ++ ++ Format: %i +--- a/drivers/leds/leds-turris-omnia.c ++++ b/drivers/leds/leds-turris-omnia.c +@@ -15,17 +15,30 @@ + #define OMNIA_BOARD_LEDS 12 + #define OMNIA_LED_NUM_CHANNELS 3 + +-#define CMD_LED_MODE 3 +-#define CMD_LED_MODE_LED(l) ((l) & 0x0f) +-#define CMD_LED_MODE_USER 0x10 +- +-#define CMD_LED_STATE 4 +-#define CMD_LED_STATE_LED(l) ((l) & 0x0f) +-#define CMD_LED_STATE_ON 0x10 +- +-#define CMD_LED_COLOR 5 +-#define CMD_LED_SET_BRIGHTNESS 7 +-#define CMD_LED_GET_BRIGHTNESS 8 ++/* MCU controller commands at I2C address 0x2a */ ++#define OMNIA_MCU_I2C_ADDR 0x2a ++ ++#define CMD_GET_STATUS_WORD 0x01 ++#define STS_FEATURES_SUPPORTED BIT(2) ++ ++#define CMD_GET_FEATURES 0x10 ++#define FEAT_LED_GAMMA_CORRECTION BIT(5) ++ ++/* LED controller commands at I2C address 0x2b */ ++#define CMD_LED_MODE 0x03 ++#define CMD_LED_MODE_LED(l) ((l) & 0x0f) ++#define CMD_LED_MODE_USER 0x10 ++ ++#define CMD_LED_STATE 0x04 ++#define CMD_LED_STATE_LED(l) ((l) & 0x0f) ++#define CMD_LED_STATE_ON 0x10 ++ ++#define CMD_LED_COLOR 0x05 ++#define CMD_LED_SET_BRIGHTNESS 0x07 ++#define CMD_LED_GET_BRIGHTNESS 0x08 ++ ++#define CMD_SET_GAMMA_CORRECTION 0x30 ++#define CMD_GET_GAMMA_CORRECTION 0x31 + + struct omnia_led { + struct led_classdev_mc mc_cdev; +@@ -40,6 +53,7 @@ struct omnia_led { + struct omnia_leds { + struct i2c_client *client; + struct mutex lock; ++ bool has_gamma_correction; + struct omnia_led leds[]; + }; + +@@ -50,30 +64,42 @@ static int omnia_cmd_write_u8(const stru + return i2c_master_send(client, buf, sizeof(buf)); + } + +-static int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd) ++static int omnia_cmd_read_raw(struct i2c_adapter *adapter, u8 addr, u8 cmd, ++ void *reply, size_t len) + { + struct i2c_msg msgs[2]; +- u8 reply; + int ret; + +- msgs[0].addr = client->addr; ++ msgs[0].addr = addr; + msgs[0].flags = 0; + msgs[0].len = 1; + msgs[0].buf = &cmd; +- msgs[1].addr = client->addr; ++ msgs[1].addr = addr; + msgs[1].flags = I2C_M_RD; +- msgs[1].len = 1; +- msgs[1].buf = &reply; ++ msgs[1].len = len; ++ msgs[1].buf = reply; + +- ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); ++ ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs)); + if (likely(ret == ARRAY_SIZE(msgs))) +- return reply; ++ return len; + else if (ret < 0) + return ret; + else + return -EIO; + } + ++static int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd) ++{ ++ u8 reply; ++ int ret; ++ ++ ret = omnia_cmd_read_raw(client->adapter, client->addr, cmd, &reply, 1); ++ if (ret < 0) ++ return ret; ++ ++ return reply; ++} ++ + static int omnia_led_send_color_cmd(const struct i2c_client *client, + struct omnia_led *led) + { +@@ -352,12 +378,74 @@ static ssize_t brightness_store(struct d + } + static DEVICE_ATTR_RW(brightness); + ++static ssize_t gamma_correction_show(struct device *dev, ++ struct device_attribute *a, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct omnia_leds *leds = i2c_get_clientdata(client); ++ int ret; ++ ++ if (leds->has_gamma_correction) { ++ ret = omnia_cmd_read_u8(client, CMD_GET_GAMMA_CORRECTION); ++ if (ret < 0) ++ return ret; ++ } else { ++ ret = 0; ++ } ++ ++ return sysfs_emit(buf, "%d\n", !!ret); ++} ++ ++static ssize_t gamma_correction_store(struct device *dev, ++ struct device_attribute *a, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct omnia_leds *leds = i2c_get_clientdata(client); ++ bool val; ++ int ret; ++ ++ if (!leds->has_gamma_correction) ++ return -EOPNOTSUPP; ++ ++ if (kstrtobool(buf, &val) < 0) ++ return -EINVAL; ++ ++ ret = omnia_cmd_write_u8(client, CMD_SET_GAMMA_CORRECTION, val); ++ ++ return ret < 0 ? ret : count; ++} ++static DEVICE_ATTR_RW(gamma_correction); ++ + static struct attribute *omnia_led_controller_attrs[] = { + &dev_attr_brightness.attr, ++ &dev_attr_gamma_correction.attr, + NULL, + }; + ATTRIBUTE_GROUPS(omnia_led_controller); + ++static int omnia_mcu_get_features(const struct i2c_client *client) ++{ ++ u16 reply; ++ int err; ++ ++ err = omnia_cmd_read_raw(client->adapter, OMNIA_MCU_I2C_ADDR, ++ CMD_GET_STATUS_WORD, &reply, sizeof(reply)); ++ if (err < 0) ++ return err; ++ ++ /* Check whether MCU firmware supports the CMD_GET_FEAUTRES command */ ++ if (!(le16_to_cpu(reply) & STS_FEATURES_SUPPORTED)) ++ return 0; ++ ++ err = omnia_cmd_read_raw(client->adapter, OMNIA_MCU_I2C_ADDR, ++ CMD_GET_FEATURES, &reply, sizeof(reply)); ++ if (err < 0) ++ return err; ++ ++ return le16_to_cpu(reply); ++} ++ + static int omnia_leds_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { +@@ -383,6 +471,21 @@ static int omnia_leds_probe(struct i2c_c + leds->client = client; + i2c_set_clientdata(client, leds); + ++ ret = omnia_mcu_get_features(client); ++ if (ret < 0) { ++ dev_err(dev, "Cannot determine MCU supported features: %d\n", ++ ret); ++ return ret; ++ } ++ ++ leds->has_gamma_correction = ret & FEAT_LED_GAMMA_CORRECTION; ++ if (!leds->has_gamma_correction) { ++ dev_info(dev, ++ "Your board's MCU firmware does not support the LED gamma correction feature.\n"); ++ dev_info(dev, ++ "Consider upgrading MCU firmware with the omnia-mcutool utility.\n"); ++ } ++ + mutex_init(&leds->lock); + + ret = devm_led_trigger_register(dev, &omnia_hw_trigger); diff --git a/lede/target/linux/generic/backport-6.1/815-v6.7-5-leds-turris-omnia-Fix-brightness-setting-and-trigger.patch b/lede/target/linux/generic/backport-6.1/815-v6.7-5-leds-turris-omnia-Fix-brightness-setting-and-trigger.patch new file mode 100644 index 0000000000..b0cebdcf14 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/815-v6.7-5-leds-turris-omnia-Fix-brightness-setting-and-trigger.patch @@ -0,0 +1,167 @@ +From ffec49d391c5f0195360912b216aa24dbc9b53c8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 16 Oct 2023 16:15:38 +0200 +Subject: [PATCH] leds: turris-omnia: Fix brightness setting and trigger + activating +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +I have improperly refactored commits + 4d5ed2621c24 ("leds: turris-omnia: Make set_brightness() more efficient") +and + aaf38273cf76 ("leds: turris-omnia: Support HW controlled mode via private trigger") +after Lee requested a change in API semantics of the new functions I +introduced in commit + 28350bc0ac77 ("leds: turris-omnia: Do not use SMBUS calls"). + +Before the change, the function omnia_cmd_write_u8() returned 0 on +success, and afterwards it returned a positive value (number of bytes +written). The latter version was applied, but the following commits did +not properly account for this change. + +This results in non-functional LED's .brightness_set_blocking() and +trigger's .activate() methods. + +The main reasoning behind the semantics change was that read/write +methods should return the number of read/written bytes on success. +It was pointed to me [1] that this is not always true (for example the +regmap API does not do so), and since the driver never uses this number +of read/written bytes information, I decided to fix this issue by +changing the functions to the original semantics (return 0 on success). + +[1] https://lore.kernel.org/linux-gpio/ZQnn+Gi0xVlsGCYA@smile.fi.intel.com/ + +Fixes: 28350bc0ac77 ("leds: turris-omnia: Do not use SMBUS calls") +Signed-off-by: Marek Behún +--- + drivers/leds/leds-turris-omnia.c | 37 +++++++++++++++++--------------- + 1 file changed, 20 insertions(+), 17 deletions(-) + +--- a/drivers/leds/leds-turris-omnia.c ++++ b/drivers/leds/leds-turris-omnia.c +@@ -60,8 +60,11 @@ struct omnia_leds { + static int omnia_cmd_write_u8(const struct i2c_client *client, u8 cmd, u8 val) + { + u8 buf[2] = { cmd, val }; ++ int ret; ++ ++ ret = i2c_master_send(client, buf, sizeof(buf)); + +- return i2c_master_send(client, buf, sizeof(buf)); ++ return ret < 0 ? ret : 0; + } + + static int omnia_cmd_read_raw(struct i2c_adapter *adapter, u8 addr, u8 cmd, +@@ -81,7 +84,7 @@ static int omnia_cmd_read_raw(struct i2c + + ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs)); + if (likely(ret == ARRAY_SIZE(msgs))) +- return len; ++ return 0; + else if (ret < 0) + return ret; + else +@@ -91,11 +94,11 @@ static int omnia_cmd_read_raw(struct i2c + static int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd) + { + u8 reply; +- int ret; ++ int err; + +- ret = omnia_cmd_read_raw(client->adapter, client->addr, cmd, &reply, 1); +- if (ret < 0) +- return ret; ++ err = omnia_cmd_read_raw(client->adapter, client->addr, cmd, &reply, 1); ++ if (err) ++ return err; + + return reply; + } +@@ -236,7 +239,7 @@ static void omnia_hwtrig_deactivate(stru + + mutex_unlock(&leds->lock); + +- if (err < 0) ++ if (err) + dev_err(cdev->dev, "Cannot put LED to software mode: %i\n", + err); + } +@@ -302,7 +305,7 @@ static int omnia_led_register(struct i2c + ret = omnia_cmd_write_u8(client, CMD_LED_MODE, + CMD_LED_MODE_LED(led->reg) | + CMD_LED_MODE_USER); +- if (ret < 0) { ++ if (ret) { + dev_err(dev, "Cannot set LED %pOF to software mode: %i\n", np, + ret); + return ret; +@@ -311,7 +314,7 @@ static int omnia_led_register(struct i2c + /* disable the LED */ + ret = omnia_cmd_write_u8(client, CMD_LED_STATE, + CMD_LED_STATE_LED(led->reg)); +- if (ret < 0) { ++ if (ret) { + dev_err(dev, "Cannot set LED %pOF brightness: %i\n", np, ret); + return ret; + } +@@ -364,7 +367,7 @@ static ssize_t brightness_store(struct d + { + struct i2c_client *client = to_i2c_client(dev); + unsigned long brightness; +- int ret; ++ int err; + + if (kstrtoul(buf, 10, &brightness)) + return -EINVAL; +@@ -372,9 +375,9 @@ static ssize_t brightness_store(struct d + if (brightness > 100) + return -EINVAL; + +- ret = omnia_cmd_write_u8(client, CMD_LED_SET_BRIGHTNESS, brightness); ++ err = omnia_cmd_write_u8(client, CMD_LED_SET_BRIGHTNESS, brightness); + +- return ret < 0 ? ret : count; ++ return err ?: count; + } + static DEVICE_ATTR_RW(brightness); + +@@ -403,7 +406,7 @@ static ssize_t gamma_correction_store(st + struct i2c_client *client = to_i2c_client(dev); + struct omnia_leds *leds = i2c_get_clientdata(client); + bool val; +- int ret; ++ int err; + + if (!leds->has_gamma_correction) + return -EOPNOTSUPP; +@@ -411,9 +414,9 @@ static ssize_t gamma_correction_store(st + if (kstrtobool(buf, &val) < 0) + return -EINVAL; + +- ret = omnia_cmd_write_u8(client, CMD_SET_GAMMA_CORRECTION, val); ++ err = omnia_cmd_write_u8(client, CMD_SET_GAMMA_CORRECTION, val); + +- return ret < 0 ? ret : count; ++ return err ?: count; + } + static DEVICE_ATTR_RW(gamma_correction); + +@@ -431,7 +434,7 @@ static int omnia_mcu_get_features(const + + err = omnia_cmd_read_raw(client->adapter, OMNIA_MCU_I2C_ADDR, + CMD_GET_STATUS_WORD, &reply, sizeof(reply)); +- if (err < 0) ++ if (err) + return err; + + /* Check whether MCU firmware supports the CMD_GET_FEAUTRES command */ +@@ -440,7 +443,7 @@ static int omnia_mcu_get_features(const + + err = omnia_cmd_read_raw(client->adapter, OMNIA_MCU_I2C_ADDR, + CMD_GET_FEATURES, &reply, sizeof(reply)); +- if (err < 0) ++ if (err) + return err; + + return le16_to_cpu(reply); diff --git a/lede/target/linux/generic/backport-6.1/816-v6.7-0001-nvmem-qfprom-Mark-core-clk-as-optional.patch b/lede/target/linux/generic/backport-6.1/816-v6.7-0001-nvmem-qfprom-Mark-core-clk-as-optional.patch new file mode 100644 index 0000000000..66d4028140 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/816-v6.7-0001-nvmem-qfprom-Mark-core-clk-as-optional.patch @@ -0,0 +1,37 @@ +From 16724d6ea40a2c9315f5a0d81005dfa4d7a6da24 Mon Sep 17 00:00:00 2001 +From: Luca Weiss +Date: Fri, 20 Oct 2023 11:55:40 +0100 +Subject: [PATCH] nvmem: qfprom: Mark core clk as optional + +On some platforms like sc7280 on non-ChromeOS devices the core clock +cannot be touched by Linux so we cannot provide it. Mark it as optional +as accessing qfprom for reading works without it but we still prohibit +writing if we cannot provide the clock. + +Signed-off-by: Luca Weiss +Reviewed-by: Douglas Anderson +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231020105545.216052-2-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/qfprom.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/nvmem/qfprom.c ++++ b/drivers/nvmem/qfprom.c +@@ -423,12 +423,12 @@ static int qfprom_probe(struct platform_ + if (IS_ERR(priv->vcc)) + return PTR_ERR(priv->vcc); + +- priv->secclk = devm_clk_get(dev, "core"); ++ priv->secclk = devm_clk_get_optional(dev, "core"); + if (IS_ERR(priv->secclk)) + return dev_err_probe(dev, PTR_ERR(priv->secclk), "Error getting clock\n"); + +- /* Only enable writing if we have SoC data. */ +- if (priv->soc_data) ++ /* Only enable writing if we have SoC data and a valid clock */ ++ if (priv->soc_data && priv->secclk) + econfig.reg_write = qfprom_reg_write; + } + diff --git a/lede/target/linux/generic/backport-6.1/816-v6.7-0002-nvmem-add-explicit-config-option-to-read-old-syntax-.patch b/lede/target/linux/generic/backport-6.1/816-v6.7-0002-nvmem-add-explicit-config-option-to-read-old-syntax-.patch new file mode 100644 index 0000000000..be293e6f2a --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/816-v6.7-0002-nvmem-add-explicit-config-option-to-read-old-syntax-.patch @@ -0,0 +1,330 @@ +From 2cc3b37f5b6df8189d55d0e812d9658ce256dfec Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 20 Oct 2023 11:55:41 +0100 +Subject: [PATCH] nvmem: add explicit config option to read old syntax fixed OF + cells +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Binding for fixed NVMEM cells defined directly as NVMEM device subnodes +has been deprecated. It has been replaced by the "fixed-layout" NVMEM +layout binding. + +New syntax is meant to be clearer and should help avoiding imprecise +bindings. + +NVMEM subsystem already supports the new binding. It should be a good +idea to limit support for old syntax to existing drivers that actually +support & use it (we can't break backward compatibility!). That way we +additionally encourage new bindings & drivers to ignore deprecated +binding. + +It wasn't clear (to me) if rtc and w1 code actually uses old syntax +fixed cells. I enabled them to don't risk any breakage. + +Signed-off-by: Rafał Miłecki +[for meson-{efuse,mx-efuse}.c] +Acked-by: Martin Blumenstingl +[for mtk-efuse.c, nvmem/core.c, nvmem-provider.h] +Reviewed-by: AngeloGioacchino Del Regno +[MT8192, MT8195 Chromebooks] +Tested-by: AngeloGioacchino Del Regno +[for microchip-otpc.c] +Reviewed-by: Claudiu Beznea +[SAMA7G5-EK] +Tested-by: Claudiu Beznea +Acked-by: Jernej Skrabec +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231020105545.216052-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mtd/mtdcore.c | 2 ++ + drivers/nvmem/apple-efuses.c | 1 + + drivers/nvmem/core.c | 8 +++++--- + drivers/nvmem/imx-ocotp-scu.c | 1 + + drivers/nvmem/imx-ocotp.c | 1 + + drivers/nvmem/meson-efuse.c | 1 + + drivers/nvmem/meson-mx-efuse.c | 1 + + drivers/nvmem/microchip-otpc.c | 1 + + drivers/nvmem/mtk-efuse.c | 1 + + drivers/nvmem/qcom-spmi-sdam.c | 1 + + drivers/nvmem/qfprom.c | 1 + + drivers/nvmem/rave-sp-eeprom.c | 1 + + drivers/nvmem/rockchip-efuse.c | 1 + + drivers/nvmem/sc27xx-efuse.c | 1 + + drivers/nvmem/sec-qfprom.c | 1 + + drivers/nvmem/sprd-efuse.c | 1 + + drivers/nvmem/stm32-romem.c | 1 + + drivers/nvmem/sunplus-ocotp.c | 1 + + drivers/nvmem/sunxi_sid.c | 1 + + drivers/nvmem/uniphier-efuse.c | 1 + + drivers/nvmem/zynqmp_nvmem.c | 1 + + drivers/rtc/nvmem.c | 1 + + drivers/w1/slaves/w1_ds250x.c | 1 + + include/linux/nvmem-provider.h | 2 ++ + 24 files changed, 30 insertions(+), 3 deletions(-) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -523,6 +523,7 @@ static int mtd_nvmem_add(struct mtd_info + config.dev = &mtd->dev; + config.name = dev_name(&mtd->dev); + config.owner = THIS_MODULE; ++ config.add_legacy_fixed_of_cells = of_device_is_compatible(node, "nvmem-cells"); + config.reg_read = mtd_nvmem_reg_read; + config.size = mtd->size; + config.word_size = 1; +@@ -891,6 +892,7 @@ static struct nvmem_device *mtd_otp_nvme + config.name = compatible; + config.id = NVMEM_DEVID_AUTO; + config.owner = THIS_MODULE; ++ config.add_legacy_fixed_of_cells = true; + config.type = NVMEM_TYPE_OTP; + config.root_only = true; + config.ignore_wp = true; +--- a/drivers/nvmem/apple-efuses.c ++++ b/drivers/nvmem/apple-efuses.c +@@ -36,6 +36,7 @@ static int apple_efuses_probe(struct pla + struct resource *res; + struct nvmem_config config = { + .dev = &pdev->dev, ++ .add_legacy_fixed_of_cells = true, + .read_only = true, + .reg_read = apple_efuses_read, + .stride = sizeof(u32), +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -998,9 +998,11 @@ struct nvmem_device *nvmem_register(cons + if (rval) + goto err_remove_cells; + +- rval = nvmem_add_cells_from_legacy_of(nvmem); +- if (rval) +- goto err_remove_cells; ++ if (config->add_legacy_fixed_of_cells) { ++ rval = nvmem_add_cells_from_legacy_of(nvmem); ++ if (rval) ++ goto err_remove_cells; ++ } + + rval = nvmem_add_cells_from_fixed_layout(nvmem); + if (rval) +--- a/drivers/nvmem/imx-ocotp-scu.c ++++ b/drivers/nvmem/imx-ocotp-scu.c +@@ -220,6 +220,7 @@ static int imx_scu_ocotp_write(void *con + + static struct nvmem_config imx_scu_ocotp_nvmem_config = { + .name = "imx-scu-ocotp", ++ .add_legacy_fixed_of_cells = true, + .read_only = false, + .word_size = 4, + .stride = 1, +--- a/drivers/nvmem/imx-ocotp.c ++++ b/drivers/nvmem/imx-ocotp.c +@@ -616,6 +616,7 @@ static int imx_ocotp_probe(struct platfo + return PTR_ERR(priv->clk); + + priv->params = of_device_get_match_data(&pdev->dev); ++ imx_ocotp_nvmem_config.add_legacy_fixed_of_cells = true; + imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; + imx_ocotp_nvmem_config.dev = dev; + imx_ocotp_nvmem_config.priv = priv; +--- a/drivers/nvmem/meson-efuse.c ++++ b/drivers/nvmem/meson-efuse.c +@@ -74,6 +74,7 @@ static int meson_efuse_probe(struct plat + + econfig->dev = dev; + econfig->name = dev_name(dev); ++ econfig->add_legacy_fixed_of_cells = true; + econfig->stride = 1; + econfig->word_size = 1; + econfig->reg_read = meson_efuse_read; +--- a/drivers/nvmem/meson-mx-efuse.c ++++ b/drivers/nvmem/meson-mx-efuse.c +@@ -211,6 +211,7 @@ static int meson_mx_efuse_probe(struct p + efuse->config.owner = THIS_MODULE; + efuse->config.dev = &pdev->dev; + efuse->config.priv = efuse; ++ efuse->config.add_legacy_fixed_of_cells = true; + efuse->config.stride = drvdata->word_size; + efuse->config.word_size = drvdata->word_size; + efuse->config.size = SZ_512; +--- a/drivers/nvmem/microchip-otpc.c ++++ b/drivers/nvmem/microchip-otpc.c +@@ -261,6 +261,7 @@ static int mchp_otpc_probe(struct platfo + return ret; + + mchp_nvmem_config.dev = otpc->dev; ++ mchp_nvmem_config.add_legacy_fixed_of_cells = true; + mchp_nvmem_config.size = size; + mchp_nvmem_config.priv = otpc; + nvmem = devm_nvmem_register(&pdev->dev, &mchp_nvmem_config); +--- a/drivers/nvmem/mtk-efuse.c ++++ b/drivers/nvmem/mtk-efuse.c +@@ -83,6 +83,7 @@ static int mtk_efuse_probe(struct platfo + return PTR_ERR(priv->base); + + pdata = device_get_match_data(dev); ++ econfig.add_legacy_fixed_of_cells = true; + econfig.stride = 1; + econfig.word_size = 1; + econfig.reg_read = mtk_reg_read; +--- a/drivers/nvmem/qcom-spmi-sdam.c ++++ b/drivers/nvmem/qcom-spmi-sdam.c +@@ -142,6 +142,7 @@ static int sdam_probe(struct platform_de + sdam->sdam_config.name = "spmi_sdam"; + sdam->sdam_config.id = NVMEM_DEVID_AUTO; + sdam->sdam_config.owner = THIS_MODULE; ++ sdam->sdam_config.add_legacy_fixed_of_cells = true; + sdam->sdam_config.stride = 1; + sdam->sdam_config.word_size = 1; + sdam->sdam_config.reg_read = sdam_read; +--- a/drivers/nvmem/qfprom.c ++++ b/drivers/nvmem/qfprom.c +@@ -357,6 +357,7 @@ static int qfprom_probe(struct platform_ + { + struct nvmem_config econfig = { + .name = "qfprom", ++ .add_legacy_fixed_of_cells = true, + .stride = 1, + .word_size = 1, + .id = NVMEM_DEVID_AUTO, +--- a/drivers/nvmem/rave-sp-eeprom.c ++++ b/drivers/nvmem/rave-sp-eeprom.c +@@ -328,6 +328,7 @@ static int rave_sp_eeprom_probe(struct p + of_property_read_string(np, "zii,eeprom-name", &config.name); + config.priv = eeprom; + config.dev = dev; ++ config.add_legacy_fixed_of_cells = true; + config.size = size; + config.reg_read = rave_sp_eeprom_reg_read; + config.reg_write = rave_sp_eeprom_reg_write; +--- a/drivers/nvmem/rockchip-efuse.c ++++ b/drivers/nvmem/rockchip-efuse.c +@@ -205,6 +205,7 @@ static int rockchip_rk3399_efuse_read(vo + + static struct nvmem_config econfig = { + .name = "rockchip-efuse", ++ .add_legacy_fixed_of_cells = true, + .stride = 1, + .word_size = 1, + .read_only = true, +--- a/drivers/nvmem/sc27xx-efuse.c ++++ b/drivers/nvmem/sc27xx-efuse.c +@@ -248,6 +248,7 @@ static int sc27xx_efuse_probe(struct pla + econfig.reg_read = sc27xx_efuse_read; + econfig.priv = efuse; + econfig.dev = &pdev->dev; ++ econfig.add_legacy_fixed_of_cells = true; + nvmem = devm_nvmem_register(&pdev->dev, &econfig); + if (IS_ERR(nvmem)) { + dev_err(&pdev->dev, "failed to register nvmem config\n"); +--- a/drivers/nvmem/sec-qfprom.c ++++ b/drivers/nvmem/sec-qfprom.c +@@ -47,6 +47,7 @@ static int sec_qfprom_probe(struct platf + { + struct nvmem_config econfig = { + .name = "sec-qfprom", ++ .add_legacy_fixed_of_cells = true, + .stride = 1, + .word_size = 1, + .id = NVMEM_DEVID_AUTO, +--- a/drivers/nvmem/sprd-efuse.c ++++ b/drivers/nvmem/sprd-efuse.c +@@ -408,6 +408,7 @@ static int sprd_efuse_probe(struct platf + econfig.read_only = false; + econfig.name = "sprd-efuse"; + econfig.size = efuse->data->blk_nums * SPRD_EFUSE_BLOCK_WIDTH; ++ econfig.add_legacy_fixed_of_cells = true; + econfig.reg_read = sprd_efuse_read; + econfig.reg_write = sprd_efuse_write; + econfig.priv = efuse; +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -207,6 +207,7 @@ static int stm32_romem_probe(struct plat + priv->cfg.priv = priv; + priv->cfg.owner = THIS_MODULE; + priv->cfg.type = NVMEM_TYPE_OTP; ++ priv->cfg.add_legacy_fixed_of_cells = true; + + priv->lower = 0; + +--- a/drivers/nvmem/sunplus-ocotp.c ++++ b/drivers/nvmem/sunplus-ocotp.c +@@ -145,6 +145,7 @@ disable_clk: + + static struct nvmem_config sp_ocotp_nvmem_config = { + .name = "sp-ocotp", ++ .add_legacy_fixed_of_cells = true, + .read_only = true, + .word_size = 1, + .size = QAC628_OTP_SIZE, +--- a/drivers/nvmem/sunxi_sid.c ++++ b/drivers/nvmem/sunxi_sid.c +@@ -154,6 +154,7 @@ static int sunxi_sid_probe(struct platfo + nvmem_cfg->dev = dev; + nvmem_cfg->name = "sunxi-sid"; + nvmem_cfg->type = NVMEM_TYPE_OTP; ++ nvmem_cfg->add_legacy_fixed_of_cells = true; + nvmem_cfg->read_only = true; + nvmem_cfg->size = cfg->size; + nvmem_cfg->word_size = 1; +--- a/drivers/nvmem/uniphier-efuse.c ++++ b/drivers/nvmem/uniphier-efuse.c +@@ -52,6 +52,7 @@ static int uniphier_efuse_probe(struct p + econfig.size = resource_size(res); + econfig.priv = priv; + econfig.dev = dev; ++ econfig.add_legacy_fixed_of_cells = true; + nvmem = devm_nvmem_register(dev, &econfig); + + return PTR_ERR_OR_ZERO(nvmem); +--- a/drivers/nvmem/zynqmp_nvmem.c ++++ b/drivers/nvmem/zynqmp_nvmem.c +@@ -58,6 +58,7 @@ static int zynqmp_nvmem_probe(struct pla + + priv->dev = dev; + econfig.dev = dev; ++ econfig.add_legacy_fixed_of_cells = true; + econfig.reg_read = zynqmp_nvmem_read; + econfig.priv = priv; + +--- a/drivers/rtc/nvmem.c ++++ b/drivers/rtc/nvmem.c +@@ -21,6 +21,7 @@ int devm_rtc_nvmem_register(struct rtc_d + + nvmem_config->dev = dev; + nvmem_config->owner = rtc->owner; ++ nvmem_config->add_legacy_fixed_of_cells = true; + nvmem = devm_nvmem_register(dev, nvmem_config); + if (IS_ERR(nvmem)) + dev_err(dev, "failed to register nvmem device for RTC\n"); +--- a/drivers/w1/slaves/w1_ds250x.c ++++ b/drivers/w1/slaves/w1_ds250x.c +@@ -168,6 +168,7 @@ static int w1_eprom_add_slave(struct w1_ + struct nvmem_device *nvmem; + struct nvmem_config nvmem_cfg = { + .dev = &sl->dev, ++ .add_legacy_fixed_of_cells = true, + .reg_read = w1_nvmem_read, + .type = NVMEM_TYPE_OTP, + .read_only = true, +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -82,6 +82,7 @@ struct nvmem_cell_info { + * @owner: Pointer to exporter module. Used for refcounting. + * @cells: Optional array of pre-defined NVMEM cells. + * @ncells: Number of elements in cells. ++ * @add_legacy_fixed_of_cells: Read fixed NVMEM cells from old OF syntax. + * @keepout: Optional array of keepout ranges (sorted ascending by start). + * @nkeepout: Number of elements in the keepout array. + * @type: Type of the nvmem storage +@@ -112,6 +113,7 @@ struct nvmem_config { + struct module *owner; + const struct nvmem_cell_info *cells; + int ncells; ++ bool add_legacy_fixed_of_cells; + const struct nvmem_keepout *keepout; + unsigned int nkeepout; + enum nvmem_type type; diff --git a/lede/target/linux/generic/backport-6.1/816-v6.7-0003-nvmem-Use-device_get_match_data.patch b/lede/target/linux/generic/backport-6.1/816-v6.7-0003-nvmem-Use-device_get_match_data.patch new file mode 100644 index 0000000000..84c0293982 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/816-v6.7-0003-nvmem-Use-device_get_match_data.patch @@ -0,0 +1,77 @@ +From 0720219f4d34a88a9badb4de70cfad7585687d48 Mon Sep 17 00:00:00 2001 +From: Rob Herring +Date: Fri, 20 Oct 2023 11:55:45 +0100 +Subject: [PATCH] nvmem: Use device_get_match_data() + +Use preferred device_get_match_data() instead of of_match_device() to +get the driver match data. With this, adjust the includes to explicitly +include the correct headers. + +Signed-off-by: Rob Herring +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231020105545.216052-7-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/mxs-ocotp.c | 10 ++++------ + drivers/nvmem/stm32-romem.c | 7 ++++--- + 2 files changed, 8 insertions(+), 9 deletions(-) + +--- a/drivers/nvmem/mxs-ocotp.c ++++ b/drivers/nvmem/mxs-ocotp.c +@@ -13,8 +13,9 @@ + #include + #include + #include +-#include ++#include + #include ++#include + #include + #include + +@@ -140,11 +141,10 @@ static int mxs_ocotp_probe(struct platfo + struct device *dev = &pdev->dev; + const struct mxs_data *data; + struct mxs_ocotp *otp; +- const struct of_device_id *match; + int ret; + +- match = of_match_device(dev->driver->of_match_table, dev); +- if (!match || !match->data) ++ data = device_get_match_data(dev); ++ if (!data) + return -EINVAL; + + otp = devm_kzalloc(dev, sizeof(*otp), GFP_KERNEL); +@@ -169,8 +169,6 @@ static int mxs_ocotp_probe(struct platfo + if (ret) + return ret; + +- data = match->data; +- + ocotp_config.size = data->size; + ocotp_config.priv = otp; + ocotp_config.dev = dev; +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -10,7 +10,9 @@ + #include + #include + #include +-#include ++#include ++#include ++#include + #include + + #include "stm32-bsec-optee-ta.h" +@@ -211,8 +213,7 @@ static int stm32_romem_probe(struct plat + + priv->lower = 0; + +- cfg = (const struct stm32_romem_cfg *) +- of_match_device(dev->driver->of_match_table, dev)->data; ++ cfg = device_get_match_data(dev); + if (!cfg) { + priv->cfg.read_only = true; + priv->cfg.size = resource_size(res); diff --git a/lede/target/linux/generic/backport-6.1/816-v6.7-0004-Revert-nvmem-add-new-config-option.patch b/lede/target/linux/generic/backport-6.1/816-v6.7-0004-Revert-nvmem-add-new-config-option.patch new file mode 100644 index 0000000000..7d80ad37f1 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/816-v6.7-0004-Revert-nvmem-add-new-config-option.patch @@ -0,0 +1,77 @@ +From f4cf4e5db331a5ce69e3f0b21d322cac0f4e4b5d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 23 Oct 2023 12:27:59 +0200 +Subject: [PATCH] Revert "nvmem: add new config option" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This reverts commit 517f14d9cf3533d5ab4fded195ab6f80a92e378f. + +Config option "no_of_node" is no longer needed since adding a more +explicit and targeted option "add_legacy_fixed_of_cells". + +That "no_of_node" config option was needed *earlier* to help mtd's case. + +DT nodes of MTD partitions (that are also NVMEM devices) may contain +subnodes. Those SHOULD NOT be treated as NVMEM fixed cells. + +To prevent NVMEM core code from parsing subnodes a "no_of_node" option +was added (and set to true in mtd) to make for_each_child_of_node() in +NVMEM a no-op. That was a bit hacky because it was messing with +"of_node" pointer to achieve some side-effect. + +With the introduction of "add_legacy_fixed_of_cells" config option +things got more explicit. MTD subsystem simply tells NVMEM when to look +for fixed cells and there is no need to hack "of_node" pointer anymore. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231023102759.31529-1-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mtd/mtdcore.c | 1 - + drivers/nvmem/core.c | 2 +- + include/linux/nvmem-provider.h | 2 -- + 3 files changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -531,7 +531,6 @@ static int mtd_nvmem_add(struct mtd_info + config.read_only = true; + config.root_only = true; + config.ignore_wp = true; +- config.no_of_node = !of_device_is_compatible(node, "nvmem-cells"); + config.priv = mtd; + + mtd->nvmem = nvmem_register(&config); +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -936,7 +936,7 @@ struct nvmem_device *nvmem_register(cons + nvmem->nkeepout = config->nkeepout; + if (config->of_node) + nvmem->dev.of_node = config->of_node; +- else if (!config->no_of_node) ++ else + nvmem->dev.of_node = config->dev->of_node; + + switch (config->id) { +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -89,7 +89,6 @@ struct nvmem_cell_info { + * @read_only: Device is read-only. + * @root_only: Device is accessibly to root only. + * @of_node: If given, this will be used instead of the parent's of_node. +- * @no_of_node: Device should not use the parent's of_node even if it's !NULL. + * @reg_read: Callback to read data. + * @reg_write: Callback to write data. + * @size: Device size. +@@ -122,7 +121,6 @@ struct nvmem_config { + bool ignore_wp; + struct nvmem_layout *layout; + struct device_node *of_node; +- bool no_of_node; + nvmem_reg_read_t reg_read; + nvmem_reg_write_t reg_write; + int size; diff --git a/lede/target/linux/generic/backport-6.1/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch b/lede/target/linux/generic/backport-6.1/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch new file mode 100644 index 0000000000..bd5ceaabf7 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/816-v6.7-0005-nvmem-Do-not-expect-fixed-layouts-to-grab-a-layout-d.patch @@ -0,0 +1,45 @@ +From b7c1e53751cb3990153084f31c41f25fde3b629c Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 24 Nov 2023 20:38:14 +0100 +Subject: [PATCH] nvmem: Do not expect fixed layouts to grab a layout driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Two series lived in parallel for some time, which led to this situation: +- The nvmem-layout container is used for dynamic layouts +- We now expect fixed layouts to also use the nvmem-layout container but +this does not require any additional driver, the support is built-in the +nvmem core. + +Ensure we don't refuse to probe for wrong reasons. + +Fixes: 27f699e578b1 ("nvmem: core: add support for fixed cells *layout*") +Cc: stable@vger.kernel.org +Reported-by: Luca Ceresoli +Signed-off-by: Miquel Raynal +Tested-by: Rafał Miłecki +Tested-by: Luca Ceresoli +Reviewed-by: Luca Ceresoli + +Link: https://lore.kernel.org/r/20231124193814.360552-1-miquel.raynal@bootlin.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -797,6 +797,12 @@ static struct nvmem_layout *nvmem_layout + if (!layout_np) + return NULL; + ++ /* Fixed layouts don't have a matching driver */ ++ if (of_device_is_compatible(layout_np, "fixed-layout")) { ++ of_node_put(layout_np); ++ return NULL; ++ } ++ + /* + * In case the nvmem device was built-in while the layout was built as a + * module, we shall manually request the layout driver loading otherwise diff --git a/lede/target/linux/generic/backport-6.1/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch b/lede/target/linux/generic/backport-6.1/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch new file mode 100644 index 0000000000..d49a20599d --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/816-v6.7-0006-nvmem-brcm_nvram-store-a-copy-of-NVRAM-content.patch @@ -0,0 +1,261 @@ +From 1e37bf84afacd5ba17b7a13a18ca2bc78aff05c0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 15 Dec 2023 11:13:58 +0000 +Subject: [PATCH] nvmem: brcm_nvram: store a copy of NVRAM content +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This driver uses MMIO access for reading NVRAM from a flash device. +Underneath there is a flash controller that reads data and provides +mapping window. + +Using MMIO interface affects controller configuration and may break real +controller driver. It was reported by multiple users of devices with +NVRAM stored on NAND. + +Modify driver to read & cache NVRAM content during init and use that +copy to provide NVMEM data when requested. On NAND flashes due to their +alignment NVRAM partitions can be quite big (1 MiB and more) while +actual NVRAM content stays quite small (usually 16 to 32 KiB). To avoid +allocating so much memory check for actual data length. + +Link: https://lore.kernel.org/linux-mtd/CACna6rwf3_9QVjYcM+847biTX=K0EoWXuXcSMkJO1Vy_5vmVqA@mail.gmail.com/ +Fixes: 3fef9ed0627a ("nvmem: brcm_nvram: new driver exposing Broadcom's NVRAM") +Cc: +Cc: Arınç ÜNAL +Cc: Florian Fainelli +Cc: Scott Branden +Signed-off-by: Rafał Miłecki +Acked-by: Arınç ÜNAL +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111358.316727-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/brcm_nvram.c | 134 ++++++++++++++++++++++++++----------- + 1 file changed, 94 insertions(+), 40 deletions(-) + +--- a/drivers/nvmem/brcm_nvram.c ++++ b/drivers/nvmem/brcm_nvram.c +@@ -17,9 +17,23 @@ + + #define NVRAM_MAGIC "FLSH" + ++/** ++ * struct brcm_nvram - driver state internal struct ++ * ++ * @dev: NVMEM device pointer ++ * @nvmem_size: Size of the whole space available for NVRAM ++ * @data: NVRAM data copy stored to avoid poking underlaying flash controller ++ * @data_len: NVRAM data size ++ * @padding_byte: Padding value used to fill remaining space ++ * @cells: Array of discovered NVMEM cells ++ * @ncells: Number of elements in cells ++ */ + struct brcm_nvram { + struct device *dev; +- void __iomem *base; ++ size_t nvmem_size; ++ uint8_t *data; ++ size_t data_len; ++ uint8_t padding_byte; + struct nvmem_cell_info *cells; + int ncells; + }; +@@ -36,10 +50,47 @@ static int brcm_nvram_read(void *context + size_t bytes) + { + struct brcm_nvram *priv = context; +- u8 *dst = val; ++ size_t to_copy; ++ ++ if (offset + bytes > priv->data_len) ++ to_copy = max_t(ssize_t, (ssize_t)priv->data_len - offset, 0); ++ else ++ to_copy = bytes; ++ ++ memcpy(val, priv->data + offset, to_copy); ++ ++ memset((uint8_t *)val + to_copy, priv->padding_byte, bytes - to_copy); ++ ++ return 0; ++} ++ ++static int brcm_nvram_copy_data(struct brcm_nvram *priv, struct platform_device *pdev) ++{ ++ struct resource *res; ++ void __iomem *base; ++ ++ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ priv->nvmem_size = resource_size(res); ++ ++ priv->padding_byte = readb(base + priv->nvmem_size - 1); ++ for (priv->data_len = priv->nvmem_size; ++ priv->data_len; ++ priv->data_len--) { ++ if (readb(base + priv->data_len - 1) != priv->padding_byte) ++ break; ++ } ++ WARN(priv->data_len > SZ_128K, "Unexpected (big) NVRAM size: %zu B\n", priv->data_len); + +- while (bytes--) +- *dst++ = readb(priv->base + offset++); ++ priv->data = devm_kzalloc(priv->dev, priv->data_len, GFP_KERNEL); ++ if (!priv->data) ++ return -ENOMEM; ++ ++ memcpy_fromio(priv->data, base, priv->data_len); ++ ++ bcm47xx_nvram_init_from_iomem(base, priv->data_len); + + return 0; + } +@@ -67,8 +118,13 @@ static int brcm_nvram_add_cells(struct b + size_t len) + { + struct device *dev = priv->dev; +- char *var, *value, *eq; ++ char *var, *value; ++ uint8_t tmp; + int idx; ++ int err = 0; ++ ++ tmp = priv->data[len - 1]; ++ priv->data[len - 1] = '\0'; + + priv->ncells = 0; + for (var = data + sizeof(struct brcm_nvram_header); +@@ -78,67 +134,68 @@ static int brcm_nvram_add_cells(struct b + } + + priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL); +- if (!priv->cells) +- return -ENOMEM; ++ if (!priv->cells) { ++ err = -ENOMEM; ++ goto out; ++ } + + for (var = data + sizeof(struct brcm_nvram_header), idx = 0; + var < (char *)data + len && *var; + var = value + strlen(value) + 1, idx++) { ++ char *eq, *name; ++ + eq = strchr(var, '='); + if (!eq) + break; + *eq = '\0'; ++ name = devm_kstrdup(dev, var, GFP_KERNEL); ++ *eq = '='; ++ if (!name) { ++ err = -ENOMEM; ++ goto out; ++ } + value = eq + 1; + +- priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL); +- if (!priv->cells[idx].name) +- return -ENOMEM; ++ priv->cells[idx].name = name; + priv->cells[idx].offset = value - (char *)data; + priv->cells[idx].bytes = strlen(value); + priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); +- if (!strcmp(var, "et0macaddr") || +- !strcmp(var, "et1macaddr") || +- !strcmp(var, "et2macaddr")) { ++ if (!strcmp(name, "et0macaddr") || ++ !strcmp(name, "et1macaddr") || ++ !strcmp(name, "et2macaddr")) { + priv->cells[idx].raw_len = strlen(value); + priv->cells[idx].bytes = ETH_ALEN; + priv->cells[idx].read_post_process = brcm_nvram_read_post_process_macaddr; + } + } + +- return 0; ++out: ++ priv->data[len - 1] = tmp; ++ return err; + } + + static int brcm_nvram_parse(struct brcm_nvram *priv) + { ++ struct brcm_nvram_header *header = (struct brcm_nvram_header *)priv->data; + struct device *dev = priv->dev; +- struct brcm_nvram_header header; +- uint8_t *data; + size_t len; + int err; + +- memcpy_fromio(&header, priv->base, sizeof(header)); +- +- if (memcmp(header.magic, NVRAM_MAGIC, 4)) { ++ if (memcmp(header->magic, NVRAM_MAGIC, 4)) { + dev_err(dev, "Invalid NVRAM magic\n"); + return -EINVAL; + } + +- len = le32_to_cpu(header.len); +- +- data = kzalloc(len, GFP_KERNEL); +- if (!data) +- return -ENOMEM; +- +- memcpy_fromio(data, priv->base, len); +- data[len - 1] = '\0'; +- +- err = brcm_nvram_add_cells(priv, data, len); +- if (err) { +- dev_err(dev, "Failed to add cells: %d\n", err); +- return err; ++ len = le32_to_cpu(header->len); ++ if (len > priv->nvmem_size) { ++ dev_err(dev, "NVRAM length (%zd) exceeds mapped size (%zd)\n", len, ++ priv->nvmem_size); ++ return -EINVAL; + } + +- kfree(data); ++ err = brcm_nvram_add_cells(priv, priv->data, len); ++ if (err) ++ dev_err(dev, "Failed to add cells: %d\n", err); + + return 0; + } +@@ -150,7 +207,6 @@ static int brcm_nvram_probe(struct platf + .reg_read = brcm_nvram_read, + }; + struct device *dev = &pdev->dev; +- struct resource *res; + struct brcm_nvram *priv; + int err; + +@@ -159,21 +215,19 @@ static int brcm_nvram_probe(struct platf + return -ENOMEM; + priv->dev = dev; + +- priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); +- if (IS_ERR(priv->base)) +- return PTR_ERR(priv->base); ++ err = brcm_nvram_copy_data(priv, pdev); ++ if (err) ++ return err; + + err = brcm_nvram_parse(priv); + if (err) + return err; + +- bcm47xx_nvram_init_from_iomem(priv->base, resource_size(res)); +- + config.dev = dev; + config.cells = priv->cells; + config.ncells = priv->ncells; + config.priv = priv; +- config.size = resource_size(res); ++ config.size = priv->nvmem_size; + + return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); + } diff --git a/lede/target/linux/generic/backport-6.1/817-v6.9-0001-dt-bindings-leds-Add-FUNCTION-defines-for-per-band-W.patch b/lede/target/linux/generic/backport-6.1/817-v6.9-0001-dt-bindings-leds-Add-FUNCTION-defines-for-per-band-W.patch new file mode 100644 index 0000000000..bf36e19fcc --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/817-v6.9-0001-dt-bindings-leds-Add-FUNCTION-defines-for-per-band-W.patch @@ -0,0 +1,34 @@ +From ec18a2a83b8b9f7e39c80105ea148c769c46227b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Wed, 17 Jan 2024 16:17:36 +0100 +Subject: [PATCH] dt-bindings: leds: Add FUNCTION defines for per-band WLANs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Most wireless routers and access points can operate in multiple bands +simultaneously. Vendors often equip their devices with per-band LEDs. + +Add defines for those very common functions to allow cleaner & clearer +bindings. + +Signed-off-by: Rafał Miłecki +Acked-by: Rob Herring +Link: https://lore.kernel.org/r/20240117151736.27440-1-zajec5@gmail.com +Signed-off-by: Lee Jones +--- + include/dt-bindings/leds/common.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/include/dt-bindings/leds/common.h ++++ b/include/dt-bindings/leds/common.h +@@ -101,6 +101,9 @@ + #define LED_FUNCTION_USB "usb" + #define LED_FUNCTION_WAN "wan" + #define LED_FUNCTION_WLAN "wlan" ++#define LED_FUNCTION_WLAN_2GHZ "wlan-2ghz" ++#define LED_FUNCTION_WLAN_5GHZ "wlan-5ghz" ++#define LED_FUNCTION_WLAN_6GHZ "wlan-6ghz" + #define LED_FUNCTION_WPS "wps" + + #endif /* __DT_BINDINGS_LEDS_H */ diff --git a/lede/target/linux/generic/backport-6.1/817-v6.9-0002-dt-bindings-leds-Add-LED_FUNCTION_WAN_ONLINE-for-Int.patch b/lede/target/linux/generic/backport-6.1/817-v6.9-0002-dt-bindings-leds-Add-LED_FUNCTION_WAN_ONLINE-for-Int.patch new file mode 100644 index 0000000000..eabb9bbe9a --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/817-v6.9-0002-dt-bindings-leds-Add-LED_FUNCTION_WAN_ONLINE-for-Int.patch @@ -0,0 +1,35 @@ +From 64e558500d2d04878b8a6d6578850c475171d6ba Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 23 Feb 2024 12:22:23 +0100 +Subject: [PATCH] dt-bindings: leds: Add LED_FUNCTION_WAN_ONLINE for Internet + access +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It's common for routers to have LED indicating link on the WAN port. + +Some devices however have an extra LED that's meant to be used if WAN +connection is actually "online" (there is Internet access available). + +It was suggested to add #define for such use case. + +Link: https://lore.kernel.org/linux-devicetree/80e92209-5578-44e7-bd4b-603a29053ddf@collabora.com/T/#u +Signed-off-by: Rafał Miłecki +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20240223112223.1368-1-zajec5@gmail.com +Signed-off-by: Lee Jones +--- + include/dt-bindings/leds/common.h | 1 + + 1 file changed, 1 insertion(+) + +--- a/include/dt-bindings/leds/common.h ++++ b/include/dt-bindings/leds/common.h +@@ -100,6 +100,7 @@ + #define LED_FUNCTION_TX "tx" + #define LED_FUNCTION_USB "usb" + #define LED_FUNCTION_WAN "wan" ++#define LED_FUNCTION_WAN_ONLINE "wan-online" + #define LED_FUNCTION_WLAN "wlan" + #define LED_FUNCTION_WLAN_2GHZ "wlan-2ghz" + #define LED_FUNCTION_WLAN_5GHZ "wlan-5ghz" diff --git a/lede/target/linux/generic/backport-6.1/818-v6.8-of-device-Export-of_device_make_bus_id.patch b/lede/target/linux/generic/backport-6.1/818-v6.8-of-device-Export-of_device_make_bus_id.patch new file mode 100644 index 0000000000..564fe9822d --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/818-v6.8-of-device-Export-of_device_make_bus_id.patch @@ -0,0 +1,140 @@ +From 7f38b70042fcaa49219045bd1a9a2836e27a58ac Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 15 Dec 2023 11:15:27 +0000 +Subject: [PATCH] of: device: Export of_device_make_bus_id() + +This helper is really handy to create unique device names based on their +device tree path, we may need it outside of the OF core (in the NVMEM +subsystem) so let's export it. As this helper has nothing patform +specific, let's move it to of/device.c instead of of/platform.c so we +can add its prototype to of_device.h. + +Signed-off-by: Miquel Raynal +Acked-by: Rob Herring +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-2-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/of/device.c | 41 +++++++++++++++++++++++++++++++++++++++ + drivers/of/platform.c | 40 -------------------------------------- + include/linux/of_device.h | 6 ++++++ + 3 files changed, 47 insertions(+), 40 deletions(-) + +--- a/drivers/of/device.c ++++ b/drivers/of/device.c +@@ -395,3 +395,44 @@ int of_device_uevent_modalias(struct dev + return 0; + } + EXPORT_SYMBOL_GPL(of_device_uevent_modalias); ++ ++/** ++ * of_device_make_bus_id - Use the device node data to assign a unique name ++ * @dev: pointer to device structure that is linked to a device tree node ++ * ++ * This routine will first try using the translated bus address to ++ * derive a unique name. If it cannot, then it will prepend names from ++ * parent nodes until a unique name can be derived. ++ */ ++void of_device_make_bus_id(struct device *dev) ++{ ++ struct device_node *node = dev->of_node; ++ const __be32 *reg; ++ u64 addr; ++ u32 mask; ++ ++ /* Construct the name, using parent nodes if necessary to ensure uniqueness */ ++ while (node->parent) { ++ /* ++ * If the address can be translated, then that is as much ++ * uniqueness as we need. Make it the first component and return ++ */ ++ reg = of_get_property(node, "reg", NULL); ++ if (reg && (addr = of_translate_address(node, reg)) != OF_BAD_ADDR) { ++ if (!of_property_read_u32(node, "mask", &mask)) ++ dev_set_name(dev, dev_name(dev) ? "%llx.%x.%pOFn:%s" : "%llx.%x.%pOFn", ++ addr, ffs(mask) - 1, node, dev_name(dev)); ++ ++ else ++ dev_set_name(dev, dev_name(dev) ? "%llx.%pOFn:%s" : "%llx.%pOFn", ++ addr, node, dev_name(dev)); ++ return; ++ } ++ ++ /* format arguments only used if dev_name() resolves to NULL */ ++ dev_set_name(dev, dev_name(dev) ? "%s:%s" : "%s", ++ kbasename(node->full_name), dev_name(dev)); ++ node = node->parent; ++ } ++} ++EXPORT_SYMBOL_GPL(of_device_make_bus_id); +--- a/drivers/of/platform.c ++++ b/drivers/of/platform.c +@@ -64,46 +64,6 @@ EXPORT_SYMBOL(of_find_device_by_node); + */ + + /** +- * of_device_make_bus_id - Use the device node data to assign a unique name +- * @dev: pointer to device structure that is linked to a device tree node +- * +- * This routine will first try using the translated bus address to +- * derive a unique name. If it cannot, then it will prepend names from +- * parent nodes until a unique name can be derived. +- */ +-static void of_device_make_bus_id(struct device *dev) +-{ +- struct device_node *node = dev->of_node; +- const __be32 *reg; +- u64 addr; +- u32 mask; +- +- /* Construct the name, using parent nodes if necessary to ensure uniqueness */ +- while (node->parent) { +- /* +- * If the address can be translated, then that is as much +- * uniqueness as we need. Make it the first component and return +- */ +- reg = of_get_property(node, "reg", NULL); +- if (reg && (addr = of_translate_address(node, reg)) != OF_BAD_ADDR) { +- if (!of_property_read_u32(node, "mask", &mask)) +- dev_set_name(dev, dev_name(dev) ? "%llx.%x.%pOFn:%s" : "%llx.%x.%pOFn", +- addr, ffs(mask) - 1, node, dev_name(dev)); +- +- else +- dev_set_name(dev, dev_name(dev) ? "%llx.%pOFn:%s" : "%llx.%pOFn", +- addr, node, dev_name(dev)); +- return; +- } +- +- /* format arguments only used if dev_name() resolves to NULL */ +- dev_set_name(dev, dev_name(dev) ? "%s:%s" : "%s", +- kbasename(node->full_name), dev_name(dev)); +- node = node->parent; +- } +-} +- +-/** + * of_device_alloc - Allocate and initialize an of_device + * @np: device node to assign to device + * @bus_id: Name to assign to the device. May be null to use default name. +--- a/include/linux/of_device.h ++++ b/include/linux/of_device.h +@@ -56,6 +56,9 @@ static inline int of_dma_configure(struc + { + return of_dma_configure_id(dev, np, force_dma, NULL); + } ++ ++void of_device_make_bus_id(struct device *dev); ++ + #else /* CONFIG_OF */ + + static inline int of_driver_match_device(struct device *dev, +@@ -113,6 +116,9 @@ static inline int of_dma_configure(struc + { + return 0; + } ++ ++static inline void of_device_make_bus_id(struct device *dev) {} ++ + #endif /* CONFIG_OF */ + + #endif /* _LINUX_OF_DEVICE_H */ diff --git a/lede/target/linux/generic/backport-6.1/819-v6.8-0001-nvmem-Move-of_nvmem_layout_get_container-in-another-.patch b/lede/target/linux/generic/backport-6.1/819-v6.8-0001-nvmem-Move-of_nvmem_layout_get_container-in-another-.patch new file mode 100644 index 0000000000..2093fac8a1 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/819-v6.8-0001-nvmem-Move-of_nvmem_layout_get_container-in-another-.patch @@ -0,0 +1,95 @@ +From 4a1a40233b4a9fc159a5c7a27dc34c5c7bc5be55 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 15 Dec 2023 11:15:28 +0000 +Subject: [PATCH] nvmem: Move of_nvmem_layout_get_container() in another header + +nvmem-consumer.h is included by consumer devices, extracting data from +NVMEM devices whereas nvmem-provider.h is included by devices providing +NVMEM content. + +The only users of of_nvmem_layout_get_container() outside of the core +are layout drivers, so better move its prototype to nvmem-provider.h. + +While we do so, we also move the kdoc associated with the function to +the header rather than the .c file. + +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-3-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 8 -------- + include/linux/nvmem-consumer.h | 7 ------- + include/linux/nvmem-provider.h | 21 +++++++++++++++++++++ + 3 files changed, 21 insertions(+), 15 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -848,14 +848,6 @@ static int nvmem_add_cells_from_layout(s + } + + #if IS_ENABLED(CONFIG_OF) +-/** +- * of_nvmem_layout_get_container() - Get OF node to layout container. +- * +- * @nvmem: nvmem device. +- * +- * Return: a node pointer with refcount incremented or NULL if no +- * container exists. Use of_node_put() on it when done. +- */ + struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem) + { + return of_get_child_by_name(nvmem->dev.of_node, "nvmem-layout"); +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -241,7 +241,6 @@ struct nvmem_cell *of_nvmem_cell_get(str + const char *id); + struct nvmem_device *of_nvmem_device_get(struct device_node *np, + const char *name); +-struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem); + #else + static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, + const char *id) +@@ -254,12 +253,6 @@ static inline struct nvmem_device *of_nv + { + return ERR_PTR(-EOPNOTSUPP); + } +- +-static inline struct device_node * +-of_nvmem_layout_get_container(struct nvmem_device *nvmem) +-{ +- return NULL; +-} + #endif /* CONFIG_NVMEM && CONFIG_OF */ + + #endif /* ifndef _LINUX_NVMEM_CONSUMER_H */ +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -244,6 +244,27 @@ nvmem_layout_get_match_data(struct nvmem + + #endif /* CONFIG_NVMEM */ + ++#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) ++ ++/** ++ * of_nvmem_layout_get_container() - Get OF node of layout container ++ * ++ * @nvmem: nvmem device ++ * ++ * Return: a node pointer with refcount incremented or NULL if no ++ * container exists. Use of_node_put() on it when done. ++ */ ++struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem); ++ ++#else /* CONFIG_NVMEM && CONFIG_OF */ ++ ++static inline struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem) ++{ ++ return NULL; ++} ++ ++#endif /* CONFIG_NVMEM && CONFIG_OF */ ++ + #define module_nvmem_layout_driver(__layout_driver) \ + module_driver(__layout_driver, nvmem_layout_register, \ + nvmem_layout_unregister) diff --git a/lede/target/linux/generic/backport-6.1/819-v6.8-0002-nvmem-Create-a-header-for-internal-sharing.patch b/lede/target/linux/generic/backport-6.1/819-v6.8-0002-nvmem-Create-a-header-for-internal-sharing.patch new file mode 100644 index 0000000000..e722109f91 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/819-v6.8-0002-nvmem-Create-a-header-for-internal-sharing.patch @@ -0,0 +1,91 @@ +From ec9c08a1cb8dc5e8e003f95f5f62de41dde235bb Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 15 Dec 2023 11:15:29 +0000 +Subject: [PATCH] nvmem: Create a header for internal sharing + +Before adding all the NVMEM layout bus infrastructure to the core, let's +move the main nvmem_device structure in an internal header, only +available to the core. This way all the additional code can be added in +a dedicated file in order to keep the current core file tidy. + +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-4-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 24 +----------------------- + drivers/nvmem/internals.h | 35 +++++++++++++++++++++++++++++++++++ + 2 files changed, 36 insertions(+), 23 deletions(-) + create mode 100644 drivers/nvmem/internals.h + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -20,29 +20,7 @@ + #include + #include + +-struct nvmem_device { +- struct module *owner; +- struct device dev; +- int stride; +- int word_size; +- int id; +- struct kref refcnt; +- size_t size; +- bool read_only; +- bool root_only; +- int flags; +- enum nvmem_type type; +- struct bin_attribute eeprom; +- struct device *base_dev; +- struct list_head cells; +- const struct nvmem_keepout *keepout; +- unsigned int nkeepout; +- nvmem_reg_read_t reg_read; +- nvmem_reg_write_t reg_write; +- struct gpio_desc *wp_gpio; +- struct nvmem_layout *layout; +- void *priv; +-}; ++#include "internals.h" + + #define to_nvmem_device(d) container_of(d, struct nvmem_device, dev) + +--- /dev/null ++++ b/drivers/nvmem/internals.h +@@ -0,0 +1,35 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef _LINUX_NVMEM_INTERNALS_H ++#define _LINUX_NVMEM_INTERNALS_H ++ ++#include ++#include ++#include ++ ++struct nvmem_device { ++ struct module *owner; ++ struct device dev; ++ struct list_head node; ++ int stride; ++ int word_size; ++ int id; ++ struct kref refcnt; ++ size_t size; ++ bool read_only; ++ bool root_only; ++ int flags; ++ enum nvmem_type type; ++ struct bin_attribute eeprom; ++ struct device *base_dev; ++ struct list_head cells; ++ const struct nvmem_keepout *keepout; ++ unsigned int nkeepout; ++ nvmem_reg_read_t reg_read; ++ nvmem_reg_write_t reg_write; ++ struct gpio_desc *wp_gpio; ++ struct nvmem_layout *layout; ++ void *priv; ++}; ++ ++#endif /* ifndef _LINUX_NVMEM_INTERNALS_H */ diff --git a/lede/target/linux/generic/backport-6.1/819-v6.8-0003-nvmem-Simplify-the-add_cells-hook.patch b/lede/target/linux/generic/backport-6.1/819-v6.8-0003-nvmem-Simplify-the-add_cells-hook.patch new file mode 100644 index 0000000000..db2d8c1b46 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/819-v6.8-0003-nvmem-Simplify-the-add_cells-hook.patch @@ -0,0 +1,79 @@ +From 1b7c298a4ecbc28cc6ee94005734bff55eb83d22 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 15 Dec 2023 11:15:30 +0000 +Subject: [PATCH] nvmem: Simplify the ->add_cells() hook + +The layout entry is not used and will anyway be made useless by the new +layout bus infrastructure coming next, so drop it. While at it, clarify +the kdoc entry. + +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-5-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 2 +- + drivers/nvmem/layouts/onie-tlv.c | 3 +-- + drivers/nvmem/layouts/sl28vpd.c | 3 +-- + include/linux/nvmem-provider.h | 8 +++----- + 4 files changed, 6 insertions(+), 10 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -817,7 +817,7 @@ static int nvmem_add_cells_from_layout(s + int ret; + + if (layout && layout->add_cells) { +- ret = layout->add_cells(&nvmem->dev, nvmem, layout); ++ ret = layout->add_cells(&nvmem->dev, nvmem); + if (ret) + return ret; + } +--- a/drivers/nvmem/layouts/onie-tlv.c ++++ b/drivers/nvmem/layouts/onie-tlv.c +@@ -182,8 +182,7 @@ static bool onie_tlv_crc_is_valid(struct + return true; + } + +-static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem, +- struct nvmem_layout *layout) ++static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem) + { + struct onie_tlv_hdr hdr; + size_t table_len, data_len, hdr_len; +--- a/drivers/nvmem/layouts/sl28vpd.c ++++ b/drivers/nvmem/layouts/sl28vpd.c +@@ -80,8 +80,7 @@ static int sl28vpd_v1_check_crc(struct d + return 0; + } + +-static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem, +- struct nvmem_layout *layout) ++static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem) + { + const struct nvmem_cell_info *pinfo; + struct nvmem_cell_info info = {0}; +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -156,9 +156,8 @@ struct nvmem_cell_table { + * + * @name: Layout name. + * @of_match_table: Open firmware match table. +- * @add_cells: Will be called if a nvmem device is found which +- * has this layout. The function will add layout +- * specific cells with nvmem_add_one_cell(). ++ * @add_cells: Called to populate the layout using ++ * nvmem_add_one_cell(). + * @fixup_cell_info: Will be called before a cell is added. Can be + * used to modify the nvmem_cell_info. + * @owner: Pointer to struct module. +@@ -172,8 +171,7 @@ struct nvmem_cell_table { + struct nvmem_layout { + const char *name; + const struct of_device_id *of_match_table; +- int (*add_cells)(struct device *dev, struct nvmem_device *nvmem, +- struct nvmem_layout *layout); ++ int (*add_cells)(struct device *dev, struct nvmem_device *nvmem); + void (*fixup_cell_info)(struct nvmem_device *nvmem, + struct nvmem_layout *layout, + struct nvmem_cell_info *cell); diff --git a/lede/target/linux/generic/backport-6.1/819-v6.8-0004-nvmem-Move-and-rename-fixup_cell_info.patch b/lede/target/linux/generic/backport-6.1/819-v6.8-0004-nvmem-Move-and-rename-fixup_cell_info.patch new file mode 100644 index 0000000000..65aa37f834 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/819-v6.8-0004-nvmem-Move-and-rename-fixup_cell_info.patch @@ -0,0 +1,169 @@ +From 1172460e716784ac7e1049a537bdca8edbf97360 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 15 Dec 2023 11:15:31 +0000 +Subject: [PATCH] nvmem: Move and rename ->fixup_cell_info() + +This hook is meant to be used by any provider and instantiating a layout +just for this is useless. Let's instead move this hook to the nvmem +device and add it to the config structure to be easily shared by the +providers. + +While at moving this hook, rename it ->fixup_dt_cell_info() to clarify +its main intended purpose. + +Signed-off-by: Miquel Raynal +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-6-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 6 +++--- + drivers/nvmem/imx-ocotp.c | 11 +++-------- + drivers/nvmem/internals.h | 2 ++ + drivers/nvmem/mtk-efuse.c | 11 +++-------- + include/linux/nvmem-provider.h | 9 ++++----- + 5 files changed, 15 insertions(+), 24 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -676,7 +676,6 @@ static int nvmem_validate_keepouts(struc + + static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np) + { +- struct nvmem_layout *layout = nvmem->layout; + struct device *dev = &nvmem->dev; + struct device_node *child; + const __be32 *addr; +@@ -706,8 +705,8 @@ static int nvmem_add_cells_from_dt(struc + + info.np = of_node_get(child); + +- if (layout && layout->fixup_cell_info) +- layout->fixup_cell_info(nvmem, layout, &info); ++ if (nvmem->fixup_dt_cell_info) ++ nvmem->fixup_dt_cell_info(nvmem, &info); + + ret = nvmem_add_one_cell(nvmem, &info); + kfree(info.name); +@@ -896,6 +895,7 @@ struct nvmem_device *nvmem_register(cons + + kref_init(&nvmem->refcnt); + INIT_LIST_HEAD(&nvmem->cells); ++ nvmem->fixup_dt_cell_info = config->fixup_dt_cell_info; + + nvmem->owner = config->owner; + if (!nvmem->owner && config->dev->driver) +--- a/drivers/nvmem/imx-ocotp.c ++++ b/drivers/nvmem/imx-ocotp.c +@@ -584,17 +584,12 @@ static const struct of_device_id imx_oco + }; + MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids); + +-static void imx_ocotp_fixup_cell_info(struct nvmem_device *nvmem, +- struct nvmem_layout *layout, +- struct nvmem_cell_info *cell) ++static void imx_ocotp_fixup_dt_cell_info(struct nvmem_device *nvmem, ++ struct nvmem_cell_info *cell) + { + cell->read_post_process = imx_ocotp_cell_pp; + } + +-static struct nvmem_layout imx_ocotp_layout = { +- .fixup_cell_info = imx_ocotp_fixup_cell_info, +-}; +- + static int imx_ocotp_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -620,7 +615,7 @@ static int imx_ocotp_probe(struct platfo + imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; + imx_ocotp_nvmem_config.dev = dev; + imx_ocotp_nvmem_config.priv = priv; +- imx_ocotp_nvmem_config.layout = &imx_ocotp_layout; ++ imx_ocotp_nvmem_config.fixup_dt_cell_info = &imx_ocotp_fixup_dt_cell_info; + + priv->config = &imx_ocotp_nvmem_config; + +--- a/drivers/nvmem/internals.h ++++ b/drivers/nvmem/internals.h +@@ -23,6 +23,8 @@ struct nvmem_device { + struct bin_attribute eeprom; + struct device *base_dev; + struct list_head cells; ++ void (*fixup_dt_cell_info)(struct nvmem_device *nvmem, ++ struct nvmem_cell_info *cell); + const struct nvmem_keepout *keepout; + unsigned int nkeepout; + nvmem_reg_read_t reg_read; +--- a/drivers/nvmem/mtk-efuse.c ++++ b/drivers/nvmem/mtk-efuse.c +@@ -45,9 +45,8 @@ static int mtk_efuse_gpu_speedbin_pp(voi + return 0; + } + +-static void mtk_efuse_fixup_cell_info(struct nvmem_device *nvmem, +- struct nvmem_layout *layout, +- struct nvmem_cell_info *cell) ++static void mtk_efuse_fixup_dt_cell_info(struct nvmem_device *nvmem, ++ struct nvmem_cell_info *cell) + { + size_t sz = strlen(cell->name); + +@@ -61,10 +60,6 @@ static void mtk_efuse_fixup_cell_info(st + cell->read_post_process = mtk_efuse_gpu_speedbin_pp; + } + +-static struct nvmem_layout mtk_efuse_layout = { +- .fixup_cell_info = mtk_efuse_fixup_cell_info, +-}; +- + static int mtk_efuse_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -91,7 +86,7 @@ static int mtk_efuse_probe(struct platfo + econfig.priv = priv; + econfig.dev = dev; + if (pdata->uses_post_processing) +- econfig.layout = &mtk_efuse_layout; ++ econfig.fixup_dt_cell_info = &mtk_efuse_fixup_dt_cell_info; + nvmem = devm_nvmem_register(dev, &econfig); + + return PTR_ERR_OR_ZERO(nvmem); +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -83,6 +83,8 @@ struct nvmem_cell_info { + * @cells: Optional array of pre-defined NVMEM cells. + * @ncells: Number of elements in cells. + * @add_legacy_fixed_of_cells: Read fixed NVMEM cells from old OF syntax. ++ * @fixup_dt_cell_info: Will be called before a cell is added. Can be ++ * used to modify the nvmem_cell_info. + * @keepout: Optional array of keepout ranges (sorted ascending by start). + * @nkeepout: Number of elements in the keepout array. + * @type: Type of the nvmem storage +@@ -113,6 +115,8 @@ struct nvmem_config { + const struct nvmem_cell_info *cells; + int ncells; + bool add_legacy_fixed_of_cells; ++ void (*fixup_dt_cell_info)(struct nvmem_device *nvmem, ++ struct nvmem_cell_info *cell); + const struct nvmem_keepout *keepout; + unsigned int nkeepout; + enum nvmem_type type; +@@ -158,8 +162,6 @@ struct nvmem_cell_table { + * @of_match_table: Open firmware match table. + * @add_cells: Called to populate the layout using + * nvmem_add_one_cell(). +- * @fixup_cell_info: Will be called before a cell is added. Can be +- * used to modify the nvmem_cell_info. + * @owner: Pointer to struct module. + * @node: List node. + * +@@ -172,9 +174,6 @@ struct nvmem_layout { + const char *name; + const struct of_device_id *of_match_table; + int (*add_cells)(struct device *dev, struct nvmem_device *nvmem); +- void (*fixup_cell_info)(struct nvmem_device *nvmem, +- struct nvmem_layout *layout, +- struct nvmem_cell_info *cell); + + /* private */ + struct module *owner; diff --git a/lede/target/linux/generic/backport-6.1/819-v6.8-0005-nvmem-core-Rework-layouts-to-become-regular-devices.patch b/lede/target/linux/generic/backport-6.1/819-v6.8-0005-nvmem-core-Rework-layouts-to-become-regular-devices.patch new file mode 100644 index 0000000000..1881332340 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/819-v6.8-0005-nvmem-core-Rework-layouts-to-become-regular-devices.patch @@ -0,0 +1,763 @@ +From fc29fd821d9ac2ae3d32a722fac39ce874efb883 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 15 Dec 2023 11:15:32 +0000 +Subject: [PATCH] nvmem: core: Rework layouts to become regular devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Current layout support was initially written without modules support in +mind. When the requirement for module support rose, the existing base +was improved to adopt modularization support, but kind of a design flaw +was introduced. With the existing implementation, when a storage device +registers into NVMEM, the core tries to hook a layout (if any) and +populates its cells immediately. This means, if the hardware description +expects a layout to be hooked up, but no driver was provided for that, +the storage medium will fail to probe and try later from +scratch. Even if we consider that the hardware description shall be +correct, we could still probe the storage device (especially if it +contains the rootfs). + +One way to overcome this situation is to consider the layouts as +devices, and leverage the native notifier mechanism. When a new NVMEM +device is registered, we can populate its nvmem-layout child, if any, +and wait for the matching to be done in order to get the cells (the +waiting can be easily done with the NVMEM notifiers). If the layout +driver is compiled as a module, it should automatically be loaded. This +way, there is no strong order to enforce, any NVMEM device creation +or NVMEM layout driver insertion will be observed as a new event which +may lead to the creation of additional cells, without disturbing the +probes with costly (and sometimes endless) deferrals. + +In order to achieve that goal we create a new bus for the nvmem-layouts +with minimal logic to match nvmem-layout devices with nvmem-layout +drivers. All this infrastructure code is created in the layouts.c file. + +Signed-off-by: Miquel Raynal +Tested-by: Rafał Miłecki +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-7-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/Kconfig | 1 + + drivers/nvmem/Makefile | 2 + + drivers/nvmem/core.c | 170 ++++++++++---------------- + drivers/nvmem/internals.h | 21 ++++ + drivers/nvmem/layouts.c | 201 +++++++++++++++++++++++++++++++ + drivers/nvmem/layouts/Kconfig | 8 ++ + drivers/nvmem/layouts/onie-tlv.c | 24 +++- + drivers/nvmem/layouts/sl28vpd.c | 24 +++- + include/linux/nvmem-provider.h | 38 +++--- + 9 files changed, 354 insertions(+), 135 deletions(-) + create mode 100644 drivers/nvmem/layouts.c + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0-only + menuconfig NVMEM + bool "NVMEM Support" ++ imply NVMEM_LAYOUTS + help + Support for NVMEM(Non Volatile Memory) devices like EEPROM, EFUSES... + +--- a/drivers/nvmem/Makefile ++++ b/drivers/nvmem/Makefile +@@ -5,6 +5,8 @@ + + obj-$(CONFIG_NVMEM) += nvmem_core.o + nvmem_core-y := core.o ++obj-$(CONFIG_NVMEM_LAYOUTS) += nvmem_layouts.o ++nvmem_layouts-y := layouts.o + obj-y += layouts/ + + # Devices +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -56,9 +56,6 @@ static LIST_HEAD(nvmem_lookup_list); + + static BLOCKING_NOTIFIER_HEAD(nvmem_notifier); + +-static DEFINE_SPINLOCK(nvmem_layout_lock); +-static LIST_HEAD(nvmem_layouts); +- + static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, + void *val, size_t bytes) + { +@@ -741,97 +738,22 @@ static int nvmem_add_cells_from_fixed_la + return err; + } + +-int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner) ++int nvmem_layout_register(struct nvmem_layout *layout) + { +- layout->owner = owner; +- +- spin_lock(&nvmem_layout_lock); +- list_add(&layout->node, &nvmem_layouts); +- spin_unlock(&nvmem_layout_lock); +- +- blocking_notifier_call_chain(&nvmem_notifier, NVMEM_LAYOUT_ADD, layout); ++ if (!layout->add_cells) ++ return -EINVAL; + +- return 0; ++ /* Populate the cells */ ++ return layout->add_cells(&layout->nvmem->dev, layout->nvmem); + } +-EXPORT_SYMBOL_GPL(__nvmem_layout_register); ++EXPORT_SYMBOL_GPL(nvmem_layout_register); + + void nvmem_layout_unregister(struct nvmem_layout *layout) + { +- blocking_notifier_call_chain(&nvmem_notifier, NVMEM_LAYOUT_REMOVE, layout); +- +- spin_lock(&nvmem_layout_lock); +- list_del(&layout->node); +- spin_unlock(&nvmem_layout_lock); ++ /* Keep the API even with an empty stub in case we need it later */ + } + EXPORT_SYMBOL_GPL(nvmem_layout_unregister); + +-static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem) +-{ +- struct device_node *layout_np; +- struct nvmem_layout *l, *layout = ERR_PTR(-EPROBE_DEFER); +- +- layout_np = of_nvmem_layout_get_container(nvmem); +- if (!layout_np) +- return NULL; +- +- /* Fixed layouts don't have a matching driver */ +- if (of_device_is_compatible(layout_np, "fixed-layout")) { +- of_node_put(layout_np); +- return NULL; +- } +- +- /* +- * In case the nvmem device was built-in while the layout was built as a +- * module, we shall manually request the layout driver loading otherwise +- * we'll never have any match. +- */ +- of_request_module(layout_np); +- +- spin_lock(&nvmem_layout_lock); +- +- list_for_each_entry(l, &nvmem_layouts, node) { +- if (of_match_node(l->of_match_table, layout_np)) { +- if (try_module_get(l->owner)) +- layout = l; +- +- break; +- } +- } +- +- spin_unlock(&nvmem_layout_lock); +- of_node_put(layout_np); +- +- return layout; +-} +- +-static void nvmem_layout_put(struct nvmem_layout *layout) +-{ +- if (layout) +- module_put(layout->owner); +-} +- +-static int nvmem_add_cells_from_layout(struct nvmem_device *nvmem) +-{ +- struct nvmem_layout *layout = nvmem->layout; +- int ret; +- +- if (layout && layout->add_cells) { +- ret = layout->add_cells(&nvmem->dev, nvmem); +- if (ret) +- return ret; +- } +- +- return 0; +-} +- +-#if IS_ENABLED(CONFIG_OF) +-struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem) +-{ +- return of_get_child_by_name(nvmem->dev.of_node, "nvmem-layout"); +-} +-EXPORT_SYMBOL_GPL(of_nvmem_layout_get_container); +-#endif +- + const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, + struct nvmem_layout *layout) + { +@@ -839,7 +761,7 @@ const void *nvmem_layout_get_match_data( + const struct of_device_id *match; + + layout_np = of_nvmem_layout_get_container(nvmem); +- match = of_match_node(layout->of_match_table, layout_np); ++ match = of_match_node(layout->dev.driver->of_match_table, layout_np); + + return match ? match->data : NULL; + } +@@ -951,19 +873,6 @@ struct nvmem_device *nvmem_register(cons + goto err_put_device; + } + +- /* +- * If the driver supplied a layout by config->layout, the module +- * pointer will be NULL and nvmem_layout_put() will be a noop. +- */ +- nvmem->layout = config->layout ?: nvmem_layout_get(nvmem); +- if (IS_ERR(nvmem->layout)) { +- rval = PTR_ERR(nvmem->layout); +- nvmem->layout = NULL; +- +- if (rval == -EPROBE_DEFER) +- goto err_teardown_compat; +- } +- + if (config->cells) { + rval = nvmem_add_cells(nvmem, config->cells, config->ncells); + if (rval) +@@ -984,24 +893,24 @@ struct nvmem_device *nvmem_register(cons + if (rval) + goto err_remove_cells; + +- rval = nvmem_add_cells_from_layout(nvmem); +- if (rval) +- goto err_remove_cells; +- + dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); + + rval = device_add(&nvmem->dev); + if (rval) + goto err_remove_cells; + ++ rval = nvmem_populate_layout(nvmem); ++ if (rval) ++ goto err_remove_dev; ++ + blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem); + + return nvmem; + ++err_remove_dev: ++ device_del(&nvmem->dev); + err_remove_cells: + nvmem_device_remove_all_cells(nvmem); +- nvmem_layout_put(nvmem->layout); +-err_teardown_compat: + if (config->compat) + nvmem_sysfs_remove_compat(nvmem, config); + err_put_device: +@@ -1023,7 +932,7 @@ static void nvmem_device_release(struct + device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom); + + nvmem_device_remove_all_cells(nvmem); +- nvmem_layout_put(nvmem->layout); ++ nvmem_destroy_layout(nvmem); + device_unregister(&nvmem->dev); + } + +@@ -1325,6 +1234,12 @@ nvmem_cell_get_from_lookup(struct device + return cell; + } + ++static void nvmem_layout_module_put(struct nvmem_device *nvmem) ++{ ++ if (nvmem->layout && nvmem->layout->dev.driver) ++ module_put(nvmem->layout->dev.driver->owner); ++} ++ + #if IS_ENABLED(CONFIG_OF) + static struct nvmem_cell_entry * + nvmem_find_cell_entry_by_node(struct nvmem_device *nvmem, struct device_node *np) +@@ -1343,6 +1258,18 @@ nvmem_find_cell_entry_by_node(struct nvm + return cell; + } + ++static int nvmem_layout_module_get_optional(struct nvmem_device *nvmem) ++{ ++ if (!nvmem->layout) ++ return 0; ++ ++ if (!nvmem->layout->dev.driver || ++ !try_module_get(nvmem->layout->dev.driver->owner)) ++ return -EPROBE_DEFER; ++ ++ return 0; ++} ++ + /** + * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id + * +@@ -1405,16 +1332,29 @@ struct nvmem_cell *of_nvmem_cell_get(str + return ERR_CAST(nvmem); + } + ++ ret = nvmem_layout_module_get_optional(nvmem); ++ if (ret) { ++ of_node_put(cell_np); ++ __nvmem_device_put(nvmem); ++ return ERR_PTR(ret); ++ } ++ + cell_entry = nvmem_find_cell_entry_by_node(nvmem, cell_np); + of_node_put(cell_np); + if (!cell_entry) { + __nvmem_device_put(nvmem); +- return ERR_PTR(-ENOENT); ++ nvmem_layout_module_put(nvmem); ++ if (nvmem->layout) ++ return ERR_PTR(-EPROBE_DEFER); ++ else ++ return ERR_PTR(-ENOENT); + } + + cell = nvmem_create_cell(cell_entry, id, cell_index); +- if (IS_ERR(cell)) ++ if (IS_ERR(cell)) { + __nvmem_device_put(nvmem); ++ nvmem_layout_module_put(nvmem); ++ } + + return cell; + } +@@ -1528,6 +1468,7 @@ void nvmem_cell_put(struct nvmem_cell *c + + kfree(cell); + __nvmem_device_put(nvmem); ++ nvmem_layout_module_put(nvmem); + } + EXPORT_SYMBOL_GPL(nvmem_cell_put); + +@@ -2105,11 +2046,22 @@ EXPORT_SYMBOL_GPL(nvmem_dev_name); + + static int __init nvmem_init(void) + { +- return bus_register(&nvmem_bus_type); ++ int ret; ++ ++ ret = bus_register(&nvmem_bus_type); ++ if (ret) ++ return ret; ++ ++ ret = nvmem_layout_bus_register(); ++ if (ret) ++ bus_unregister(&nvmem_bus_type); ++ ++ return ret; + } + + static void __exit nvmem_exit(void) + { ++ nvmem_layout_bus_unregister(); + bus_unregister(&nvmem_bus_type); + } + +--- a/drivers/nvmem/internals.h ++++ b/drivers/nvmem/internals.h +@@ -34,4 +34,25 @@ struct nvmem_device { + void *priv; + }; + ++#if IS_ENABLED(CONFIG_OF) ++int nvmem_layout_bus_register(void); ++void nvmem_layout_bus_unregister(void); ++int nvmem_populate_layout(struct nvmem_device *nvmem); ++void nvmem_destroy_layout(struct nvmem_device *nvmem); ++#else /* CONFIG_OF */ ++static inline int nvmem_layout_bus_register(void) ++{ ++ return 0; ++} ++ ++static inline void nvmem_layout_bus_unregister(void) {} ++ ++static inline int nvmem_populate_layout(struct nvmem_device *nvmem) ++{ ++ return 0; ++} ++ ++static inline void nvmem_destroy_layout(struct nvmem_device *nvmem) { } ++#endif /* CONFIG_OF */ ++ + #endif /* ifndef _LINUX_NVMEM_INTERNALS_H */ +--- /dev/null ++++ b/drivers/nvmem/layouts.c +@@ -0,0 +1,201 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * NVMEM layout bus handling ++ * ++ * Copyright (C) 2023 Bootlin ++ * Author: Miquel Raynal ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "internals.h" ++ ++#define to_nvmem_layout_driver(drv) \ ++ (container_of((drv), struct nvmem_layout_driver, driver)) ++#define to_nvmem_layout_device(_dev) \ ++ container_of((_dev), struct nvmem_layout, dev) ++ ++static int nvmem_layout_bus_match(struct device *dev, struct device_driver *drv) ++{ ++ return of_driver_match_device(dev, drv); ++} ++ ++static int nvmem_layout_bus_probe(struct device *dev) ++{ ++ struct nvmem_layout_driver *drv = to_nvmem_layout_driver(dev->driver); ++ struct nvmem_layout *layout = to_nvmem_layout_device(dev); ++ ++ if (!drv->probe || !drv->remove) ++ return -EINVAL; ++ ++ return drv->probe(layout); ++} ++ ++static void nvmem_layout_bus_remove(struct device *dev) ++{ ++ struct nvmem_layout_driver *drv = to_nvmem_layout_driver(dev->driver); ++ struct nvmem_layout *layout = to_nvmem_layout_device(dev); ++ ++ return drv->remove(layout); ++} ++ ++static struct bus_type nvmem_layout_bus_type = { ++ .name = "nvmem-layout", ++ .match = nvmem_layout_bus_match, ++ .probe = nvmem_layout_bus_probe, ++ .remove = nvmem_layout_bus_remove, ++}; ++ ++int nvmem_layout_driver_register(struct nvmem_layout_driver *drv) ++{ ++ drv->driver.bus = &nvmem_layout_bus_type; ++ ++ return driver_register(&drv->driver); ++} ++EXPORT_SYMBOL_GPL(nvmem_layout_driver_register); ++ ++void nvmem_layout_driver_unregister(struct nvmem_layout_driver *drv) ++{ ++ driver_unregister(&drv->driver); ++} ++EXPORT_SYMBOL_GPL(nvmem_layout_driver_unregister); ++ ++static void nvmem_layout_release_device(struct device *dev) ++{ ++ struct nvmem_layout *layout = to_nvmem_layout_device(dev); ++ ++ of_node_put(layout->dev.of_node); ++ kfree(layout); ++} ++ ++static int nvmem_layout_create_device(struct nvmem_device *nvmem, ++ struct device_node *np) ++{ ++ struct nvmem_layout *layout; ++ struct device *dev; ++ int ret; ++ ++ layout = kzalloc(sizeof(*layout), GFP_KERNEL); ++ if (!layout) ++ return -ENOMEM; ++ ++ /* Create a bidirectional link */ ++ layout->nvmem = nvmem; ++ nvmem->layout = layout; ++ ++ /* Device model registration */ ++ dev = &layout->dev; ++ device_initialize(dev); ++ dev->parent = &nvmem->dev; ++ dev->bus = &nvmem_layout_bus_type; ++ dev->release = nvmem_layout_release_device; ++ dev->coherent_dma_mask = DMA_BIT_MASK(32); ++ dev->dma_mask = &dev->coherent_dma_mask; ++ device_set_node(dev, of_fwnode_handle(of_node_get(np))); ++ of_device_make_bus_id(dev); ++ of_msi_configure(dev, dev->of_node); ++ ++ ret = device_add(dev); ++ if (ret) { ++ put_device(dev); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id of_nvmem_layout_skip_table[] = { ++ { .compatible = "fixed-layout", }, ++ {} ++}; ++ ++static int nvmem_layout_bus_populate(struct nvmem_device *nvmem, ++ struct device_node *layout_dn) ++{ ++ int ret; ++ ++ /* Make sure it has a compatible property */ ++ if (!of_get_property(layout_dn, "compatible", NULL)) { ++ pr_debug("%s() - skipping %pOF, no compatible prop\n", ++ __func__, layout_dn); ++ return 0; ++ } ++ ++ /* Fixed layouts are parsed manually somewhere else for now */ ++ if (of_match_node(of_nvmem_layout_skip_table, layout_dn)) { ++ pr_debug("%s() - skipping %pOF node\n", __func__, layout_dn); ++ return 0; ++ } ++ ++ if (of_node_check_flag(layout_dn, OF_POPULATED_BUS)) { ++ pr_debug("%s() - skipping %pOF, already populated\n", ++ __func__, layout_dn); ++ ++ return 0; ++ } ++ ++ /* NVMEM layout buses expect only a single device representing the layout */ ++ ret = nvmem_layout_create_device(nvmem, layout_dn); ++ if (ret) ++ return ret; ++ ++ of_node_set_flag(layout_dn, OF_POPULATED_BUS); ++ ++ return 0; ++} ++ ++struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem) ++{ ++ return of_get_child_by_name(nvmem->dev.of_node, "nvmem-layout"); ++} ++EXPORT_SYMBOL_GPL(of_nvmem_layout_get_container); ++ ++/* ++ * Returns the number of devices populated, 0 if the operation was not relevant ++ * for this nvmem device, an error code otherwise. ++ */ ++int nvmem_populate_layout(struct nvmem_device *nvmem) ++{ ++ struct device_node *layout_dn; ++ int ret; ++ ++ layout_dn = of_nvmem_layout_get_container(nvmem); ++ if (!layout_dn) ++ return 0; ++ ++ /* Populate the layout device */ ++ device_links_supplier_sync_state_pause(); ++ ret = nvmem_layout_bus_populate(nvmem, layout_dn); ++ device_links_supplier_sync_state_resume(); ++ ++ of_node_put(layout_dn); ++ return ret; ++} ++ ++void nvmem_destroy_layout(struct nvmem_device *nvmem) ++{ ++ struct device *dev; ++ ++ if (!nvmem->layout) ++ return; ++ ++ dev = &nvmem->layout->dev; ++ of_node_clear_flag(dev->of_node, OF_POPULATED_BUS); ++ device_unregister(dev); ++} ++ ++int nvmem_layout_bus_register(void) ++{ ++ return bus_register(&nvmem_layout_bus_type); ++} ++ ++void nvmem_layout_bus_unregister(void) ++{ ++ bus_unregister(&nvmem_layout_bus_type); ++} +--- a/drivers/nvmem/layouts/Kconfig ++++ b/drivers/nvmem/layouts/Kconfig +@@ -1,5 +1,11 @@ + # SPDX-License-Identifier: GPL-2.0 + ++config NVMEM_LAYOUTS ++ bool ++ depends on OF ++ ++if NVMEM_LAYOUTS ++ + menu "Layout Types" + + config NVMEM_LAYOUT_SL28_VPD +@@ -21,3 +27,5 @@ config NVMEM_LAYOUT_ONIE_TLV + If unsure, say N. + + endmenu ++ ++endif +--- a/drivers/nvmem/layouts/onie-tlv.c ++++ b/drivers/nvmem/layouts/onie-tlv.c +@@ -225,16 +225,32 @@ static int onie_tlv_parse_table(struct d + return 0; + } + ++static int onie_tlv_probe(struct nvmem_layout *layout) ++{ ++ layout->add_cells = onie_tlv_parse_table; ++ ++ return nvmem_layout_register(layout); ++} ++ ++static void onie_tlv_remove(struct nvmem_layout *layout) ++{ ++ nvmem_layout_unregister(layout); ++} ++ + static const struct of_device_id onie_tlv_of_match_table[] = { + { .compatible = "onie,tlv-layout", }, + {}, + }; + MODULE_DEVICE_TABLE(of, onie_tlv_of_match_table); + +-static struct nvmem_layout onie_tlv_layout = { +- .name = "ONIE tlv layout", +- .of_match_table = onie_tlv_of_match_table, +- .add_cells = onie_tlv_parse_table, ++static struct nvmem_layout_driver onie_tlv_layout = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "onie-tlv-layout", ++ .of_match_table = onie_tlv_of_match_table, ++ }, ++ .probe = onie_tlv_probe, ++ .remove = onie_tlv_remove, + }; + module_nvmem_layout_driver(onie_tlv_layout); + +--- a/drivers/nvmem/layouts/sl28vpd.c ++++ b/drivers/nvmem/layouts/sl28vpd.c +@@ -134,16 +134,32 @@ static int sl28vpd_add_cells(struct devi + return 0; + } + ++static int sl28vpd_probe(struct nvmem_layout *layout) ++{ ++ layout->add_cells = sl28vpd_add_cells; ++ ++ return nvmem_layout_register(layout); ++} ++ ++static void sl28vpd_remove(struct nvmem_layout *layout) ++{ ++ nvmem_layout_unregister(layout); ++} ++ + static const struct of_device_id sl28vpd_of_match_table[] = { + { .compatible = "kontron,sl28-vpd" }, + {}, + }; + MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table); + +-static struct nvmem_layout sl28vpd_layout = { +- .name = "sl28-vpd", +- .of_match_table = sl28vpd_of_match_table, +- .add_cells = sl28vpd_add_cells, ++static struct nvmem_layout_driver sl28vpd_layout = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "kontron-sl28vpd-layout", ++ .of_match_table = sl28vpd_of_match_table, ++ }, ++ .probe = sl28vpd_probe, ++ .remove = sl28vpd_remove, + }; + module_nvmem_layout_driver(sl28vpd_layout); + +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -9,6 +9,7 @@ + #ifndef _LINUX_NVMEM_PROVIDER_H + #define _LINUX_NVMEM_PROVIDER_H + ++#include + #include + #include + #include +@@ -158,12 +159,11 @@ struct nvmem_cell_table { + /** + * struct nvmem_layout - NVMEM layout definitions + * +- * @name: Layout name. +- * @of_match_table: Open firmware match table. +- * @add_cells: Called to populate the layout using +- * nvmem_add_one_cell(). +- * @owner: Pointer to struct module. +- * @node: List node. ++ * @dev: Device-model layout device. ++ * @nvmem: The underlying NVMEM device ++ * @add_cells: Will be called if a nvmem device is found which ++ * has this layout. The function will add layout ++ * specific cells with nvmem_add_one_cell(). + * + * A nvmem device can hold a well defined structure which can just be + * evaluated during runtime. For example a TLV list, or a list of "name=val" +@@ -171,13 +171,15 @@ struct nvmem_cell_table { + * cells. + */ + struct nvmem_layout { +- const char *name; +- const struct of_device_id *of_match_table; ++ struct device dev; ++ struct nvmem_device *nvmem; + int (*add_cells)(struct device *dev, struct nvmem_device *nvmem); ++}; + +- /* private */ +- struct module *owner; +- struct list_head node; ++struct nvmem_layout_driver { ++ struct device_driver driver; ++ int (*probe)(struct nvmem_layout *layout); ++ void (*remove)(struct nvmem_layout *layout); + }; + + #if IS_ENABLED(CONFIG_NVMEM) +@@ -194,11 +196,15 @@ void nvmem_del_cell_table(struct nvmem_c + int nvmem_add_one_cell(struct nvmem_device *nvmem, + const struct nvmem_cell_info *info); + +-int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner); +-#define nvmem_layout_register(layout) \ +- __nvmem_layout_register(layout, THIS_MODULE) ++int nvmem_layout_register(struct nvmem_layout *layout); + void nvmem_layout_unregister(struct nvmem_layout *layout); + ++int nvmem_layout_driver_register(struct nvmem_layout_driver *drv); ++void nvmem_layout_driver_unregister(struct nvmem_layout_driver *drv); ++#define module_nvmem_layout_driver(__nvmem_layout_driver) \ ++ module_driver(__nvmem_layout_driver, nvmem_layout_driver_register, \ ++ nvmem_layout_driver_unregister) ++ + const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, + struct nvmem_layout *layout); + +@@ -262,8 +268,4 @@ static inline struct device_node *of_nvm + + #endif /* CONFIG_NVMEM && CONFIG_OF */ + +-#define module_nvmem_layout_driver(__layout_driver) \ +- module_driver(__layout_driver, nvmem_layout_register, \ +- nvmem_layout_unregister) +- + #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */ diff --git a/lede/target/linux/generic/backport-6.1/819-v6.8-0006-nvmem-core-Expose-cells-through-sysfs.patch b/lede/target/linux/generic/backport-6.1/819-v6.8-0006-nvmem-core-Expose-cells-through-sysfs.patch new file mode 100644 index 0000000000..89872bec2e --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/819-v6.8-0006-nvmem-core-Expose-cells-through-sysfs.patch @@ -0,0 +1,240 @@ +From 0331c611949fffdf486652450901a4dc52bc5cca Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 15 Dec 2023 11:15:34 +0000 +Subject: [PATCH] nvmem: core: Expose cells through sysfs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The binary content of nvmem devices is available to the user so in the +easiest cases, finding the content of a cell is rather easy as it is +just a matter of looking at a known and fixed offset. However, nvmem +layouts have been recently introduced to cope with more advanced +situations, where the offset and size of the cells is not known in +advance or is dynamic. When using layouts, more advanced parsers are +used by the kernel in order to give direct access to the content of each +cell, regardless of its position/size in the underlying +device. Unfortunately, these information are not accessible by users, +unless by fully re-implementing the parser logic in userland. + +Let's expose the cells and their content through sysfs to avoid these +situations. Of course the relevant NVMEM sysfs Kconfig option must be +enabled for this support to be available. + +Not all nvmem devices expose cells. Indeed, the .bin_attrs attribute +group member will be filled at runtime only when relevant and will +remain empty otherwise. In this case, as the cells attribute group will +be empty, it will not lead to any additional folder/file creation. + +Exposed cells are read-only. There is, in practice, everything in the +core to support a write path, but as I don't see any need for that, I +prefer to keep the interface simple (and probably safer). The interface +is documented as being in the "testing" state which means we can later +add a write attribute if though relevant. + +Signed-off-by: Miquel Raynal +Tested-by: Rafał Miłecki +Tested-by: Chen-Yu Tsai +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-9-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 135 +++++++++++++++++++++++++++++++++++++- + drivers/nvmem/internals.h | 1 + + 2 files changed, 135 insertions(+), 1 deletion(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -300,6 +300,43 @@ static umode_t nvmem_bin_attr_is_visible + return nvmem_bin_attr_get_umode(nvmem); + } + ++static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, ++ const char *id, int index); ++ ++static ssize_t nvmem_cell_attr_read(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *attr, char *buf, ++ loff_t pos, size_t count) ++{ ++ struct nvmem_cell_entry *entry; ++ struct nvmem_cell *cell = NULL; ++ size_t cell_sz, read_len; ++ void *content; ++ ++ entry = attr->private; ++ cell = nvmem_create_cell(entry, entry->name, 0); ++ if (IS_ERR(cell)) ++ return PTR_ERR(cell); ++ ++ if (!cell) ++ return -EINVAL; ++ ++ content = nvmem_cell_read(cell, &cell_sz); ++ if (IS_ERR(content)) { ++ read_len = PTR_ERR(content); ++ goto destroy_cell; ++ } ++ ++ read_len = min_t(unsigned int, cell_sz - pos, count); ++ memcpy(buf, content + pos, read_len); ++ kfree(content); ++ ++destroy_cell: ++ kfree_const(cell->id); ++ kfree(cell); ++ ++ return read_len; ++} ++ + /* default read/write permissions */ + static struct bin_attribute bin_attr_rw_nvmem = { + .attr = { +@@ -321,11 +358,21 @@ static const struct attribute_group nvme + .is_bin_visible = nvmem_bin_attr_is_visible, + }; + ++/* Cell attributes will be dynamically allocated */ ++static struct attribute_group nvmem_cells_group = { ++ .name = "cells", ++}; ++ + static const struct attribute_group *nvmem_dev_groups[] = { + &nvmem_bin_group, + NULL, + }; + ++static const struct attribute_group *nvmem_cells_groups[] = { ++ &nvmem_cells_group, ++ NULL, ++}; ++ + static struct bin_attribute bin_attr_nvmem_eeprom_compat = { + .attr = { + .name = "eeprom", +@@ -381,6 +428,68 @@ static void nvmem_sysfs_remove_compat(st + device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom); + } + ++static int nvmem_populate_sysfs_cells(struct nvmem_device *nvmem) ++{ ++ struct bin_attribute **cells_attrs, *attrs; ++ struct nvmem_cell_entry *entry; ++ unsigned int ncells = 0, i = 0; ++ int ret = 0; ++ ++ mutex_lock(&nvmem_mutex); ++ ++ if (list_empty(&nvmem->cells) || nvmem->sysfs_cells_populated) { ++ nvmem_cells_group.bin_attrs = NULL; ++ goto unlock_mutex; ++ } ++ ++ /* Allocate an array of attributes with a sentinel */ ++ ncells = list_count_nodes(&nvmem->cells); ++ cells_attrs = devm_kcalloc(&nvmem->dev, ncells + 1, ++ sizeof(struct bin_attribute *), GFP_KERNEL); ++ if (!cells_attrs) { ++ ret = -ENOMEM; ++ goto unlock_mutex; ++ } ++ ++ attrs = devm_kcalloc(&nvmem->dev, ncells, sizeof(struct bin_attribute), GFP_KERNEL); ++ if (!attrs) { ++ ret = -ENOMEM; ++ goto unlock_mutex; ++ } ++ ++ /* Initialize each attribute to take the name and size of the cell */ ++ list_for_each_entry(entry, &nvmem->cells, node) { ++ sysfs_bin_attr_init(&attrs[i]); ++ attrs[i].attr.name = devm_kasprintf(&nvmem->dev, GFP_KERNEL, ++ "%s@%x", entry->name, ++ entry->offset); ++ attrs[i].attr.mode = 0444; ++ attrs[i].size = entry->bytes; ++ attrs[i].read = &nvmem_cell_attr_read; ++ attrs[i].private = entry; ++ if (!attrs[i].attr.name) { ++ ret = -ENOMEM; ++ goto unlock_mutex; ++ } ++ ++ cells_attrs[i] = &attrs[i]; ++ i++; ++ } ++ ++ nvmem_cells_group.bin_attrs = cells_attrs; ++ ++ ret = devm_device_add_groups(&nvmem->dev, nvmem_cells_groups); ++ if (ret) ++ goto unlock_mutex; ++ ++ nvmem->sysfs_cells_populated = true; ++ ++unlock_mutex: ++ mutex_unlock(&nvmem_mutex); ++ ++ return ret; ++} ++ + #else /* CONFIG_NVMEM_SYSFS */ + + static int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem, +@@ -740,11 +849,25 @@ static int nvmem_add_cells_from_fixed_la + + int nvmem_layout_register(struct nvmem_layout *layout) + { ++ int ret; ++ + if (!layout->add_cells) + return -EINVAL; + + /* Populate the cells */ +- return layout->add_cells(&layout->nvmem->dev, layout->nvmem); ++ ret = layout->add_cells(&layout->nvmem->dev, layout->nvmem); ++ if (ret) ++ return ret; ++ ++#ifdef CONFIG_NVMEM_SYSFS ++ ret = nvmem_populate_sysfs_cells(layout->nvmem); ++ if (ret) { ++ nvmem_device_remove_all_cells(layout->nvmem); ++ return ret; ++ } ++#endif ++ ++ return 0; + } + EXPORT_SYMBOL_GPL(nvmem_layout_register); + +@@ -903,10 +1026,20 @@ struct nvmem_device *nvmem_register(cons + if (rval) + goto err_remove_dev; + ++#ifdef CONFIG_NVMEM_SYSFS ++ rval = nvmem_populate_sysfs_cells(nvmem); ++ if (rval) ++ goto err_destroy_layout; ++#endif ++ + blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem); + + return nvmem; + ++#ifdef CONFIG_NVMEM_SYSFS ++err_destroy_layout: ++ nvmem_destroy_layout(nvmem); ++#endif + err_remove_dev: + device_del(&nvmem->dev); + err_remove_cells: +--- a/drivers/nvmem/internals.h ++++ b/drivers/nvmem/internals.h +@@ -32,6 +32,7 @@ struct nvmem_device { + struct gpio_desc *wp_gpio; + struct nvmem_layout *layout; + void *priv; ++ bool sysfs_cells_populated; + }; + + #if IS_ENABLED(CONFIG_OF) diff --git a/lede/target/linux/generic/backport-6.1/819-v6.8-0007-nvmem-stm32-add-support-for-STM32MP25-BSEC-to-contro.patch b/lede/target/linux/generic/backport-6.1/819-v6.8-0007-nvmem-stm32-add-support-for-STM32MP25-BSEC-to-contro.patch new file mode 100644 index 0000000000..f686222f88 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/819-v6.8-0007-nvmem-stm32-add-support-for-STM32MP25-BSEC-to-contro.patch @@ -0,0 +1,65 @@ +From f0ac5b23039610619ca4a4805528553ecb6bc815 Mon Sep 17 00:00:00 2001 +From: Patrick Delaunay +Date: Fri, 15 Dec 2023 11:15:36 +0000 +Subject: [PATCH] nvmem: stm32: add support for STM32MP25 BSEC to control OTP + data + +On STM32MP25, OTP area may be read/written by using BSEC (boot, security +and OTP control). The BSEC internal peripheral is only managed by the +secure world. + +The 12 Kbits of OTP (effective) are organized into the following regions: +- lower OTP (OTP0 to OTP127) = 4096 lower OTP bits, + bitwise (1-bit) programmable +- mid OTP (OTP128 to OTP255) = 4096 middle OTP bits, + bulk (32-bit) programmable +- upper OTP (OTP256 to OTP383) = 4096 upper OTP bits, + bulk (32-bit) programmable, + only accessible when BSEC is in closed state. + +As HWKEY and ECIES key are only accessible by ROM code; +only 368 OTP words are managed in this driver (OTP0 to OTP267). + +This patch adds the STM32MP25 configuration for reading and writing +the OTP data using the OP-TEE BSEC TA services. + +Signed-off-by: Patrick Delaunay +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231215111536.316972-11-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/stm32-romem.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/nvmem/stm32-romem.c ++++ b/drivers/nvmem/stm32-romem.c +@@ -269,6 +269,19 @@ static const struct stm32_romem_cfg stm3 + .ta = true, + }; + ++/* ++ * STM32MP25 BSEC OTP: 3 regions of 32-bits data words ++ * lower OTP (OTP0 to OTP127), bitwise (1-bit) programmable ++ * mid OTP (OTP128 to OTP255), bulk (32-bit) programmable ++ * upper OTP (OTP256 to OTP383), bulk (32-bit) programmable ++ * but no access to HWKEY and ECIES key: limited at OTP367 ++ */ ++static const struct stm32_romem_cfg stm32mp25_bsec_cfg = { ++ .size = 368 * 4, ++ .lower = 127, ++ .ta = true, ++}; ++ + static const struct of_device_id stm32_romem_of_match[] __maybe_unused = { + { .compatible = "st,stm32f4-otp", }, { + .compatible = "st,stm32mp15-bsec", +@@ -276,6 +289,9 @@ static const struct of_device_id stm32_r + }, { + .compatible = "st,stm32mp13-bsec", + .data = (void *)&stm32mp13_bsec_cfg, ++ }, { ++ .compatible = "st,stm32mp25-bsec", ++ .data = (void *)&stm32mp25_bsec_cfg, + }, + { /* sentinel */ }, + }; diff --git a/lede/target/linux/generic/backport-6.1/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch b/lede/target/linux/generic/backport-6.1/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch new file mode 100644 index 0000000000..1bf3ba35b6 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch @@ -0,0 +1,94 @@ +From 401df0d4f4098ecc9c5278da2f50756d62e5b37d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 19 Dec 2023 13:01:03 +0100 +Subject: [PATCH] nvmem: layouts: refactor .add_cells() callback arguments +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Simply pass whole "struct nvmem_layout" instead of single variables. +There is nothing in "struct nvmem_layout" that we have to hide from +layout drivers. They also access it during .probe() and .remove(). + +Thanks to this change: + +1. API gets more consistent + All layouts drivers callbacks get the same argument + +2. Layouts get correct device + Before this change NVMEM core code was passing NVMEM device instead + of layout device. That resulted in: + * Confusing prints + * Calling devm_*() helpers on wrong device + * Helpers like of_device_get_match_data() dereferencing NULLs + +3. It gets possible to get match data + First of all nvmem_layout_get_match_data() requires passing "struct + nvmem_layout" which .add_cells() callback didn't have before this. It + doesn't matter much as it's rather useless now anyway (and will be + dropped). + What's more important however is that of_device_get_match_data() can + be used now thanks to owning a proper device pointer. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Reviewed-by: Michael Walle +Link: https://lore.kernel.org/r/20231219120104.3422-1-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 2 +- + drivers/nvmem/layouts/onie-tlv.c | 4 +++- + drivers/nvmem/layouts/sl28vpd.c | 4 +++- + include/linux/nvmem-provider.h | 2 +- + 4 files changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -855,7 +855,7 @@ int nvmem_layout_register(struct nvmem_l + return -EINVAL; + + /* Populate the cells */ +- ret = layout->add_cells(&layout->nvmem->dev, layout->nvmem); ++ ret = layout->add_cells(layout); + if (ret) + return ret; + +--- a/drivers/nvmem/layouts/onie-tlv.c ++++ b/drivers/nvmem/layouts/onie-tlv.c +@@ -182,8 +182,10 @@ static bool onie_tlv_crc_is_valid(struct + return true; + } + +-static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem) ++static int onie_tlv_parse_table(struct nvmem_layout *layout) + { ++ struct nvmem_device *nvmem = layout->nvmem; ++ struct device *dev = &layout->dev; + struct onie_tlv_hdr hdr; + size_t table_len, data_len, hdr_len; + u8 *table, *data; +--- a/drivers/nvmem/layouts/sl28vpd.c ++++ b/drivers/nvmem/layouts/sl28vpd.c +@@ -80,8 +80,10 @@ static int sl28vpd_v1_check_crc(struct d + return 0; + } + +-static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem) ++static int sl28vpd_add_cells(struct nvmem_layout *layout) + { ++ struct nvmem_device *nvmem = layout->nvmem; ++ struct device *dev = &layout->dev; + const struct nvmem_cell_info *pinfo; + struct nvmem_cell_info info = {0}; + struct device_node *layout_np; +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -173,7 +173,7 @@ struct nvmem_cell_table { + struct nvmem_layout { + struct device dev; + struct nvmem_device *nvmem; +- int (*add_cells)(struct device *dev, struct nvmem_device *nvmem); ++ int (*add_cells)(struct nvmem_layout *layout); + }; + + struct nvmem_layout_driver { diff --git a/lede/target/linux/generic/backport-6.1/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch b/lede/target/linux/generic/backport-6.1/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch new file mode 100644 index 0000000000..514b5f2de5 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch @@ -0,0 +1,72 @@ +From 43f60e3fb62edc7bd8891de8779fb422f4ae23ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 19 Dec 2023 13:01:04 +0100 +Subject: [PATCH] nvmem: drop nvmem_layout_get_match_data() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Thanks for layouts refactoring we now have "struct device" associated +with layout. Also its OF pointer points directly to the "nvmem-layout" +DT node. + +All it takes to get match data is a generic of_device_get_match_data(). + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Reviewed-by: Michael Walle +Link: https://lore.kernel.org/r/20231219120104.3422-2-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 13 ------------- + include/linux/nvmem-provider.h | 10 ---------- + 2 files changed, 23 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -877,19 +877,6 @@ void nvmem_layout_unregister(struct nvme + } + EXPORT_SYMBOL_GPL(nvmem_layout_unregister); + +-const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout) +-{ +- struct device_node __maybe_unused *layout_np; +- const struct of_device_id *match; +- +- layout_np = of_nvmem_layout_get_container(nvmem); +- match = of_match_node(layout->dev.driver->of_match_table, layout_np); +- +- return match ? match->data : NULL; +-} +-EXPORT_SYMBOL_GPL(nvmem_layout_get_match_data); +- + /** + * nvmem_register() - Register a nvmem device for given nvmem_config. + * Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -205,9 +205,6 @@ void nvmem_layout_driver_unregister(stru + module_driver(__nvmem_layout_driver, nvmem_layout_driver_register, \ + nvmem_layout_driver_unregister) + +-const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout); +- + #else + + static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c) +@@ -238,13 +235,6 @@ static inline int nvmem_layout_register( + + static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {} + +-static inline const void * +-nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout) +-{ +- return NULL; +-} +- + #endif /* CONFIG_NVMEM */ + + #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) diff --git a/lede/target/linux/generic/backport-6.1/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch b/lede/target/linux/generic/backport-6.1/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch new file mode 100644 index 0000000000..aa0bbaa0c5 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch @@ -0,0 +1,53 @@ +From 33cf42e68efc8ff529a7eee08a4f0ba8c8d0a207 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:17 +0100 +Subject: [PATCH] nvmem: core: add nvmem_dev_size() helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is required by layouts that need to read whole NVMEM content. It's +especially useful for NVMEM devices without hardcoded layout (like +U-Boot environment data block). + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-2-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 13 +++++++++++++ + include/linux/nvmem-consumer.h | 1 + + 2 files changed, 14 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -2164,6 +2164,19 @@ const char *nvmem_dev_name(struct nvmem_ + } + EXPORT_SYMBOL_GPL(nvmem_dev_name); + ++/** ++ * nvmem_dev_size() - Get the size of a given nvmem device. ++ * ++ * @nvmem: nvmem device. ++ * ++ * Return: size of the nvmem device. ++ */ ++size_t nvmem_dev_size(struct nvmem_device *nvmem) ++{ ++ return nvmem->size; ++} ++EXPORT_SYMBOL_GPL(nvmem_dev_size); ++ + static int __init nvmem_init(void) + { + int ret; +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -81,6 +81,7 @@ int nvmem_device_cell_write(struct nvmem + struct nvmem_cell_info *info, void *buf); + + const char *nvmem_dev_name(struct nvmem_device *nvmem); ++size_t nvmem_dev_size(struct nvmem_device *nvmem); + + void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, + size_t nentries); diff --git a/lede/target/linux/generic/backport-6.1/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch b/lede/target/linux/generic/backport-6.1/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch new file mode 100644 index 0000000000..fc826f3f7e --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch @@ -0,0 +1,126 @@ +From 7c8979b42b1a9c5604f431ba804928e55919263c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:18 +0100 +Subject: [PATCH] nvmem: u-boot-env: use nvmem_add_one_cell() nvmem subsystem + helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Simplify adding NVMEM cells. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-3-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 55 +++++++++++++++----------------------- + 1 file changed, 21 insertions(+), 34 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -23,13 +23,10 @@ enum u_boot_env_format { + + struct u_boot_env { + struct device *dev; ++ struct nvmem_device *nvmem; + enum u_boot_env_format format; + + struct mtd_info *mtd; +- +- /* Cells */ +- struct nvmem_cell_info *cells; +- int ncells; + }; + + struct u_boot_env_image_single { +@@ -94,43 +91,36 @@ static int u_boot_env_read_post_process_ + static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, + size_t data_offset, size_t data_len) + { ++ struct nvmem_device *nvmem = priv->nvmem; + struct device *dev = priv->dev; + char *data = buf + data_offset; + char *var, *value, *eq; +- int idx; +- +- priv->ncells = 0; +- for (var = data; var < data + data_len && *var; var += strlen(var) + 1) +- priv->ncells++; +- +- priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL); +- if (!priv->cells) +- return -ENOMEM; + +- for (var = data, idx = 0; ++ for (var = data; + var < data + data_len && *var; +- var = value + strlen(value) + 1, idx++) { ++ var = value + strlen(value) + 1) { ++ struct nvmem_cell_info info = {}; ++ + eq = strchr(var, '='); + if (!eq) + break; + *eq = '\0'; + value = eq + 1; + +- priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL); +- if (!priv->cells[idx].name) ++ info.name = devm_kstrdup(dev, var, GFP_KERNEL); ++ if (!info.name) + return -ENOMEM; +- priv->cells[idx].offset = data_offset + value - data; +- priv->cells[idx].bytes = strlen(value); +- priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); ++ info.offset = data_offset + value - data; ++ info.bytes = strlen(value); ++ info.np = of_get_child_by_name(dev->of_node, info.name); + if (!strcmp(var, "ethaddr")) { +- priv->cells[idx].raw_len = strlen(value); +- priv->cells[idx].bytes = ETH_ALEN; +- priv->cells[idx].read_post_process = u_boot_env_read_post_process_ethaddr; ++ info.raw_len = strlen(value); ++ info.bytes = ETH_ALEN; ++ info.read_post_process = u_boot_env_read_post_process_ethaddr; + } +- } + +- if (WARN_ON(idx != priv->ncells)) +- priv->ncells = idx; ++ nvmem_add_one_cell(nvmem, &info); ++ } + + return 0; + } +@@ -209,7 +199,6 @@ static int u_boot_env_probe(struct platf + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct u_boot_env *priv; +- int err; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -224,17 +213,15 @@ static int u_boot_env_probe(struct platf + return PTR_ERR(priv->mtd); + } + +- err = u_boot_env_parse(priv); +- if (err) +- return err; +- + config.dev = dev; +- config.cells = priv->cells; +- config.ncells = priv->ncells; + config.priv = priv; + config.size = priv->mtd->size; + +- return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); ++ priv->nvmem = devm_nvmem_register(dev, &config); ++ if (IS_ERR(priv->nvmem)) ++ return PTR_ERR(priv->nvmem); ++ ++ return u_boot_env_parse(priv); + } + + static const struct of_device_id u_boot_env_of_match_table[] = { diff --git a/lede/target/linux/generic/backport-6.1/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch b/lede/target/linux/generic/backport-6.1/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch new file mode 100644 index 0000000000..70abc7cf14 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch @@ -0,0 +1,81 @@ +From a832556d23c5a11115f300011a5874d6107a0d62 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:19 +0100 +Subject: [PATCH] nvmem: u-boot-env: use nvmem device helpers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use nvmem_dev_size() and nvmem_device_read() to make this driver less +mtd dependent. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-4-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -127,27 +127,34 @@ static int u_boot_env_add_cells(struct u + + static int u_boot_env_parse(struct u_boot_env *priv) + { ++ struct nvmem_device *nvmem = priv->nvmem; + struct device *dev = priv->dev; + size_t crc32_data_offset; + size_t crc32_data_len; + size_t crc32_offset; + size_t data_offset; + size_t data_len; ++ size_t dev_size; + uint32_t crc32; + uint32_t calc; +- size_t bytes; + uint8_t *buf; ++ int bytes; + int err; + +- buf = kcalloc(1, priv->mtd->size, GFP_KERNEL); ++ dev_size = nvmem_dev_size(nvmem); ++ ++ buf = kcalloc(1, dev_size, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_out; + } + +- err = mtd_read(priv->mtd, 0, priv->mtd->size, &bytes, buf); +- if ((err && !mtd_is_bitflip(err)) || bytes != priv->mtd->size) { +- dev_err(dev, "Failed to read from mtd: %d\n", err); ++ bytes = nvmem_device_read(nvmem, 0, dev_size, buf); ++ if (bytes < 0) { ++ err = bytes; ++ goto err_kfree; ++ } else if (bytes != dev_size) { ++ err = -EIO; + goto err_kfree; + } + +@@ -169,8 +176,8 @@ static int u_boot_env_parse(struct u_boo + break; + } + crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); +- crc32_data_len = priv->mtd->size - crc32_data_offset; +- data_len = priv->mtd->size - data_offset; ++ crc32_data_len = dev_size - crc32_data_offset; ++ data_len = dev_size - data_offset; + + calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; + if (calc != crc32) { +@@ -179,7 +186,7 @@ static int u_boot_env_parse(struct u_boo + goto err_kfree; + } + +- buf[priv->mtd->size - 1] = '\0'; ++ buf[dev_size - 1] = '\0'; + err = u_boot_env_add_cells(priv, buf, data_offset, data_len); + if (err) + dev_err(dev, "Failed to add cells: %d\n", err); diff --git a/lede/target/linux/generic/backport-6.1/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch b/lede/target/linux/generic/backport-6.1/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch new file mode 100644 index 0000000000..273cfed874 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch @@ -0,0 +1,62 @@ +From 6bafe07c930676d6430be471310958070816a595 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:20 +0100 +Subject: [PATCH] nvmem: u-boot-env: improve coding style +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +1. Prefer kzalloc() over kcalloc() + See memory-allocation.rst which says: "to be on the safe side it's + best to use routines that set memory to zero, like kzalloc()" +2. Drop dev_err() for u_boot_env_add_cells() fail + It can fail only on -ENOMEM. We don't want to print error then. +3. Add extra "crc32_addr" variable + It makes code reading header's crc32 easier to understand / review. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-5-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -132,6 +132,7 @@ static int u_boot_env_parse(struct u_boo + size_t crc32_data_offset; + size_t crc32_data_len; + size_t crc32_offset; ++ __le32 *crc32_addr; + size_t data_offset; + size_t data_len; + size_t dev_size; +@@ -143,7 +144,7 @@ static int u_boot_env_parse(struct u_boo + + dev_size = nvmem_dev_size(nvmem); + +- buf = kcalloc(1, dev_size, GFP_KERNEL); ++ buf = kzalloc(dev_size, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_out; +@@ -175,7 +176,8 @@ static int u_boot_env_parse(struct u_boo + data_offset = offsetof(struct u_boot_env_image_broadcom, data); + break; + } +- crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); ++ crc32_addr = (__le32 *)(buf + crc32_offset); ++ crc32 = le32_to_cpu(*crc32_addr); + crc32_data_len = dev_size - crc32_data_offset; + data_len = dev_size - data_offset; + +@@ -188,8 +190,6 @@ static int u_boot_env_parse(struct u_boo + + buf[dev_size - 1] = '\0'; + err = u_boot_env_add_cells(priv, buf, data_offset, data_len); +- if (err) +- dev_err(dev, "Failed to add cells: %d\n", err); + + err_kfree: + kfree(buf); diff --git a/lede/target/linux/generic/backport-6.1/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch b/lede/target/linux/generic/backport-6.1/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch index 1de086417b..3b68403690 100644 --- a/lede/target/linux/generic/backport-6.1/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch +++ b/lede/target/linux/generic/backport-6.1/820-v6.4-net-phy-fix-circular-LEDS_CLASS-dependencies.patch @@ -53,7 +53,7 @@ Signed-off-by: Jakub Kicinski tristate "MDIO Bus/PHY emulation with fixed speed/link PHYs" --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -3210,7 +3210,8 @@ static int phy_probe(struct device *dev) +@@ -3314,7 +3314,8 @@ static int phy_probe(struct device *dev) /* Get the LEDs from the device tree, and instantiate standard * LEDs for them. */ diff --git a/lede/target/linux/generic/backport-6.1/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch b/lede/target/linux/generic/backport-6.1/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch index d6081d0e63..622bb9e94a 100644 --- a/lede/target/linux/generic/backport-6.1/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch +++ b/lede/target/linux/generic/backport-6.1/821-v6.4-net-phy-Fix-reading-LED-reg-property.patch @@ -18,7 +18,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -2971,6 +2971,7 @@ static int of_phy_led(struct phy_device +@@ -3075,6 +3075,7 @@ static int of_phy_led(struct phy_device struct led_init_data init_data = {}; struct led_classdev *cdev; struct phy_led *phyled; @@ -26,7 +26,7 @@ Signed-off-by: Jakub Kicinski int err; phyled = devm_kzalloc(dev, sizeof(*phyled), GFP_KERNEL); -@@ -2980,10 +2981,13 @@ static int of_phy_led(struct phy_device +@@ -3084,10 +3085,13 @@ static int of_phy_led(struct phy_device cdev = &phyled->led_cdev; phyled->phydev = phydev; diff --git a/lede/target/linux/generic/backport-6.1/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch b/lede/target/linux/generic/backport-6.1/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch index 8f076be640..80197e963b 100644 --- a/lede/target/linux/generic/backport-6.1/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch +++ b/lede/target/linux/generic/backport-6.1/822-v6.4-net-phy-Manual-remove-LEDs-to-ensure-correct-orderin.patch @@ -22,7 +22,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -2964,6 +2964,15 @@ static int phy_led_blink_set(struct led_ +@@ -3068,6 +3068,15 @@ static int phy_led_blink_set(struct led_ return err; } @@ -38,7 +38,7 @@ Signed-off-by: David S. Miller static int of_phy_led(struct phy_device *phydev, struct device_node *led) { -@@ -2997,7 +3006,7 @@ static int of_phy_led(struct phy_device +@@ -3101,7 +3110,7 @@ static int of_phy_led(struct phy_device init_data.fwnode = of_fwnode_handle(led); init_data.devname_mandatory = true; @@ -47,7 +47,7 @@ Signed-off-by: David S. Miller if (err) return err; -@@ -3026,6 +3035,7 @@ static int of_phy_leds(struct phy_device +@@ -3130,6 +3139,7 @@ static int of_phy_leds(struct phy_device err = of_phy_led(phydev, led); if (err) { of_node_put(led); @@ -55,7 +55,7 @@ Signed-off-by: David S. Miller return err; } } -@@ -3231,6 +3241,9 @@ static int phy_remove(struct device *dev +@@ -3335,6 +3345,9 @@ static int phy_remove(struct device *dev cancel_delayed_work_sync(&phydev->state_queue); diff --git a/lede/target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/lede/target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch index 6cd798fc5d..505513a53f 100644 --- a/lede/target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ b/lede/target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -23,7 +23,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -2964,6 +2964,61 @@ static int phy_led_blink_set(struct led_ +@@ -3068,6 +3068,61 @@ static int phy_led_blink_set(struct led_ return err; } @@ -85,7 +85,7 @@ Signed-off-by: Jakub Kicinski static void phy_leds_unregister(struct phy_device *phydev) { struct phy_led *phyled; -@@ -3001,6 +3056,19 @@ static int of_phy_led(struct phy_device +@@ -3105,6 +3160,19 @@ static int of_phy_led(struct phy_device cdev->brightness_set_blocking = phy_led_set_brightness; if (phydev->drv->led_blink_set) cdev->blink_set = phy_led_blink_set; @@ -107,7 +107,7 @@ Signed-off-by: Jakub Kicinski init_data.fwnode = of_fwnode_handle(led); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -1013,6 +1013,39 @@ struct phy_driver { +@@ -1026,6 +1026,39 @@ struct phy_driver { int (*led_blink_set)(struct phy_device *dev, u8 index, unsigned long *delay_on, unsigned long *delay_off); diff --git a/lede/target/linux/generic/backport-6.1/831-v6.7-rtc-rtc7301-Support-byte-addressed-IO.patch b/lede/target/linux/generic/backport-6.1/831-v6.7-rtc-rtc7301-Support-byte-addressed-IO.patch new file mode 100644 index 0000000000..ddda6e4e78 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/831-v6.7-rtc-rtc7301-Support-byte-addressed-IO.patch @@ -0,0 +1,93 @@ +From edd25a77e69b7c546c28077e5dffe72c54c0afe8 Mon Sep 17 00:00:00 2001 +From: Linus Walleij +Date: Thu, 21 Sep 2023 22:18:12 +0200 +Subject: [PATCH 2/4] rtc: rtc7301: Support byte-addressed IO + +The old RTC7301 driver in OpenWrt used byte access, but the +current mainline Linux driver uses 32bit word access. + +Make this configurable using device properties using the +standard property "reg-io-width" in e.g. device tree. + +This is needed for the USRobotics USR8200 which has the +chip connected using byte accesses. + +Debugging and testing by Howard Harte. + +Signed-off-by: Linus Walleij +--- + drivers/rtc/rtc-r7301.c | 35 +++++++++++++++++++++++++++++++++-- + 1 file changed, 33 insertions(+), 2 deletions(-) + +--- a/drivers/rtc/rtc-r7301.c ++++ b/drivers/rtc/rtc-r7301.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -55,12 +56,23 @@ struct rtc7301_priv { + u8 bank; + }; + +-static const struct regmap_config rtc7301_regmap_config = { ++/* ++ * When the device is memory-mapped, some platforms pack the registers into ++ * 32-bit access using the lower 8 bits at each 4-byte stride, while others ++ * expose them as simply consecutive bytes. ++ */ ++static const struct regmap_config rtc7301_regmap_32_config = { + .reg_bits = 32, + .val_bits = 8, + .reg_stride = 4, + }; + ++static const struct regmap_config rtc7301_regmap_8_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .reg_stride = 1, ++}; ++ + static u8 rtc7301_read(struct rtc7301_priv *priv, unsigned int reg) + { + int reg_stride = regmap_get_reg_stride(priv->regmap); +@@ -356,7 +368,9 @@ static int __init rtc7301_rtc_probe(stru + void __iomem *regs; + struct rtc7301_priv *priv; + struct rtc_device *rtc; ++ static const struct regmap_config *mapconf; + int ret; ++ u32 val; + + priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -366,8 +380,25 @@ static int __init rtc7301_rtc_probe(stru + if (IS_ERR(regs)) + return PTR_ERR(regs); + ++ ret = device_property_read_u32(&dev->dev, "reg-io-width", &val); ++ if (ret) ++ /* Default to 32bit accesses */ ++ val = 4; ++ ++ switch (val) { ++ case 1: ++ mapconf = &rtc7301_regmap_8_config; ++ break; ++ case 4: ++ mapconf = &rtc7301_regmap_32_config; ++ break; ++ default: ++ dev_err(&dev->dev, "invalid reg-io-width %d\n", val); ++ return -EINVAL; ++ } ++ + priv->regmap = devm_regmap_init_mmio(&dev->dev, regs, +- &rtc7301_regmap_config); ++ mapconf); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + diff --git a/lede/target/linux/generic/backport-6.1/832-v6.7-net-phy-amd-Support-the-Altima-AMI101L.patch b/lede/target/linux/generic/backport-6.1/832-v6.7-net-phy-amd-Support-the-Altima-AMI101L.patch new file mode 100644 index 0000000000..e8e73c1e5f --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/832-v6.7-net-phy-amd-Support-the-Altima-AMI101L.patch @@ -0,0 +1,82 @@ +From 49e5663b505070424e18099841943f34342aa405 Mon Sep 17 00:00:00 2001 +From: Linus Walleij +Date: Sun, 24 Sep 2023 01:09:01 +0200 +Subject: [PATCH] net: phy: amd: Support the Altima AMI101L + +The Altima AC101L is obviously compatible with the AMD PHY, +as seen by reading the datasheet. + +Datasheet: https://docs.broadcom.com/doc/AC101L-DS05-405-RDS.pdf + +Signed-off-by: Linus Walleij +--- + drivers/net/phy/Kconfig | 4 ++-- + drivers/net/phy/amd.c | 33 +++++++++++++++++++++++---------- + 2 files changed, 25 insertions(+), 12 deletions(-) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -77,9 +77,9 @@ config AIR_EN8811H_PHY + Currently supports the Airoha EN8811H PHY. + + config AMD_PHY +- tristate "AMD PHYs" ++ tristate "AMD and Altima PHYs" + help +- Currently supports the am79c874 ++ Currently supports the AMD am79c874 and Altima AC101L. + + config MESON_GXL_PHY + tristate "Amlogic Meson GXL Internal PHY" +--- a/drivers/net/phy/amd.c ++++ b/drivers/net/phy/amd.c +@@ -13,6 +13,7 @@ + #include + #include + ++#define PHY_ID_AC101L 0x00225520 + #define PHY_ID_AM79C874 0x0022561b + + #define MII_AM79C_IR 17 /* Interrupt Status/Control Register */ +@@ -87,19 +88,31 @@ static irqreturn_t am79c_handle_interrup + return IRQ_HANDLED; + } + +-static struct phy_driver am79c_driver[] = { { +- .phy_id = PHY_ID_AM79C874, +- .name = "AM79C874", +- .phy_id_mask = 0xfffffff0, +- /* PHY_BASIC_FEATURES */ +- .config_init = am79c_config_init, +- .config_intr = am79c_config_intr, +- .handle_interrupt = am79c_handle_interrupt, +-} }; ++static struct phy_driver am79c_drivers[] = { ++ { ++ .phy_id = PHY_ID_AM79C874, ++ .name = "AM79C874", ++ .phy_id_mask = 0xfffffff0, ++ /* PHY_BASIC_FEATURES */ ++ .config_init = am79c_config_init, ++ .config_intr = am79c_config_intr, ++ .handle_interrupt = am79c_handle_interrupt, ++ }, ++ { ++ .phy_id = PHY_ID_AC101L, ++ .name = "AC101L", ++ .phy_id_mask = 0xfffffff0, ++ /* PHY_BASIC_FEATURES */ ++ .config_init = am79c_config_init, ++ .config_intr = am79c_config_intr, ++ .handle_interrupt = am79c_handle_interrupt, ++ }, ++}; + +-module_phy_driver(am79c_driver); ++module_phy_driver(am79c_drivers); + + static struct mdio_device_id __maybe_unused amd_tbl[] = { ++ { PHY_ID_AC101L, 0xfffffff0 }, + { PHY_ID_AM79C874, 0xfffffff0 }, + { } + }; diff --git a/lede/target/linux/generic/backport-6.1/833-v6.8-leds-core-Add-more-colors-from-DT-bindings-to-led_co.patch.patch b/lede/target/linux/generic/backport-6.1/833-v6.8-leds-core-Add-more-colors-from-DT-bindings-to-led_co.patch.patch new file mode 100644 index 0000000000..b71df6fa57 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/833-v6.8-leds-core-Add-more-colors-from-DT-bindings-to-led_co.patch.patch @@ -0,0 +1,29 @@ +From a067943129b4ec6b835e02cfd5fbef01093c1471 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Sun, 8 Oct 2023 16:40:13 +0200 +Subject: [PATCH] leds: core: Add more colors from DT bindings to led_colors + +The colors are already part of DT bindings. Make sure the kernel is +able to convert them to strings. + +Signed-off-by: Ondrej Jirman +Link: https://lore.kernel.org/r/20231008144014.1180334-1-megi@xff.cz +Signed-off-by: Lee Jones +--- + drivers/leds/led-core.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/leds/led-core.c ++++ b/drivers/leds/led-core.c +@@ -36,6 +36,11 @@ const char * const led_colors[LED_COLOR_ + [LED_COLOR_ID_IR] = "ir", + [LED_COLOR_ID_MULTI] = "multicolor", + [LED_COLOR_ID_RGB] = "rgb", ++ [LED_COLOR_ID_PURPLE] = "purple", ++ [LED_COLOR_ID_ORANGE] = "orange", ++ [LED_COLOR_ID_PINK] = "pink", ++ [LED_COLOR_ID_CYAN] = "cyan", ++ [LED_COLOR_ID_LIME] = "lime", + }; + EXPORT_SYMBOL_GPL(led_colors); + diff --git a/lede/target/linux/generic/backport-6.1/834-v6.8-leds-trigger-netdev-Extend-speeds-up-to-10G.patch b/lede/target/linux/generic/backport-6.1/834-v6.8-leds-trigger-netdev-Extend-speeds-up-to-10G.patch new file mode 100644 index 0000000000..1c8e014a1a --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/834-v6.8-leds-trigger-netdev-Extend-speeds-up-to-10G.patch @@ -0,0 +1,111 @@ +From bc8e1da69a68d9871773b657d18400a7941cbdef Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 28 Nov 2023 04:00:10 +0000 +Subject: [PATCH] leds: trigger: netdev: Extend speeds up to 10G + +Add 2.5G, 5G and 10G as available speeds to the netdev LED trigger. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/99e7d3304c6bba7f4863a4a80764a869855f2085.1701143925.git.daniel@makrotopia.org +Signed-off-by: Lee Jones +--- + drivers/leds/trigger/ledtrig-netdev.c | 32 ++++++++++++++++++++++++++- + include/linux/leds.h | 3 +++ + 2 files changed, 34 insertions(+), 1 deletion(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -99,6 +99,18 @@ static void set_baseline_state(struct le + trigger_data->link_speed == SPEED_1000) + blink_on = true; + ++ if (test_bit(TRIGGER_NETDEV_LINK_2500, &trigger_data->mode) && ++ trigger_data->link_speed == SPEED_2500) ++ blink_on = true; ++ ++ if (test_bit(TRIGGER_NETDEV_LINK_5000, &trigger_data->mode) && ++ trigger_data->link_speed == SPEED_5000) ++ blink_on = true; ++ ++ if (test_bit(TRIGGER_NETDEV_LINK_10000, &trigger_data->mode) && ++ trigger_data->link_speed == SPEED_10000) ++ blink_on = true; ++ + if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) && + trigger_data->duplex == DUPLEX_HALF) + blink_on = true; +@@ -286,6 +298,9 @@ static ssize_t netdev_led_attr_show(stru + case TRIGGER_NETDEV_LINK_10: + case TRIGGER_NETDEV_LINK_100: + case TRIGGER_NETDEV_LINK_1000: ++ case TRIGGER_NETDEV_LINK_2500: ++ case TRIGGER_NETDEV_LINK_5000: ++ case TRIGGER_NETDEV_LINK_10000: + case TRIGGER_NETDEV_HALF_DUPLEX: + case TRIGGER_NETDEV_FULL_DUPLEX: + case TRIGGER_NETDEV_TX: +@@ -316,6 +331,9 @@ static ssize_t netdev_led_attr_store(str + case TRIGGER_NETDEV_LINK_10: + case TRIGGER_NETDEV_LINK_100: + case TRIGGER_NETDEV_LINK_1000: ++ case TRIGGER_NETDEV_LINK_2500: ++ case TRIGGER_NETDEV_LINK_5000: ++ case TRIGGER_NETDEV_LINK_10000: + case TRIGGER_NETDEV_HALF_DUPLEX: + case TRIGGER_NETDEV_FULL_DUPLEX: + case TRIGGER_NETDEV_TX: +@@ -334,7 +352,10 @@ static ssize_t netdev_led_attr_store(str + if (test_bit(TRIGGER_NETDEV_LINK, &mode) && + (test_bit(TRIGGER_NETDEV_LINK_10, &mode) || + test_bit(TRIGGER_NETDEV_LINK_100, &mode) || +- test_bit(TRIGGER_NETDEV_LINK_1000, &mode))) ++ test_bit(TRIGGER_NETDEV_LINK_1000, &mode) || ++ test_bit(TRIGGER_NETDEV_LINK_2500, &mode) || ++ test_bit(TRIGGER_NETDEV_LINK_5000, &mode) || ++ test_bit(TRIGGER_NETDEV_LINK_10000, &mode))) + return -EINVAL; + + cancel_delayed_work_sync(&trigger_data->work); +@@ -364,6 +385,9 @@ DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETD + DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10); + DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100); + DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000); ++DEFINE_NETDEV_TRIGGER(link_2500, TRIGGER_NETDEV_LINK_2500); ++DEFINE_NETDEV_TRIGGER(link_5000, TRIGGER_NETDEV_LINK_5000); ++DEFINE_NETDEV_TRIGGER(link_10000, TRIGGER_NETDEV_LINK_10000); + DEFINE_NETDEV_TRIGGER(half_duplex, TRIGGER_NETDEV_HALF_DUPLEX); + DEFINE_NETDEV_TRIGGER(full_duplex, TRIGGER_NETDEV_FULL_DUPLEX); + DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); +@@ -422,6 +446,9 @@ static struct attribute *netdev_trig_att + &dev_attr_link_10.attr, + &dev_attr_link_100.attr, + &dev_attr_link_1000.attr, ++ &dev_attr_link_2500.attr, ++ &dev_attr_link_5000.attr, ++ &dev_attr_link_10000.attr, + &dev_attr_full_duplex.attr, + &dev_attr_half_duplex.attr, + &dev_attr_rx.attr, +@@ -519,6 +546,9 @@ static void netdev_trig_work(struct work + test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) || ++ test_bit(TRIGGER_NETDEV_LINK_2500, &trigger_data->mode) || ++ test_bit(TRIGGER_NETDEV_LINK_5000, &trigger_data->mode) || ++ test_bit(TRIGGER_NETDEV_LINK_10000, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode); + interval = jiffies_to_msecs( +--- a/include/linux/leds.h ++++ b/include/linux/leds.h +@@ -533,6 +533,9 @@ enum led_trigger_netdev_modes { + TRIGGER_NETDEV_LINK_10, + TRIGGER_NETDEV_LINK_100, + TRIGGER_NETDEV_LINK_1000, ++ TRIGGER_NETDEV_LINK_2500, ++ TRIGGER_NETDEV_LINK_5000, ++ TRIGGER_NETDEV_LINK_10000, + TRIGGER_NETDEV_HALF_DUPLEX, + TRIGGER_NETDEV_FULL_DUPLEX, + TRIGGER_NETDEV_TX, diff --git a/lede/target/linux/generic/backport-6.1/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch b/lede/target/linux/generic/backport-6.1/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch new file mode 100644 index 0000000000..0182e6d1a2 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch @@ -0,0 +1,98 @@ +From 7ae215ee7bb855f13c80565470fc7f67db4ba82f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 25 Jan 2024 21:36:59 +0100 +Subject: [PATCH 3/5] net: phy: add support for PHY LEDs polarity modes + +Add support for PHY LEDs polarity modes. Some PHY require LED to be set +to active low to be turned ON. Adds support for this by declaring +active-low property in DT. + +PHY driver needs to declare .led_polarity_set() to configure LED +polarity modes. Function will pass the index with the LED index and a +bitmap with all the required modes to set. + +Current supported modes are: +- active-low with the flag PHY_LED_ACTIVE_LOW. LED is set to active-low + to turn it ON. +- inactive-high-impedance with the flag PHY_LED_INACTIVE_HIGH_IMPEDANCE. + LED is set to high impedance to turn it OFF. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240125203702.4552-4-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phy_device.c | 16 ++++++++++++++++ + include/linux/phy.h | 22 ++++++++++++++++++++++ + 2 files changed, 38 insertions(+) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -3138,6 +3138,7 @@ static int of_phy_led(struct phy_device + struct device *dev = &phydev->mdio.dev; + struct led_init_data init_data = {}; + struct led_classdev *cdev; ++ unsigned long modes = 0; + struct phy_led *phyled; + u32 index; + int err; +@@ -3155,6 +3156,21 @@ static int of_phy_led(struct phy_device + if (index > U8_MAX) + return -EINVAL; + ++ if (of_property_read_bool(led, "active-low")) ++ set_bit(PHY_LED_ACTIVE_LOW, &modes); ++ if (of_property_read_bool(led, "inactive-high-impedance")) ++ set_bit(PHY_LED_INACTIVE_HIGH_IMPEDANCE, &modes); ++ ++ if (modes) { ++ /* Return error if asked to set polarity modes but not supported */ ++ if (!phydev->drv->led_polarity_set) ++ return -EINVAL; ++ ++ err = phydev->drv->led_polarity_set(phydev, index, modes); ++ if (err) ++ return err; ++ } ++ + phyled->index = index; + if (phydev->drv->led_brightness_set) + cdev->brightness_set_blocking = phy_led_set_brightness; +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -791,6 +791,15 @@ struct phy_led { + + #define to_phy_led(d) container_of(d, struct phy_led, led_cdev) + ++/* Modes for PHY LED configuration */ ++enum phy_led_modes { ++ PHY_LED_ACTIVE_LOW = 0, ++ PHY_LED_INACTIVE_HIGH_IMPEDANCE = 1, ++ ++ /* keep it last */ ++ __PHY_LED_MODES_NUM, ++}; ++ + /** + * struct phy_driver - Driver structure for a particular PHY type + * +@@ -1059,6 +1068,19 @@ struct phy_driver { + int (*led_hw_control_get)(struct phy_device *dev, u8 index, + unsigned long *rules); + ++ /** ++ * @led_polarity_set: Set the LED polarity modes ++ * @dev: PHY device which has the LED ++ * @index: Which LED of the PHY device ++ * @modes: bitmap of LED polarity modes ++ * ++ * Configure LED with all the required polarity modes in @modes ++ * to make it correctly turn ON or OFF. ++ * ++ * Returns 0, or an error code. ++ */ ++ int (*led_polarity_set)(struct phy_device *dev, int index, ++ unsigned long modes); + }; + #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \ + struct phy_driver, mdiodrv) diff --git a/lede/target/linux/generic/backport-6.1/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch b/lede/target/linux/generic/backport-6.1/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch new file mode 100644 index 0000000000..cbb9172032 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/836-v6.7-leds-trigger-netdev-fix-RTNL-handling-to-prevent-pot.patch @@ -0,0 +1,170 @@ +From fe2b1226656afae56702d1d84c6900f6b67df297 Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Fri, 1 Dec 2023 11:23:22 +0100 +Subject: [PATCH] leds: trigger: netdev: fix RTNL handling to prevent potential + deadlock + +When working on LED support for r8169 I got the following lockdep +warning. Easiest way to prevent this scenario seems to be to take +the RTNL lock before the trigger_data lock in set_device_name(). + +====================================================== +WARNING: possible circular locking dependency detected +6.7.0-rc2-next-20231124+ #2 Not tainted +------------------------------------------------------ +bash/383 is trying to acquire lock: +ffff888103aa1c68 (&trigger_data->lock){+.+.}-{3:3}, at: netdev_trig_notify+0xec/0x190 [ledtrig_netdev] + +but task is already holding lock: +ffffffff8cddf808 (rtnl_mutex){+.+.}-{3:3}, at: rtnl_lock+0x12/0x20 + +which lock already depends on the new lock. + +the existing dependency chain (in reverse order) is: + +-> #1 (rtnl_mutex){+.+.}-{3:3}: + __mutex_lock+0x9b/0xb50 + mutex_lock_nested+0x16/0x20 + rtnl_lock+0x12/0x20 + set_device_name+0xa9/0x120 [ledtrig_netdev] + netdev_trig_activate+0x1a1/0x230 [ledtrig_netdev] + led_trigger_set+0x172/0x2c0 + led_trigger_write+0xf1/0x140 + sysfs_kf_bin_write+0x5d/0x80 + kernfs_fop_write_iter+0x15d/0x210 + vfs_write+0x1f0/0x510 + ksys_write+0x6c/0xf0 + __x64_sys_write+0x14/0x20 + do_syscall_64+0x3f/0xf0 + entry_SYSCALL_64_after_hwframe+0x6c/0x74 + +-> #0 (&trigger_data->lock){+.+.}-{3:3}: + __lock_acquire+0x1459/0x25a0 + lock_acquire+0xc8/0x2d0 + __mutex_lock+0x9b/0xb50 + mutex_lock_nested+0x16/0x20 + netdev_trig_notify+0xec/0x190 [ledtrig_netdev] + call_netdevice_register_net_notifiers+0x5a/0x100 + register_netdevice_notifier+0x85/0x120 + netdev_trig_activate+0x1d4/0x230 [ledtrig_netdev] + led_trigger_set+0x172/0x2c0 + led_trigger_write+0xf1/0x140 + sysfs_kf_bin_write+0x5d/0x80 + kernfs_fop_write_iter+0x15d/0x210 + vfs_write+0x1f0/0x510 + ksys_write+0x6c/0xf0 + __x64_sys_write+0x14/0x20 + do_syscall_64+0x3f/0xf0 + entry_SYSCALL_64_after_hwframe+0x6c/0x74 + +other info that might help us debug this: + + Possible unsafe locking scenario: + + CPU0 CPU1 + ---- ---- + lock(rtnl_mutex); + lock(&trigger_data->lock); + lock(rtnl_mutex); + lock(&trigger_data->lock); + + *** DEADLOCK *** + +8 locks held by bash/383: + #0: ffff888103ff33f0 (sb_writers#3){.+.+}-{0:0}, at: ksys_write+0x6c/0xf0 + #1: ffff888103aa1e88 (&of->mutex){+.+.}-{3:3}, at: kernfs_fop_write_iter+0x114/0x210 + #2: ffff8881036f1890 (kn->active#82){.+.+}-{0:0}, at: kernfs_fop_write_iter+0x11d/0x210 + #3: ffff888108e2c358 (&led_cdev->led_access){+.+.}-{3:3}, at: led_trigger_write+0x30/0x140 + #4: ffffffff8cdd9e10 (triggers_list_lock){++++}-{3:3}, at: led_trigger_write+0x75/0x140 + #5: ffff888108e2c270 (&led_cdev->trigger_lock){++++}-{3:3}, at: led_trigger_write+0xe3/0x140 + #6: ffffffff8cdde3d0 (pernet_ops_rwsem){++++}-{3:3}, at: register_netdevice_notifier+0x1c/0x120 + #7: ffffffff8cddf808 (rtnl_mutex){+.+.}-{3:3}, at: rtnl_lock+0x12/0x20 + +stack backtrace: +CPU: 0 PID: 383 Comm: bash Not tainted 6.7.0-rc2-next-20231124+ #2 +Hardware name: Default string Default string/Default string, BIOS ADLN.M6.SODIMM.ZB.CY.015 08/08/2023 +Call Trace: + + dump_stack_lvl+0x5c/0xd0 + dump_stack+0x10/0x20 + print_circular_bug+0x2dd/0x410 + check_noncircular+0x131/0x150 + __lock_acquire+0x1459/0x25a0 + lock_acquire+0xc8/0x2d0 + ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev] + __mutex_lock+0x9b/0xb50 + ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev] + ? __this_cpu_preempt_check+0x13/0x20 + ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev] + ? __cancel_work_timer+0x11c/0x1b0 + ? __mutex_lock+0x123/0xb50 + mutex_lock_nested+0x16/0x20 + ? mutex_lock_nested+0x16/0x20 + netdev_trig_notify+0xec/0x190 [ledtrig_netdev] + call_netdevice_register_net_notifiers+0x5a/0x100 + register_netdevice_notifier+0x85/0x120 + netdev_trig_activate+0x1d4/0x230 [ledtrig_netdev] + led_trigger_set+0x172/0x2c0 + ? preempt_count_add+0x49/0xc0 + led_trigger_write+0xf1/0x140 + sysfs_kf_bin_write+0x5d/0x80 + kernfs_fop_write_iter+0x15d/0x210 + vfs_write+0x1f0/0x510 + ksys_write+0x6c/0xf0 + __x64_sys_write+0x14/0x20 + do_syscall_64+0x3f/0xf0 + entry_SYSCALL_64_after_hwframe+0x6c/0x74 +RIP: 0033:0x7f269055d034 +Code: c7 00 16 00 00 00 b8 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 80 3d 35 c3 0d 00 00 74 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 48 83 ec 28 48 89 54 24 18 48 +RSP: 002b:00007ffddb7ef748 EFLAGS: 00000202 ORIG_RAX: 0000000000000001 +RAX: ffffffffffffffda RBX: 0000000000000007 RCX: 00007f269055d034 +RDX: 0000000000000007 RSI: 000055bf5f4af3c0 RDI: 0000000000000001 +RBP: 000055bf5f4af3c0 R08: 0000000000000073 R09: 0000000000000001 +R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000007 +R13: 00007f26906325c0 R14: 00007f269062ff20 R15: 0000000000000000 + + +Fixes: d5e01266e7f5 ("leds: trigger: netdev: add additional specific link speed mode") +Cc: stable@vger.kernel.org +Signed-off-by: Heiner Kallweit +Reviewed-by: Andrew Lunn +Acked-by: Lee Jones +Link: https://lore.kernel.org/r/fb5c8294-2a10-4bf5-8f10-3d2b77d2757e@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/leds/trigger/ledtrig-netdev.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -235,6 +235,11 @@ static int set_device_name(struct led_ne + { + cancel_delayed_work_sync(&trigger_data->work); + ++ /* ++ * Take RTNL lock before trigger_data lock to prevent potential ++ * deadlock with netdev notifier registration. ++ */ ++ rtnl_lock(); + mutex_lock(&trigger_data->lock); + + if (trigger_data->net_dev) { +@@ -254,16 +259,14 @@ static int set_device_name(struct led_ne + trigger_data->carrier_link_up = false; + trigger_data->link_speed = SPEED_UNKNOWN; + trigger_data->duplex = DUPLEX_UNKNOWN; +- if (trigger_data->net_dev != NULL) { +- rtnl_lock(); ++ if (trigger_data->net_dev) + get_device_state(trigger_data); +- rtnl_unlock(); +- } + + trigger_data->last_activity = 0; + + set_baseline_state(trigger_data); + mutex_unlock(&trigger_data->lock); ++ rtnl_unlock(); + + return 0; + } diff --git a/lede/target/linux/generic/backport-6.1/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch b/lede/target/linux/generic/backport-6.1/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch new file mode 100644 index 0000000000..51b4bbbfcb --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/837-v6.4-net-phy-hide-the-PHYLIB_LEDS-knob.patch @@ -0,0 +1,43 @@ +From 9b78d919632b7149d311aaad5a977e4b48b10321 Mon Sep 17 00:00:00 2001 +From: Paolo Abeni +Date: Wed, 26 Apr 2023 10:15:31 +0200 +Subject: [PATCH] net: phy: hide the PHYLIB_LEDS knob + +commit 4bb7aac70b5d ("net: phy: fix circular LEDS_CLASS dependencies") +solved a build failure, but introduces a new config knob with a default +'y' value: PHYLIB_LEDS. + +The latter is against the current new config policy. The exception +was raised to allow the user to catch bad configurations without led +support. + +Anyway the current definition of PHYLIB_LEDS does not fit the above +goal: if LEDS_CLASS is disabled, the new config will be available +only with PHYLIB disabled, too. + +Hide the mentioned config, to preserve the randconfig testing done so +far, while respecting the mentioned policy. + +Suggested-by: Andrew Lunn +Suggested-by: Arnd Bergmann +Signed-off-by: Paolo Abeni +Link: https://lore.kernel.org/r/d82489be8ed911c383c3447e9abf469995ccf39a.1682496488.git.pabeni@redhat.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/Kconfig | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -45,10 +45,8 @@ config LED_TRIGGER_PHY + for any speed known to the PHY. + + config PHYLIB_LEDS +- bool "Support probing LEDs from device tree" ++ def_bool OF + depends on LEDS_CLASS=y || LEDS_CLASS=PHYLIB +- depends on OF +- default y + help + When LED class support is enabled, phylib can automatically + probe LED setting from device tree. diff --git a/lede/target/linux/generic/backport-6.1/838-v6.9-leds-trigger-netdev-Fix-kernel-panic-on-interface-re.patch b/lede/target/linux/generic/backport-6.1/838-v6.9-leds-trigger-netdev-Fix-kernel-panic-on-interface-re.patch new file mode 100644 index 0000000000..8d391678ff --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/838-v6.9-leds-trigger-netdev-Fix-kernel-panic-on-interface-re.patch @@ -0,0 +1,55 @@ +From 12ce20e02e532f101b725d71c52a36c5cc8ad1e6 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 4 Feb 2024 00:54:01 +0100 +Subject: [PATCH] leds: trigger: netdev: Fix kernel panic on interface rename + trig notify + +Commit d5e01266e7f5 ("leds: trigger: netdev: add additional specific link +speed mode") in the various changes, reworked the way to set the LINKUP +mode in commit cee4bd16c319 ("leds: trigger: netdev: Recheck +NETDEV_LED_MODE_LINKUP on dev rename") and moved it to a generic function. + +This changed the logic where, in the previous implementation the dev +from the trigger event was used to check if the carrier was ok, but in +the new implementation with the generic function, the dev in +trigger_data is used instead. + +This is problematic and cause a possible kernel panic due to the fact +that the dev in the trigger_data still reference the old one as the +new one (passed from the trigger event) still has to be hold and saved +in the trigger_data struct (done in the NETDEV_REGISTER case). + +On calling of get_device_state(), an invalid net_dev is used and this +cause a kernel panic. + +To handle this correctly, move the call to get_device_state() after the +new net_dev is correctly set in trigger_data (in the NETDEV_REGISTER +case) and correctly parse the new dev. + +Fixes: d5e01266e7f5 ("leds: trigger: netdev: add additional specific link speed mode") +Cc: stable@vger.kernel.org +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240203235413.1146-1-ansuelsmth@gmail.com +Signed-off-by: Lee Jones +--- + drivers/leds/trigger/ledtrig-netdev.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -489,12 +489,12 @@ static int netdev_trig_notify(struct not + trigger_data->duplex = DUPLEX_UNKNOWN; + switch (evt) { + case NETDEV_CHANGENAME: +- get_device_state(trigger_data); +- fallthrough; + case NETDEV_REGISTER: + dev_put(trigger_data->net_dev); + dev_hold(dev); + trigger_data->net_dev = dev; ++ if (evt == NETDEV_CHANGENAME) ++ get_device_state(trigger_data); + break; + case NETDEV_UNREGISTER: + dev_put(trigger_data->net_dev); diff --git a/lede/target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Fix-order-of-pek-rise-and-fall-events.patch b/lede/target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Fix-order-of-pek-rise-and-fall-events.patch new file mode 100644 index 0000000000..23681ba937 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Fix-order-of-pek-rise-and-fall-events.patch @@ -0,0 +1,80 @@ +From 8781ba7f45695af3ab8e8d1b55a31f527c9201a3 Mon Sep 17 00:00:00 2001 +From: Aren Moynihan +Date: Thu, 8 Dec 2022 17:02:26 -0500 +Subject: [PATCH] mfd: axp20x: Fix order of pek rise and fall events + +The power button can get "stuck" if the rising edge and falling edge irq +are read in the same pass. This can often be triggered when resuming +from suspend if the power button is released before the kernel handles +the interrupt. + +Swapping the order of the rise and fall events makes sure that the press +event is handled first, which prevents this situation. + +Signed-off-by: Aren Moynihan +Reviewed-by: Samuel Holland +Tested-by: Samuel Holland +Acked-by: Chen-Yu Tsai +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20221208220225.635414-1-aren@peacevolution.org +--- + include/linux/mfd/axp20x.h | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/include/linux/mfd/axp20x.h ++++ b/include/linux/mfd/axp20x.h +@@ -432,8 +432,9 @@ enum { + AXP152_IRQ_PEK_SHORT, + AXP152_IRQ_PEK_LONG, + AXP152_IRQ_TIMER, +- AXP152_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP152_IRQ_PEK_FAL_EDGE, ++ AXP152_IRQ_PEK_RIS_EDGE, + AXP152_IRQ_GPIO3_INPUT, + AXP152_IRQ_GPIO2_INPUT, + AXP152_IRQ_GPIO1_INPUT, +@@ -472,8 +473,9 @@ enum { + AXP20X_IRQ_LOW_PWR_LVL1, + AXP20X_IRQ_LOW_PWR_LVL2, + AXP20X_IRQ_TIMER, +- AXP20X_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP20X_IRQ_PEK_FAL_EDGE, ++ AXP20X_IRQ_PEK_RIS_EDGE, + AXP20X_IRQ_GPIO3_INPUT, + AXP20X_IRQ_GPIO2_INPUT, + AXP20X_IRQ_GPIO1_INPUT, +@@ -502,8 +504,9 @@ enum axp22x_irqs { + AXP22X_IRQ_LOW_PWR_LVL1, + AXP22X_IRQ_LOW_PWR_LVL2, + AXP22X_IRQ_TIMER, +- AXP22X_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP22X_IRQ_PEK_FAL_EDGE, ++ AXP22X_IRQ_PEK_RIS_EDGE, + AXP22X_IRQ_GPIO1_INPUT, + AXP22X_IRQ_GPIO0_INPUT, + }; +@@ -571,8 +574,9 @@ enum axp803_irqs { + AXP803_IRQ_LOW_PWR_LVL1, + AXP803_IRQ_LOW_PWR_LVL2, + AXP803_IRQ_TIMER, +- AXP803_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP803_IRQ_PEK_FAL_EDGE, ++ AXP803_IRQ_PEK_RIS_EDGE, + AXP803_IRQ_PEK_SHORT, + AXP803_IRQ_PEK_LONG, + AXP803_IRQ_PEK_OVER_OFF, +@@ -623,8 +627,9 @@ enum axp809_irqs { + AXP809_IRQ_LOW_PWR_LVL1, + AXP809_IRQ_LOW_PWR_LVL2, + AXP809_IRQ_TIMER, +- AXP809_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP809_IRQ_PEK_FAL_EDGE, ++ AXP809_IRQ_PEK_RIS_EDGE, + AXP809_IRQ_PEK_SHORT, + AXP809_IRQ_PEK_LONG, + AXP809_IRQ_PEK_OVER_OFF, diff --git a/lede/target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch b/lede/target/linux/generic/backport-6.1/881-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch similarity index 100% rename from lede/target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch rename to lede/target/linux/generic/backport-6.1/881-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch diff --git a/lede/target/linux/generic/backport-6.1/882-v6.3-mfd-axp20x-Fix-axp288-writable-ranges.patch b/lede/target/linux/generic/backport-6.1/882-v6.3-mfd-axp20x-Fix-axp288-writable-ranges.patch new file mode 100644 index 0000000000..b84815e1a8 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/882-v6.3-mfd-axp20x-Fix-axp288-writable-ranges.patch @@ -0,0 +1,28 @@ +From 2405fbfb384ef39e9560d76d3f6e4c90519f90aa Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 29 Mar 2023 22:55:44 +0200 +Subject: [PATCH] mfd: axp20x: Fix axp288 writable-ranges + +Register AXP288_POWER_REASON is writable and needs to be written +to reset the reset- / power-on-reason bits. + +Add it to the axp288 writable-ranges so that the extcon-axp288 +driver can properly clear the reset- / power-on-reason bits. + +Signed-off-by: Hans de Goede +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20230329205544.1051393-1-hdegoede@redhat.com +--- + drivers/mfd/axp20x.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -119,6 +119,7 @@ static const struct regmap_access_table + + /* AXP288 ranges are shared with the AXP803, as they cover the same range */ + static const struct regmap_range axp288_writeable_ranges[] = { ++ regmap_reg_range(AXP288_POWER_REASON, AXP288_POWER_REASON), + regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE), + regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5), + }; diff --git a/lede/target/linux/generic/backport-6.1/881-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch b/lede/target/linux/generic/backport-6.1/883-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch similarity index 95% rename from lede/target/linux/generic/backport-6.1/881-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch rename to lede/target/linux/generic/backport-6.1/883-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch index ec8d38a183..83ef60aecd 100644 --- a/lede/target/linux/generic/backport-6.1/881-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch +++ b/lede/target/linux/generic/backport-6.1/883-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch @@ -57,7 +57,7 @@ Link: https://lore.kernel.org/r/TY3P286MB261162D57695AC8164ED50E298609@TY3P286MB }; static const struct regmap_range axp152_writeable_ranges[] = { -@@ -168,6 +169,31 @@ static const struct regmap_access_table +@@ -169,6 +170,31 @@ static const struct regmap_access_table .n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges), }; @@ -89,7 +89,7 @@ Link: https://lore.kernel.org/r/TY3P286MB261162D57695AC8164ED50E298609@TY3P286MB static const struct resource axp152_pek_resources[] = { DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"), DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"), -@@ -236,6 +262,11 @@ static const struct resource axp809_pek_ +@@ -237,6 +263,11 @@ static const struct resource axp809_pek_ DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"), }; @@ -101,7 +101,7 @@ Link: https://lore.kernel.org/r/TY3P286MB261162D57695AC8164ED50E298609@TY3P286MB static const struct regmap_config axp152_regmap_config = { .reg_bits = 8, .val_bits = 8, -@@ -281,6 +312,15 @@ static const struct regmap_config axp806 +@@ -282,6 +313,15 @@ static const struct regmap_config axp806 .cache_type = REGCACHE_RBTREE, }; @@ -117,7 +117,7 @@ Link: https://lore.kernel.org/r/TY3P286MB261162D57695AC8164ED50E298609@TY3P286MB #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \ [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) } -@@ -502,6 +542,23 @@ static const struct regmap_irq axp809_re +@@ -503,6 +543,23 @@ static const struct regmap_irq axp809_re INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0), }; @@ -141,7 +141,7 @@ Link: https://lore.kernel.org/r/TY3P286MB261162D57695AC8164ED50E298609@TY3P286MB static const struct regmap_irq_chip axp152_regmap_irq_chip = { .name = "axp152_irq_chip", .status_base = AXP152_IRQ1_STATE, -@@ -588,6 +645,17 @@ static const struct regmap_irq_chip axp8 +@@ -589,6 +646,17 @@ static const struct regmap_irq_chip axp8 .num_regs = 5, }; @@ -159,7 +159,7 @@ Link: https://lore.kernel.org/r/TY3P286MB261162D57695AC8164ED50E298609@TY3P286MB static const struct mfd_cell axp20x_cells[] = { { .name = "axp20x-gpio", -@@ -832,6 +900,23 @@ static const struct mfd_cell axp813_cell +@@ -833,6 +901,23 @@ static const struct mfd_cell axp813_cell }, }; @@ -183,7 +183,7 @@ Link: https://lore.kernel.org/r/TY3P286MB261162D57695AC8164ED50E298609@TY3P286MB static int axp20x_power_off(struct sys_off_data *data) { struct axp20x_dev *axp20x = data->cb_data; -@@ -941,6 +1026,28 @@ int axp20x_match_device(struct axp20x_de +@@ -942,6 +1027,28 @@ int axp20x_match_device(struct axp20x_de */ axp20x->regmap_irq_chip = &axp803_regmap_irq_chip; break; @@ -317,7 +317,7 @@ Link: https://lore.kernel.org/r/TY3P286MB261162D57695AC8164ED50E298609@TY3P286MB /* IRQs */ enum { AXP152_IRQ_LDO0IN_CONNECT = 1, -@@ -632,6 +700,23 @@ enum axp809_irqs { +@@ -637,6 +705,23 @@ enum axp809_irqs { AXP809_IRQ_GPIO0_INPUT, }; diff --git a/lede/target/linux/generic/backport-6.1/882-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch b/lede/target/linux/generic/backport-6.1/884-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch similarity index 93% rename from lede/target/linux/generic/backport-6.1/882-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch rename to lede/target/linux/generic/backport-6.1/884-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch index 9fe70c1032..c9470eacec 100644 --- a/lede/target/linux/generic/backport-6.1/882-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch +++ b/lede/target/linux/generic/backport-6.1/884-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch @@ -58,7 +58,7 @@ Signed-off-by: Lee Jones "AXP803", "AXP806", "AXP809", -@@ -155,6 +156,25 @@ static const struct regmap_range axp806_ +@@ -156,6 +157,25 @@ static const struct regmap_range axp806_ regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT), }; @@ -84,7 +84,7 @@ Signed-off-by: Lee Jones static const struct regmap_range axp806_volatile_ranges[] = { regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE), }; -@@ -247,6 +267,11 @@ static const struct resource axp288_fuel +@@ -248,6 +268,11 @@ static const struct resource axp288_fuel DEFINE_RES_IRQ(AXP288_IRQ_WL1), }; @@ -96,7 +96,7 @@ Signed-off-by: Lee Jones static const struct resource axp803_pek_resources[] = { DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"), DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"), -@@ -303,6 +328,15 @@ static const struct regmap_config axp288 +@@ -304,6 +329,15 @@ static const struct regmap_config axp288 .cache_type = REGCACHE_RBTREE, }; @@ -112,7 +112,7 @@ Signed-off-by: Lee Jones static const struct regmap_config axp806_regmap_config = { .reg_bits = 8, .val_bits = 8, -@@ -455,6 +489,16 @@ static const struct regmap_irq axp288_re +@@ -456,6 +490,16 @@ static const struct regmap_irq axp288_re INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), }; @@ -129,7 +129,7 @@ Signed-off-by: Lee Jones static const struct regmap_irq axp803_regmap_irqs[] = { INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V, 0, 7), INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN, 0, 6), -@@ -609,6 +653,17 @@ static const struct regmap_irq_chip axp2 +@@ -610,6 +654,17 @@ static const struct regmap_irq_chip axp2 }; @@ -147,7 +147,7 @@ Signed-off-by: Lee Jones static const struct regmap_irq_chip axp803_regmap_irq_chip = { .name = "axp803", .status_base = AXP20X_IRQ1_STATE, -@@ -751,6 +806,11 @@ static const struct mfd_cell axp152_cell +@@ -752,6 +807,11 @@ static const struct mfd_cell axp152_cell }, }; @@ -159,7 +159,7 @@ Signed-off-by: Lee Jones static const struct resource axp288_adc_resources[] = { DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"), }; -@@ -920,8 +980,18 @@ static const struct mfd_cell axp_regulat +@@ -921,8 +981,18 @@ static const struct mfd_cell axp_regulat static int axp20x_power_off(struct sys_off_data *data) { struct axp20x_dev *axp20x = data->cb_data; @@ -179,7 +179,7 @@ Signed-off-by: Lee Jones /* Give capacitors etc. time to drain to avoid kernel panic msg. */ mdelay(500); -@@ -984,6 +1054,12 @@ int axp20x_match_device(struct axp20x_de +@@ -985,6 +1055,12 @@ int axp20x_match_device(struct axp20x_de axp20x->regmap_irq_chip = &axp288_regmap_irq_chip; axp20x->irq_flags = IRQF_TRIGGER_LOW; break; @@ -237,7 +237,7 @@ Signed-off-by: Lee Jones AXP806_DCDCA = 0, AXP806_DCDCB, AXP806_DCDCC, -@@ -613,6 +635,16 @@ enum axp288_irqs { +@@ -616,6 +638,16 @@ enum axp288_irqs { AXP288_IRQ_BC_USB_CHNG, }; diff --git a/lede/target/linux/generic/backport-6.1/883-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch b/lede/target/linux/generic/backport-6.1/885-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch similarity index 100% rename from lede/target/linux/generic/backport-6.1/883-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch rename to lede/target/linux/generic/backport-6.1/885-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch diff --git a/lede/target/linux/generic/backport-6.1/884-v6.5-regulator-axp20x-Add-AXP15060-support.patch b/lede/target/linux/generic/backport-6.1/886-v6.5-regulator-axp20x-Add-AXP15060-support.patch similarity index 100% rename from lede/target/linux/generic/backport-6.1/884-v6.5-regulator-axp20x-Add-AXP15060-support.patch rename to lede/target/linux/generic/backport-6.1/886-v6.5-regulator-axp20x-Add-AXP15060-support.patch diff --git a/lede/target/linux/generic/backport-6.1/885-v6.5-mfd-axp20x-Add-support-for-AXP192.patch b/lede/target/linux/generic/backport-6.1/887-v6.5-mfd-axp20x-Add-support-for-AXP192.patch similarity index 96% rename from lede/target/linux/generic/backport-6.1/885-v6.5-mfd-axp20x-Add-support-for-AXP192.patch rename to lede/target/linux/generic/backport-6.1/887-v6.5-mfd-axp20x-Add-support-for-AXP192.patch index 20a26db3e6..d75b4e7453 100644 --- a/lede/target/linux/generic/backport-6.1/885-v6.5-mfd-axp20x-Add-support-for-AXP192.patch +++ b/lede/target/linux/generic/backport-6.1/887-v6.5-mfd-axp20x-Add-support-for-AXP192.patch @@ -79,7 +79,7 @@ Signed-off-by: Lee Jones /* AXP22x ranges are shared with the AXP809, as they cover the same range */ static const struct regmap_range axp22x_writeable_ranges[] = { regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE), -@@ -219,6 +249,19 @@ static const struct resource axp152_pek_ +@@ -220,6 +250,19 @@ static const struct resource axp152_pek_ DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"), }; @@ -99,7 +99,7 @@ Signed-off-by: Lee Jones static const struct resource axp20x_ac_power_supply_resources[] = { DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"), DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"), -@@ -301,6 +344,15 @@ static const struct regmap_config axp152 +@@ -302,6 +345,15 @@ static const struct regmap_config axp152 .cache_type = REGCACHE_RBTREE, }; @@ -115,7 +115,7 @@ Signed-off-by: Lee Jones static const struct regmap_config axp20x_regmap_config = { .reg_bits = 8, .val_bits = 8, -@@ -378,6 +430,42 @@ static const struct regmap_irq axp152_re +@@ -379,6 +431,42 @@ static const struct regmap_irq axp152_re INIT_REGMAP_IRQ(AXP152, GPIO0_INPUT, 2, 0), }; @@ -158,7 +158,7 @@ Signed-off-by: Lee Jones static const struct regmap_irq axp20x_regmap_irqs[] = { INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V, 0, 7), INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN, 0, 6), -@@ -615,6 +703,32 @@ static const struct regmap_irq_chip axp1 +@@ -616,6 +704,32 @@ static const struct regmap_irq_chip axp1 .num_regs = 3, }; @@ -191,7 +191,7 @@ Signed-off-by: Lee Jones static const struct regmap_irq_chip axp20x_regmap_irq_chip = { .name = "axp20x_irq_chip", .status_base = AXP20X_IRQ1_STATE, -@@ -711,6 +825,27 @@ static const struct regmap_irq_chip axp1 +@@ -712,6 +826,27 @@ static const struct regmap_irq_chip axp1 .num_regs = 2, }; @@ -219,7 +219,7 @@ Signed-off-by: Lee Jones static const struct mfd_cell axp20x_cells[] = { { .name = "axp20x-gpio", -@@ -1028,6 +1163,12 @@ int axp20x_match_device(struct axp20x_de +@@ -1029,6 +1164,12 @@ int axp20x_match_device(struct axp20x_de axp20x->regmap_cfg = &axp152_regmap_config; axp20x->regmap_irq_chip = &axp152_regmap_irq_chip; break; @@ -338,7 +338,7 @@ Signed-off-by: Lee Jones AXP20X_LDO1 = 0, AXP20X_LDO2, AXP20X_LDO3, -@@ -530,6 +578,42 @@ enum { +@@ -531,6 +579,42 @@ enum { AXP152_IRQ_GPIO0_INPUT, }; diff --git a/lede/target/linux/generic/backport-6.1/895-01-v6.8-net-phy-add-possible-interfaces.patch b/lede/target/linux/generic/backport-6.1/895-01-v6.8-net-phy-add-possible-interfaces.patch new file mode 100644 index 0000000000..3a9b856a20 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/895-01-v6.8-net-phy-add-possible-interfaces.patch @@ -0,0 +1,60 @@ +From 1a7aa058bc92f0edae7a0d1ef1a7b05aec0c643a Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:27:52 +0000 +Subject: [PATCH 1/7] net: phy: add possible interfaces + +Add a possible_interfaces member to struct phy_device to indicate which +interfaces a clause 45 PHY may switch between depending on the media. +This must be populated by the PHY driver by the time the .config_init() +method completes according to the PHYs host-side configuration. + +For example, the Marvell 88x3310 PHY can switch between 10GBASE-R, +5GBASE-R, 2500BASE-X, and SGMII on the host side depending on the media +side speed, so all these interface modes are set in the +possible_interfaces member. + +This allows phylib users (such as phylink) to know in advance which +interface modes to expect, which allows them to appropriately restrict +the advertised link modes according to the capabilities of other parts +of the link. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VHk-00DDLN-I7@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phy_device.c | 2 ++ + include/linux/phy.h | 3 +++ + 2 files changed, 5 insertions(+) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1215,6 +1215,8 @@ int phy_init_hw(struct phy_device *phyde + if (ret < 0) + return ret; + ++ phy_interface_zero(phydev->possible_interfaces); ++ + if (phydev->drv->config_init) { + ret = phydev->drv->config_init(phydev); + if (ret < 0) +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -600,6 +600,8 @@ struct macsec_ops; + * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended, + * requiring a rerun of the interrupt handler after resume + * @interface: enum phy_interface_t value ++ * @possible_interfaces: bitmap if interface modes that the attached PHY ++ * will switch between depending on media speed. + * @skb: Netlink message for cable diagnostics + * @nest: Netlink nest used for cable diagnostics + * @ehdr: nNtlink header for cable diagnostics +@@ -665,6 +667,7 @@ struct phy_device { + u32 dev_flags; + + phy_interface_t interface; ++ DECLARE_PHY_INTERFACE_MASK(possible_interfaces); + + /* + * forced speed & duplex (no autoneg) diff --git a/lede/target/linux/generic/backport-6.1/895-02-v6.8-net-phylink-use-for_each_set_bit.patch b/lede/target/linux/generic/backport-6.1/895-02-v6.8-net-phylink-use-for_each_set_bit.patch new file mode 100644 index 0000000000..155ec1c2d9 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/895-02-v6.8-net-phylink-use-for_each_set_bit.patch @@ -0,0 +1,46 @@ +From 85631f5b33f2acce7d42dec1d0a062ab40de95b8 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Sun, 19 Nov 2023 21:07:43 +0000 +Subject: [PATCH 2/7] net: phylink: use for_each_set_bit() + +Use for_each_set_bit() rather than open coding the for() test_bit() +loop. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Reviewed-by: Wojciech Drewek +Link: https://lore.kernel.org/r/E1r4p15-00Cpxe-C7@rmk-PC.armlinux.org.uk +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/phylink.c | 18 ++++++++---------- + 1 file changed, 8 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -690,18 +690,16 @@ static int phylink_validate_mask(struct + __ETHTOOL_DECLARE_LINK_MODE_MASK(all_s) = { 0, }; + __ETHTOOL_DECLARE_LINK_MODE_MASK(s); + struct phylink_link_state t; +- int intf; ++ int interface; + +- for (intf = 0; intf < PHY_INTERFACE_MODE_MAX; intf++) { +- if (test_bit(intf, interfaces)) { +- linkmode_copy(s, supported); ++ for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) { ++ linkmode_copy(s, supported); + +- t = *state; +- t.interface = intf; +- if (!phylink_validate_mac_and_pcs(pl, s, &t)) { +- linkmode_or(all_s, all_s, s); +- linkmode_or(all_adv, all_adv, t.advertising); +- } ++ t = *state; ++ t.interface = interface; ++ if (!phylink_validate_mac_and_pcs(pl, s, &t)) { ++ linkmode_or(all_s, all_s, s); ++ linkmode_or(all_adv, all_adv, t.advertising); + } + } + diff --git a/lede/target/linux/generic/backport-6.1/895-03-v6.8-net-phylink-split-out-per-interface-validation.patch b/lede/target/linux/generic/backport-6.1/895-03-v6.8-net-phylink-split-out-per-interface-validation.patch new file mode 100644 index 0000000000..163cb953f7 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/895-03-v6.8-net-phylink-split-out-per-interface-validation.patch @@ -0,0 +1,76 @@ +From d4788b4383ce5caeb4e68818357c81a02117a3f9 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:19 +0000 +Subject: [PATCH 3/7] net: phylink: split out per-interface validation + +Split out the internals of phylink_validate_mask() to make the code +easier to read. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIB-00DDLr-7g@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 42 ++++++++++++++++++++++++++++----------- + 1 file changed, 30 insertions(+), 12 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -682,26 +682,44 @@ static int phylink_validate_mac_and_pcs( + return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; + } + ++static void phylink_validate_one(struct phylink *pl, ++ const unsigned long *supported, ++ const struct phylink_link_state *state, ++ phy_interface_t interface, ++ unsigned long *accum_supported, ++ unsigned long *accum_advertising) ++{ ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(tmp_supported); ++ struct phylink_link_state tmp_state; ++ ++ linkmode_copy(tmp_supported, supported); ++ ++ tmp_state = *state; ++ tmp_state.interface = interface; ++ ++ if (!phylink_validate_mac_and_pcs(pl, tmp_supported, &tmp_state)) { ++ phylink_dbg(pl, " interface %u (%s) rate match %s supports %*pbl\n", ++ interface, phy_modes(interface), ++ phy_rate_matching_to_str(tmp_state.rate_matching), ++ __ETHTOOL_LINK_MODE_MASK_NBITS, tmp_supported); ++ ++ linkmode_or(accum_supported, accum_supported, tmp_supported); ++ linkmode_or(accum_advertising, accum_advertising, ++ tmp_state.advertising); ++ } ++} ++ + static int phylink_validate_mask(struct phylink *pl, unsigned long *supported, + struct phylink_link_state *state, + const unsigned long *interfaces) + { + __ETHTOOL_DECLARE_LINK_MODE_MASK(all_adv) = { 0, }; + __ETHTOOL_DECLARE_LINK_MODE_MASK(all_s) = { 0, }; +- __ETHTOOL_DECLARE_LINK_MODE_MASK(s); +- struct phylink_link_state t; + int interface; + +- for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) { +- linkmode_copy(s, supported); +- +- t = *state; +- t.interface = interface; +- if (!phylink_validate_mac_and_pcs(pl, s, &t)) { +- linkmode_or(all_s, all_s, s); +- linkmode_or(all_adv, all_adv, t.advertising); +- } +- } ++ for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) ++ phylink_validate_one(pl, supported, state, interface, ++ all_s, all_adv); + + linkmode_copy(supported, all_s); + linkmode_copy(state->advertising, all_adv); diff --git a/lede/target/linux/generic/backport-6.1/895-04-v6.8-net-phylink-pass-PHY-into-phylink_validate_one.patch b/lede/target/linux/generic/backport-6.1/895-04-v6.8-net-phylink-pass-PHY-into-phylink_validate_one.patch new file mode 100644 index 0000000000..5012020676 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/895-04-v6.8-net-phylink-pass-PHY-into-phylink_validate_one.patch @@ -0,0 +1,47 @@ +From ce7273c31fadb3143fc80c96a72a42adc19c2757 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:24 +0000 +Subject: [PATCH 4/7] net: phylink: pass PHY into phylink_validate_one() + +Pass the phy (if any) into phylink_validate_one() so that we can +validate each interface with its rate matching setting. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIG-00DDLx-Cb@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -682,7 +682,7 @@ static int phylink_validate_mac_and_pcs( + return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; + } + +-static void phylink_validate_one(struct phylink *pl, ++static void phylink_validate_one(struct phylink *pl, struct phy_device *phy, + const unsigned long *supported, + const struct phylink_link_state *state, + phy_interface_t interface, +@@ -697,6 +697,9 @@ static void phylink_validate_one(struct + tmp_state = *state; + tmp_state.interface = interface; + ++ if (phy) ++ tmp_state.rate_matching = phy_get_rate_matching(phy, interface); ++ + if (!phylink_validate_mac_and_pcs(pl, tmp_supported, &tmp_state)) { + phylink_dbg(pl, " interface %u (%s) rate match %s supports %*pbl\n", + interface, phy_modes(interface), +@@ -718,7 +721,7 @@ static int phylink_validate_mask(struct + int interface; + + for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) +- phylink_validate_one(pl, supported, state, interface, ++ phylink_validate_one(pl, NULL, supported, state, interface, + all_s, all_adv); + + linkmode_copy(supported, all_s); diff --git a/lede/target/linux/generic/backport-6.1/895-05-v6.8-net-phylink-pass-PHY-into-phylink_validate_mask.patch b/lede/target/linux/generic/backport-6.1/895-05-v6.8-net-phylink-pass-PHY-into-phylink_validate_mask.patch new file mode 100644 index 0000000000..997c74346c --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/895-05-v6.8-net-phylink-pass-PHY-into-phylink_validate_mask.patch @@ -0,0 +1,58 @@ +From c6fec66d3cd76d797f70b30f1511bed10ba45a96 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:29 +0000 +Subject: [PATCH 5/7] net: phylink: pass PHY into phylink_validate_mask() + +Pass the phy (if any) into phylink_validate_mask() so that we can +validate each interface with its rate matching setting. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIL-00DDM3-HJ@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -712,7 +712,8 @@ static void phylink_validate_one(struct + } + } + +-static int phylink_validate_mask(struct phylink *pl, unsigned long *supported, ++static int phylink_validate_mask(struct phylink *pl, struct phy_device *phy, ++ unsigned long *supported, + struct phylink_link_state *state, + const unsigned long *interfaces) + { +@@ -721,7 +722,7 @@ static int phylink_validate_mask(struct + int interface; + + for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) +- phylink_validate_one(pl, NULL, supported, state, interface, ++ phylink_validate_one(pl, phy, supported, state, interface, + all_s, all_adv); + + linkmode_copy(supported, all_s); +@@ -736,7 +737,8 @@ static int phylink_validate(struct phyli + const unsigned long *interfaces = pl->config->supported_interfaces; + + if (state->interface == PHY_INTERFACE_MODE_NA) +- return phylink_validate_mask(pl, supported, state, interfaces); ++ return phylink_validate_mask(pl, NULL, supported, state, ++ interfaces); + + if (!test_bit(state->interface, interfaces)) + return -EINVAL; +@@ -3132,7 +3134,8 @@ static int phylink_sfp_config_optical(st + /* For all the interfaces that are supported, reduce the sfp_support + * mask to only those link modes that can be supported. + */ +- ret = phylink_validate_mask(pl, pl->sfp_support, &config, interfaces); ++ ret = phylink_validate_mask(pl, NULL, pl->sfp_support, &config, ++ interfaces); + if (ret) { + phylink_err(pl, "unsupported SFP module: validation with support %*pb failed\n", + __ETHTOOL_LINK_MODE_MASK_NBITS, support); diff --git a/lede/target/linux/generic/backport-6.1/895-06-v6.8-net-phylink-split-out-PHY-validation-from-phylink_br.patch b/lede/target/linux/generic/backport-6.1/895-06-v6.8-net-phylink-split-out-PHY-validation-from-phylink_br.patch new file mode 100644 index 0000000000..d3d24c58fb --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/895-06-v6.8-net-phylink-split-out-PHY-validation-from-phylink_br.patch @@ -0,0 +1,95 @@ +From ee0e0ddb910e7e989b65a19d72b6435baa641fc7 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:34 +0000 +Subject: [PATCH 6/7] net: phylink: split out PHY validation from + phylink_bringup_phy() + +When bringing up a PHY, we need to work out which ethtool link modes it +should support and advertise. Clause 22 PHYs operate in a single +interface mode, which can be easily dealt with. However, clause 45 PHYs +tend to switch interface mode depending on the media. We need more +flexible validation at this point, so this patch splits out that code +in preparation to changing it. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIQ-00DDM9-LK@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 56 ++++++++++++++++++++++----------------- + 1 file changed, 31 insertions(+), 25 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1738,6 +1738,35 @@ static void phylink_phy_change(struct ph + phylink_pause_to_str(pl->phy_state.pause)); + } + ++static int phylink_validate_phy(struct phylink *pl, struct phy_device *phy, ++ unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ /* Check whether we would use rate matching for the proposed interface ++ * mode. ++ */ ++ state->rate_matching = phy_get_rate_matching(phy, state->interface); ++ ++ /* Clause 45 PHYs may switch their Serdes lane between, e.g. 10GBASE-R, ++ * 5GBASE-R, 2500BASE-X and SGMII if they are not using rate matching. ++ * For some interface modes (e.g. RXAUI, XAUI and USXGMII) switching ++ * their Serdes is either unnecessary or not reasonable. ++ * ++ * For these which switch interface modes, we really need to know which ++ * interface modes the PHY supports to properly work out which ethtool ++ * linkmodes can be supported. For now, as a work-around, we validate ++ * against all interface modes, which may lead to more ethtool link ++ * modes being advertised than are actually supported. ++ */ ++ if (phy->is_c45 && state->rate_matching == RATE_MATCH_NONE && ++ state->interface != PHY_INTERFACE_MODE_RXAUI && ++ state->interface != PHY_INTERFACE_MODE_XAUI && ++ state->interface != PHY_INTERFACE_MODE_USXGMII) ++ state->interface = PHY_INTERFACE_MODE_NA; ++ ++ return phylink_validate(pl, supported, state); ++} ++ + static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, + phy_interface_t interface) + { +@@ -1758,32 +1787,9 @@ static int phylink_bringup_phy(struct ph + memset(&config, 0, sizeof(config)); + linkmode_copy(supported, phy->supported); + linkmode_copy(config.advertising, phy->advertising); ++ config.interface = interface; + +- /* Check whether we would use rate matching for the proposed interface +- * mode. +- */ +- config.rate_matching = phy_get_rate_matching(phy, interface); +- +- /* Clause 45 PHYs may switch their Serdes lane between, e.g. 10GBASE-R, +- * 5GBASE-R, 2500BASE-X and SGMII if they are not using rate matching. +- * For some interface modes (e.g. RXAUI, XAUI and USXGMII) switching +- * their Serdes is either unnecessary or not reasonable. +- * +- * For these which switch interface modes, we really need to know which +- * interface modes the PHY supports to properly work out which ethtool +- * linkmodes can be supported. For now, as a work-around, we validate +- * against all interface modes, which may lead to more ethtool link +- * modes being advertised than are actually supported. +- */ +- if (phy->is_c45 && config.rate_matching == RATE_MATCH_NONE && +- interface != PHY_INTERFACE_MODE_RXAUI && +- interface != PHY_INTERFACE_MODE_XAUI && +- interface != PHY_INTERFACE_MODE_USXGMII) +- config.interface = PHY_INTERFACE_MODE_NA; +- else +- config.interface = interface; +- +- ret = phylink_validate(pl, supported, &config); ++ ret = phylink_validate_phy(pl, phy, supported, &config); + if (ret) { + phylink_warn(pl, "validation of %s with support %*pb and advertisement %*pb failed: %pe\n", + phy_modes(config.interface), diff --git a/lede/target/linux/generic/backport-6.1/895-07-v6.8-net-phylink-use-the-PHY-s-possible_interfaces-if-pop.patch b/lede/target/linux/generic/backport-6.1/895-07-v6.8-net-phylink-use-the-PHY-s-possible_interfaces-if-pop.patch new file mode 100644 index 0000000000..201afbb7cf --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/895-07-v6.8-net-phylink-use-the-PHY-s-possible_interfaces-if-pop.patch @@ -0,0 +1,130 @@ +From 8f7a9799c5949f94ecc3acfd71b36437a7ade73b Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:39 +0000 +Subject: [PATCH 7/7] net: phylink: use the PHY's possible_interfaces if + populated + +Some PHYs such as Aquantia, Broadcom 84881, and Marvell 88X33x0 can +switch between a set of interface types depending on the negotiated +media speed, or can use rate adaption for some or all of these +interface types. + +We currently assume that these are Clause 45 PHYs that are configured +not to use a specific set of interface modes, which has worked so far, +but is just a work-around. In this workaround, we validate using all +interfaces that the MAC supports, which can lead to extra modes being +advertised that can not be supported. + +To properly address this, switch to using the newly introduced PHY +possible_interfaces bitmap which indicates which interface modes will +be used by the PHY as configured. We calculate the union of the PHY's +possible interfaces and MACs supported interfaces, checking that is +non-empty. If the PHY is on a SFP, we further reduce the set by those +which can be used on a SFP module, again checking that is non-empty. +Finally, we validate the subset of interfaces, taking account of +whether rate matching will be used for each individual interface mode. + +This becomes independent of whether the PHY is clause 22 or clause 45. + +It is encouraged that all PHYs that switch interface modes or use +rate matching should populate phydev->possible_interfaces. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIV-00DDMF-Pi@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 67 +++++++++++++++++++++++++++++++-------- + 1 file changed, 54 insertions(+), 13 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -121,6 +121,19 @@ do { \ + }) + #endif + ++static const phy_interface_t phylink_sfp_interface_preference[] = { ++ PHY_INTERFACE_MODE_25GBASER, ++ PHY_INTERFACE_MODE_USXGMII, ++ PHY_INTERFACE_MODE_10GBASER, ++ PHY_INTERFACE_MODE_5GBASER, ++ PHY_INTERFACE_MODE_2500BASEX, ++ PHY_INTERFACE_MODE_SGMII, ++ PHY_INTERFACE_MODE_1000BASEX, ++ PHY_INTERFACE_MODE_100BASEX, ++}; ++ ++static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces); ++ + /** + * phylink_set_port_modes() - set the port type modes in the ethtool mask + * @mask: ethtool link mode mask +@@ -1742,6 +1755,47 @@ static int phylink_validate_phy(struct p + unsigned long *supported, + struct phylink_link_state *state) + { ++ DECLARE_PHY_INTERFACE_MASK(interfaces); ++ ++ /* If the PHY provides a bitmap of the interfaces it will be using ++ * depending on the negotiated media speeds, use this to validate ++ * which ethtool link modes can be used. ++ */ ++ if (!phy_interface_empty(phy->possible_interfaces)) { ++ /* We only care about the union of the PHY's interfaces and ++ * those which the host supports. ++ */ ++ phy_interface_and(interfaces, phy->possible_interfaces, ++ pl->config->supported_interfaces); ++ ++ if (phy_interface_empty(interfaces)) { ++ phylink_err(pl, "PHY has no common interfaces\n"); ++ return -EINVAL; ++ } ++ ++ if (phy_on_sfp(phy)) { ++ /* If the PHY is on a SFP, limit the interfaces to ++ * those that can be used with a SFP module. ++ */ ++ phy_interface_and(interfaces, interfaces, ++ phylink_sfp_interfaces); ++ ++ if (phy_interface_empty(interfaces)) { ++ phylink_err(pl, "SFP PHY's possible interfaces becomes empty\n"); ++ return -EINVAL; ++ } ++ } ++ ++ phylink_dbg(pl, "PHY %s uses interfaces %*pbl, validating %*pbl\n", ++ phydev_name(phy), ++ (int)PHY_INTERFACE_MODE_MAX, ++ phy->possible_interfaces, ++ (int)PHY_INTERFACE_MODE_MAX, interfaces); ++ ++ return phylink_validate_mask(pl, phy, supported, state, ++ interfaces); ++ } ++ + /* Check whether we would use rate matching for the proposed interface + * mode. + */ +@@ -2985,19 +3039,6 @@ static void phylink_sfp_detach(void *ups + pl->netdev->sfp_bus = NULL; + } + +-static const phy_interface_t phylink_sfp_interface_preference[] = { +- PHY_INTERFACE_MODE_25GBASER, +- PHY_INTERFACE_MODE_USXGMII, +- PHY_INTERFACE_MODE_10GBASER, +- PHY_INTERFACE_MODE_5GBASER, +- PHY_INTERFACE_MODE_2500BASEX, +- PHY_INTERFACE_MODE_SGMII, +- PHY_INTERFACE_MODE_1000BASEX, +- PHY_INTERFACE_MODE_100BASEX, +-}; +- +-static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces); +- + static phy_interface_t phylink_choose_sfp_interface(struct phylink *pl, + const unsigned long *intf) + { diff --git a/lede/target/linux/generic/backport-6.1/897-01-v6.9-net-phy-qcom-qca808x-add-helper-for-checking-for-1G-.patch b/lede/target/linux/generic/backport-6.1/897-01-v6.9-net-phy-qcom-qca808x-add-helper-for-checking-for-1G-.patch new file mode 100644 index 0000000000..a11e804958 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/897-01-v6.9-net-phy-qcom-qca808x-add-helper-for-checking-for-1G-.patch @@ -0,0 +1,50 @@ +From f058b2dd70b1a5503dff899010aeb53b436091e5 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 28 Feb 2024 18:24:09 +0100 +Subject: [PATCH 1/2] net: phy: qcom: qca808x: add helper for checking for 1G + only model + +There are 2 versions of QCA808x, one 2.5G capable and one 1G capable. +Currently, this matter only in the .get_features call however, it will +be required for filling supported interface modes so lets add a helper +that can be reused. + +Signed-off-by: Robert Marko +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca808x.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -156,6 +156,17 @@ static bool qca808x_has_fast_retrain_or_ + return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); + } + ++static bool qca808x_is_1g_only(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); ++ if (ret < 0) ++ return true; ++ ++ return !!(QCA808X_PHY_CHIP_TYPE_1G & ret); ++} ++ + static int qca808x_probe(struct phy_device *phydev) + { + struct device *dev = &phydev->mdio.dev; +@@ -350,11 +361,7 @@ static int qca808x_get_features(struct p + * existed in the bit0 of MMD1.21, we need to remove it manually if + * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. + */ +- ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); +- if (ret < 0) +- return ret; +- +- if (QCA808X_PHY_CHIP_TYPE_1G & ret) ++ if (qca808x_is_1g_only(phydev)) + linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); + + return 0; diff --git a/lede/target/linux/generic/backport-6.1/897-02-v6.9-net-phy-qcom-qca808x-fill-in-possible_interfaces.patch b/lede/target/linux/generic/backport-6.1/897-02-v6.9-net-phy-qcom-qca808x-fill-in-possible_interfaces.patch new file mode 100644 index 0000000000..c162fc7348 --- /dev/null +++ b/lede/target/linux/generic/backport-6.1/897-02-v6.9-net-phy-qcom-qca808x-fill-in-possible_interfaces.patch @@ -0,0 +1,44 @@ +From cb28f702960695e26597c332b0e46776e825cc34 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 28 Feb 2024 18:24:10 +0100 +Subject: [PATCH 2/2] net: phy: qcom: qca808x: fill in possible_interfaces + +Currently QCA808x driver does not fill the possible_interfaces. +2.5G QCA808x support SGMII and 2500Base-X while 1G model only supports +SGMII, so fill the possible_interfaces accordingly. + +Signed-off-by: Robert Marko +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca808x.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -167,6 +167,16 @@ static bool qca808x_is_1g_only(struct ph + return !!(QCA808X_PHY_CHIP_TYPE_1G & ret); + } + ++static void qca808x_fill_possible_interfaces(struct phy_device *phydev) ++{ ++ unsigned long *possible = phydev->possible_interfaces; ++ ++ __set_bit(PHY_INTERFACE_MODE_SGMII, possible); ++ ++ if (!qca808x_is_1g_only(phydev)) ++ __set_bit(PHY_INTERFACE_MODE_2500BASEX, possible); ++} ++ + static int qca808x_probe(struct phy_device *phydev) + { + struct device *dev = &phydev->mdio.dev; +@@ -231,6 +241,8 @@ static int qca808x_config_init(struct ph + } + } + ++ qca808x_fill_possible_interfaces(phydev); ++ + /* Configure adc threshold as 100mv for the link 10M */ + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, + QCA808X_ADC_THRESHOLD_MASK, diff --git a/lede/target/linux/generic/config-6.1 b/lede/target/linux/generic/config-6.1 index 33bceba08c..70e87665b7 100644 --- a/lede/target/linux/generic/config-6.1 +++ b/lede/target/linux/generic/config-6.1 @@ -157,6 +157,7 @@ CONFIG_AF_UNIX_OOB=y CONFIG_AIO=y # CONFIG_AIRO is not set # CONFIG_AIRO_CS is not set +# CONFIG_AIR_EN8811H_PHY is not set # CONFIG_AIX_PARTITION is not set # CONFIG_AK09911 is not set # CONFIG_AK8974 is not set @@ -730,6 +731,7 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_ZONED is not set # CONFIG_BLK_INLINE_ENCRYPTION is not set +# CONFIG_BLK_NVMEM is not set # CONFIG_BLK_SED_OPAL is not set # CONFIG_BLK_WBT is not set CONFIG_BLOCK=y @@ -2345,6 +2347,7 @@ CONFIG_GPIO_SYSFS=y # CONFIG_GPIO_TPIC2810 is not set # CONFIG_GPIO_TS4900 is not set # CONFIG_GPIO_TS5500 is not set +# CONFIG_GPIO_VF610 is not set # CONFIG_GPIO_VIRTIO is not set # CONFIG_GPIO_VX855 is not set # CONFIG_GPIO_WATCHDOG is not set @@ -4039,6 +4042,7 @@ CONFIG_MTD_SPLIT_SUPPORT=y # CONFIG_MTD_UBI is not set # CONFIG_MTD_UBI_FASTMAP is not set # CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UBI_NVMEM is not set # CONFIG_MTD_UIMAGE_SPLIT is not set # CONFIG_MTD_VIRT_CONCAT is not set # CONFIG_MTK_DEVAPC is not set @@ -5078,6 +5082,9 @@ CONFIG_PWRSEQ_SIMPLE=y # CONFIG_QCA7000 is not set # CONFIG_QCA7000_SPI is not set # CONFIG_QCA7000_UART is not set +# CONFIG_QCA807X_PHY is not set +# CONFIG_QCA808X_PHY is not set +# CONFIG_QCA83XX_PHY is not set # CONFIG_QCOM_A7PLL is not set # CONFIG_QCOM_BAM_DMUX is not set # CONFIG_QCOM_EMAC is not set @@ -5954,7 +5961,6 @@ CONFIG_SERIAL_EARLYCON=y # CONFIG_SG_SPLIT is not set # CONFIG_SHADOW_CALL_STACK is not set CONFIG_SHMEM=y -# CONFIG_SHORTCUT_FE is not set # CONFIG_SHRINKER_DEBUG is not set # CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set # CONFIG_SH_ETH is not set @@ -6730,6 +6736,8 @@ CONFIG_TCP_CONG_CUBIC=y # CONFIG_TCS3414 is not set # CONFIG_TCS3472 is not set # CONFIG_TEE is not set +# CONFIG_TEGRA210_ADMA is not set +# CONFIG_TEGRA_ACONNECT is not set # CONFIG_TEGRA_AHB is not set # CONFIG_TEGRA_HOST1X is not set # CONFIG_TEHUTI is not set @@ -7813,15 +7821,15 @@ CONFIG_WATCHDOG_OPEN_TIMEOUT=0 # CONFIG_WDAT_WDT is not set # CONFIG_WDTPCI is not set # CONFIG_WERROR is not set -CONFIG_WEXT_CORE=y -CONFIG_WEXT_PRIV=y -CONFIG_WEXT_PROC=y -CONFIG_WEXT_SPY=y +# CONFIG_WEXT_CORE is not set +# CONFIG_WEXT_PRIV is not set +# CONFIG_WEXT_PROC is not set +# CONFIG_WEXT_SPY is not set CONFIG_WILINK_PLATFORM_DATA=y # CONFIG_WIMAX is not set # CONFIG_WIREGUARD is not set CONFIG_WIRELESS=y -CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_EXT is not set # CONFIG_WIRELESS_WDS is not set # CONFIG_WIZNET_W5100 is not set # CONFIG_WIZNET_W5300 is not set diff --git a/lede/target/linux/generic/config-6.6 b/lede/target/linux/generic/config-6.6 index 6ae27dbadd..20fe98099f 100644 --- a/lede/target/linux/generic/config-6.6 +++ b/lede/target/linux/generic/config-6.6 @@ -1,13 +1,11 @@ # CONFIG_104_QUAD_8 is not set CONFIG_32BIT=y -CONFIG_64BIT_TIME=y # CONFIG_6LOWPAN is not set # CONFIG_6LOWPAN_DEBUGFS is not set # CONFIG_6PACK is not set # CONFIG_8139CP is not set # CONFIG_8139TOO is not set # CONFIG_9P_FS is not set -# CONFIG_AB3100_CORE is not set # CONFIG_AB8500_CORE is not set # CONFIG_ABP060MG is not set # CONFIG_ABX500_CORE is not set @@ -60,7 +58,6 @@ CONFIG_64BIT_TIME=y # CONFIG_AD7091R5 is not set # CONFIG_AD7124 is not set # CONFIG_AD7150 is not set -# CONFIG_AD7152 is not set # CONFIG_AD7192 is not set # CONFIG_AD7266 is not set # CONFIG_AD7280 is not set @@ -94,7 +91,6 @@ CONFIG_64BIT_TIME=y # CONFIG_AD9834 is not set # CONFIG_ADA4250 is not set # CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_ADE7854 is not set # CONFIG_ADF4350 is not set # CONFIG_ADF4371 is not set # CONFIG_ADF4377 is not set @@ -161,6 +157,7 @@ CONFIG_AF_UNIX_OOB=y CONFIG_AIO=y # CONFIG_AIRO is not set # CONFIG_AIRO_CS is not set +# CONFIG_AIR_EN8811H_PHY is not set # CONFIG_AIX_PARTITION is not set # CONFIG_AK09911 is not set # CONFIG_AK8974 is not set @@ -187,9 +184,7 @@ CONFIG_ALLOW_DEV_COREDUMP=y # CONFIG_AMILO_RFKILL is not set # CONFIG_AMPERE_ERRATUM_AC03_CPU_38 is not set # CONFIG_AMT is not set -# CONFIG_ANDROID is not set # CONFIG_ANDROID_BINDER_IPC is not set -CONFIG_ANON_INODES=y # CONFIG_ANON_VMA_NAME is not set # CONFIG_APDS9300 is not set # CONFIG_APDS9802ALS is not set @@ -207,7 +202,6 @@ CONFIG_ANON_INODES=y # CONFIG_AR8216_PHY is not set # CONFIG_AR8216_PHY_LEDS is not set # CONFIG_ARCH_ACTIONS is not set -# CONFIG_ARCH_AGILEX is not set # CONFIG_ARCH_AIROHA is not set # CONFIG_ARCH_ALPINE is not set # CONFIG_ARCH_APPLE is not set @@ -217,14 +211,12 @@ CONFIG_ANON_INODES=y # CONFIG_ARCH_AXXIA is not set # CONFIG_ARCH_BCM is not set # CONFIG_ARCH_BCM2835 is not set -# CONFIG_ARCH_BCM4908 is not set # CONFIG_ARCH_BCMBCA is not set # CONFIG_ARCH_BCM_21664 is not set # CONFIG_ARCH_BCM_23550 is not set # CONFIG_ARCH_BCM_281XX is not set # CONFIG_ARCH_BCM_5301X is not set # CONFIG_ARCH_BCM_53573 is not set -# CONFIG_ARCH_BCM_63XX is not set # CONFIG_ARCH_BCM_CYGNUS is not set # CONFIG_ARCH_BCM_HR2 is not set # CONFIG_ARCH_BCM_IPROC is not set @@ -234,12 +226,10 @@ CONFIG_ARCH_BINFMT_ELF_STATE=y # CONFIG_ARCH_BITMAIN is not set # CONFIG_ARCH_BRCMSTB is not set # CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CNS3XXX is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_DIGICOLOR is not set # CONFIG_ARCH_DMA_ADDR_T_64BIT is not set # CONFIG_ARCH_DOVE is not set -# CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_EXYNOS is not set CONFIG_ARCH_FLATMEM_ENABLE=y @@ -252,14 +242,10 @@ CONFIG_ARCH_FORCE_MAX_ORDER=11 # CONFIG_ARCH_HPE is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_INTEL_SOCFPGA is not set -# CONFIG_ARCH_IOP13XX is not set -# CONFIG_ARCH_IOP32X is not set -# CONFIG_ARCH_IOP33X is not set # CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_K3 is not set # CONFIG_ARCH_KEEMBAY is not set # CONFIG_ARCH_KEYSTONE is not set -# CONFIG_ARCH_KS8695 is not set # CONFIG_ARCH_LAYERSCAPE is not set # CONFIG_ARCH_LG1K is not set # CONFIG_ARCH_LPC32XX is not set @@ -282,7 +268,6 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARCH_MXC is not set # CONFIG_ARCH_MXS is not set # CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set -# CONFIG_ARCH_NETX is not set # CONFIG_ARCH_NOMADIK is not set # CONFIG_ARCH_NPCM is not set # CONFIG_ARCH_NSPIRE is not set @@ -294,12 +279,8 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARCH_OMAP3 is not set # CONFIG_ARCH_OMAP4 is not set # CONFIG_ARCH_ORION5X is not set -# CONFIG_ARCH_OXNAS is not set -# CONFIG_ARCH_PICOXCELL is not set -# CONFIG_ARCH_PRIMA2 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_QCOM is not set -# CONFIG_ARCH_RANDOM is not set # CONFIG_ARCH_RDA is not set # CONFIG_ARCH_REALTEK is not set # CONFIG_ARCH_REALVIEW is not set @@ -307,27 +288,21 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARCH_ROCKCHIP is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_S32 is not set -# CONFIG_ARCH_S3C24XX is not set # CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_S5PV210 is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_SEATTLE is not set # CONFIG_ARCH_SHMOBILE is not set -# CONFIG_ARCH_SIRF is not set -# CONFIG_ARCH_SOCFPGA is not set # CONFIG_ARCH_SPARX5 is not set # CONFIG_ARCH_SPRD is not set # CONFIG_ARCH_STI is not set # CONFIG_ARCH_STM32 is not set -# CONFIG_ARCH_STRATIX10 is not set # CONFIG_ARCH_SUNPLUS is not set # CONFIG_ARCH_SUNXI is not set # CONFIG_ARCH_SYNQUACER is not set -# CONFIG_ARCH_TANGO is not set # CONFIG_ARCH_TEGRA is not set # CONFIG_ARCH_THUNDER is not set # CONFIG_ARCH_THUNDER2 is not set -# CONFIG_ARCH_U300 is not set # CONFIG_ARCH_U8500 is not set # CONFIG_ARCH_UNIPHIER is not set # CONFIG_ARCH_VERSATILE is not set @@ -335,14 +310,11 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARCH_VIRT is not set # CONFIG_ARCH_VISCONTI is not set # CONFIG_ARCH_VT8500 is not set -# CONFIG_ARCH_VULCAN is not set -# CONFIG_ARCH_W90X900 is not set # CONFIG_ARCH_WANTS_THP_SWAP is not set # CONFIG_ARCH_WM8505 is not set # CONFIG_ARCH_WM8750 is not set # CONFIG_ARCH_WM8850 is not set # CONFIG_ARCH_XGENE is not set -# CONFIG_ARCH_ZX is not set # CONFIG_ARCH_ZYNQ is not set # CONFIG_ARCH_ZYNQMP is not set # CONFIG_ARCNET is not set @@ -352,7 +324,6 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARM64_64K_PAGES is not set # CONFIG_ARM64_AMU_EXTN is not set # CONFIG_ARM64_BTI is not set -# CONFIG_ARM64_CRYPTO is not set # CONFIG_ARM64_E0PD is not set # CONFIG_ARM64_ERRATUM_1024718 is not set # CONFIG_ARM64_ERRATUM_1165522 is not set @@ -385,37 +356,31 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARM64_ERRATUM_858921 is not set # CONFIG_ARM64_HW_AFDBM is not set # CONFIG_ARM64_LSE_ATOMICS is not set -CONFIG_ARM64_MODULE_PLTS=y # CONFIG_ARM64_MTE is not set # CONFIG_ARM64_PAN is not set # CONFIG_ARM64_PMEM is not set # CONFIG_ARM64_PSEUDO_NMI is not set -# CONFIG_ARM64_PTDUMP_DEBUGFS is not set # CONFIG_ARM64_PTR_AUTH is not set -# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set # CONFIG_ARM64_RAS_EXTN is not set # CONFIG_ARM64_RELOC_TEST is not set # CONFIG_ARM64_SME is not set # CONFIG_ARM64_SVE is not set CONFIG_ARM64_SW_TTBR0_PAN=y # CONFIG_ARM64_TLB_RANGE is not set -# CONFIG_ARM64_UAO is not set # CONFIG_ARM64_USE_LSE_ATOMICS is not set # CONFIG_ARM64_VA_BITS_48 is not set -# CONFIG_ARM64_VHE is not set # CONFIG_ARM_APPENDED_DTB is not set # CONFIG_ARM_ARCH_TIMER is not set # CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set -# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set # CONFIG_ARM_CCI is not set # CONFIG_ARM_CCI400_PMU is not set # CONFIG_ARM_CCI5xx_PMU is not set # CONFIG_ARM_CCI_PMU is not set # CONFIG_ARM_CCN is not set # CONFIG_ARM_CMN is not set +# CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU is not set # CONFIG_ARM_CPUIDLE is not set CONFIG_ARM_CPU_TOPOLOGY=y -# CONFIG_ARM_CRYPTO is not set CONFIG_ARM_DMA_MEM_BUFFERABLE=y # CONFIG_ARM_DSU_PMU is not set # CONFIG_ARM_ERRATA_326103 is not set @@ -464,6 +429,7 @@ CONFIG_ARM_MODULE_PLTS=y # CONFIG_ARM_SDE_INTERFACE is not set # CONFIG_ARM_SMCCC_SOC_ID is not set # CONFIG_ARM_SMC_WATCHDOG is not set +# CONFIG_ARM_SMMU_V3_PMU is not set # CONFIG_ARM_SP805_WATCHDOG is not set # CONFIG_ARM_SPE_PMU is not set # CONFIG_ARM_THUMBEE is not set @@ -516,7 +482,6 @@ CONFIG_ATA_SFF=y # CONFIG_ATMEL is not set # CONFIG_ATMEL_PIT is not set # CONFIG_ATMEL_SSC is not set -# CONFIG_ATM_AMBASSADOR is not set # CONFIG_ATM_BR2684 is not set CONFIG_ATM_BR2684_IPFILTER=y # CONFIG_ATM_CLIP is not set @@ -524,10 +489,8 @@ CONFIG_ATM_CLIP_NO_ICMP=y # CONFIG_ATM_DRIVERS is not set # CONFIG_ATM_DUMMY is not set # CONFIG_ATM_ENI is not set -# CONFIG_ATM_FIRESTREAM is not set # CONFIG_ATM_FORE200E is not set # CONFIG_ATM_HE is not set -# CONFIG_ATM_HORIZON is not set # CONFIG_ATM_IA is not set # CONFIG_ATM_IDT77252 is not set # CONFIG_ATM_LANAI is not set @@ -536,13 +499,10 @@ CONFIG_ATM_CLIP_NO_ICMP=y # CONFIG_ATM_NICSTAR is not set # CONFIG_ATM_SOLOS is not set # CONFIG_ATM_TCP is not set -# CONFIG_ATM_ZATM is not set # CONFIG_ATOMIC64_SELFTEST is not set # CONFIG_ATP is not set # CONFIG_AUDIT is not set # CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set -# CONFIG_AURORA_NB8800 is not set -# CONFIG_AUTOFS4_FS is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTO_ZRELADDR is not set # CONFIG_AUXDISPLAY is not set @@ -569,21 +529,17 @@ CONFIG_ATM_CLIP_NO_ICMP=y # CONFIG_BACKLIGHT_ARCXCNN is not set # CONFIG_BACKLIGHT_BD6107 is not set # CONFIG_BACKLIGHT_CLASS_DEVICE is not set -# CONFIG_BACKLIGHT_GENERIC is not set # CONFIG_BACKLIGHT_GPIO is not set # CONFIG_BACKLIGHT_KTD253 is not set # CONFIG_BACKLIGHT_KTZ8866 is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # CONFIG_BACKLIGHT_LED is not set # CONFIG_BACKLIGHT_LM3630A is not set # CONFIG_BACKLIGHT_LM3639 is not set # CONFIG_BACKLIGHT_LP855X is not set # CONFIG_BACKLIGHT_LV5207LP is not set # CONFIG_BACKLIGHT_PANDORA is not set -# CONFIG_BACKLIGHT_PM8941_WLED is not set # CONFIG_BACKLIGHT_PWM is not set # CONFIG_BACKLIGHT_QCOM_WLED is not set -# CONFIG_BACKLIGHT_RPI is not set # CONFIG_BACKLIGHT_SAHARA is not set # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_BACKTRACE_VERBOSE is not set @@ -613,7 +569,6 @@ CONFIG_BASE_SMALL=0 # CONFIG_BAYCOM_SER_FDX is not set # CONFIG_BAYCOM_SER_HDX is not set # CONFIG_BCACHE is not set -# CONFIG_BCM2712_MIP is not set # CONFIG_BCM47XX is not set # CONFIG_BCM54140_PHY is not set # CONFIG_BCM63XX is not set @@ -643,7 +598,6 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_BIG_KEYS is not set # CONFIG_BIG_LITTLE is not set CONFIG_BINARY_PRINTF=y -# CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_ELF_FDPIC is not set # CONFIG_BINFMT_FLAT is not set @@ -653,92 +607,35 @@ CONFIG_BITREVERSE=y # CONFIG_BLK_CGROUP_IOCOST is not set # CONFIG_BLK_CGROUP_IOLATENCY is not set # CONFIG_BLK_CGROUP_IOPRIO is not set -# CONFIG_BLK_CMDLINE_PARSER is not set # CONFIG_BLK_DEBUG_FS is not set CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_BLK_DEV_4DRIVES is not set -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_BLK_DEV_ALI14XX is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_BLK_DEV_ATIIXP is not set # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_BSGLIB is not set -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD64X is not set # CONFIG_BLK_DEV_COW_COMMON is not set -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_CS5520 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_CS5535 is not set -# CONFIG_BLK_DEV_CS5536 is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_DELKIN is not set # CONFIG_BLK_DEV_DM is not set # CONFIG_BLK_DEV_DRBD is not set -# CONFIG_BLK_DEV_DTC2278 is not set # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_GENERIC is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_HT6560B is not set -# CONFIG_BLK_DEV_IDEACPI is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDECS is not set -# CONFIG_BLK_DEV_IDEPCI is not set -# CONFIG_BLK_DEV_IDEPNP is not set -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDE_AU1XXX is not set -# CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_INITRD=y # CONFIG_BLK_DEV_INTEGRITY is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_BLK_DEV_IT8172 is not set -# CONFIG_BLK_DEV_IT8213 is not set -# CONFIG_BLK_DEV_IT821X is not set -# CONFIG_BLK_DEV_JMICRON is not set # CONFIG_BLK_DEV_LOOP is not set CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # CONFIG_BLK_DEV_MD is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_NULL_BLK is not set # CONFIG_BLK_DEV_NVME is not set -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_BLK_DEV_PIIX is not set -# CONFIG_BLK_DEV_PLATFORM is not set # CONFIG_BLK_DEV_PMEM is not set -# CONFIG_BLK_DEV_QD65XX is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_RBD is not set -# CONFIG_BLK_DEV_RSXX is not set -# CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_SC1200 is not set # CONFIG_BLK_DEV_SD is not set -# CONFIG_BLK_DEV_SIIMAGE is not set -# CONFIG_BLK_DEV_SIS5513 is not set -# CONFIG_BLK_DEV_SKD is not set -# CONFIG_BLK_DEV_SL82C105 is not set -# CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_SR is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SX8 is not set -# CONFIG_BLK_DEV_TC86C001 is not set # CONFIG_BLK_DEV_THROTTLING is not set -# CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_UBLK is not set -# CONFIG_BLK_DEV_UMC8672 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_ZONED is not set # CONFIG_BLK_INLINE_ENCRYPTION is not set -# CONFIG_BLK_NVMEM is not set +# CONFIG_BLOCK_NOTIFIERS is not set # CONFIG_BLK_SED_OPAL is not set # CONFIG_BLK_WBT is not set CONFIG_BLOCK=y @@ -864,7 +761,6 @@ CONFIG_BT_HCIUART_H4=y # CONFIG_BT_HCIUART_RTL is not set # CONFIG_BT_HCIVHCI is not set # CONFIG_BT_HIDP is not set -# CONFIG_BT_HS is not set # CONFIG_BT_LE is not set # CONFIG_BT_LEDS is not set CONFIG_BT_LE_L2CAP_ECRED=y @@ -879,9 +775,7 @@ CONFIG_BT_RFCOMM_TTY=y # CONFIG_BT_VIRTIO is not set CONFIG_BUG=y # CONFIG_BUG_ON_DATA_CORRUPTION is not set -CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_BUILDTIME_TABLE_SORT=y -# CONFIG_BUILD_BIN2C is not set CONFIG_BUILD_SALT="" # CONFIG_C2PORT is not set # CONFIG_CACHESTAT_SYSCALL is not set @@ -918,12 +812,8 @@ CONFIG_CACHE_L2X0_PMU=y # CONFIG_CAN_UCAN is not set # CONFIG_CAN_VCAN is not set # CONFIG_CAN_VXCAN is not set -# CONFIG_CAPI_AVM is not set -# CONFIG_CAPI_EICON is not set # CONFIG_CAPI_TRACE is not set CONFIG_CARDBUS=y -# CONFIG_CARDMAN_4000 is not set -# CONFIG_CARDMAN_4040 is not set # CONFIG_CARL9170 is not set # CONFIG_CASSINI is not set # CONFIG_CAVIUM_CPT is not set @@ -966,7 +856,6 @@ CONFIG_CFG80211_HEADERS=y # CONFIG_CHARGER_ISP1704 is not set # CONFIG_CHARGER_LP8727 is not set # CONFIG_CHARGER_LT3651 is not set -# CONFIG_CHARGER_LTC3651 is not set # CONFIG_CHARGER_LTC4162L is not set # CONFIG_CHARGER_MANAGER is not set # CONFIG_CHARGER_MAX77976 is not set @@ -980,35 +869,27 @@ CONFIG_CFG80211_HEADERS=y # CONFIG_CHARGER_SMB347 is not set # CONFIG_CHARGER_TWL4030 is not set # CONFIG_CHARGER_UCS1002 is not set -# CONFIG_CHASH_SELFTEST is not set -# CONFIG_CHASH_STATS is not set # CONFIG_CHECKPOINT_RESTORE is not set # CONFIG_CHELSIO_T1 is not set # CONFIG_CHELSIO_T3 is not set # CONFIG_CHELSIO_T4 is not set # CONFIG_CHELSIO_T4VF is not set # CONFIG_CHROME_PLATFORMS is not set -# CONFIG_CHR_DEV_OSST is not set # CONFIG_CHR_DEV_SCH is not set # CONFIG_CHR_DEV_SG is not set # CONFIG_CHR_DEV_ST is not set # CONFIG_CICADA_PHY is not set # CONFIG_CIFS is not set -# CONFIG_CIFS_ACL is not set CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y # CONFIG_CIFS_DEBUG is not set # CONFIG_CIFS_DEBUG2 is not set # CONFIG_CIFS_FSCACHE is not set # CONFIG_CIFS_NFSD_EXPORT is not set CONFIG_CIFS_POSIX=y -# CONFIG_CIFS_SMB2 is not set -# CONFIG_CIFS_STATS is not set # CONFIG_CIFS_STATS2 is not set # CONFIG_CIFS_SWN_UPCALL is not set -# CONFIG_CIFS_WEAK_PW_HASH is not set CONFIG_CIFS_XATTR=y # CONFIG_CIO_DAC is not set -# CONFIG_CLEANCACHE is not set # CONFIG_CLKSRC_PISTACHIO is not set # CONFIG_CLKSRC_VERSATILE is not set # CONFIG_CLK_GFM_LPASS_SM8250 is not set @@ -1016,7 +897,6 @@ CONFIG_CIFS_XATTR=y # CONFIG_CLK_ICST is not set # CONFIG_CLK_QORIQ is not set # CONFIG_CLK_SP810 is not set -# CONFIG_CLOCK_THERMAL is not set CONFIG_CLS_U32_MARK=y # CONFIG_CLS_U32_PERF is not set # CONFIG_CM32181 is not set @@ -1059,8 +939,6 @@ CONFIG_CMDLINE="" # CONFIG_COMMON_CLK_PWM is not set # CONFIG_COMMON_CLK_PXA is not set # CONFIG_COMMON_CLK_QCOM is not set -# CONFIG_COMMON_CLK_RP1 is not set -# CONFIG_COMMON_CLK_RP1_SDIO is not set # CONFIG_COMMON_CLK_RS9_PCIE is not set # CONFIG_COMMON_CLK_SI514 is not set # CONFIG_COMMON_CLK_SI521XX is not set @@ -1104,7 +982,6 @@ CONFIG_CONSTRUCTORS=y # CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set # CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set -# CONFIG_CPU_FREQ_STAT_DETAILS is not set # CONFIG_CPU_FREQ_THERMAL is not set # CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set # CONFIG_CPU_ICACHE_DISABLE is not set @@ -1138,7 +1015,7 @@ CONFIG_CRC32_SARWATE=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC_ITU_T is not set # CONFIG_CRC_T10DIF is not set -CONFIG_CROSS_COMPILE="" +# CONFIG_CROS_HPS_I2C is not set # CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_CRYPTO=y # CONFIG_CRYPTO_842 is not set @@ -1147,13 +1024,8 @@ CONFIG_CRYPTO_ACOMP2=y CONFIG_CRYPTO_AEAD=y CONFIG_CRYPTO_AEAD2=y # CONFIG_CRYPTO_AEGIS128 is not set -# CONFIG_CRYPTO_AEGIS128L is not set -# CONFIG_CRYPTO_AEGIS128L_AESNI_SSE2 is not set # CONFIG_CRYPTO_AEGIS128_AESNI_SSE2 is not set -# CONFIG_CRYPTO_AEGIS256 is not set -# CONFIG_CRYPTO_AEGIS256_AESNI_SSE2 is not set CONFIG_CRYPTO_AES=y -# CONFIG_CRYPTO_AES_586 is not set # CONFIG_CRYPTO_AES_ARM is not set # CONFIG_CRYPTO_AES_ARM64 is not set # CONFIG_CRYPTO_AES_ARM64_BS is not set @@ -1219,14 +1091,14 @@ CONFIG_CRYPTO_CTR=y # CONFIG_CRYPTO_DEV_CCREE is not set # CONFIG_CRYPTO_DEV_FSL_CAAM is not set # CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC is not set +# CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG is not set +# CONFIG_CRYPTO_DEV_FSL_CAAM_INTC is not set +# CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST is not set # CONFIG_CRYPTO_DEV_HIFN_795X is not set # CONFIG_CRYPTO_DEV_HISI_SEC is not set # CONFIG_CRYPTO_DEV_HISI_ZIP is not set # CONFIG_CRYPTO_DEV_IMGTEC_HASH is not set # CONFIG_CRYPTO_DEV_MARVELL_CESA is not set -# CONFIG_CRYPTO_DEV_MEDIATEK is not set -# CONFIG_CRYPTO_DEV_MV_CESA is not set -# CONFIG_CRYPTO_DEV_MXC_SCC is not set # CONFIG_CRYPTO_DEV_MXS_DCP is not set # CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set # CONFIG_CRYPTO_DEV_OCTEONTX_CPT is not set @@ -1257,7 +1129,6 @@ CONFIG_CRYPTO_CTR=y # CONFIG_CRYPTO_FCRYPT is not set # CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_GCM=y -CONFIG_CRYPTO_GF128MUL=y CONFIG_CRYPTO_GHASH=y # CONFIG_CRYPTO_GHASH_ARM64_CE is not set # CONFIG_CRYPTO_GHASH_ARM_CE is not set @@ -1288,22 +1159,14 @@ CONFIG_CRYPTO_LIB_POLY1305_RSIZE=9 CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_MANAGER2=y CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y -# CONFIG_CRYPTO_MCRYPTD is not set # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_MORUS1280 is not set -# CONFIG_CRYPTO_MORUS1280_AVX2 is not set -# CONFIG_CRYPTO_MORUS1280_SSE2 is not set -# CONFIG_CRYPTO_MORUS640 is not set -# CONFIG_CRYPTO_MORUS640_SSE2 is not set # CONFIG_CRYPTO_NHPOLY1305_NEON is not set CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_NULL2=y # CONFIG_CRYPTO_OFB is not set # CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_PCOMP is not set -# CONFIG_CRYPTO_PCOMP2 is not set CONFIG_CRYPTO_PCRYPT=y # CONFIG_CRYPTO_POLY1305 is not set # CONFIG_CRYPTO_POLY1305_ARM is not set @@ -1348,7 +1211,6 @@ CONFIG_CRYPTO_SKCIPHER2=y # CONFIG_CRYPTO_SM4_ARM64_CE_GCM is not set # CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set # CONFIG_CRYPTO_SM4_GENERIC is not set -# CONFIG_CRYPTO_SPECK is not set # CONFIG_CRYPTO_STATS is not set # CONFIG_CRYPTO_STREEBOG is not set # CONFIG_CRYPTO_TEA is not set @@ -1368,7 +1230,6 @@ CONFIG_CRYPTO_SKCIPHER2=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_XTS is not set # CONFIG_CRYPTO_XXHASH is not set -# CONFIG_CRYPTO_ZLIB is not set # CONFIG_CRYPTO_ZSTD is not set # CONFIG_CS5535_MFGPT is not set # CONFIG_CS89x0 is not set @@ -1377,12 +1238,8 @@ CONFIG_CRYPTO_SKCIPHER2=y # CONFIG_CUSE is not set # CONFIG_CW1200 is not set # CONFIG_CXD2880_SPI_DRV is not set -# CONFIG_CXL_AFU_DRIVER_OPS is not set # CONFIG_CXL_BASE is not set # CONFIG_CXL_BUS is not set -# CONFIG_CXL_EEH is not set -# CONFIG_CXL_KERNEL_API is not set -# CONFIG_CXL_LIB is not set # CONFIG_CYPRESS_FIRMWARE is not set # CONFIG_DA280 is not set # CONFIG_DA311 is not set @@ -1393,14 +1250,11 @@ CONFIG_CRYPTO_SKCIPHER2=y # CONFIG_DDR is not set # CONFIG_DEBUG_ALIGN_RODATA is not set # CONFIG_DEBUG_ATOMIC_SLEEP is not set -# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_DEBUG_CGROUP_REF is not set -# CONFIG_DEBUG_CREDENTIALS is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_EFI is not set -# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_32B is not set # CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set CONFIG_DEBUG_FS=y @@ -1440,14 +1294,12 @@ CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_NET is not set # CONFIG_DEBUG_NOTIFIERS is not set -# CONFIG_DEBUG_NX_TEST is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_PAGEALLOC is not set # CONFIG_DEBUG_PAGE_REF is not set # CONFIG_DEBUG_PERF_USE_VMALLOC is not set # CONFIG_DEBUG_PER_CPU_MAPS is not set # CONFIG_DEBUG_PINCTRL is not set -# CONFIG_DEBUG_PI_LIST is not set # CONFIG_DEBUG_PLIST is not set # CONFIG_DEBUG_PREEMPT is not set # CONFIG_DEBUG_RODATA_TEST is not set @@ -1462,12 +1314,10 @@ CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set # CONFIG_DEBUG_TIMEKEEPING is not set # CONFIG_DEBUG_UART_8250_PALMCHIP is not set # CONFIG_DEBUG_UART_8250_WORD is not set -# CONFIG_DEBUG_UART_BCM63XX is not set # CONFIG_DEBUG_UART_FLOW_CONTROL is not set # CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_VIRTUAL is not set @@ -1476,15 +1326,12 @@ CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_VM_PGFLAGS is not set # CONFIG_DEBUG_VM_PGTABLE is not set # CONFIG_DEBUG_VM_RB is not set -# CONFIG_DEBUG_VM_VMACACHE is not set # CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set # CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set # CONFIG_DEBUG_WX is not set # CONFIG_DEBUG_ZBOOT is not set -# CONFIG_DECNET is not set # CONFIG_DEFAULT_CODEL is not set CONFIG_DEFAULT_CUBIC=y -CONFIG_DEFAULT_DEADLINE=y # CONFIG_DEFAULT_FQ is not set CONFIG_DEFAULT_FQ_CODEL=y # CONFIG_DEFAULT_FQ_PIE is not set @@ -1493,15 +1340,12 @@ CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 CONFIG_DEFAULT_INIT="" CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_DEFAULT_NET_SCH="fq_codel" -# CONFIG_DEFAULT_NOOP is not set # CONFIG_DEFAULT_PFIFO_FAST is not set # CONFIG_DEFAULT_RENO is not set -CONFIG_DEFAULT_SECURITY="" CONFIG_DEFAULT_SECURITY_DAC=y # CONFIG_DEFAULT_SECURITY_SELINUX is not set # CONFIG_DEFAULT_SFQ is not set CONFIG_DEFAULT_TCP_CONG="cubic" -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set # CONFIG_DELL_LAPTOP is not set # CONFIG_DELL_RBTN is not set @@ -1509,27 +1353,13 @@ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # CONFIG_DELL_SMO8800 is not set # CONFIG_DEPRECATED_PARAM_STRUCT is not set # CONFIG_DETECT_HUNG_TASK is not set -# CONFIG_DEVKMEM is not set # CONFIG_DEVMEM is not set CONFIG_DEVPORT=y -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_DEVTMPFS is not set # CONFIG_DEVTMPFS_MOUNT is not set # CONFIG_DEVTMPFS_SAFE is not set # CONFIG_DEV_DAX is not set -# CONFIG_DGAP is not set -# CONFIG_DGNC is not set # CONFIG_DHT11 is not set -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_DISPLAY_CONNECTOR_ANALOG_TV is not set -# CONFIG_DISPLAY_CONNECTOR_DVI is not set -# CONFIG_DISPLAY_CONNECTOR_HDMI is not set -# CONFIG_DISPLAY_ENCODER_TFP410 is not set -# CONFIG_DISPLAY_ENCODER_TPD12S015 is not set -# CONFIG_DISPLAY_PANEL_DPI is not set -# CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02 is not set -# CONFIG_DISPLAY_PANEL_TPO_TD028TTEC1 is not set -# CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1 is not set # CONFIG_DL2K is not set # CONFIG_DLHL60D is not set # CONFIG_DLM is not set @@ -1546,7 +1376,6 @@ CONFIG_DEVPORT=y # CONFIG_DMARD06 is not set # CONFIG_DMARD09 is not set # CONFIG_DMARD10 is not set -# CONFIG_DMASCC is not set # CONFIG_DMATEST is not set # CONFIG_DMA_API_DEBUG is not set CONFIG_DMA_COHERENT_POOL=y @@ -1556,11 +1385,8 @@ CONFIG_DMA_DECLARE_COHERENT=y # CONFIG_DMA_JZ4780 is not set # CONFIG_DMA_MAP_BENCHMARK is not set CONFIG_DMA_NONCOHERENT_MMAP=y -# CONFIG_DMA_NOOP_OPS is not set -# CONFIG_DMA_PERNUMA_CMA is not set # CONFIG_DMA_RESTRICTED_POOL is not set # CONFIG_DMA_SHARED_BUFFER is not set -# CONFIG_DMA_VIRT_OPS is not set # CONFIG_DM_CACHE is not set # CONFIG_DM_CLONE is not set # CONFIG_DM_DEBUG is not set @@ -1572,7 +1398,6 @@ CONFIG_DMA_NONCOHERENT_MMAP=y # CONFIG_DM_INTEGRITY is not set # CONFIG_DM_LOG_USERSPACE is not set # CONFIG_DM_LOG_WRITES is not set -# CONFIG_DM_MQ_DEFAULT is not set # CONFIG_DM_MULTIPATH is not set # CONFIG_DM_RAID is not set # CONFIG_DM_SWITCH is not set @@ -1586,7 +1411,6 @@ CONFIG_DMA_NONCOHERENT_MMAP=y # CONFIG_DNET is not set # CONFIG_DNOTIFY is not set # CONFIG_DNS_RESOLVER is not set -CONFIG_DOUBLEFAULT=y # CONFIG_DP83640_PHY is not set # CONFIG_DP83822_PHY is not set # CONFIG_DP83848_PHY is not set @@ -1603,14 +1427,10 @@ CONFIG_DQL=y # CONFIG_DRM_ACCEL is not set # CONFIG_DRM_AMDGPU is not set # CONFIG_DRM_AMDGPU_CIK is not set -# CONFIG_DRM_AMDGPU_GART_DEBUGFS is not set # CONFIG_DRM_AMDGPU_SI is not set # CONFIG_DRM_AMDGPU_USERPTR is not set # CONFIG_DRM_AMDGPU_WERROR is not set # CONFIG_DRM_AMD_ACP is not set -# CONFIG_DRM_AMD_DC_DCN2_0 is not set -# CONFIG_DRM_AMD_DC_DCN3_0 is not set -# CONFIG_DRM_AMD_DC_HDCP is not set # CONFIG_DRM_AMD_DC_SI is not set # CONFIG_DRM_AMD_SECURE_DISPLAY is not set # CONFIG_DRM_ANALOGIX_ANX6345 is not set @@ -1629,11 +1449,9 @@ CONFIG_DQL=y # CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set # CONFIG_DRM_DEBUG_MM is not set # CONFIG_DRM_DEBUG_MODESET_LOCK is not set -# CONFIG_DRM_DEBUG_SELFTEST is not set # CONFIG_DRM_DISPLAY_CONNECTOR is not set # CONFIG_DRM_DP_AUX_CHARDEV is not set # CONFIG_DRM_DP_CEC is not set -# CONFIG_DRM_DUMB_VGA_DAC is not set # CONFIG_DRM_DW_HDMI_CEC is not set # CONFIG_DRM_ETNAVIV is not set # CONFIG_DRM_EXYNOS is not set @@ -1667,7 +1485,6 @@ CONFIG_DQL=y # CONFIG_DRM_LONTIUM_LT9611UXC is not set # CONFIG_DRM_LOONGSON is not set # CONFIG_DRM_LVDS_CODEC is not set -# CONFIG_DRM_LVDS_ENCODER is not set # CONFIG_DRM_MALI_DISPLAY is not set # CONFIG_DRM_MCDE is not set # CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set @@ -1693,7 +1510,6 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_HIMAX_HX8394 is not set # CONFIG_DRM_PANEL_ILITEK_IL9322 is not set # CONFIG_DRM_PANEL_ILITEK_ILI9341 is not set -# CONFIG_DRM_PANEL_ILITEK_ILI9806E is not set # CONFIG_DRM_PANEL_ILITEK_ILI9881C is not set # CONFIG_DRM_PANEL_INNOLUX_EJ030NA is not set # CONFIG_DRM_PANEL_INNOLUX_P079ZCA is not set @@ -1727,7 +1543,6 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set # CONFIG_DRM_PANEL_RAYDIUM_RM67191 is not set # CONFIG_DRM_PANEL_RAYDIUM_RM68200 is not set -# CONFIG_DRM_PANEL_ROCKTECH_JH057N00900 is not set # CONFIG_DRM_PANEL_RONBO_RB070D30 is not set # CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20 is not set # CONFIG_DRM_PANEL_SAMSUNG_DB7430 is not set @@ -1750,7 +1565,6 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_SITRONIX_ST7701 is not set # CONFIG_DRM_PANEL_SITRONIX_ST7703 is not set # CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set -# CONFIG_DRM_PANEL_SONY_ACX424AKP is not set # CONFIG_DRM_PANEL_SONY_ACX565AKM is not set # CONFIG_DRM_PANEL_SONY_TD4353_JDI is not set # CONFIG_DRM_PANEL_SONY_TULIP_TRULY_NT35521 is not set @@ -1759,12 +1573,10 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_TPO_TD028TTEC1 is not set # CONFIG_DRM_PANEL_TPO_TD043MTEA1 is not set # CONFIG_DRM_PANEL_TPO_TPG110 is not set -# CONFIG_DRM_PANEL_TPO_Y17P is not set # CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA is not set # CONFIG_DRM_PANEL_VISIONOX_R66451 is not set # CONFIG_DRM_PANEL_VISIONOX_RM69299 is not set # CONFIG_DRM_PANEL_VISIONOX_VTDR6130 is not set -# CONFIG_DRM_PANEL_WAVESHARE_TOUCHSCREEN is not set # CONFIG_DRM_PANEL_WIDECHIPS_WS2401 is not set # CONFIG_DRM_PANEL_XINPENG_XPP055C272 is not set # CONFIG_DRM_PANFROST is not set @@ -1779,9 +1591,6 @@ CONFIG_DQL=y # CONFIG_DRM_RCAR_USE_LVDS is not set # CONFIG_DRM_RCAR_USE_MIPI_DSI is not set # CONFIG_DRM_ROCKCHIP is not set -# CONFIG_DRM_RP1_DPI is not set -# CONFIG_DRM_RP1_DSI is not set -# CONFIG_DRM_RP1_VEC is not set # CONFIG_DRM_SAMSUNG_DSIM is not set # CONFIG_DRM_SII902X is not set # CONFIG_DRM_SII9234 is not set @@ -1795,7 +1604,6 @@ CONFIG_DQL=y # CONFIG_DRM_THINE_THC63LVD1024 is not set # CONFIG_DRM_TIDSS is not set # CONFIG_DRM_TILCDC is not set -# CONFIG_DRM_TINYDRM is not set # CONFIG_DRM_TI_DLPC3433 is not set # CONFIG_DRM_TI_SN65DSI83 is not set # CONFIG_DRM_TI_SN65DSI86 is not set @@ -2010,9 +1818,7 @@ CONFIG_EFI_PARTITION=y CONFIG_ELFCORE=y # CONFIG_ELF_CORE is not set # CONFIG_EMAC_ROCKCHIP is not set -CONFIG_EMBEDDED=y # CONFIG_EM_TIMER_STI is not set -CONFIG_ENABLE_WARN_DEPRECATED=y # CONFIG_ENA_ETHERNET is not set # CONFIG_ENC28J60 is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -2040,14 +1846,12 @@ CONFIG_EXPORTFS=y CONFIG_EXT2_FS_XATTR=y # CONFIG_EXT3_FS is not set # CONFIG_EXT4_DEBUG is not set -# CONFIG_EXT4_ENCRYPTION is not set # CONFIG_EXT4_FS is not set # CONFIG_EXT4_FS_POSIX_ACL is not set # CONFIG_EXT4_FS_SECURITY is not set CONFIG_EXT4_USE_FOR_EXT2=y # CONFIG_EXTCON is not set # CONFIG_EXTCON_ADC_JACK is not set -# CONFIG_EXTCON_ARIZONA is not set # CONFIG_EXTCON_AXP288 is not set # CONFIG_EXTCON_FSA9480 is not set # CONFIG_EXTCON_GPIO is not set @@ -2062,19 +1866,16 @@ CONFIG_EXT4_USE_FOR_EXT2=y CONFIG_EXTRA_FIRMWARE="" CONFIG_EXTRA_TARGETS="" # CONFIG_EXYNOS_ADC is not set -# CONFIG_EXYNOS_VIDEO is not set # CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set # CONFIG_EZX_PCAP is not set # CONFIG_F2FS_CHECK_FS is not set # CONFIG_F2FS_FAULT_INJECTION is not set # CONFIG_F2FS_FS is not set # CONFIG_F2FS_FS_COMPRESSION is not set -# CONFIG_F2FS_FS_ENCRYPTION is not set # CONFIG_F2FS_FS_POSIX_ACL is not set # CONFIG_F2FS_FS_SECURITY is not set CONFIG_F2FS_FS_XATTR=y # CONFIG_F2FS_IOSTAT is not set -# CONFIG_F2FS_IO_TRACE is not set CONFIG_F2FS_STAT_FS=y # CONFIG_F2FS_UNFAIR_RWSEM is not set # CONFIG_FAILOVER is not set @@ -2095,10 +1896,8 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_FB_ATMEL is not set # CONFIG_FB_ATY is not set # CONFIG_FB_ATY128 is not set -# CONFIG_FB_AUO_K190X is not set # CONFIG_FB_BACKLIGHT is not set # CONFIG_FB_BIG_ENDIAN is not set -# CONFIG_FB_BOOT_VESA_SUPPORT is not set # CONFIG_FB_BOTH_ENDIAN is not set # CONFIG_FB_BROADSHEET is not set # CONFIG_FB_CARMINE is not set @@ -2111,7 +1910,6 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_FB_DA8XX is not set # CONFIG_FB_DDC is not set # CONFIG_FB_DEVICE is not set -# CONFIG_FB_FLEX is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_FSL_DIU is not set # CONFIG_FB_GEODE is not set @@ -2129,7 +1927,6 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_FB_MB862XX is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_MODE_HELPERS is not set -# CONFIG_FB_MXS is not set # CONFIG_FB_N411 is not set # CONFIG_FB_NEOMAGIC is not set CONFIG_FB_NOTIFY=y @@ -2143,7 +1940,6 @@ CONFIG_FB_NOTIFY=y # CONFIG_FB_PXA is not set # CONFIG_FB_RADEON is not set # CONFIG_FB_RIVA is not set -# CONFIG_FB_RPISENSE is not set # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_S3 is not set # CONFIG_FB_SAVAGE is not set @@ -2161,7 +1957,6 @@ CONFIG_FB_NOTIFY=y # CONFIG_FB_TFT is not set # CONFIG_FB_TFT_AGM1264K_FL is not set # CONFIG_FB_TFT_BD663474 is not set -# CONFIG_FB_TFT_FBTFT_DEVICE is not set # CONFIG_FB_TFT_HX8340BN is not set # CONFIG_FB_TFT_HX8347D is not set # CONFIG_FB_TFT_HX8353D is not set @@ -2182,7 +1977,6 @@ CONFIG_FB_NOTIFY=y # CONFIG_FB_TFT_SSD1289 is not set # CONFIG_FB_TFT_SSD1305 is not set # CONFIG_FB_TFT_SSD1306 is not set -# CONFIG_FB_TFT_SSD1325 is not set # CONFIG_FB_TFT_SSD1331 is not set # CONFIG_FB_TFT_SSD1351 is not set # CONFIG_FB_TFT_ST7735R is not set @@ -2192,9 +1986,7 @@ CONFIG_FB_NOTIFY=y # CONFIG_FB_TFT_UC1611 is not set # CONFIG_FB_TFT_UC1701 is not set # CONFIG_FB_TFT_UPD161704 is not set -# CONFIG_FB_TFT_WATTEROTT is not set # CONFIG_FB_TILEBLITTING is not set -# CONFIG_FB_TMIO is not set # CONFIG_FB_TRIDENT is not set # CONFIG_FB_UDL is not set # CONFIG_FB_UVESA is not set @@ -2203,12 +1995,10 @@ CONFIG_FB_NOTIFY=y # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_VOODOO1 is not set # CONFIG_FB_VT8623 is not set -# CONFIG_FB_XGI is not set # CONFIG_FCOE is not set # CONFIG_FCOE_FNIC is not set # CONFIG_FDDI is not set # CONFIG_FEALNX is not set -# CONFIG_FENCE_TRACE is not set # CONFIG_FHANDLE is not set CONFIG_FIB_RULES=y # CONFIG_FIELDBUS_DEV is not set @@ -2216,16 +2006,12 @@ CONFIG_FILE_LOCKING=y # CONFIG_FIND_BIT_BENCHMARK is not set # CONFIG_FIREWIRE is not set # CONFIG_FIREWIRE_NOSY is not set -# CONFIG_FIREWIRE_SERIAL is not set # CONFIG_FIRMWARE_EDID is not set -# CONFIG_FIRMWARE_IN_KERNEL is not set # CONFIG_FIRMWARE_MEMMAP is not set # CONFIG_FIXED_PHY is not set CONFIG_FLATMEM=y CONFIG_FLATMEM_MANUAL=y -CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_FM10K is not set -# CONFIG_FMC is not set # CONFIG_FONTS is not set # CONFIG_FONT_6x8 is not set # CONFIG_FONT_TER16x32 is not set @@ -2239,7 +2025,6 @@ CONFIG_FORTIFY_SOURCE=y # CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set # CONFIG_FRAME_POINTER is not set # CONFIG_FREEZER is not set -# CONFIG_FRONTSWAP is not set # CONFIG_FSCACHE is not set # CONFIG_FSI is not set # CONFIG_FSL_DPAA2_SWITCH is not set @@ -2299,7 +2084,6 @@ CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y CONFIG_GACT_PROB=y # CONFIG_GADGET_UAC1 is not set # CONFIG_GAMEPORT is not set -# CONFIG_GATEWORKS_GW16083 is not set # CONFIG_GCC_PLUGINS is not set # CONFIG_GCOV is not set # CONFIG_GCOV_KERNEL is not set @@ -2320,9 +2104,6 @@ CONFIG_GENERIC_VDSO_TIME_NS=y # CONFIG_GENEVE is not set # CONFIG_GENWQE is not set # CONFIG_GFS2_FS is not set -# CONFIG_GIGASET_CAPI is not set -# CONFIG_GIGASET_DEBUG is not set -# CONFIG_GIGASET_DUMMYLL is not set # CONFIG_GLOB_SELFTEST is not set # CONFIG_GNSS is not set # CONFIG_GOLDFISH is not set @@ -2342,7 +2123,6 @@ CONFIG_GPIOLIB_FASTPATH_LIMIT=512 # CONFIG_GPIO_74X164 is not set # CONFIG_GPIO_74XX_MMIO is not set # CONFIG_GPIO_ADNP is not set -# CONFIG_GPIO_ADP5588 is not set # CONFIG_GPIO_AGGREGATOR is not set # CONFIG_GPIO_ALTERA is not set # CONFIG_GPIO_AMD8111 is not set @@ -2373,7 +2153,6 @@ CONFIG_GPIOLIB_FASTPATH_LIMIT=512 # CONFIG_GPIO_IT87 is not set # CONFIG_GPIO_LATCH is not set # CONFIG_GPIO_LOGICVC is not set -# CONFIG_GPIO_LYNXPOINT is not set # CONFIG_GPIO_MAX3191X is not set # CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX7301 is not set @@ -2392,7 +2171,6 @@ CONFIG_GPIOLIB_FASTPATH_LIMIT=512 # CONFIG_GPIO_PCI_IDIO_16 is not set # CONFIG_GPIO_PISOSR is not set # CONFIG_GPIO_PL061 is not set -# CONFIG_GPIO_PWM is not set # CONFIG_GPIO_RCAR is not set # CONFIG_GPIO_RDC321X is not set # CONFIG_GPIO_SAMA5D2_PIOBU is not set @@ -2400,7 +2178,6 @@ CONFIG_GPIOLIB_FASTPATH_LIMIT=512 # CONFIG_GPIO_SCH311X is not set # CONFIG_GPIO_SIFIVE is not set # CONFIG_GPIO_SIM is not set -# CONFIG_GPIO_SX150X is not set # CONFIG_GPIO_SYSCON is not set CONFIG_GPIO_SYSFS=y # CONFIG_GPIO_TPIC2810 is not set @@ -2415,24 +2192,17 @@ CONFIG_GPIO_SYSFS=y # CONFIG_GPIO_XILINX is not set # CONFIG_GPIO_XRA1403 is not set # CONFIG_GPIO_ZEVIO is not set -# CONFIG_GPIO_ZX is not set # CONFIG_GP_PCI1XXXX is not set # CONFIG_GREENASIA_FF is not set # CONFIG_GREYBUS is not set -# CONFIG_GS_FPGABOOT is not set # CONFIG_GTP is not set -# CONFIG_GUP_BENCHMARK is not set # CONFIG_GUP_TEST is not set # CONFIG_GVE is not set -# CONFIG_HABANA_AI is not set # CONFIG_HAMACHI is not set # CONFIG_HAMRADIO is not set # CONFIG_HAPPYMEAL is not set CONFIG_HARDENED_USERCOPY=y -# CONFIG_HARDENED_USERCOPY_FALLBACK is not set -# CONFIG_HARDENED_USERCOPY_PAGESPAN is not set CONFIG_HARDEN_BRANCH_HISTORY=y -CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HARDLOCKUP_DETECTOR is not set # CONFIG_HAVE_ARM_ARCH_TIMER is not set # CONFIG_HCALL_STATS is not set @@ -2446,14 +2216,10 @@ CONFIG_HARDEN_EL2_VECTORS=y # CONFIG_HDLC_RAW_ETH is not set # CONFIG_HDMI_LPE_AUDIO is not set # CONFIG_HDQ_MASTER_OMAP is not set -# CONFIG_HEADERS_CHECK is not set # CONFIG_HEADERS_INSTALL is not set -# CONFIG_HEADER_TEST is not set # CONFIG_HERMES is not set # CONFIG_HFSPLUS_FS is not set -# CONFIG_HFSPLUS_FS_POSIX_ACL is not set # CONFIG_HFS_FS is not set -# CONFIG_HFS_FS_POSIX_ACL is not set # CONFIG_HI6421V600_IRQ is not set # CONFIG_HI8435 is not set # CONFIG_HIBERNATION is not set @@ -2600,19 +2366,15 @@ CONFIG_HIGH_RES_TIMERS=y # CONFIG_HOTPLUG_CPU is not set # CONFIG_HOTPLUG_PCI is not set # CONFIG_HP03 is not set -# CONFIG_HP100 is not set # CONFIG_HP206C is not set CONFIG_HPET_MMAP_DEFAULT=y # CONFIG_HPFS_FS is not set # CONFIG_HP_ILO is not set # CONFIG_HP_WATCHDOG is not set -# CONFIG_HP_WIRELESS is not set # CONFIG_HSA_AMD is not set # CONFIG_HSI is not set # CONFIG_HSR is not set # CONFIG_HTC_EGPIO is not set -# CONFIG_HTC_I2CPLD is not set -# CONFIG_HTC_PASIC3 is not set # CONFIG_HTE is not set # CONFIG_HTS221 is not set # CONFIG_HTU21 is not set @@ -2652,8 +2414,6 @@ CONFIG_HW_RANDOM_TPM=y # CONFIG_HW_RANDOM_XIPHERA is not set # CONFIG_HX711 is not set # CONFIG_HYPERV is not set -# CONFIG_HYPERV_TSCPAGE is not set -# CONFIG_HYSDN is not set CONFIG_HZ=100 CONFIG_HZ_100=y # CONFIG_HZ_1000 is not set @@ -2730,7 +2490,6 @@ CONFIG_HZ_100=y # CONFIG_I2C_OCORES is not set # CONFIG_I2C_OCTEON is not set # CONFIG_I2C_PARPORT is not set -# CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PCA_ISA is not set # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_PCI1XXXX is not set @@ -2779,12 +2538,7 @@ CONFIG_HZ_100=y # CONFIG_ICP10100 is not set # CONFIG_ICPLUS_PHY is not set # CONFIG_ICS932S401 is not set -# CONFIG_ICST is not set -# CONFIG_IDE is not set # CONFIG_IDEAPAD_LAPTOP is not set -# CONFIG_IDE_GD is not set -# CONFIG_IDE_PROC_FS is not set -# CONFIG_IDE_TASK_IOCTL is not set # CONFIG_IDLE_PAGE_TRACKING is not set # CONFIG_IEEE802154 is not set # CONFIG_IEEE802154_ADF7242 is not set @@ -2801,7 +2555,6 @@ CONFIG_HZ_100=y # CONFIG_IIO_BUFFER_CB is not set # CONFIG_IIO_BUFFER_DMA is not set # CONFIG_IIO_BUFFER_DMAENGINE is not set -# CONFIG_IIO_BUFFER_HDC2010 is not set # CONFIG_IIO_BUFFER_HW_CONSUMER is not set # CONFIG_IIO_CONFIGFS is not set CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 @@ -2810,7 +2563,6 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # CONFIG_IIO_KX022A_I2C is not set # CONFIG_IIO_KX022A_SPI is not set # CONFIG_IIO_MUX is not set -# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set # CONFIG_IIO_RESCALE is not set # CONFIG_IIO_SIMPLE_DUMMY is not set # CONFIG_IIO_SSP_SENSORHUB is not set @@ -2829,11 +2581,11 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # CONFIG_IKCONFIG_PROC is not set # CONFIG_IKHEADERS is not set # CONFIG_IMA is not set -# CONFIG_IMAGE_CMDLINE_HACK is not set # CONFIG_IMGPDC_WDT is not set # CONFIG_IMG_MDC_DMA is not set # CONFIG_IMX7D_ADC is not set # CONFIG_IMX8QXP_ADC is not set +# CONFIG_IMX93_ADC is not set # CONFIG_IMX_IPUV3_CORE is not set # CONFIG_IMX_THERMAL is not set # CONFIG_INA2XX_ADC is not set @@ -2850,7 +2602,6 @@ CONFIG_INET=y # CONFIG_INET_ESP is not set # CONFIG_INET_ESPINTCP is not set # CONFIG_INET_IPCOMP is not set -# CONFIG_INET_LRO is not set CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_TCP_DIAG is not set # CONFIG_INET_TUNNEL is not set @@ -2899,11 +2650,9 @@ CONFIG_INOTIFY_USER=y # CONFIG_INPUT_EVBUG is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_FF_MEMLESS is not set -# CONFIG_INPUT_GP2A is not set # CONFIG_INPUT_GPIO_BEEPER is not set # CONFIG_INPUT_GPIO_DECODER is not set # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set -# CONFIG_INPUT_GPIO_TILT_POLLED is not set # CONFIG_INPUT_GPIO_VIBRA is not set # CONFIG_INPUT_IBM_PANEL is not set # CONFIG_INPUT_IDEAPAD_SLIDEBAR is not set @@ -2923,18 +2672,14 @@ CONFIG_INPUT_MISC=y # CONFIG_INPUT_MMA8450 is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_MPU3050 is not set -# CONFIG_INPUT_MSM_VIBRATOR is not set # CONFIG_INPUT_PALMAS_PWRBUTTON is not set # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_PCSPKR is not set # CONFIG_INPUT_PM8941_PWRKEY is not set # CONFIG_INPUT_PM8XXX_VIBRATOR is not set -# CONFIG_INPUT_POLLDEV is not set # CONFIG_INPUT_POWERMATE is not set # CONFIG_INPUT_PWM_BEEPER is not set # CONFIG_INPUT_PWM_VIBRA is not set -# CONFIG_INPUT_RASPBERRYPI_BUTTON is not set # CONFIG_INPUT_REGULATOR_HAPTIC is not set # CONFIG_INPUT_SOC_BUTTON_ARRAY is not set # CONFIG_INPUT_SPARSEKMAP is not set @@ -2953,7 +2698,6 @@ CONFIG_INPUT_MISC=y # CONFIG_INTEGRITY_SIGNATURE is not set # CONFIG_INTEL_ATOMISP2_LED is not set # CONFIG_INTEL_ATOMISP2_PM is not set -# CONFIG_INTEL_CHT_INT33FE is not set # CONFIG_INTEL_HID_EVENT is not set # CONFIG_INTEL_IDLE is not set # CONFIG_INTEL_IDMA64 is not set @@ -2963,9 +2707,6 @@ CONFIG_INPUT_MISC=y # CONFIG_INTEL_MEI is not set # CONFIG_INTEL_MEI_ME is not set # CONFIG_INTEL_MEI_TXE is not set -# CONFIG_INTEL_MIC_CARD is not set -# CONFIG_INTEL_MIC_HOST is not set -# CONFIG_INTEL_MID_PTI is not set # CONFIG_INTEL_OAKTRAIL is not set # CONFIG_INTEL_PMC_CORE is not set # CONFIG_INTEL_PUNIT_IPC is not set @@ -3050,7 +2791,6 @@ CONFIG_IPW2200_MONITOR=y # CONFIG_IPW2200_QOS is not set # CONFIG_IPW2200_RADIOTAP is not set # CONFIG_IPWIRELESS is not set -# CONFIG_IPX is not set CONFIG_IP_ADVANCED_ROUTER=y # CONFIG_IP_DCCP is not set # CONFIG_IP_FIB_TRIE_STATS is not set @@ -3070,7 +2810,6 @@ CONFIG_IP_MULTIPLE_TABLES=y # CONFIG_IP_NF_MATCH_TTL is not set # CONFIG_IP_NF_RAW is not set # CONFIG_IP_NF_SECURITY is not set -# CONFIG_IP_NF_TARGET_CLUSTERIP is not set # CONFIG_IP_NF_TARGET_ECN is not set # CONFIG_IP_NF_TARGET_MASQUERADE is not set # CONFIG_IP_NF_TARGET_NETMAP is not set @@ -3090,10 +2829,8 @@ CONFIG_IP_ROUTE_VERBOSE=y # CONFIG_IP_VS_MH is not set CONFIG_IP_VS_MH_TAB_INDEX=10 # CONFIG_IP_VS_TWOS is not set -# CONFIG_IRDA is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_IRQ_ALL_CPUS is not set -# CONFIG_IRQ_DOMAIN_DEBUG is not set # CONFIG_IRQ_POLL is not set # CONFIG_IRQ_TIME_ACCOUNTING is not set # CONFIG_IRSD200 is not set @@ -3105,14 +2842,12 @@ CONFIG_IP_VS_MH_TAB_INDEX=10 # CONFIG_IR_IMON is not set # CONFIG_IR_IMON_RAW is not set # CONFIG_IR_JVC_DECODER is not set -# CONFIG_IR_LIRC_CODEC is not set # CONFIG_IR_MCEUSB is not set # CONFIG_IR_NEC_DECODER is not set # CONFIG_IR_RC5_DECODER is not set # CONFIG_IR_RC6_DECODER is not set # CONFIG_IR_REDRAT3 is not set # CONFIG_IR_SERIAL is not set -# CONFIG_IR_SIR is not set # CONFIG_IR_SONY_DECODER is not set # CONFIG_IR_STREAMZAP is not set # CONFIG_IR_TOY is not set @@ -3122,18 +2857,7 @@ CONFIG_IP_VS_MH_TAB_INDEX=10 # CONFIG_ISCSI_BOOT_SYSFS is not set # CONFIG_ISCSI_TCP is not set CONFIG_ISDN=y -# CONFIG_ISDN_AUDIO is not set # CONFIG_ISDN_CAPI is not set -# CONFIG_ISDN_CAPI_CAPIDRV is not set -# CONFIG_ISDN_DIVERSION is not set -# CONFIG_ISDN_DRV_ACT2000 is not set -# CONFIG_ISDN_DRV_GIGASET is not set -# CONFIG_ISDN_DRV_HISAX is not set -# CONFIG_ISDN_DRV_ICN is not set -# CONFIG_ISDN_DRV_LOOP is not set -# CONFIG_ISDN_DRV_PCBIT is not set -# CONFIG_ISDN_DRV_SC is not set -# CONFIG_ISDN_I4L is not set # CONFIG_ISL29003 is not set # CONFIG_ISL29020 is not set # CONFIG_ISL29125 is not set @@ -3143,7 +2867,6 @@ CONFIG_ISDN=y # CONFIG_ITG3200 is not set # CONFIG_IWL3945 is not set # CONFIG_IWLWIFI is not set -# CONFIG_IXGB is not set # CONFIG_IXGBE is not set # CONFIG_IXGBEVF is not set # CONFIG_JAILHOUSE_GUEST is not set @@ -3176,7 +2899,6 @@ CONFIG_JOLIET=y # CONFIG_JSA1212 is not set # CONFIG_JUMP_LABEL is not set # CONFIG_JZ4740_WDT is not set -# CONFIG_JZ4770_PHY is not set # CONFIG_KALLSYMS is not set # CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set # CONFIG_KALLSYMS_ALL is not set @@ -3192,7 +2914,6 @@ CONFIG_KASAN_STACK=y CONFIG_KCOV_IRQ_AREA_SIZE=0x40000 # CONFIG_KCSAN is not set # CONFIG_KERNEL_BZIP2 is not set -# CONFIG_KERNEL_CAT is not set # CONFIG_KERNEL_GZIP is not set # CONFIG_KERNEL_LZ4 is not set # CONFIG_KERNEL_LZMA is not set @@ -3248,9 +2969,7 @@ CONFIG_KERNFS=y # CONFIG_KEY_DH_OPERATIONS is not set # CONFIG_KFENCE is not set # CONFIG_KGDB is not set -# CONFIG_KMEMCHECK is not set # CONFIG_KMX61 is not set -# CONFIG_KPC2000 is not set # CONFIG_KPROBES is not set # CONFIG_KPROBES_SANITY_TEST is not set # CONFIG_KPROBE_EVENTS_ON_NOTRACE is not set @@ -3277,25 +2996,20 @@ CONFIG_KUSER_HELPERS=y # CONFIG_L2TP_V3 is not set # CONFIG_LAN743X is not set # CONFIG_LAN966X_SWITCH is not set -# CONFIG_LANMEDIA is not set # CONFIG_LANTIQ is not set # CONFIG_LAPB is not set -# CONFIG_LASAT is not set # CONFIG_LATENCYTOP is not set # CONFIG_LATTICE_ECP3_CONFIG is not set -CONFIG_LBDAF=y # CONFIG_LCD_AMS369FG06 is not set # CONFIG_LCD_CLASS_DEVICE is not set # CONFIG_LCD_HX8357 is not set # CONFIG_LCD_ILI922X is not set # CONFIG_LCD_ILI9320 is not set # CONFIG_LCD_L4F00242T03 is not set -# CONFIG_LCD_LD9040 is not set # CONFIG_LCD_LMS283GF05 is not set # CONFIG_LCD_LMS501KF03 is not set # CONFIG_LCD_LTV350QV is not set # CONFIG_LCD_OTM3225A is not set -# CONFIG_LCD_S6E63M0 is not set # CONFIG_LCD_TDO24M is not set # CONFIG_LCD_VGG2432A4 is not set CONFIG_LDISC_AUTOLOAD=y @@ -3379,7 +3093,6 @@ CONFIG_LEDS_TRIGGER_TIMER=y # CONFIG_LED_TRIGGER_PHY is not set # CONFIG_LEGACY_PTYS is not set # CONFIG_LEGACY_TIOCSTI is not set -# CONFIG_LGUEST is not set # CONFIG_LIB80211 is not set # CONFIG_LIB80211_CRYPT_CCMP is not set # CONFIG_LIB80211_CRYPT_TKIP is not set @@ -3393,13 +3106,11 @@ CONFIG_LEDS_TRIGGER_TIMER=y # CONFIG_LIBFCOE is not set # CONFIG_LIBIPW_DEBUG is not set # CONFIG_LIBNVDIMM is not set -CONFIG_LIB_MEMNEQ=y # CONFIG_LIDAR_LITE_V2 is not set CONFIG_LINEAR_RANGES=y # CONFIG_LIQUIDIO is not set # CONFIG_LIQUIDIO_VF is not set # CONFIG_LIRC is not set -# CONFIG_LIS3L02DQ is not set # CONFIG_LIST_HARDENED is not set # CONFIG_LITEX_LITEETH is not set # CONFIG_LITEX_SOC_CONTROLLER is not set @@ -3409,7 +3120,6 @@ CONFIG_LLC=y # CONFIG_LLC2 is not set # CONFIG_LMK04832 is not set # CONFIG_LMP91000 is not set -# CONFIG_LNET is not set CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set # CONFIG_LOCKD is not set @@ -3425,7 +3135,6 @@ CONFIG_LOCKD_V4=y CONFIG_LOCK_MM_AND_FIND_VMA=y # CONFIG_LOCK_STAT is not set # CONFIG_LOCK_TORTURE_TEST is not set -# CONFIG_LOGFS is not set # CONFIG_LOGIG940_FF is not set # CONFIG_LOGIRUMBLEPAD2_FF is not set # CONFIG_LOGITECH_FF is not set @@ -3453,10 +3162,8 @@ CONFIG_LSM_MMAP_MIN_ADDR=65536 # CONFIG_LTC2983 is not set # CONFIG_LTE_GDM724X is not set CONFIG_LTO_NONE=y -# CONFIG_LTPC is not set # CONFIG_LTR501 is not set # CONFIG_LTRF216A is not set -# CONFIG_LUSTRE_FS is not set # CONFIG_LV0104CS is not set # CONFIG_LWTUNNEL is not set # CONFIG_LXT_PHY is not set @@ -3483,12 +3190,8 @@ CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 # CONFIG_MACH_LOONGSON64 is not set # CONFIG_MACH_NINTENDO64 is not set # CONFIG_MACH_PIC32 is not set -# CONFIG_MACH_PISTACHIO is not set # CONFIG_MACH_REALTEK_RTL is not set -# CONFIG_MACH_TX39XX is not set # CONFIG_MACH_TX49XX is not set -# CONFIG_MACH_VR41XX is not set -# CONFIG_MACH_XILFPGA is not set # CONFIG_MACINTOSH_DRIVERS is not set # CONFIG_MACSEC is not set # CONFIG_MACVLAN is not set @@ -3502,7 +3205,6 @@ CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" # CONFIG_MAILBOX is not set # CONFIG_MANAGER_SBS is not set -# CONFIG_MANDATORY_FILE_LOCKING is not set # CONFIG_MANGLE_BOOTARGS is not set # CONFIG_MARVELL_10G_PHY is not set # CONFIG_MARVELL_88Q2XXX_PHY is not set @@ -3534,7 +3236,6 @@ CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" # CONFIG_MAXIM_THERMOCOUPLE is not set # CONFIG_MAXLINEAR_GPHY is not set CONFIG_MAX_SKB_FRAGS=17 -CONFIG_MAY_USE_DEVLINK=y # CONFIG_MB1232 is not set # CONFIG_MC3230 is not set # CONFIG_MCB is not set @@ -3565,7 +3266,6 @@ CONFIG_MAY_USE_DEVLINK=y # CONFIG_MDIO_MVUSB is not set # CONFIG_MDIO_OCTEON is not set # CONFIG_MDIO_THUNDER is not set -# CONFIG_MDIO_XPCS is not set # CONFIG_MDM_GCC_9607 is not set # CONFIG_MD_BITMAP_FILE is not set # CONFIG_MD_FAULTY is not set @@ -3582,7 +3282,6 @@ CONFIG_MAY_USE_DEVLINK=y # CONFIG_MEDIA_PLATFORM_DRIVERS is not set # CONFIG_MEDIA_PLATFORM_SUPPORT is not set # CONFIG_MEDIA_RADIO_SUPPORT is not set -# CONFIG_MEDIA_RC_SUPPORT is not set # CONFIG_MEDIA_SDR_SUPPORT is not set # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set # CONFIG_MEDIA_SUPPORT is not set @@ -3650,7 +3349,6 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_ARIZONA_SPI is not set # CONFIG_MFD_AS3711 is not set # CONFIG_MFD_AS3722 is not set -# CONFIG_MFD_ASIC3 is not set # CONFIG_MFD_ATC260X_I2C is not set # CONFIG_MFD_ATMEL_FLEXCOM is not set # CONFIG_MFD_ATMEL_HLCDC is not set @@ -3660,7 +3358,6 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_BD9571MWV is not set # CONFIG_MFD_CORE is not set # CONFIG_MFD_CPCAP is not set -# CONFIG_MFD_CROS_EC is not set # CONFIG_MFD_CS42L43_I2C is not set # CONFIG_MFD_CS5535 is not set # CONFIG_MFD_DA9052_I2C is not set @@ -3674,7 +3371,6 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_GATEWORKS_GSC is not set # CONFIG_MFD_HI6421_PMIC is not set # CONFIG_MFD_INTEL_M10_BMC_SPI is not set -# CONFIG_MFD_INTEL_PMT is not set # CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set # CONFIG_MFD_IQS62X is not set # CONFIG_MFD_JANZ_CMODIO is not set @@ -3710,52 +3406,39 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_OMAP_USB_HOST is not set # CONFIG_MFD_PALMAS is not set # CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_PM8921_CORE is not set # CONFIG_MFD_PM8XXX is not set # CONFIG_MFD_QCOM_PM8008 is not set -# CONFIG_MFD_RASPBERRYPI_POE_HAT is not set # CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_RDC321X is not set # CONFIG_MFD_RETU is not set -# CONFIG_MFD_RK808 is not set # CONFIG_MFD_RK8XX_I2C is not set # CONFIG_MFD_RK8XX_SPI is not set # CONFIG_MFD_RN5T618 is not set -# CONFIG_MFD_ROHM_BD70528 is not set # CONFIG_MFD_ROHM_BD71828 is not set # CONFIG_MFD_ROHM_BD718XX is not set # CONFIG_MFD_ROHM_BD957XMUF is not set -# CONFIG_MFD_RP1 is not set -# CONFIG_MFD_RPISENSE_CORE is not set # CONFIG_MFD_RSMU_I2C is not set # CONFIG_MFD_RSMU_SPI is not set # CONFIG_MFD_RT4831 is not set # CONFIG_MFD_RT5033 is not set # CONFIG_MFD_RT5120 is not set -# CONFIG_MFD_RTSX_PCI is not set -# CONFIG_MFD_RTSX_USB is not set # CONFIG_MFD_SEC_CORE is not set # CONFIG_MFD_SI476X_CORE is not set # CONFIG_MFD_SKY81452 is not set # CONFIG_MFD_SL28CPLD is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SMPRO is not set -# CONFIG_MFD_SMSC is not set # CONFIG_MFD_STMFX is not set # CONFIG_MFD_STMPE is not set # CONFIG_MFD_STPMIC1 is not set # CONFIG_MFD_SY7636A is not set # CONFIG_MFD_SYSCON is not set -# CONFIG_MFD_T7L66XB is not set # CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TC6387XB is not set -# CONFIG_MFD_TC6393XB is not set # CONFIG_MFD_TIMBERDALE is not set # CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_TI_LMU is not set # CONFIG_MFD_TI_LP873X is not set # CONFIG_MFD_TI_LP87565 is not set -# CONFIG_MFD_TMIO is not set # CONFIG_MFD_TPS65086 is not set # CONFIG_MFD_TPS65090 is not set # CONFIG_MFD_TPS65217 is not set @@ -3768,8 +3451,6 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_TPS65912_SPI is not set # CONFIG_MFD_TPS6594_I2C is not set # CONFIG_MFD_TPS6594_SPI is not set -# CONFIG_MFD_TPS68470 is not set -# CONFIG_MFD_TPS80031 is not set # CONFIG_MFD_TQMX86 is not set # CONFIG_MFD_VIPERBOARD is not set # CONFIG_MFD_VX855 is not set @@ -3780,7 +3461,6 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MG_DISK is not set # CONFIG_MHI_BUS is not set # CONFIG_MHI_BUS_DEBUG is not set # CONFIG_MHI_BUS_EP is not set @@ -3790,7 +3470,6 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MHI_WWAN_MBIM is not set # CONFIG_MICREL_KS8995MA is not set # CONFIG_MICREL_PHY is not set -# CONFIG_MICROCHIP_KSZ is not set # CONFIG_MICROCHIP_PHY is not set # CONFIG_MICROCHIP_PIT64B is not set # CONFIG_MICROCHIP_T1S_PHY is not set @@ -3809,20 +3488,16 @@ CONFIG_MII=y # CONFIG_MIPS_CDMM is not set # CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set # CONFIG_MIPS_CMDLINE_FROM_DTB is not set -# CONFIG_MIPS_CMP is not set # CONFIG_MIPS_COBALT is not set # CONFIG_MIPS_CPS is not set # CONFIG_MIPS_ELF_APPENDED_DTB is not set -# CONFIG_MIPS_FPU_EMULATOR is not set # CONFIG_MIPS_FP_SUPPORT is not set # CONFIG_MIPS_GENERIC is not set # CONFIG_MIPS_GENERIC_KERNEL is not set # CONFIG_MIPS_MALTA is not set # CONFIG_MIPS_O32_FP64_SUPPORT is not set -# CONFIG_MIPS_PARAVIRT is not set # CONFIG_MIPS_PLATFORM_DEVICES is not set # CONFIG_MIPS_RAW_APPENDED_DTB is not set -# CONFIG_MIPS_SEAD3 is not set # CONFIG_MIPS_VA_BITS_48 is not set # CONFIG_MIPS_VPE_LOADER is not set # CONFIG_MISC_ALCOR_PCI is not set @@ -3842,7 +3517,6 @@ CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=y # CONFIG_MLX4_CORE is not set # CONFIG_MLX4_EN is not set # CONFIG_MLX5_CORE is not set -# CONFIG_MLX5_EN_MACSEC is not set # CONFIG_MLX5_MACSEC is not set # CONFIG_MLX5_SF is not set # CONFIG_MLX5_VFIO_PCI is not set @@ -3850,7 +3524,6 @@ CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=y # CONFIG_MLX90632 is not set # CONFIG_MLXFW is not set # CONFIG_MLXSW_CORE is not set -# CONFIG_MLX_CPLD_PLATFORM is not set # CONFIG_MLX_PLATFORM is not set # CONFIG_MMA7455_I2C is not set # CONFIG_MMA7455_SPI is not set @@ -3863,7 +3536,6 @@ CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=y # CONFIG_MMC_ARMMMCI is not set # CONFIG_MMC_AU1X is not set # CONFIG_MMC_BLOCK is not set -CONFIG_MMC_BLOCK_BOUNCE=y CONFIG_MMC_BLOCK_MINORS=8 # CONFIG_MMC_CAVIUM_THUNDERX is not set # CONFIG_MMC_CB710 is not set @@ -3874,7 +3546,6 @@ CONFIG_MMC_BLOCK_MINORS=8 # CONFIG_MMC_JZ4740 is not set # CONFIG_MMC_MTK is not set # CONFIG_MMC_MVSDIO is not set -# CONFIG_MMC_S3C is not set # CONFIG_MMC_SDHCI is not set # CONFIG_MMC_SDHCI_ACPI is not set # CONFIG_MMC_SDHCI_AM654 is not set @@ -3913,7 +3584,6 @@ CONFIG_MMU_GATHER_TABLE_FREE=y CONFIG_MODPROBE_PATH="/sbin/modprobe" CONFIG_MODULES=y # CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set -# CONFIG_MODULE_COMPRESS is not set # CONFIG_MODULE_COMPRESS_GZIP is not set CONFIG_MODULE_COMPRESS_NONE=y # CONFIG_MODULE_COMPRESS_XZ is not set @@ -3989,15 +3659,12 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y # CONFIG_MTD_DATAFLASH is not set # CONFIG_MTD_DOCG3 is not set CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_GPIO_ADDR is not set # CONFIG_MTD_HYPERBUS is not set # CONFIG_MTD_IMPA7 is not set # CONFIG_MTD_INTEL_VR_NOR is not set # CONFIG_MTD_JEDECPROBE is not set -# CONFIG_MTD_LATCH_ADDR is not set # CONFIG_MTD_LPDDR is not set # CONFIG_MTD_LPDDR2_NVM is not set -# CONFIG_MTD_M25P80 is not set CONFIG_MTD_MAP_BANK_WIDTH_1=y # CONFIG_MTD_MAP_BANK_WIDTH_16 is not set CONFIG_MTD_MAP_BANK_WIDTH_2=y @@ -4006,18 +3673,12 @@ CONFIG_MTD_MAP_BANK_WIDTH_4=y # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set # CONFIG_MTD_MCHP23K256 is not set # CONFIG_MTD_MCHP48L640 is not set -# CONFIG_MTD_MT81xx_NOR is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_MYLOADER_PARTS is not set -# CONFIG_MTD_NAND is not set # CONFIG_MTD_NAND_AMS_DELTA is not set -# CONFIG_MTD_NAND_AR934X is not set -# CONFIG_MTD_NAND_AR934X_HW_ECC is not set # CONFIG_MTD_NAND_ARASAN is not set # CONFIG_MTD_NAND_ATMEL is not set # CONFIG_MTD_NAND_AU1550 is not set -# CONFIG_MTD_NAND_BCH is not set -# CONFIG_MTD_NAND_BF5XX is not set # CONFIG_MTD_NAND_BRCMNAND is not set # CONFIG_MTD_NAND_BRCMNAND_BCM63XX is not set # CONFIG_MTD_NAND_BRCMNAND_BCMBCA is not set @@ -4025,19 +3686,14 @@ CONFIG_MTD_MAP_BANK_WIDTH_4=y # CONFIG_MTD_NAND_BRCMNAND_IPROC is not set # CONFIG_MTD_NAND_CADENCE is not set # CONFIG_MTD_NAND_CAFE is not set -# CONFIG_MTD_NAND_CM_X270 is not set # CONFIG_MTD_NAND_CS553X is not set # CONFIG_MTD_NAND_DAVINCI is not set # CONFIG_MTD_NAND_DENALI is not set # CONFIG_MTD_NAND_DENALI_DT is not set # CONFIG_MTD_NAND_DENALI_PCI is not set -CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xff108018 # CONFIG_MTD_NAND_DISKONCHIP is not set -# CONFIG_MTD_NAND_DOCG4 is not set # CONFIG_MTD_NAND_ECC is not set -# CONFIG_MTD_NAND_ECC_BCH is not set # CONFIG_MTD_NAND_ECC_MXIC is not set -# CONFIG_MTD_NAND_ECC_SMC is not set # CONFIG_MTD_NAND_ECC_SW_BCH is not set # CONFIG_MTD_NAND_ECC_SW_HAMMING is not set # CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC is not set @@ -4048,9 +3704,7 @@ CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xff108018 # CONFIG_MTD_NAND_GPIO is not set # CONFIG_MTD_NAND_GPMI_NAND is not set # CONFIG_MTD_NAND_HISI504 is not set -CONFIG_MTD_NAND_IDS=y # CONFIG_MTD_NAND_INTEL_LGM is not set -# CONFIG_MTD_NAND_JZ4740 is not set # CONFIG_MTD_NAND_MPC5121_NFC is not set # CONFIG_MTD_NAND_MTK is not set # CONFIG_MTD_NAND_MTK_BMT is not set @@ -4058,22 +3712,16 @@ CONFIG_MTD_NAND_IDS=y # CONFIG_MTD_NAND_MXIC is not set # CONFIG_MTD_NAND_NANDSIM is not set # CONFIG_MTD_NAND_NDFC is not set -# CONFIG_MTD_NAND_NUC900 is not set # CONFIG_MTD_NAND_OMAP2 is not set # CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set # CONFIG_MTD_NAND_ORION is not set # CONFIG_MTD_NAND_PASEMI is not set # CONFIG_MTD_NAND_PLATFORM is not set -# CONFIG_MTD_NAND_PXA3xx is not set -# CONFIG_MTD_NAND_RB4XX is not set -# CONFIG_MTD_NAND_RB750 is not set -# CONFIG_MTD_NAND_RB91X is not set # CONFIG_MTD_NAND_RICOH is not set # CONFIG_MTD_NAND_S3C2410 is not set # CONFIG_MTD_NAND_SHARPSL is not set # CONFIG_MTD_NAND_SH_FLCTL is not set # CONFIG_MTD_NAND_SOCRATES is not set -# CONFIG_MTD_NAND_TMIO is not set # CONFIG_MTD_NAND_TXX9NDFMC is not set CONFIG_MTD_OF_PARTS=y # CONFIG_MTD_ONENAND is not set @@ -4090,8 +3738,6 @@ CONFIG_MTD_OF_PARTS=y # CONFIG_MTD_PHYSMAP_GPIO_ADDR is not set # CONFIG_MTD_PHYSMAP_IXP4XX is not set CONFIG_MTD_PHYSMAP_OF=y -# CONFIG_MTD_PHYSMAP_OF_GEMINI is not set -# CONFIG_MTD_PHYSMAP_OF_VERSATILE is not set # CONFIG_MTD_PHYSMAP_VERSATILE is not set # CONFIG_MTD_PLATRAM is not set # CONFIG_MTD_PMC551 is not set @@ -4107,7 +3753,6 @@ CONFIG_MTD_ROOTFS_ROOT_DEV=y # CONFIG_MTD_SERCOMM_PARTS is not set # CONFIG_MTD_SLRAM is not set # CONFIG_MTD_SM_COMMON is not set -# CONFIG_MTD_SPINAND_MT29F is not set # CONFIG_MTD_SPI_NAND is not set # CONFIG_MTD_SPI_NOR is not set # CONFIG_MTD_SPI_NOR_SWP_DISABLE is not set @@ -4143,10 +3788,8 @@ CONFIG_MTD_SPLIT_SUPPORT=y # CONFIG_MTD_UBI_FASTMAP is not set # CONFIG_MTD_UBI_GLUEBI is not set # CONFIG_MTD_UBI_NVMEM is not set -# CONFIG_MTD_UIMAGE_SPLIT is not set # CONFIG_MTD_VIRT_CONCAT is not set # CONFIG_MTK_DEVAPC is not set -# CONFIG_MTK_MMC is not set # CONFIG_MTK_MMSYS is not set # CONFIG_MTK_T7XX is not set # CONFIG_MTK_THERMAL is not set @@ -4160,7 +3803,6 @@ CONFIG_MULTIUSER=y # CONFIG_MV643XX_ETH is not set # CONFIG_MVMDIO is not set # CONFIG_MVNETA_BM is not set -# CONFIG_MVSW61XX_PHY is not set # CONFIG_MV_XOR_V2 is not set # CONFIG_MWAVE is not set # CONFIG_MWL8K is not set @@ -4173,10 +3815,8 @@ CONFIG_MULTIUSER=y # CONFIG_NAU7802 is not set # CONFIG_NBPFAXI_DMA is not set # CONFIG_NCN26000_PHY is not set -# CONFIG_NCP_FS is not set # CONFIG_NE2000 is not set # CONFIG_NE2K_PCI is not set -# CONFIG_NEC_MARKEINS is not set CONFIG_NET=y # CONFIG_NETCONSOLE is not set # CONFIG_NETCONSOLE_EXTENDED_LOG is not set @@ -4184,7 +3824,6 @@ CONFIG_NETDEVICES=y # CONFIG_NETDEVSIM is not set # CONFIG_NETFILTER is not set # CONFIG_NETFILTER_ADVANCED is not set -# CONFIG_NETFILTER_DEBUG is not set # CONFIG_NETFILTER_EGRESS is not set # CONFIG_NETFILTER_INGRESS is not set # CONFIG_NETFILTER_NETLINK is not set @@ -4270,7 +3909,6 @@ CONFIG_NETDEVICES=y # CONFIG_NETFS_STATS is not set # CONFIG_NETLABEL is not set # CONFIG_NETLINK_DIAG is not set -# CONFIG_NETLINK_MMAP is not set # CONFIG_NETPOLL is not set # CONFIG_NETROM is not set CONFIG_NETWORK_FILESYSTEMS=y @@ -4296,7 +3934,6 @@ CONFIG_NETWORK_FILESYSTEMS=y # CONFIG_NET_ACT_SKBMOD is not set # CONFIG_NET_ACT_TUNNEL_KEY is not set # CONFIG_NET_ACT_VLAN is not set -CONFIG_NET_CADENCE=y # CONFIG_NET_CALXEDA_XGMAC is not set CONFIG_NET_CLS=y # CONFIG_NET_CLS_ACT is not set @@ -4305,11 +3942,8 @@ CONFIG_NET_CLS=y # CONFIG_NET_CLS_FLOW is not set # CONFIG_NET_CLS_FLOWER is not set # CONFIG_NET_CLS_FW is not set -CONFIG_NET_CLS_IND=y # CONFIG_NET_CLS_MATCHALL is not set # CONFIG_NET_CLS_ROUTE4 is not set -# CONFIG_NET_CLS_RSVP is not set -# CONFIG_NET_CLS_RSVP6 is not set # CONFIG_NET_CLS_U32 is not set CONFIG_NET_CORE=y # CONFIG_NET_DEVLINK is not set @@ -4319,22 +3953,14 @@ CONFIG_NET_CORE=y # CONFIG_NET_DSA_AR9331 is not set # CONFIG_NET_DSA_BCM_SF2 is not set # CONFIG_NET_DSA_LANTIQ_GSWIP is not set -# CONFIG_NET_DSA_LEGACY is not set # CONFIG_NET_DSA_LOOP is not set -# CONFIG_NET_DSA_MICROCHIP_KSZ8795 is not set -# CONFIG_NET_DSA_MICROCHIP_KSZ9477 is not set # CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON is not set # CONFIG_NET_DSA_MSCC_FELIX is not set # CONFIG_NET_DSA_MSCC_OCELOT_EXT is not set # CONFIG_NET_DSA_MSCC_SEVILLE is not set # CONFIG_NET_DSA_MT7530 is not set # CONFIG_NET_DSA_MV88E6060 is not set -# CONFIG_NET_DSA_MV88E6123_61_65 is not set -# CONFIG_NET_DSA_MV88E6131 is not set -# CONFIG_NET_DSA_MV88E6171 is not set -# CONFIG_NET_DSA_MV88E6352 is not set # CONFIG_NET_DSA_MV88E6XXX is not set -# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set # CONFIG_NET_DSA_MV88E6XXX_PTP is not set # CONFIG_NET_DSA_QCA8K is not set # CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT is not set @@ -4343,7 +3969,6 @@ CONFIG_NET_CORE=y # CONFIG_NET_DSA_SJA1105 is not set # CONFIG_NET_DSA_SMSC_LAN9303_I2C is not set # CONFIG_NET_DSA_SMSC_LAN9303_MDIO is not set -# CONFIG_NET_DSA_TAG_8021Q is not set # CONFIG_NET_DSA_TAG_AR9331 is not set # CONFIG_NET_DSA_TAG_BRCM is not set # CONFIG_NET_DSA_TAG_BRCM_LEGACY is not set @@ -4398,7 +4023,6 @@ CONFIG_NET_IPGRE_BROADCAST=y # CONFIG_NET_NCSI is not set # CONFIG_NET_NSH is not set # CONFIG_NET_NS_REFCNT_TRACKER is not set -# CONFIG_NET_PACKET_ENGINE is not set # CONFIG_NET_PKTGEN is not set # CONFIG_NET_POLL_CONTROLLER is not set # CONFIG_NET_PTP_CLASSIFY is not set @@ -4436,11 +4060,9 @@ CONFIG_NET_SCH_FQ_CODEL=y # CONFIG_NET_SCH_TAPRIO is not set # CONFIG_NET_SCH_TBF is not set # CONFIG_NET_SCH_TEQL is not set -# CONFIG_NET_SCTPPROBE is not set # CONFIG_NET_SELFTESTS is not set CONFIG_NET_SOCK_MSG=y # CONFIG_NET_SWITCHDEV is not set -# CONFIG_NET_TCPPROBE is not set # CONFIG_NET_TC_SKB_EXT is not set # CONFIG_NET_TEAM is not set # CONFIG_NET_TULIP is not set @@ -4458,7 +4080,6 @@ CONFIG_NET_VENDOR_AQUANTIA=y CONFIG_NET_VENDOR_ARC=y # CONFIG_NET_VENDOR_ASIX is not set CONFIG_NET_VENDOR_ATHEROS=y -CONFIG_NET_VENDOR_AURORA=y CONFIG_NET_VENDOR_BROADCOM=y CONFIG_NET_VENDOR_BROCADE=y CONFIG_NET_VENDOR_CADENCE=y @@ -4472,7 +4093,6 @@ CONFIG_NET_VENDOR_DEC=y CONFIG_NET_VENDOR_DLINK=y CONFIG_NET_VENDOR_EMULEX=y # CONFIG_NET_VENDOR_ENGLEDER is not set -CONFIG_NET_VENDOR_EXAR=y CONFIG_NET_VENDOR_EZCHIP=y CONFIG_NET_VENDOR_FARADAY=y CONFIG_NET_VENDOR_FREESCALE=y @@ -4480,7 +4100,6 @@ CONFIG_NET_VENDOR_FUJITSU=y # CONFIG_NET_VENDOR_FUNGIBLE is not set CONFIG_NET_VENDOR_GOOGLE=y CONFIG_NET_VENDOR_HISILICON=y -CONFIG_NET_VENDOR_HP=y CONFIG_NET_VENDOR_HUAWEI=y CONFIG_NET_VENDOR_I825XX=y CONFIG_NET_VENDOR_IBM=y @@ -4534,7 +4153,6 @@ CONFIG_NEW_LEDS=y # CONFIG_NFSD is not set # CONFIG_NFSD_V2 is not set # CONFIG_NFSD_V2_ACL is not set -CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set # CONFIG_NFSD_V4 is not set # CONFIG_NFS_ACL_SUPPORT is not set @@ -4558,11 +4176,8 @@ CONFIG_NFS_V3=y # CONFIG_NFT_FIB_IPV6 is not set # CONFIG_NFT_FIB_NETDEV is not set # CONFIG_NFT_FLOW_OFFLOAD is not set -# CONFIG_NFT_OBJREF is not set # CONFIG_NFT_OSF is not set # CONFIG_NFT_REJECT_NETDEV is not set -# CONFIG_NFT_RT is not set -# CONFIG_NFT_SET_BITMAP is not set # CONFIG_NFT_SOCKET is not set # CONFIG_NFT_SYNPROXY is not set # CONFIG_NFT_TPROXY is not set @@ -4580,7 +4195,6 @@ CONFIG_NFS_V3=y # CONFIG_NF_CONNTRACK_NETBIOS_NS is not set # CONFIG_NF_CONNTRACK_PPTP is not set CONFIG_NF_CONNTRACK_PROCFS=y -# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set # CONFIG_NF_CONNTRACK_SANE is not set # CONFIG_NF_CONNTRACK_SECMARK is not set # CONFIG_NF_CONNTRACK_SIP is not set @@ -4602,18 +4216,14 @@ CONFIG_NF_CONNTRACK_PROCFS=y # CONFIG_NF_FLOW_TABLE is not set # CONFIG_NF_FLOW_TABLE_PROCFS is not set # CONFIG_NF_LOG_ARP is not set -# CONFIG_NF_LOG_BRIDGE is not set # CONFIG_NF_LOG_IPV4 is not set -# CONFIG_NF_LOG_NETDEV is not set # CONFIG_NF_LOG_SYSLOG is not set # CONFIG_NF_NAT is not set # CONFIG_NF_NAT_AMANDA is not set # CONFIG_NF_NAT_FTP is not set # CONFIG_NF_NAT_H323 is not set # CONFIG_NF_NAT_IRC is not set -# CONFIG_NF_NAT_NEEDED is not set # CONFIG_NF_NAT_PPTP is not set -# CONFIG_NF_NAT_PROTO_GRE is not set # CONFIG_NF_NAT_SIP is not set # CONFIG_NF_NAT_SNMP_BASIC is not set # CONFIG_NF_NAT_TFTP is not set @@ -4628,11 +4238,9 @@ CONFIG_NF_TABLES_INET=y CONFIG_NF_TABLES_IPV4=y CONFIG_NF_TABLES_IPV6=y CONFIG_NF_TABLES_NETDEV=y -# CONFIG_NF_TABLES_SET is not set # CONFIG_NF_TPROXY_IPV4 is not set # CONFIG_NF_TPROXY_IPV6 is not set # CONFIG_NGBE is not set -# CONFIG_NI65 is not set # CONFIG_NI903X_WDT is not set # CONFIG_NIC7018_WDT is not set # CONFIG_NILFS2_FS is not set @@ -4640,8 +4248,6 @@ CONFIG_NF_TABLES_NETDEV=y # CONFIG_NI_XGE_MANAGEMENT_ENET is not set CONFIG_NLATTR=y # CONFIG_NLMON is not set -# CONFIG_NLM_XLP_BOARD is not set -# CONFIG_NLM_XLR_BOARD is not set # CONFIG_NLS is not set # CONFIG_NLS_ASCII is not set # CONFIG_NLS_CODEPAGE_1250 is not set @@ -4694,14 +4300,11 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_MAC_TURKISH is not set # CONFIG_NLS_UCS2_UTILS is not set # CONFIG_NLS_UTF8 is not set -CONFIG_NMI_LOG_BUF_SHIFT=13 # CONFIG_NOA1305 is not set # CONFIG_NOP_USB_XCEIV is not set # CONFIG_NORTEL_HERMES is not set # CONFIG_NOTIFIER_ERROR_INJECTION is not set -# CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT is not set # CONFIG_NOZOMI is not set -# CONFIG_NO_BOOTMEM is not set # CONFIG_NO_HZ is not set # CONFIG_NO_HZ_FULL is not set # CONFIG_NO_HZ_IDLE is not set @@ -4718,9 +4321,9 @@ CONFIG_NMI_LOG_BUF_SHIFT=13 # CONFIG_NULL_TTY is not set # CONFIG_NUMA is not set # CONFIG_NVIDIA_CARMEL_CNP_ERRATUM is not set -# CONFIG_NVM is not set # CONFIG_NVMEM is not set # CONFIG_NVMEM_BCM_OCOTP is not set +# CONFIG_NVMEM_BLOCK is not set # CONFIG_NVMEM_IMX_OCOTP is not set # CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set # CONFIG_NVMEM_LAYOUT_SL28_VPD is not set @@ -4737,8 +4340,6 @@ CONFIG_NMI_LOG_BUF_SHIFT=13 # CONFIG_NV_TCO is not set # CONFIG_NXP_C45_TJA11XX_PHY is not set # CONFIG_NXP_CBTX_PHY is not set -# CONFIG_NXP_STB220 is not set -# CONFIG_NXP_STB225 is not set # CONFIG_NXP_TJA11XX_PHY is not set # CONFIG_N_GSM is not set # CONFIG_OABI_COMPAT is not set @@ -4759,11 +4360,8 @@ CONFIG_OF_RESERVED_MEM=y # CONFIG_OMFS_FS is not set # CONFIG_OPENVSWITCH is not set # CONFIG_OPEN_DICE is not set -# CONFIG_OPROFILE is not set -# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set # CONFIG_OPT3001 is not set # CONFIG_OPT4001 is not set -CONFIG_OPTIMIZE_INLINING=y # CONFIG_ORANGEFS_FS is not set # CONFIG_ORION_WATCHDOG is not set # CONFIG_OSF_PARTITION is not set @@ -4775,7 +4373,6 @@ CONFIG_OVERLAY_FS=y CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y # CONFIG_OVERLAY_FS_REDIRECT_DIR is not set CONFIG_OVERLAY_FS_XINO_AUTO=y -# CONFIG_OWL_LOADER is not set # CONFIG_P54_COMMON is not set # CONFIG_PA12203001 is not set CONFIG_PACKET=y @@ -4804,7 +4401,6 @@ CONFIG_PANIC_TIMEOUT=1 # CONFIG_PARAVIRT_TIME_ACCOUNTING is not set # CONFIG_PARPORT is not set # CONFIG_PARPORT_1284 is not set -# CONFIG_PARPORT_AX88796 is not set # CONFIG_PARPORT_GSC is not set # CONFIG_PARPORT_PC is not set CONFIG_PARTITION_ADVANCED=y @@ -4883,7 +4479,6 @@ CONFIG_PCIE_BUS_DEFAULT=y # CONFIG_PCIE_BUS_PERFORMANCE is not set # CONFIG_PCIE_BUS_SAFE is not set # CONFIG_PCIE_BUS_TUNE_OFF is not set -# CONFIG_PCIE_BW is not set # CONFIG_PCIE_CADENCE_HOST is not set # CONFIG_PCIE_CADENCE_PLAT_HOST is not set # CONFIG_PCIE_DPC is not set @@ -4954,7 +4549,6 @@ CONFIG_PCI_SYSCALL=y # CONFIG_PCS_MTK_USXGMII is not set # CONFIG_PCS_XPCS is not set # CONFIG_PD6729 is not set -# CONFIG_PDA_POWER is not set # CONFIG_PDC_ADMA is not set # CONFIG_PDS_CORE is not set # CONFIG_PECI is not set @@ -4970,7 +4564,6 @@ CONFIG_PCI_SYSCALL=y # CONFIG_PHYLIB_LEDS is not set # CONFIG_PHYS_ADDR_T_64BIT is not set # CONFIG_PHY_BRCM_USB is not set -# CONFIG_PHY_CADENCE_DP is not set # CONFIG_PHY_CADENCE_DPHY is not set # CONFIG_PHY_CADENCE_DPHY_RX is not set # CONFIG_PHY_CADENCE_SALVO is not set @@ -4994,7 +4587,6 @@ CONFIG_PCI_SYSCALL=y # CONFIG_PHY_PISTACHIO_USB is not set # CONFIG_PHY_PXA_28NM_HSIC is not set # CONFIG_PHY_PXA_28NM_USB2 is not set -# CONFIG_PHY_QCOM_DWC3 is not set # CONFIG_PHY_QCOM_USB_HS is not set # CONFIG_PHY_QCOM_USB_HSIC is not set # CONFIG_PHY_SAMSUNG_USB2 is not set @@ -5007,11 +4599,9 @@ CONFIG_PINCONF=y # CONFIG_PINCTRL is not set # CONFIG_PINCTRL_AMD is not set # CONFIG_PINCTRL_AXP209 is not set -# CONFIG_PINCTRL_BCM2712 is not set # CONFIG_PINCTRL_CEDARFORK is not set # CONFIG_PINCTRL_CY8C95X0 is not set # CONFIG_PINCTRL_EXYNOS is not set -# CONFIG_PINCTRL_EXYNOS5440 is not set # CONFIG_PINCTRL_ICELAKE is not set # CONFIG_PINCTRL_INGENIC is not set # CONFIG_PINCTRL_LPASS_LPI is not set @@ -5028,7 +4618,6 @@ CONFIG_PINCONF=y # CONFIG_PINCTRL_MTK_V2 is not set # CONFIG_PINCTRL_OCELOT is not set # CONFIG_PINCTRL_PISTACHIO is not set -# CONFIG_PINCTRL_RP1 is not set # CONFIG_PINCTRL_SC7280 is not set # CONFIG_PINCTRL_SC8180X is not set # CONFIG_PINCTRL_SDX55 is not set @@ -5054,7 +4643,6 @@ CONFIG_PINMUX=y # CONFIG_PLX_HERMES is not set # CONFIG_PM is not set # CONFIG_PMBUS is not set -# CONFIG_PMC_MSP is not set # CONFIG_PMIC_ADP5520 is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMS7003 is not set @@ -5066,7 +4654,6 @@ CONFIG_PINMUX=y # CONFIG_POSIX_MQUEUE is not set CONFIG_POSIX_TIMERS=y # CONFIG_POWERCAP is not set -# CONFIG_POWER_AVS is not set # CONFIG_POWER_RESET is not set # CONFIG_POWER_RESET_BRCMKONA is not set # CONFIG_POWER_RESET_BRCMSTB is not set @@ -5118,7 +4705,6 @@ CONFIG_PPP_MULTILINK=y # CONFIG_PPTP is not set # CONFIG_PREEMPT is not set # CONFIG_PREEMPTIRQ_DELAY_TEST is not set -# CONFIG_PREEMPTIRQ_EVENTS is not set # CONFIG_PREEMPT_DYNAMIC is not set CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_TRACER is not set @@ -5129,12 +4715,9 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_PRINTK=y # CONFIG_PRINTK_CALLER is not set # CONFIG_PRINTK_INDEX is not set -CONFIG_PRINTK_NMI=y -CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 # CONFIG_PRINTK_TIME is not set CONFIG_PRINT_STACK_DEPTH=64 # CONFIG_PRISM2_USB is not set -# CONFIG_PRISM54 is not set # CONFIG_PROC_CHILDREN is not set CONFIG_PROC_FS=y # CONFIG_PROC_KCORE is not set @@ -5149,26 +4732,18 @@ CONFIG_PROC_SYSCTL=y # CONFIG_PROVE_RAW_LOCK_NESTING is not set # CONFIG_PROVE_RCU is not set # CONFIG_PROVE_RCU_LIST is not set -# CONFIG_PROVE_RCU_REPEATEDLY is not set # CONFIG_PSAMPLE is not set # CONFIG_PSB6970_PHY is not set # CONFIG_PSE_CONTROLLER is not set # CONFIG_PSI is not set # CONFIG_PSTORE is not set -# CONFIG_PSTORE_842_COMPRESS is not set # CONFIG_PSTORE_BLK is not set # CONFIG_PSTORE_COMPRESS is not set # CONFIG_PSTORE_CONSOLE is not set CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 -# CONFIG_PSTORE_DEFLATE_COMPRESS is not set -# CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT is not set # CONFIG_PSTORE_FTRACE is not set -# CONFIG_PSTORE_LZ4HC_COMPRESS is not set -# CONFIG_PSTORE_LZ4_COMPRESS is not set -# CONFIG_PSTORE_LZO_COMPRESS is not set # CONFIG_PSTORE_PMSG is not set # CONFIG_PSTORE_RAM is not set -# CONFIG_PSTORE_ZSTD_COMPRESS is not set # CONFIG_PTDUMP_DEBUGFS is not set # CONFIG_PTP_1588_CLOCK is not set # CONFIG_PTP_1588_CLOCK_IDT82P33 is not set @@ -5179,7 +4754,6 @@ CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 # CONFIG_PTP_1588_CLOCK_OCP is not set # CONFIG_PTP_1588_CLOCK_PCH is not set # CONFIG_PTP_1588_CLOCK_VMW is not set -# CONFIG_PUBLIC_KEY_ALGO_RSA is not set # CONFIG_PVPANIC is not set # CONFIG_PWM is not set # CONFIG_PWM_ATMEL_TCB is not set @@ -5192,7 +4766,6 @@ CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 # CONFIG_PWM_MEDIATEK is not set # CONFIG_PWM_PCA9685 is not set # CONFIG_PWM_RASPBERRYPI_POE is not set -# CONFIG_PWM_RP1 is not set # CONFIG_PWM_XILINX is not set CONFIG_PWRSEQ_EMMC=y # CONFIG_PWRSEQ_SD8787 is not set @@ -5233,18 +4806,15 @@ CONFIG_PWRSEQ_SIMPLE=y # CONFIG_QRTR_MHI is not set # CONFIG_QRTR_TUN is not set # CONFIG_QSEMI_PHY is not set -# CONFIG_QUEUED_LOCK_STAT is not set # CONFIG_QUICC_ENGINE is not set # CONFIG_QUOTA is not set # CONFIG_QUOTACTL is not set # CONFIG_QUOTA_DEBUG is not set # CONFIG_QUOTA_NETLINK_INTERFACE is not set -# CONFIG_R3964 is not set # CONFIG_R6040 is not set # CONFIG_R8169 is not set -# CONFIG_R8188EU is not set +# CONFIG_R8169_LEDS is not set # CONFIG_R8712U is not set -# CONFIG_R8723AU is not set # CONFIG_RADIO_ADAPTERS is not set # CONFIG_RADIO_AZTECH is not set # CONFIG_RADIO_CADET is not set @@ -5266,29 +4836,22 @@ CONFIG_PWRSEQ_SIMPLE=y CONFIG_RANDOMIZE_KSTACK_OFFSET=y # CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT is not set # CONFIG_RANDOM_KMALLOC_CACHES is not set -CONFIG_RANDOM_TRUST_BOOTLOADER=y -CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDSTRUCT_NONE is not set # CONFIG_RAPIDIO is not set # CONFIG_RAS is not set -# CONFIG_RASPBERRYPI_GPIOMEM is not set # CONFIG_RBTREE_TEST is not set # CONFIG_RCU_BOOST is not set # CONFIG_RCU_CPU_STALL_CPUTIME is not set CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_RCU_EQS_DEBUG is not set -# CONFIG_RCU_EXPEDITE_BOOT is not set # CONFIG_RCU_EXPERT is not set CONFIG_RCU_EXP_CPU_STALL_TIMEOUT=0 -CONFIG_RCU_KTHREAD_PRIO=0 CONFIG_RCU_NEED_SEGCBLIST=y -# CONFIG_RCU_PERF_TEST is not set # CONFIG_RCU_REF_SCALE_TEST is not set # CONFIG_RCU_SCALE_TEST is not set CONFIG_RCU_STALL_COMMON=y # CONFIG_RCU_STRICT_GRACE_PERIOD is not set # CONFIG_RCU_TORTURE_TEST is not set -CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 # CONFIG_RCU_TRACE is not set # CONFIG_RC_ATI_REMOTE is not set # CONFIG_RC_CORE is not set @@ -5367,7 +4930,6 @@ CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 # CONFIG_REGULATOR_QCOM_REFGEN is not set # CONFIG_REGULATOR_RAA215300 is not set # CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY is not set -# CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_V2 is not set # CONFIG_REGULATOR_RT4801 is not set # CONFIG_REGULATOR_RT4803 is not set # CONFIG_REGULATOR_RT5190A is not set @@ -5419,7 +4981,6 @@ CONFIG_REISERFS_FS_XATTR=y # CONFIG_RESET_PISTACHIO is not set # CONFIG_RESET_SIMPLE is not set # CONFIG_RESET_SOCFPGA is not set -# CONFIG_RESET_STM32 is not set # CONFIG_RESET_SUNXI is not set # CONFIG_RESET_TEGRA_BPMP is not set # CONFIG_RESET_TI_SYSCON is not set @@ -5432,7 +4993,6 @@ CONFIG_RFKILL=y # CONFIG_RFKILL_GPIO is not set # CONFIG_RFKILL_INPUT is not set # CONFIG_RFKILL_LEDS is not set -# CONFIG_RFKILL_REGULATOR is not set # CONFIG_RICHTEK_RTQ6056 is not set # CONFIG_RING_BUFFER_BENCHMARK is not set # CONFIG_RING_BUFFER_STARTUP_TEST is not set @@ -5475,7 +5035,6 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_RTC_DRV_DS1305 is not set # CONFIG_RTC_DRV_DS1307 is not set # CONFIG_RTC_DRV_DS1307_CENTURY is not set -# CONFIG_RTC_DRV_DS1307_HWMON is not set # CONFIG_RTC_DRV_DS1343 is not set # CONFIG_RTC_DRV_DS1347 is not set # CONFIG_RTC_DRV_DS1374 is not set @@ -5487,7 +5046,6 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_RTC_DRV_DS1742 is not set # CONFIG_RTC_DRV_DS2404 is not set # CONFIG_RTC_DRV_DS3232 is not set -# CONFIG_RTC_DRV_DS3234 is not set # CONFIG_RTC_DRV_EM3027 is not set # CONFIG_RTC_DRV_EP93XX is not set # CONFIG_RTC_DRV_FM3130 is not set @@ -5498,7 +5056,6 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_RTC_DRV_HYM8563 is not set # CONFIG_RTC_DRV_ISL12022 is not set # CONFIG_RTC_DRV_ISL12026 is not set -# CONFIG_RTC_DRV_ISL12057 is not set # CONFIG_RTC_DRV_ISL1208 is not set # CONFIG_RTC_DRV_JZ4740 is not set # CONFIG_RTC_DRV_M41T80 is not set @@ -5528,13 +5085,11 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_RTC_DRV_PL030 is not set # CONFIG_RTC_DRV_PL031 is not set # CONFIG_RTC_DRV_PS3 is not set -# CONFIG_RTC_DRV_PT7C4338 is not set # CONFIG_RTC_DRV_R7301 is not set # CONFIG_RTC_DRV_R9701 is not set # CONFIG_RTC_DRV_RP5C01 is not set # CONFIG_RTC_DRV_RS5C348 is not set # CONFIG_RTC_DRV_RS5C372 is not set -# CONFIG_RTC_DRV_RTC7301 is not set # CONFIG_RTC_DRV_RV3028 is not set # CONFIG_RTC_DRV_RV3029C2 is not set # CONFIG_RTC_DRV_RV3032 is not set @@ -5551,7 +5106,6 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_RTC_DRV_SUN6I is not set # CONFIG_RTC_DRV_TEGRA is not set # CONFIG_RTC_DRV_TEST is not set -# CONFIG_RTC_DRV_V3020 is not set # CONFIG_RTC_DRV_X1205 is not set # CONFIG_RTC_DRV_XGENE is not set # CONFIG_RTC_DRV_ZYNQMP is not set @@ -5580,10 +5134,8 @@ CONFIG_RTC_SYSTOHC_DEVICE="rtc0" # CONFIG_RTL_CARDS is not set # CONFIG_RTS5208 is not set CONFIG_RT_MUTEXES=y -# CONFIG_RUNTIME_DEBUG is not set CONFIG_RUNTIME_TESTING_MENU=y # CONFIG_RV is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_RXKAD=y # CONFIG_RXPERF is not set # CONFIG_S2IO is not set @@ -5633,11 +5185,9 @@ CONFIG_SCHED_OMIT_FRAME_POINTER=y # CONFIG_SCHED_SMT is not set CONFIG_SCHED_STACK_END_CHECK=y # CONFIG_SCHED_TRACER is not set -# CONFIG_SCR24X is not set # CONFIG_SCSI is not set # CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_3W_SAS is not set -# CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_ADVANSYS is not set @@ -5661,20 +5211,13 @@ CONFIG_SCHED_STACK_END_CHECK=y # CONFIG_SCSI_DH is not set CONFIG_SCSI_DMA=y # CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set # CONFIG_SCSI_ESAS2R is not set # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_FDOMAIN_PCI is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set # CONFIG_SCSI_HISI_SAS is not set # CONFIG_SCSI_HPSA is not set # CONFIG_SCSI_HPTIOP is not set -# CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_IPR is not set @@ -5689,17 +5232,13 @@ CONFIG_SCSI_MOD=y # CONFIG_SCSI_MPI3MR is not set # CONFIG_SCSI_MPT2SAS is not set # CONFIG_SCSI_MPT3SAS is not set -# CONFIG_SCSI_MQ_DEFAULT is not set # CONFIG_SCSI_MVSAS is not set # CONFIG_SCSI_MVSAS_DEBUG is not set # CONFIG_SCSI_MVUMI is not set # CONFIG_SCSI_MYRB is not set # CONFIG_SCSI_MYRS is not set -# CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_NETLINK is not set # CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_OSD_INITIATOR is not set -# CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PM8001 is not set # CONFIG_SCSI_PMCRAID is not set CONFIG_SCSI_PROC_FS=y @@ -5715,12 +5254,8 @@ CONFIG_SCSI_PROC_FS=y # CONFIG_SCSI_SPI_ATTRS is not set # CONFIG_SCSI_SRP_ATTRS is not set # CONFIG_SCSI_STEX is not set -# CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_UFSHCD is not set -# CONFIG_SCSI_ULTRASTOR is not set # CONFIG_SCSI_VIRTIO is not set # CONFIG_SCSI_WD719X is not set # CONFIG_SC_CAMCC_7180 is not set @@ -5754,10 +5289,8 @@ CONFIG_SECURITY_DMESG_RESTRICT=y # CONFIG_SECURITY_SAFESETID is not set # CONFIG_SECURITY_SELINUX_AVC_STATS is not set # CONFIG_SECURITY_SELINUX_BOOTPARAM is not set -CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0 # CONFIG_SECURITY_SELINUX_DEBUG is not set # CONFIG_SECURITY_SELINUX_DEVELOP is not set -# CONFIG_SECURITY_SELINUX_DISABLE is not set # CONFIG_SECURITY_SMACK is not set # CONFIG_SECURITY_TOMOYO is not set # CONFIG_SECURITY_YAMA is not set @@ -5783,7 +5316,6 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_ADM1266 is not set # CONFIG_SENSORS_ADM1275 is not set # CONFIG_SENSORS_ADM9240 is not set -# CONFIG_SENSORS_ADS1015 is not set # CONFIG_SENSORS_ADS7828 is not set # CONFIG_SENSORS_ADS7871 is not set # CONFIG_SENSORS_ADT7310 is not set @@ -5806,7 +5338,6 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_AXI_FAN_CONTROL is not set # CONFIG_SENSORS_BEL_PFE is not set # CONFIG_SENSORS_BH1770 is not set -# CONFIG_SENSORS_BH1780 is not set # CONFIG_SENSORS_BPA_RS600 is not set # CONFIG_SENSORS_CORETEMP is not set # CONFIG_SENSORS_CORSAIR_CPRO is not set @@ -5841,7 +5372,6 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_HMC5843_I2C is not set # CONFIG_SENSORS_HMC5843_SPI is not set # CONFIG_SENSORS_HS3001 is not set -# CONFIG_SENSORS_HTU21 is not set # CONFIG_SENSORS_I5500 is not set # CONFIG_SENSORS_I5K_AMB is not set # CONFIG_SENSORS_IBM_CFFPS is not set @@ -5953,7 +5483,6 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_Q54SJ108A2 is not set # CONFIG_SENSORS_RM3100_I2C is not set # CONFIG_SENSORS_RM3100_SPI is not set -# CONFIG_SENSORS_RP1_ADC is not set # CONFIG_SENSORS_SBRMI is not set # CONFIG_SENSORS_SBTSI is not set # CONFIG_SENSORS_SCH5627 is not set @@ -5965,7 +5494,6 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_SHT4x is not set # CONFIG_SENSORS_SHTC1 is not set # CONFIG_SENSORS_SIS5595 is not set -# CONFIG_SENSORS_SMM665 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_SMSC47M192 is not set @@ -6031,7 +5559,6 @@ CONFIG_SERIAL_8250_DMA=y # CONFIG_SERIAL_8250_LPSS is not set # CONFIG_SERIAL_8250_MANY_PORTS is not set # CONFIG_SERIAL_8250_MID is not set -# CONFIG_SERIAL_8250_MOXA is not set CONFIG_SERIAL_8250_NR_UARTS=2 # CONFIG_SERIAL_8250_PCI is not set # CONFIG_SERIAL_8250_PCI1XXXX is not set @@ -6054,13 +5581,11 @@ CONFIG_SERIAL_EARLYCON=y # CONFIG_SERIAL_FSL_LINFLEXUART is not set # CONFIG_SERIAL_FSL_LPUART is not set # CONFIG_SERIAL_GRLIB_GAISLER_APBUART is not set -# CONFIG_SERIAL_IFX6X60 is not set # CONFIG_SERIAL_JSM is not set # CONFIG_SERIAL_MAX3100 is not set # CONFIG_SERIAL_MAX310X is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_SERIAL_OF_PLATFORM is not set -# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set # CONFIG_SERIAL_PCH_UART is not set # CONFIG_SERIAL_RP2 is not set # CONFIG_SERIAL_SC16IS7XX is not set @@ -6091,11 +5616,9 @@ CONFIG_SERIAL_EARLYCON=y # CONFIG_SFC is not set # CONFIG_SFC_FALCON is not set # CONFIG_SFC_SIENA is not set -# CONFIG_SFI is not set # CONFIG_SFP is not set # CONFIG_SF_PDMA is not set # CONFIG_SGETMASK_SYSCALL is not set -# CONFIG_SGI_IOC4 is not set # CONFIG_SGI_IP22 is not set # CONFIG_SGI_IP27 is not set # CONFIG_SGI_IP28 is not set @@ -6107,7 +5630,6 @@ CONFIG_SERIAL_EARLYCON=y # CONFIG_SG_SPLIT is not set # CONFIG_SHADOW_CALL_STACK is not set CONFIG_SHMEM=y -# CONFIG_SHORTCUT_FE is not set # CONFIG_SHRINKER_DEBUG is not set # CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set # CONFIG_SH_ETH is not set @@ -6119,8 +5641,6 @@ CONFIG_SHMEM=y # CONFIG_SI7005 is not set # CONFIG_SI7020 is not set # CONFIG_SIBYTE_BIGSUR is not set -# CONFIG_SIBYTE_CARMEL is not set -# CONFIG_SIBYTE_CRHINE is not set # CONFIG_SIBYTE_CRHONE is not set # CONFIG_SIBYTE_LITTLESUR is not set # CONFIG_SIBYTE_RHONE is not set @@ -6128,15 +5648,12 @@ CONFIG_SHMEM=y # CONFIG_SIBYTE_SWARM is not set CONFIG_SIGNALFD=y # CONFIG_SIGNED_PE_FILE_VERIFICATION is not set -# CONFIG_SIMPLE_GPIO is not set -# CONFIG_SIMPLE_PM_BUS is not set # CONFIG_SIOX is not set # CONFIG_SIS190 is not set # CONFIG_SIS900 is not set # CONFIG_SKGE is not set # CONFIG_SKY2 is not set # CONFIG_SKY2_DEBUG is not set -CONFIG_SLABINFO=y # CONFIG_SLAB_DEPRECATED is not set CONFIG_SLAB_FREELIST_HARDENED=y CONFIG_SLAB_FREELIST_RANDOM=y @@ -6145,17 +5662,14 @@ CONFIG_SLAB_MERGE_DEFAULT=y # CONFIG_SLICOSS is not set # CONFIG_SLIMBUS is not set # CONFIG_SLIP is not set -# CONFIG_SLOB is not set CONFIG_SLUB=y CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_SLUB_DEBUG is not set # CONFIG_SLUB_DEBUG_ON is not set -# CONFIG_SLUB_MEMCG_SYSFS_ON is not set # CONFIG_SLUB_STATS is not set # CONFIG_SLUB_TINY is not set # CONFIG_SMARTJOYPLUS_FF is not set # CONFIG_SMB_SERVER is not set -# CONFIG_SMC911X is not set # CONFIG_SMC9194 is not set # CONFIG_SMC91X is not set # CONFIG_SMP is not set @@ -6194,7 +5708,6 @@ CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_SND_AU8830 is not set # CONFIG_SND_AUDIO_GRAPH_CARD is not set # CONFIG_SND_AUDIO_GRAPH_CARD2 is not set -# CONFIG_SND_AUDIO_GRAPH_SCU_CARD is not set # CONFIG_SND_AW2 is not set # CONFIG_SND_AZT2320 is not set # CONFIG_SND_AZT3328 is not set @@ -6222,7 +5735,6 @@ CONFIG_SND_DRIVERS=y # CONFIG_SND_DUMMY is not set # CONFIG_SND_DYNAMIC_MINORS is not set # CONFIG_SND_ECHO3G is not set -# CONFIG_SND_EDMA_SOC is not set # CONFIG_SND_EMU10K1 is not set # CONFIG_SND_EMU10K1X is not set # CONFIG_SND_EMU10K1_SEQ is not set @@ -6241,7 +5753,6 @@ CONFIG_SND_DRIVERS=y # CONFIG_SND_GUSMAX is not set # CONFIG_SND_HDA_CODEC_CS8409 is not set # CONFIG_SND_HDA_INTEL is not set -# CONFIG_SND_HDA_INTEL_DETECT_DMIC is not set # CONFIG_SND_HDA_INTEL_HDMI_SILENT_STREAM is not set CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 CONFIG_SND_HDA_PREALLOC_SIZE=64 @@ -6306,12 +5817,10 @@ CONFIG_SND_PCM_OSS_PLUGINS=y # CONFIG_SND_PPC is not set CONFIG_SND_PROC_FS=y # CONFIG_SND_RAWMIDI is not set -# CONFIG_SND_RAWMIDI_SEQ is not set # CONFIG_SND_RIPTIDE is not set # CONFIG_SND_RME32 is not set # CONFIG_SND_RME96 is not set # CONFIG_SND_RME9652 is not set -# CONFIG_SND_RTCTIMER is not set # CONFIG_SND_SB16 is not set # CONFIG_SND_SB8 is not set # CONFIG_SND_SBAWE is not set @@ -6322,7 +5831,6 @@ CONFIG_SND_PROC_FS=y # CONFIG_SND_SERIAL_GENERIC is not set # CONFIG_SND_SERIAL_U16550 is not set # CONFIG_SND_SIMPLE_CARD is not set -# CONFIG_SND_SIMPLE_SCU_CARD is not set # CONFIG_SND_SIS7019 is not set # CONFIG_SND_SOC is not set # CONFIG_SND_SOC_AC97_CODEC is not set @@ -6391,7 +5899,6 @@ CONFIG_SND_PROC_FS=y # CONFIG_SND_SOC_CS53L30 is not set # CONFIG_SND_SOC_CX2072X is not set # CONFIG_SND_SOC_DA7213 is not set -# CONFIG_SND_SOC_DIO2125 is not set # CONFIG_SND_SOC_DMIC is not set # CONFIG_SND_SOC_ES7134 is not set # CONFIG_SND_SOC_ES7241 is not set @@ -6424,10 +5931,8 @@ CONFIG_SND_PROC_FS=y # CONFIG_SND_SOC_IMX_HDMI is not set # CONFIG_SND_SOC_IMX_RPMSG is not set # CONFIG_SND_SOC_IMX_SPDIF is not set -# CONFIG_SND_SOC_IMX_WM8962 is not set # CONFIG_SND_SOC_INNO_RK3036 is not set # CONFIG_SND_SOC_INTEL_APL is not set -# CONFIG_SND_SOC_INTEL_BAYTRAIL is not set # CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH is not set # CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH is not set # CONFIG_SND_SOC_INTEL_BXT_RT298_MACH is not set @@ -6436,8 +5941,6 @@ CONFIG_SND_PROC_FS=y # CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH is not set # CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH is not set # CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH is not set -# CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH is not set -# CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH is not set # CONFIG_SND_SOC_INTEL_CATPT is not set # CONFIG_SND_SOC_INTEL_CFL is not set # CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH is not set @@ -6470,7 +5973,6 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_LPASS_TX_MACRO is not set # CONFIG_SND_SOC_LPASS_VA_MACRO is not set # CONFIG_SND_SOC_LPASS_WSA_MACRO is not set -# CONFIG_SND_SOC_MA120X0P is not set # CONFIG_SND_SOC_MAX9759 is not set # CONFIG_SND_SOC_MAX98088 is not set # CONFIG_SND_SOC_MAX98090 is not set @@ -6512,7 +6014,6 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_NAU8824 is not set # CONFIG_SND_SOC_PCM1681 is not set # CONFIG_SND_SOC_PCM1789_I2C is not set -# CONFIG_SND_SOC_PCM1792A is not set # CONFIG_SND_SOC_PCM179X_I2C is not set # CONFIG_SND_SOC_PCM179X_SPI is not set # CONFIG_SND_SOC_PCM186X_I2C is not set @@ -6538,7 +6039,6 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_SGTL5000 is not set # CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set # CONFIG_SND_SOC_SIMPLE_MUX is not set -# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set # CONFIG_SND_SOC_SMA1303 is not set # CONFIG_SND_SOC_SOF_TOPLEVEL is not set # CONFIG_SND_SOC_SPDIF is not set @@ -6613,7 +6113,6 @@ CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y # CONFIG_SND_SOC_XILINX_SPDIF is not set # CONFIG_SND_SOC_XTFPGA_I2S is not set # CONFIG_SND_SOC_ZL38060 is not set -# CONFIG_SND_SOC_ZX_AUD96P22 is not set # CONFIG_SND_SONICVIBES is not set # CONFIG_SND_SPI is not set # CONFIG_SND_SSCAPE is not set @@ -6655,7 +6154,6 @@ CONFIG_SND_X86=y # CONFIG_SOC_AM33XX is not set # CONFIG_SOC_AM43XX is not set # CONFIG_SOC_BRCMSTB is not set -# CONFIG_SOC_CAMERA is not set # CONFIG_SOC_DRA7XX is not set # CONFIG_SOC_HAS_OMAP2_SDRC is not set # CONFIG_SOC_OMAP5 is not set @@ -6669,13 +6167,11 @@ CONFIG_SND_X86=y # CONFIG_SOUNDWIRE is not set # CONFIG_SOUND_OSS_CORE is not set # CONFIG_SOUND_OSS_CORE_PRECLAIM is not set -# CONFIG_SOUND_PRIME is not set # CONFIG_SP5100_TCO is not set # CONFIG_SPARSEMEM_MANUAL is not set # CONFIG_SPARSEMEM_STATIC is not set # CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set # CONFIG_SPARSE_IRQ is not set -# CONFIG_SPARSE_RCU_POINTER is not set # CONFIG_SPEAKUP is not set # CONFIG_SPI is not set # CONFIG_SPINLOCK_TEST is not set @@ -6687,6 +6183,7 @@ CONFIG_SND_X86=y # CONFIG_SPI_BCM2835 is not set # CONFIG_SPI_BCM63XX_HSSPI is not set # CONFIG_SPI_BCM_QSPI is not set +# CONFIG_SPI_BCMBCA_HSSPI is not set # CONFIG_SPI_BITBANG is not set # CONFIG_SPI_BUTTERFLY is not set # CONFIG_SPI_CADENCE is not set @@ -6698,7 +6195,6 @@ CONFIG_SND_X86=y # CONFIG_SPI_FSL_ESPI is not set # CONFIG_SPI_FSL_SPI is not set # CONFIG_SPI_GPIO is not set -# CONFIG_SPI_GPIO_OLD is not set # CONFIG_SPI_IMG_SPFI is not set # CONFIG_SPI_LANTIQ_SSC is not set # CONFIG_SPI_LM70_LLP is not set @@ -6709,7 +6205,6 @@ CONFIG_SND_X86=y # CONFIG_SPI_MICROCHIP_CORE_QSPI is not set # CONFIG_SPI_MPC52xx is not set # CONFIG_SPI_MPC52xx_PSC is not set -# CONFIG_SPI_MTK_QUADSPI is not set # CONFIG_SPI_MUX is not set # CONFIG_SPI_MXIC is not set # CONFIG_SPI_NXP_FLEXSPI is not set @@ -6735,7 +6230,6 @@ CONFIG_SND_X86=y # CONFIG_SPI_TOPCLIFF_PCH is not set # CONFIG_SPI_XCOMM is not set # CONFIG_SPI_XILINX is not set -# CONFIG_SPI_XWAY is not set # CONFIG_SPI_ZYNQMP_GQSPI is not set CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_SPMI is not set @@ -6762,13 +6256,11 @@ CONFIG_SQUASHFS_XZ=y # CONFIG_SRF04 is not set # CONFIG_SRF08 is not set # CONFIG_SSB is not set -# CONFIG_SSB_DEBUG is not set # CONFIG_SSB_DRIVER_GPIO is not set # CONFIG_SSB_HOST_SOC is not set # CONFIG_SSB_PCMCIAHOST is not set CONFIG_SSB_POSSIBLE=y # CONFIG_SSB_SDIOHOST is not set -# CONFIG_SSB_SILENT is not set # CONFIG_SSFDC is not set # CONFIG_SSIF_IPMI_BMC is not set # CONFIG_STACKPROTECTOR is not set @@ -6777,19 +6269,15 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_STACKTRACE is not set # CONFIG_STACKTRACE_BUILD_ID is not set CONFIG_STACKTRACE_SUPPORT=y -CONFIG_STACK_HASH_ORDER=20 # CONFIG_STACK_TRACER is not set # CONFIG_STACK_VALIDATION is not set CONFIG_STAGING=y # CONFIG_STAGING_BOARD is not set -# CONFIG_STAGING_GASKET_FRAMEWORK is not set # CONFIG_STAGING_MEDIA is not set CONFIG_STANDALONE=y # CONFIG_STATIC_KEYS_SELFTEST is not set # CONFIG_STATIC_USERMODEHELPER is not set -CONFIG_STDBINUTILS=y # CONFIG_STE10XP is not set -# CONFIG_STE_MODEM_RPROC is not set # CONFIG_STK3310 is not set # CONFIG_STK8312 is not set # CONFIG_STK8BA50 is not set @@ -6817,18 +6305,15 @@ CONFIG_STRIP_ASM_SYMS=y # CONFIG_SUNGEM is not set # CONFIG_SUNRPC is not set # CONFIG_SUNRPC_DEBUG is not set -CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES=y # CONFIG_SUNRPC_GSS is not set # CONFIG_SUNXI_SRAM is not set # CONFIG_SUN_PARTITION is not set -# CONFIG_SURFACE_3_BUTTON is not set # CONFIG_SURFACE_PLATFORMS is not set # CONFIG_SUSPEND is not set # CONFIG_SUSPEND_SKIP_SYNC is not set CONFIG_SWAP=y # CONFIG_SWCONFIG is not set # CONFIG_SWCONFIG_B53 is not set -# CONFIG_SWCONFIG_B53_MDIO_DRIVER is not set # CONFIG_SWCONFIG_B53_MMAP_DRIVER is not set # CONFIG_SWCONFIG_B53_SPI_DRIVER is not set # CONFIG_SWCONFIG_B53_SRAB_DRIVER is not set @@ -6842,18 +6327,13 @@ CONFIG_SWAP=y # CONFIG_SX9500 is not set # CONFIG_SXGBE_ETH is not set CONFIG_SYMBOLIC_ERRNAME=y -# CONFIG_SYNCLINK_CS is not set # CONFIG_SYNC_FILE is not set -# CONFIG_SYNOPSYS_DWC_ETH_QOS is not set # CONFIG_SYNTH_EVENTS is not set # CONFIG_SYNTH_EVENT_GEN_TEST is not set CONFIG_SYN_COOKIES=y # CONFIG_SYSCON_REBOOT_MODE is not set CONFIG_SYSCTL=y -# CONFIG_SYSCTL_SYSCALL is not set CONFIG_SYSFS=y -# CONFIG_SYSFS_DEPRECATED is not set -# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_SYSFS_SYSCALL is not set # CONFIG_SYSTEMPORT is not set # CONFIG_SYSTEM_BLACKLIST_KEYRING is not set @@ -6876,7 +6356,6 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_TCG_FTPM_TEE is not set # CONFIG_TCG_INFINEON is not set # CONFIG_TCG_NSC is not set -# CONFIG_TCG_ST33_I2C is not set # CONFIG_TCG_TIS is not set # CONFIG_TCG_TIS_I2C is not set # CONFIG_TCG_TIS_I2C_ATMEL is not set @@ -6916,7 +6395,6 @@ CONFIG_TCP_CONG_CUBIC=y # CONFIG_TEHUTI is not set # CONFIG_TERANETICS_PHY is not set # CONFIG_TEST_ASYNC_DRIVER_PROBE is not set -# CONFIG_TEST_BITFIELD is not set # CONFIG_TEST_BITMAP is not set # CONFIG_TEST_BITOPS is not set # CONFIG_TEST_BLACKHOLE_DEV is not set @@ -6928,10 +6406,8 @@ CONFIG_TCP_CONG_CUBIC=y # CONFIG_TEST_DYNAMIC_DEBUG is not set # CONFIG_TEST_FIRMWARE is not set # CONFIG_TEST_FREE_PAGES is not set -# CONFIG_TEST_HASH is not set # CONFIG_TEST_HEXDUMP is not set # CONFIG_TEST_IDA is not set -# CONFIG_TEST_KASAN_MODULE is not set # CONFIG_TEST_KMOD is not set # CONFIG_TEST_KSTRTOX is not set # CONFIG_TEST_LIST_SORT is not set @@ -6941,18 +6417,14 @@ CONFIG_TCP_CONG_CUBIC=y # CONFIG_TEST_MEMCAT_P is not set # CONFIG_TEST_MEMINIT is not set # CONFIG_TEST_MIN_HEAP is not set -# CONFIG_TEST_OVERFLOW is not set # CONFIG_TEST_POWER is not set # CONFIG_TEST_PRINTF is not set # CONFIG_TEST_REF_TRACKER is not set # CONFIG_TEST_RHASHTABLE is not set # CONFIG_TEST_SCANF is not set -# CONFIG_TEST_SIPHASH is not set # CONFIG_TEST_SORT is not set -# CONFIG_TEST_STACKINIT is not set # CONFIG_TEST_STATIC_KEYS is not set # CONFIG_TEST_STRING_HELPERS is not set -# CONFIG_TEST_STRSCPY is not set # CONFIG_TEST_SYSCTL is not set # CONFIG_TEST_UBSAN is not set # CONFIG_TEST_UDELAY is not set @@ -6980,10 +6452,8 @@ CONFIG_TEXTSEARCH=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_THERMAL_WRITABLE_TRIPS is not set # CONFIG_THINKPAD_ACPI is not set -CONFIG_THIN_ARCHIVES=y # CONFIG_THRUSTMASTER_FF is not set # CONFIG_THUMB2_KERNEL is not set -# CONFIG_THUNDERBOLT is not set # CONFIG_THUNDER_NIC_BGX is not set # CONFIG_THUNDER_NIC_PF is not set # CONFIG_THUNDER_NIC_RGX is not set @@ -6995,7 +6465,6 @@ CONFIG_TICK_ONESHOT=y # CONFIG_TIMB_DMA is not set CONFIG_TIMERFD=y # CONFIG_TIMERLAT_TRACER is not set -# CONFIG_TIMER_STATS is not set # CONFIG_TIME_NS is not set # CONFIG_TINYDRM_HX8357D is not set # CONFIG_TINYDRM_ILI9163 is not set @@ -7025,19 +6494,15 @@ CONFIG_TINY_RCU=y # CONFIG_TI_ADS8688 is not set # CONFIG_TI_AM335X_ADC is not set # CONFIG_TI_CPSW is not set -# CONFIG_TI_CPSW_ALE is not set # CONFIG_TI_CPSW_PHY_SEL is not set # CONFIG_TI_CPTS is not set # CONFIG_TI_DAC082S085 is not set # CONFIG_TI_DAC5571 is not set # CONFIG_TI_DAC7311 is not set -# CONFIG_TI_DAC7512 is not set # CONFIG_TI_DAC7612 is not set -# CONFIG_TI_DAVINCI_CPDMA is not set # CONFIG_TI_DAVINCI_MDIO is not set # CONFIG_TI_LMP92064 is not set # CONFIG_TI_ST is not set -# CONFIG_TI_SYSCON_RESET is not set # CONFIG_TI_TLC4541 is not set # CONFIG_TI_TMAG5273 is not set # CONFIG_TI_TSC2046 is not set @@ -7129,12 +6594,9 @@ CONFIG_TMPFS_XATTR=y # CONFIG_TOUCHSCREEN_PCAP is not set # CONFIG_TOUCHSCREEN_PENMOUNT is not set # CONFIG_TOUCHSCREEN_PIXCIR is not set -# CONFIG_TOUCHSCREEN_PROPERTIES is not set # CONFIG_TOUCHSCREEN_RASPBERRYPI_FW is not set # CONFIG_TOUCHSCREEN_RM_TS is not set # CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set -# CONFIG_TOUCHSCREEN_RPI_FT5406 is not set -# CONFIG_TOUCHSCREEN_S3C2410 is not set # CONFIG_TOUCHSCREEN_S6SY761 is not set # CONFIG_TOUCHSCREEN_SILEAD is not set # CONFIG_TOUCHSCREEN_SIS_I2C is not set @@ -7157,7 +6619,6 @@ CONFIG_TMPFS_XATTR=y # CONFIG_TOUCHSCREEN_TSC2007_IIO is not set # CONFIG_TOUCHSCREEN_TSC200X_CORE is not set # CONFIG_TOUCHSCREEN_TSC_SERIO is not set -# CONFIG_TOUCHSCREEN_UCB1400 is not set # CONFIG_TOUCHSCREEN_USB_3M is not set # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set # CONFIG_TOUCHSCREEN_USB_DMC_TSC10 is not set @@ -7177,7 +6638,6 @@ CONFIG_TMPFS_XATTR=y # CONFIG_TOUCHSCREEN_USB_NEXIO is not set # CONFIG_TOUCHSCREEN_USB_PANJIT is not set # CONFIG_TOUCHSCREEN_USB_ZYTRONIC is not set -# CONFIG_TOUCHSCREEN_W90X900 is not set # CONFIG_TOUCHSCREEN_WACOM_I2C is not set # CONFIG_TOUCHSCREEN_WACOM_W8001 is not set # CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set @@ -7187,7 +6647,6 @@ CONFIG_TMPFS_XATTR=y # CONFIG_TOUCHSCREEN_WM9713 is not set # CONFIG_TOUCHSCREEN_WM97XX is not set # CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE is not set -# CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE is not set # CONFIG_TOUCHSCREEN_ZET6223 is not set # CONFIG_TOUCHSCREEN_ZFORCE is not set # CONFIG_TOUCHSCREEN_ZINITIX is not set @@ -7203,13 +6662,10 @@ CONFIG_TMPFS_XATTR=y # CONFIG_TRACE_EVENT_INJECT is not set CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_TRACE_MMIO_ACCESS is not set -# CONFIG_TRACE_SINK is not set -# CONFIG_TRACING_EVENTS_GPIO is not set CONFIG_TRACING_SUPPORT=y CONFIG_TRAD_SIGNALS=y # CONFIG_TRANSPARENT_HUGEPAGE is not set # CONFIG_TREE_RCU is not set -# CONFIG_TREE_RCU_TRACE is not set # CONFIG_TRIM_UNUSED_KSYMS is not set # CONFIG_TRUSTED_FOUNDATIONS is not set # CONFIG_TRUSTED_KEYS is not set @@ -7219,7 +6675,6 @@ CONFIG_TRAD_SIGNALS=y # CONFIG_TSL2583 is not set # CONFIG_TSL2591 is not set # CONFIG_TSL2772 is not set -# CONFIG_TSL2x7x is not set # CONFIG_TSL4531 is not set # CONFIG_TSNEP is not set # CONFIG_TSYS01 is not set @@ -7244,7 +6699,6 @@ CONFIG_TTY=y # CONFIG_UBIFS_ATIME_SUPPORT is not set # CONFIG_UBIFS_FS_ADVANCED_COMPR is not set # CONFIG_UBIFS_FS_AUTHENTICATION is not set -# CONFIG_UBIFS_FS_ENCRYPTION is not set CONFIG_UBIFS_FS_LZO=y # CONFIG_UBIFS_FS_SECURITY is not set CONFIG_UBIFS_FS_XATTR=y @@ -7255,11 +6709,8 @@ CONFIG_UBSAN_ALIGNMENT=y CONFIG_UBSAN_BOOL=y # CONFIG_UBSAN_DIV_ZERO is not set CONFIG_UBSAN_ENUM=y -# CONFIG_UBSAN_MISC is not set CONFIG_UBSAN_SHIFT=y # CONFIG_UBSAN_UNREACHABLE is not set -# CONFIG_UCB1400_CORE is not set -# CONFIG_UCSI is not set # CONFIG_UDF_FS is not set # CONFIG_UDMABUF is not set CONFIG_UEVENT_HELPER=y @@ -7272,15 +6723,11 @@ CONFIG_UID16=y # CONFIG_ULTRA is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_UNICODE is not set -# CONFIG_UNISYSSPAR is not set -# CONFIG_UNISYS_VISORBUS is not set CONFIG_UNIX=y CONFIG_UNIX98_PTYS=y # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_UNIX_DIAG is not set CONFIG_UNIX_SCM=y -# CONFIG_UNUSED_BOARD_FILES is not set -# CONFIG_UNUSED_SYMBOLS is not set # CONFIG_UNWINDER_FRAME_POINTER is not set # CONFIG_UPROBES is not set # CONFIG_UPROBE_EVENTS is not set @@ -7313,8 +6760,8 @@ CONFIG_USB_BELKIN=y # CONFIG_USB_CDNS3 is not set # CONFIG_USB_CDNS3_IMX is not set # CONFIG_USB_CDNS3_PCI_WRAP is not set -# CONFIG_USB_CDNSP_PCI is not set # CONFIG_USB_CDNS_SUPPORT is not set +# CONFIG_USB_CDNSP_PCI is not set # CONFIG_USB_CHAOSKEY is not set # CONFIG_USB_CHIPIDEA is not set # CONFIG_USB_CHIPIDEA_GENERIC is not set @@ -7346,13 +6793,11 @@ CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DWC3_ULPI is not set # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_EG20T is not set -# CONFIG_USB_EHCI_ATH79 is not set # CONFIG_USB_EHCI_FSL is not set # CONFIG_USB_EHCI_HCD is not set # CONFIG_USB_EHCI_HCD_AT91 is not set # CONFIG_USB_EHCI_HCD_OMAP is not set # CONFIG_USB_EHCI_HCD_PPC_OF is not set -# CONFIG_USB_EHCI_MSM is not set # CONFIG_USB_EHCI_MV is not set CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y @@ -7366,7 +6811,6 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y # CONFIG_USB_FOTG210_HCD is not set # CONFIG_USB_FOTG210_UDC is not set # CONFIG_USB_FSL_USB2 is not set -# CONFIG_USB_FTDI_ELAN is not set # CONFIG_USB_FUNCTIONFS is not set # CONFIG_USB_FUSB300 is not set # CONFIG_USB_GADGET is not set @@ -7445,9 +6889,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=2 # CONFIG_USB_HSIC_USB4604 is not set # CONFIG_USB_HSO is not set # CONFIG_USB_HUB_USB251XB is not set -# CONFIG_USB_HWA_HCD is not set # CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_IMX21_HCD is not set # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_IPHETH is not set # CONFIG_USB_ISIGHTFW is not set @@ -7462,7 +6904,6 @@ CONFIG_USB_GADGET_VBUS_DRAW=2 # CONFIG_USB_LAN78XX is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LD is not set -# CONFIG_USB_LED is not set # CONFIG_USB_LEDS_TRIGGER_USBPORT is not set # CONFIG_USB_LED_TRIG is not set # CONFIG_USB_LEGOTOWER is not set @@ -7479,7 +6920,6 @@ CONFIG_USB_GADGET_VBUS_DRAW=2 # CONFIG_USB_MON is not set # CONFIG_USB_MOUSE is not set # CONFIG_USB_MSI2500 is not set -# CONFIG_USB_MSM_OTG is not set # CONFIG_USB_MTU3 is not set # CONFIG_USB_MUSB_GADGET is not set # CONFIG_USB_MUSB_HDRC is not set @@ -7525,11 +6965,9 @@ CONFIG_USB_GADGET_VBUS_DRAW=2 CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_ONBOARD_HUB is not set # CONFIG_USB_OTG is not set -# CONFIG_USB_OTG_BLACKLIST_HUB is not set # CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB is not set # CONFIG_USB_OTG_FSM is not set # CONFIG_USB_OTG_PRODUCTLIST is not set -# CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_PCI is not set # CONFIG_USB_PEGASUS is not set @@ -7541,9 +6979,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_R8A66597 is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_RAW_GADGET is not set -# CONFIG_USB_RCAR_PHY is not set # CONFIG_USB_RENESAS_USBHS is not set -# CONFIG_USB_RIO500 is not set # CONFIG_USB_ROLES_INTEL_XHCI is not set # CONFIG_USB_ROLE_SWITCH is not set # CONFIG_USB_RTL8150 is not set @@ -7573,19 +7009,7 @@ CONFIG_USB_SERIAL_GENERIC=y # CONFIG_USB_SERIAL_IR is not set # CONFIG_USB_SERIAL_IUU is not set # CONFIG_USB_SERIAL_KEYSPAN is not set -CONFIG_USB_SERIAL_KEYSPAN_MPR=y # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -CONFIG_USB_SERIAL_KEYSPAN_USA18X=y -CONFIG_USB_SERIAL_KEYSPAN_USA19=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -CONFIG_USB_SERIAL_KEYSPAN_USA28=y -CONFIG_USB_SERIAL_KEYSPAN_USA28X=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y # CONFIG_USB_SERIAL_KLSI is not set # CONFIG_USB_SERIAL_KOBIL_SCT is not set # CONFIG_USB_SERIAL_MCT_U232 is not set @@ -7615,7 +7039,6 @@ CONFIG_USB_SERIAL_SAFE_PADDED=y # CONFIG_USB_SERIAL_VISOR is not set # CONFIG_USB_SERIAL_WHITEHEAT is not set # CONFIG_USB_SERIAL_WISHBONE is not set -# CONFIG_USB_SERIAL_XIRCOM is not set # CONFIG_USB_SERIAL_XR is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SEVSEG is not set @@ -7624,7 +7047,6 @@ CONFIG_USB_SERIAL_SAFE_PADDED=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_SNP_UDC_PLAT is not set # CONFIG_USB_SPEEDTOUCH is not set -# CONFIG_USB_STKWEBCAM is not set # CONFIG_USB_STORAGE is not set # CONFIG_USB_STORAGE_ALAUDA is not set # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set @@ -7642,7 +7064,6 @@ CONFIG_USB_SERIAL_SAFE_PADDED=y # CONFIG_USB_STORAGE_USBAT is not set # CONFIG_USB_STV06XX is not set # CONFIG_USB_SUPPORT is not set -# CONFIG_USB_SWITCH_FSA9480 is not set # CONFIG_USB_TEST is not set # CONFIG_USB_TMC is not set # CONFIG_USB_TRANCEVIBRATOR is not set @@ -7656,9 +7077,6 @@ CONFIG_USB_SERIAL_SAFE_PADDED=y CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y # CONFIG_USB_VL600 is not set # CONFIG_USB_WDM is not set -# CONFIG_USB_WHCI_HCD is not set -# CONFIG_USB_WUSB is not set -# CONFIG_USB_WUSB_CBAF is not set # CONFIG_USB_XEN_HCD is not set # CONFIG_USB_XHCI_DBGCAP is not set # CONFIG_USB_XHCI_HCD is not set @@ -7668,7 +7086,6 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y # CONFIG_USB_YUREX is not set # CONFIG_USB_ZD1201 is not set # CONFIG_USB_ZERO is not set -# CONFIG_USB_ZR364XX is not set # CONFIG_USELIB is not set # CONFIG_USERFAULTFD is not set # CONFIG_USERIO is not set @@ -7676,7 +7093,6 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y # CONFIG_USER_EVENTS is not set # CONFIG_USE_OF is not set # CONFIG_UTS_NS is not set -# CONFIG_UWB is not set # CONFIG_U_SERIAL_CONSOLE is not set # CONFIG_V4L_MEM2MEM_DRIVERS is not set # CONFIG_V4L_PLATFORM_DRIVERS is not set @@ -7710,9 +7126,7 @@ CONFIG_VHOST_MENU=y # CONFIG_VHOST_VSOCK is not set # CONFIG_VIA_RHINE is not set # CONFIG_VIA_VELOCITY is not set -# CONFIG_VIDEO_AD5398 is not set # CONFIG_VIDEO_AD5820 is not set -# CONFIG_VIDEO_AD9389B is not set # CONFIG_VIDEO_ADP1653 is not set # CONFIG_VIDEO_ADV7170 is not set # CONFIG_VIDEO_ADV7175 is not set @@ -7729,20 +7143,15 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_AK881X is not set # CONFIG_VIDEO_AM437X_VPFE is not set # CONFIG_VIDEO_AR0521 is not set -# CONFIG_VIDEO_ARDUCAM_64MP is not set -# CONFIG_VIDEO_ARDUCAM_PIVARIETY is not set # CONFIG_VIDEO_ASPEED is not set # CONFIG_VIDEO_ATMEL_ISC is not set # CONFIG_VIDEO_ATMEL_ISI is not set # CONFIG_VIDEO_AU0828 is not set # CONFIG_VIDEO_BCM2835 is not set -# CONFIG_VIDEO_BCM2835_UNICAM is not set # CONFIG_VIDEO_BT819 is not set # CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_BT856 is not set # CONFIG_VIDEO_BT866 is not set -# CONFIG_VIDEO_BU64754 is not set -# CONFIG_VIDEO_CADENCE is not set # CONFIG_VIDEO_CADENCE_CSI2RX is not set # CONFIG_VIDEO_CADENCE_CSI2TX is not set # CONFIG_VIDEO_CAFE_CCIC is not set @@ -7750,7 +7159,6 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_CCS is not set # CONFIG_VIDEO_COBALT is not set # CONFIG_VIDEO_CODA is not set -# CONFIG_VIDEO_CODEC_BCM2835 is not set # CONFIG_VIDEO_CS3308 is not set # CONFIG_VIDEO_CS5345 is not set # CONFIG_VIDEO_CS53L32A is not set @@ -7760,7 +7168,6 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_CX25840 is not set # CONFIG_VIDEO_CX88 is not set # CONFIG_VIDEO_DEV is not set -# CONFIG_VIDEO_DM6446_CCDC is not set # CONFIG_VIDEO_DS90UB913 is not set # CONFIG_VIDEO_DS90UB953 is not set # CONFIG_VIDEO_DS90UB960 is not set @@ -7793,45 +7200,38 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_IMX335 is not set # CONFIG_VIDEO_IMX355 is not set # CONFIG_VIDEO_IMX412 is not set -# CONFIG_VIDEO_IMX477 is not set -# CONFIG_VIDEO_IMX519 is not set -# CONFIG_VIDEO_IMX708 is not set +# CONFIG_VIDEO_IMX7_CSI is not set +# CONFIG_VIDEO_IMX8MQ_MIPI_CSI2 is not set +# CONFIG_VIDEO_IMX8_ISI is not set # CONFIG_VIDEO_IMX8_JPEG is not set # CONFIG_VIDEO_IMX_MIPI_CSIS is not set # CONFIG_VIDEO_IMX_PXP is not set -# CONFIG_VIDEO_IRS1125 is not set # CONFIG_VIDEO_IR_I2C is not set # CONFIG_VIDEO_ISL7998X is not set -# CONFIG_VIDEO_ISP_BCM2835 is not set # CONFIG_VIDEO_IVTV is not set # CONFIG_VIDEO_KS0127 is not set # CONFIG_VIDEO_LM3560 is not set # CONFIG_VIDEO_LM3646 is not set # CONFIG_VIDEO_M52790 is not set -# CONFIG_VIDEO_M5MOLS is not set # CONFIG_VIDEO_MAX9286 is not set # CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set # CONFIG_VIDEO_ML86V7667 is not set # CONFIG_VIDEO_MSP3400 is not set # CONFIG_VIDEO_MT9M001 is not set -# CONFIG_VIDEO_MT9M032 is not set # CONFIG_VIDEO_MT9M111 is not set # CONFIG_VIDEO_MT9P031 is not set -# CONFIG_VIDEO_MT9T001 is not set # CONFIG_VIDEO_MT9T112 is not set # CONFIG_VIDEO_MT9V011 is not set # CONFIG_VIDEO_MT9V032 is not set # CONFIG_VIDEO_MT9V111 is not set # CONFIG_VIDEO_MUX is not set # CONFIG_VIDEO_MXB is not set -# CONFIG_VIDEO_NOON010PC30 is not set # CONFIG_VIDEO_OG01A1B is not set # CONFIG_VIDEO_OMAP2_VOUT is not set # CONFIG_VIDEO_OV02A10 is not set # CONFIG_VIDEO_OV08D10 is not set # CONFIG_VIDEO_OV13858 is not set # CONFIG_VIDEO_OV13B10 is not set -# CONFIG_VIDEO_OV2311 is not set # CONFIG_VIDEO_OV2640 is not set # CONFIG_VIDEO_OV2659 is not set # CONFIG_VIDEO_OV2680 is not set @@ -7845,7 +7245,6 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_OV5675 is not set # CONFIG_VIDEO_OV5693 is not set # CONFIG_VIDEO_OV5695 is not set -# CONFIG_VIDEO_OV64A40 is not set # CONFIG_VIDEO_OV6650 is not set # CONFIG_VIDEO_OV7251 is not set # CONFIG_VIDEO_OV7640 is not set @@ -7854,13 +7253,11 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_OV7740 is not set # CONFIG_VIDEO_OV8856 is not set # CONFIG_VIDEO_OV8865 is not set -# CONFIG_VIDEO_OV9281 is not set # CONFIG_VIDEO_OV9282 is not set # CONFIG_VIDEO_OV9640 is not set # CONFIG_VIDEO_OV9650 is not set # CONFIG_VIDEO_OV9734 is not set # CONFIG_VIDEO_PVRUSB2 is not set -# CONFIG_VIDEO_RASPBERRYPI_PISP_BE is not set # CONFIG_VIDEO_RCAR_CSI2 is not set # CONFIG_VIDEO_RCAR_ISP is not set # CONFIG_VIDEO_RCAR_VIN is not set @@ -7868,12 +7265,9 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_RDACM21 is not set # CONFIG_VIDEO_RJ54N1 is not set # CONFIG_VIDEO_ROCKCHIP_ISP1 is not set -# CONFIG_VIDEO_RP1_CFE is not set # CONFIG_VIDEO_S5C73M3 is not set -# CONFIG_VIDEO_S5K4ECGX is not set # CONFIG_VIDEO_S5K5BAF is not set # CONFIG_VIDEO_S5K6A3 is not set -# CONFIG_VIDEO_S5K6AA is not set # CONFIG_VIDEO_SAA6588 is not set # CONFIG_VIDEO_SAA6752HS is not set # CONFIG_VIDEO_SAA7110 is not set @@ -7883,13 +7277,9 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_SAA7164 is not set # CONFIG_VIDEO_SAA717X is not set # CONFIG_VIDEO_SAA7185 is not set -# CONFIG_VIDEO_SH_MOBILE_CEU is not set -# CONFIG_VIDEO_SMIAPP is not set # CONFIG_VIDEO_SOLO6X10 is not set # CONFIG_VIDEO_SONY_BTF_MPX is not set -# CONFIG_VIDEO_SR030PC30 is not set # CONFIG_VIDEO_STK1160 is not set -# CONFIG_VIDEO_STK1160_COMMON is not set # CONFIG_VIDEO_ST_MIPID02 is not set # CONFIG_VIDEO_SUN4I_CSI is not set # CONFIG_VIDEO_SUN6I_CSI is not set @@ -7903,9 +7293,7 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_TEA6420 is not set # CONFIG_VIDEO_THS7303 is not set # CONFIG_VIDEO_THS8200 is not set -# CONFIG_VIDEO_TIMBERDALE is not set # CONFIG_VIDEO_TLV320AIC23B is not set -# CONFIG_VIDEO_TM6000 is not set # CONFIG_VIDEO_TVAUDIO is not set # CONFIG_VIDEO_TVP514X is not set # CONFIG_VIDEO_TVP5150 is not set @@ -7920,17 +7308,13 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_UPD64031A is not set # CONFIG_VIDEO_UPD64083 is not set # CONFIG_VIDEO_USBTV is not set -# CONFIG_VIDEO_USBVISION is not set -# CONFIG_VIDEO_V4L2 is not set # CONFIG_VIDEO_VP27SMPX is not set # CONFIG_VIDEO_VPX3220 is not set -# CONFIG_VIDEO_VS6624 is not set # CONFIG_VIDEO_WM8739 is not set # CONFIG_VIDEO_WM8775 is not set # CONFIG_VIDEO_XILINX is not set # CONFIG_VIDEO_ZORAN is not set # CONFIG_VIRTIO_BALLOON is not set -# CONFIG_VIRTIO_BLK_SCSI is not set # CONFIG_VIRTIO_CONSOLE is not set # CONFIG_VIRTIO_FS is not set # CONFIG_VIRTIO_INPUT is not set @@ -7941,7 +7325,6 @@ CONFIG_VIRTIO_MENU=y # CONFIG_VIRTUALIZATION is not set # CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set # CONFIG_VIRT_DRIVERS is not set -CONFIG_VIRT_TO_BUS=y # CONFIG_VITESSE_PHY is not set # CONFIG_VL53L0X_I2C is not set # CONFIG_VL6180 is not set @@ -7960,7 +7343,6 @@ CONFIG_VMSPLIT_3G=y # CONFIG_VMWARE_VMCI is not set # CONFIG_VMXNET3 is not set # CONFIG_VM_EVENT_COUNTERS is not set -# CONFIG_VOP_BUS is not set # CONFIG_VORTEX is not set # CONFIG_VSOCKETS is not set # CONFIG_VSOCKETS_DIAG is not set @@ -7968,12 +7350,10 @@ CONFIG_VMSPLIT_3G=y # CONFIG_VT6655 is not set # CONFIG_VT6656 is not set # CONFIG_VXFS_FS is not set -# CONFIG_VXGE is not set # CONFIG_VXLAN is not set # CONFIG_VZ89X is not set # CONFIG_W1 is not set # CONFIG_W1_CON is not set -# CONFIG_W1_MASTER_DS1WM is not set # CONFIG_W1_MASTER_DS2482 is not set # CONFIG_W1_MASTER_DS2490 is not set # CONFIG_W1_MASTER_GPIO is not set @@ -8015,16 +7395,13 @@ CONFIG_WATCHDOG_OPEN_TIMEOUT=0 # CONFIG_WDAT_WDT is not set # CONFIG_WDTPCI is not set # CONFIG_WERROR is not set -CONFIG_WEXT_CORE=y -CONFIG_WEXT_PRIV=y -CONFIG_WEXT_PROC=y -CONFIG_WEXT_SPY=y -CONFIG_WILINK_PLATFORM_DATA=y -# CONFIG_WIMAX is not set +# CONFIG_WEXT_CORE is not set +# CONFIG_WEXT_PRIV is not set +# CONFIG_WEXT_PROC is not set +# CONFIG_WEXT_SPY is not set # CONFIG_WIREGUARD is not set CONFIG_WIRELESS=y -CONFIG_WIRELESS_EXT=y -# CONFIG_WIRELESS_WDS is not set +# CONFIG_WIRELESS_EXT is not set # CONFIG_WIZNET_W5100 is not set # CONFIG_WIZNET_W5300 is not set # CONFIG_WL1251 is not set @@ -8061,7 +7438,6 @@ CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y # CONFIG_X25 is not set # CONFIG_X509_CERTIFICATE_PARSER is not set # CONFIG_X86_PKG_TEMP_THERMAL is not set -CONFIG_X86_SYSFB=y # CONFIG_X9250 is not set # CONFIG_XDP_SOCKETS is not set # CONFIG_XEN is not set @@ -8146,4 +7522,3 @@ CONFIG_ZONE_DMA=y # CONFIG_ZSMALLOC is not set CONFIG_ZSMALLOC_CHAIN_SIZE=8 # CONFIG_ZSWAP is not set -# CONFIG_ZX_TDM is not set diff --git a/lede/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig b/lede/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig index 794a39f2c3..17d590890d 100644 --- a/lede/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig +++ b/lede/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig @@ -12,7 +12,6 @@ config MTD_SPLIT_SQUASHFS_ROOT bool "Squashfs based root partition parser" depends on MTD_SPLIT_SUPPORT select MTD_SPLIT - default n help This provides a parsing function which allows to detect the offset and size of the unused portion of a rootfs partition @@ -32,7 +31,7 @@ config MTD_SPLIT_BCM_WFI_FW config MTD_SPLIT_CFE_BOOTFS bool "Parser finding rootfs appended to the CFE bootfs" - depends on MTD_SPLIT_SUPPORT && ARCH_BCM4908 + depends on MTD_SPLIT_SUPPORT && (ARCH_BCM4908 || ARCH_BCMBCA) select MTD_SPLIT help cferom on BCM4908 (and bcm63xx) uses JFFS2 bootfs partition @@ -101,3 +100,13 @@ config MTD_SPLIT_ELF_FW bool "ELF loader firmware partition parser" depends on MTD_SPLIT_SUPPORT select MTD_SPLIT + +config MTD_SPLIT_H3C_VFS + bool "Parser finding rootfs appended to H3C VFS" + depends on MTD_SPLIT_SUPPORT + select MTD_SPLIT + +config MTD_SPLIT_SEIL_FW + bool "IIJ SEIL firmware parser" + depends on MTD_SPLIT_SUPPORT + select MTD_SPLIT diff --git a/lede/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile b/lede/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile index 1461099b7c..e9d63c8332 100644 --- a/lede/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile +++ b/lede/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_MTD_SPLIT_BCM63XX_FW) += mtdsplit_bcm63xx.o obj-$(CONFIG_MTD_SPLIT_BCM_WFI_FW) += mtdsplit_bcm_wfi.o obj-$(CONFIG_MTD_SPLIT_CFE_BOOTFS) += mtdsplit_cfe_bootfs.o obj-$(CONFIG_MTD_SPLIT_SEAMA_FW) += mtdsplit_seama.o +obj-$(CONFIG_MTD_SPLIT_SEIL_FW) += mtdsplit_seil.o obj-$(CONFIG_MTD_SPLIT_SQUASHFS_ROOT) += mtdsplit_squashfs.o obj-$(CONFIG_MTD_SPLIT_UIMAGE_FW) += mtdsplit_uimage.o obj-$(CONFIG_MTD_SPLIT_FIT_FW) += mtdsplit_fit.o @@ -15,3 +16,4 @@ obj-$(CONFIG_MTD_SPLIT_WRGG_FW) += mtdsplit_wrgg.o obj-$(CONFIG_MTD_SPLIT_MINOR_FW) += mtdsplit_minor.o obj-$(CONFIG_MTD_SPLIT_JIMAGE_FW) += mtdsplit_jimage.o obj-$(CONFIG_MTD_SPLIT_ELF_FW) += mtdsplit_elf.o +obj-$(CONFIG_MTD_SPLIT_H3C_VFS) += mtdsplit_h3c_vfs.o diff --git a/lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c b/lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c index 1ddcf6745f..1cafc91fde 100644 --- a/lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c +++ b/lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c @@ -31,6 +31,7 @@ #define CFERAM_NAME "cferam" #define CFERAM_NAME_LEN (sizeof(CFERAM_NAME) - 1) +#define CFERAM_NAME_MAX_LEN 32 #define KERNEL_NAME "vmlinux.lz" #define KERNEL_NAME_LEN (sizeof(KERNEL_NAME) - 1) #define OPENWRT_NAME "1-openwrt" @@ -157,17 +158,28 @@ static int parse_bcm_wfi(struct mtd_info *master, const struct mtd_partition **pparts, uint8_t *buf, loff_t off, loff_t size, bool cfe_part) { + struct device_node *mtd_node; struct mtd_partition *parts; loff_t cfe_off, kernel_off, rootfs_off; unsigned int num_parts = BCM_WFI_PARTS, cur_part = 0; + const char *cferam_name = CFERAM_NAME; + size_t cferam_name_len; int ret; + mtd_node = mtd_get_of_node(master); + if (mtd_node) + of_property_read_string(mtd_node, "brcm,cferam", &cferam_name); + + cferam_name_len = strnlen(cferam_name, CFERAM_NAME_MAX_LEN); + if (cferam_name_len > 0) + cferam_name_len--; + if (cfe_part) { num_parts++; cfe_off = off; - ret = jffs2_find_file(master, buf, CFERAM_NAME, - CFERAM_NAME_LEN, &cfe_off, + ret = jffs2_find_file(master, buf, cferam_name, + cferam_name_len, &cfe_off, size - (cfe_off - off), NULL, NULL); if (ret) return ret; diff --git a/lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c b/lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c index 3230d859b0..3b71597d23 100644 --- a/lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c +++ b/lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c @@ -199,6 +199,7 @@ mtdsplit_fit_parse(struct mtd_info *mtd, struct fdt_header hdr; size_t hdr_len, retlen; size_t offset; + u32 offset_start = 0; size_t fit_offset, fit_size; size_t rootfs_offset, rootfs_size; size_t data_size, img_total, max_size = 0; @@ -211,11 +212,13 @@ mtdsplit_fit_parse(struct mtd_info *mtd, if (cmdline_match && !strstr(saved_command_line, cmdline_match)) return -ENODEV; + of_property_read_u32(np, "openwrt,fit-offset", &offset_start); + hdr_len = sizeof(struct fdt_header); /* Parse the MTD device & search for the FIT image location */ for(offset = 0; offset + hdr_len <= mtd->size; offset += mtd->erasesize) { - ret = mtd_read(mtd, offset, hdr_len, &retlen, (void*) &hdr); + ret = mtd_read(mtd, offset + offset_start, hdr_len, &retlen, (void*) &hdr); if (ret) { pr_err("read error in \"%s\" at offset 0x%llx\n", mtd->name, (unsigned long long) offset); @@ -256,9 +259,11 @@ mtdsplit_fit_parse(struct mtd_info *mtd, * last external data refernced. */ if (fit_size > 0x1000) { + enum mtdsplit_part_type type; + /* Search for the rootfs partition after the FIT image */ - ret = mtd_find_rootfs_from(mtd, fit_offset + fit_size, mtd->size, - &rootfs_offset, NULL); + ret = mtd_find_rootfs_from(mtd, fit_offset + fit_size + offset_start, mtd->size, + &rootfs_offset, &type); if (ret) { pr_info("no rootfs found after FIT image in \"%s\"\n", mtd->name); @@ -273,9 +278,12 @@ mtdsplit_fit_parse(struct mtd_info *mtd, parts[0].name = KERNEL_PART_NAME; parts[0].offset = fit_offset; - parts[0].size = mtd_rounddown_to_eb(fit_size, mtd) + mtd->erasesize; + parts[0].size = mtd_rounddown_to_eb(fit_size + offset_start, mtd) + mtd->erasesize; - parts[1].name = ROOTFS_PART_NAME; + if (type == MTDSPLIT_PART_TYPE_UBI) + parts[1].name = UBI_PART_NAME; + else + parts[1].name = ROOTFS_PART_NAME; parts[1].offset = rootfs_offset; parts[1].size = rootfs_size; @@ -285,7 +293,7 @@ mtdsplit_fit_parse(struct mtd_info *mtd, } else { /* Search for rootfs_data after FIT external data */ fit = kzalloc(fit_size, GFP_KERNEL); - ret = mtd_read(mtd, offset, fit_size, &retlen, fit); + ret = mtd_read(mtd, offset, fit_size + offset_start, &retlen, fit); if (ret) { pr_err("read error in \"%s\" at offset 0x%llx\n", mtd->name, (unsigned long long) offset); diff --git a/lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c b/lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c new file mode 100644 index 0000000000..f264233dbd --- /dev/null +++ b/lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Some devices made by H3C use a "VFS" filesystem to store firmware images. + * This parses the start of the filesystem to read the length of the first + * file (the kernel image). It then searches for the rootfs after the end of + * the file data. This driver assumes that the filesystem was generated by + * mkh3cvfs, and only works if the filesystem matches the expected layout, + * which includes the file name of the kernel image. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "mtdsplit.h" + +#define VFS_ERASEBLOCK_SIZE 0x10000 +#define VFS_BLOCK_SIZE 0x400 +#define VFS_BLOCKS_PER_ERASEBLOCK (VFS_ERASEBLOCK_SIZE / VFS_BLOCK_SIZE) + +#define FORMAT_FLAG_OFFSET 0x0 + +#define FORMAT_FLAG (VFS_ERASEBLOCK_SIZE << 12 | VFS_BLOCK_SIZE) + +#define FILE_ENTRY_OFFSET 0x800 + +#define FILE_ENTRY_FLAGS 0x3f +#define FILE_ENTRY_PARENT_BLOCK 0 +#define FILE_ENTRY_PARENT_INDEX 0 +#define FILE_ENTRY_DATA_BLOCK 2 +#define FILE_ENTRY_NAME "openwrt-kernel.bin" + +#define NR_PARTS 2 + +struct file_entry { + uint8_t flags; + + uint8_t res0[5]; + + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + + uint8_t res1[3]; + + uint32_t length; + + uint32_t parent_block; + uint16_t parent_index; + + uint8_t res2[2]; + + uint32_t data_block; + + char name[96]; +} __attribute__ ((packed)); + +static inline size_t block_offset(int block) +{ + return VFS_ERASEBLOCK_SIZE * (block / (VFS_BLOCKS_PER_ERASEBLOCK-1)) + + VFS_BLOCK_SIZE * (1 + (block % (VFS_BLOCKS_PER_ERASEBLOCK-1))); +} + +static inline int block_count(size_t size) +{ + return (size + VFS_BLOCK_SIZE - 1) / VFS_BLOCK_SIZE; +} + +static int mtdsplit_h3c_vfs_parse(struct mtd_info *mtd, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) +{ + struct mtd_partition *parts; + uint32_t format_flag; + struct file_entry file_entry; + size_t retlen; + int err; + size_t kernel_size; + size_t expected_offset; + size_t rootfs_offset; + + if (mtd->erasesize != VFS_ERASEBLOCK_SIZE) + return -EINVAL; + + /* Check format flag */ + err = mtd_read(mtd, FORMAT_FLAG_OFFSET, sizeof(format_flag), &retlen, + (void *) &format_flag); + if (err) + return err; + + if (retlen != sizeof(format_flag)) + return -EIO; + + if (format_flag != FORMAT_FLAG) + return -EINVAL; + + /* Check file entry */ + err = mtd_read(mtd, FILE_ENTRY_OFFSET, sizeof(file_entry), &retlen, + (void *) &file_entry); + if (err) + return err; + + if (retlen != sizeof(file_entry)) + return -EIO; + + if (file_entry.flags != FILE_ENTRY_FLAGS) + return -EINVAL; + + if (file_entry.parent_block != FILE_ENTRY_PARENT_BLOCK) + return -EINVAL; + + if (file_entry.parent_index != FILE_ENTRY_PARENT_INDEX) + return -EINVAL; + + if (file_entry.data_block != FILE_ENTRY_DATA_BLOCK) + return -EINVAL; + + if (strncmp(file_entry.name, FILE_ENTRY_NAME, sizeof(file_entry.name)) != 0) + return -EINVAL; + + /* Find rootfs offset */ + kernel_size = block_offset(file_entry.data_block + + block_count(file_entry.length) - 1) + + VFS_BLOCK_SIZE; + + expected_offset = mtd_roundup_to_eb(kernel_size, mtd); + + err = mtd_find_rootfs_from(mtd, expected_offset, mtd->size, + &rootfs_offset, NULL); + if (err) + return err; + + parts = kzalloc(NR_PARTS * sizeof(*parts), GFP_KERNEL); + if (!parts) + return -ENOMEM; + + parts[0].name = KERNEL_PART_NAME; + parts[0].offset = 0; + parts[0].size = rootfs_offset; + + parts[1].name = ROOTFS_PART_NAME; + parts[1].offset = rootfs_offset; + parts[1].size = mtd->size - rootfs_offset; + + *pparts = parts; + return NR_PARTS; +} + +static const struct of_device_id mtdsplit_h3c_vfs_of_match_table[] = { + { .compatible = "h3c,vfs-firmware" }, + {}, +}; +MODULE_DEVICE_TABLE(of, mtdsplit_h3c_vfs_of_match_table); + +static struct mtd_part_parser mtdsplit_h3c_vfs_parser = { + .owner = THIS_MODULE, + .name = "h3c-vfs", + .of_match_table = mtdsplit_h3c_vfs_of_match_table, + .parse_fn = mtdsplit_h3c_vfs_parse, + .type = MTD_PARSER_TYPE_FIRMWARE, +}; + +module_mtd_part_parser(mtdsplit_h3c_vfs_parser); diff --git a/lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seil.c b/lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seil.c new file mode 100644 index 0000000000..e58bb49b23 --- /dev/null +++ b/lede/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seil.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* a mtdsplit driver for IIJ SEIL devices */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mtdsplit.h" + +#define NR_PARTS 2 +#define SEIL_VFMT 1 +#define LDR_ENV_PART_NAME "bootloader-env" +#define LDR_ENV_KEY_BOOTDEV "BOOTDEV" + +struct seil_header { + uint64_t id; /* Identifier */ + uint8_t copy[80]; /* Copyright */ + uint32_t dcrc; /* Data CRC Checksum */ + uint32_t vfmt; /* Image Version Format */ + uint32_t vmjr; /* Image Version Major */ + uint32_t vmnr; /* Image Version Minor */ + uint8_t vrel[32]; /* Image Version Release */ + uint32_t dxor; /* xor value for Data? */ + uint32_t dlen; /* Data Length */ +}; + +/* + * check whether the current mtd device is active or not + * + * example of BOOTDEV value (IIJ SA-W2): + * - "flash" : primary image on flash + * - "rescue" : secondary image on flash + * - "usb" : usb storage + * - "lan0/1" : network + */ +static bool seil_bootdev_is_active(struct device_node *np) +{ + struct mtd_info *env_mtd; + char *buf, *var, *value, *eq; + const char *devnm; + size_t rdlen; + int ret; + + /* + * read bootdev name of the partition + * if doesn't exist, return true and skip checking of active device + */ + ret = of_property_read_string(np, "iij,bootdev-name", &devnm); + if (ret == -EINVAL) + return true; + else if (ret < 0) + return false; + + env_mtd = get_mtd_device_nm(LDR_ENV_PART_NAME); + if (IS_ERR(env_mtd)) { + pr_err("failed to get mtd device \"%s\"", LDR_ENV_PART_NAME); + return false; + } + + buf = vmalloc(env_mtd->size); + if (!buf) + return false; + + ret = mtd_read(env_mtd, 0, env_mtd->size, &rdlen, buf); + if (ret || rdlen != env_mtd->size) { + pr_err("failed to read from mtd (%d)\n", ret); + ret = 0; + goto exit_vfree; + } + + for (var = buf, ret = false; + var < buf + env_mtd->size && *var; + var = value + strlen(value) + 1) { + eq = strchr(var, '='); + if (!eq) + break; + *eq = '\0'; + value = eq + 1; + + pr_debug("ENV: %s=%s\n", var, value); + if (!strcmp(var, LDR_ENV_KEY_BOOTDEV)) { + ret = !strcmp(devnm, value); + break; + } + } + +exit_vfree: + vfree(buf); + + return ret; +} + +static int mtdsplit_parse_seil_fw(struct mtd_info *master, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) +{ + struct device_node *np = mtd_get_of_node(master); + struct mtd_partition *parts; + struct seil_header header; + size_t image_size = 0; + size_t rootfs_offset; + size_t hdrlen = sizeof(header); + size_t retlen; + int ret; + u64 id; + + if (!seil_bootdev_is_active(np)) + return -ENODEV; + + ret = of_property_read_u64(np, "iij,seil-id", &id); + if (ret) { + pr_err("failed to get iij,seil-id from dt\n"); + return ret; + } + pr_debug("got seil-id=0x%016llx from dt\n", id); + + parts = kcalloc(NR_PARTS, sizeof(*parts), GFP_KERNEL); + if (!parts) + return -ENOMEM; + + ret = mtd_read(master, 0, hdrlen, &retlen, (void *)&header); + if (ret) + goto err_free_parts; + + if (retlen != hdrlen) { + ret = -EIO; + goto err_free_parts; + } + + if (be64_to_cpu(header.id) != id || + be32_to_cpu(header.vfmt) != SEIL_VFMT) { + pr_debug("no valid seil image found in \"%s\"\n", master->name); + ret = -ENODEV; + goto err_free_parts; + } + + image_size = hdrlen + be32_to_cpu(header.dlen); + if (image_size > master->size) { + pr_err("seil image exceeds MTD device \"%s\"\n", master->name); + ret = -EINVAL; + goto err_free_parts; + } + + /* find the roots after the seil image */ + ret = mtd_find_rootfs_from(master, image_size, + master->size, &rootfs_offset, NULL); + if (ret || (master->size - rootfs_offset) == 0) { + pr_debug("no rootfs after seil image in \"%s\"\n", + master->name); + ret = -ENODEV; + goto err_free_parts; + } + + parts[0].name = KERNEL_PART_NAME; + parts[0].offset = 0; + parts[0].size = rootfs_offset; + + parts[1].name = ROOTFS_PART_NAME; + parts[1].offset = rootfs_offset; + parts[1].size = master->size - rootfs_offset; + + *pparts = parts; + return NR_PARTS; + +err_free_parts: + kfree(parts); + return ret; +} + +static const struct of_device_id mtdsplit_seil_fw_of_match_table[] = { + { .compatible = "iij,seil-firmware" }, + {}, +}; +MODULE_DEVICE_TABLE(of, mtdsplit_seil_fw_of_match_table); + +static struct mtd_part_parser mtdsplit_seil_fw_parser = { + .owner = THIS_MODULE, + .name = "seil-fw", + .of_match_table = mtdsplit_seil_fw_of_match_table, + .parse_fn = mtdsplit_parse_seil_fw, + .type = MTD_PARSER_TYPE_FIRMWARE, +}; + +module_mtd_part_parser(mtdsplit_seil_fw_parser); diff --git a/lede/target/linux/generic/files/drivers/mtd/nand/mtk_bmt.h b/lede/target/linux/generic/files/drivers/mtd/nand/mtk_bmt.h index dff1f28c81..517ff7414f 100644 --- a/lede/target/linux/generic/files/drivers/mtd/nand/mtk_bmt.h +++ b/lede/target/linux/generic/files/drivers/mtd/nand/mtk_bmt.h @@ -95,8 +95,14 @@ bbt_nand_read(u32 page, unsigned char *dat, int dat_len, .datbuf = dat, .len = dat_len, }; + int ret; - return bmtd._read_oob(bmtd.mtd, page << bmtd.pg_shift, &ops); + ret = bmtd._read_oob(bmtd.mtd, page << bmtd.pg_shift, &ops); + if (ret < 0) + return ret; + if (ret) + pr_info("%s: %d bitflips\n", __func__, ret); + return 0; } static inline int bbt_nand_erase(u16 block) diff --git a/lede/target/linux/generic/files/drivers/mtd/nand/mtk_bmt_v2.c b/lede/target/linux/generic/files/drivers/mtd/nand/mtk_bmt_v2.c index 2770376e98..6b06948c0f 100644 --- a/lede/target/linux/generic/files/drivers/mtd/nand/mtk_bmt_v2.c +++ b/lede/target/linux/generic/files/drivers/mtd/nand/mtk_bmt_v2.c @@ -191,36 +191,6 @@ static u16 get_bmt_index(struct bbmt *bmt) return 0; } -static int -read_bmt(u16 block, unsigned char *dat, unsigned char *fdm, int fdm_len) -{ - u32 len = bmtd.bmt_pgs << bmtd.pg_shift; - - return bbt_nand_read(blk_pg(block), dat, len, fdm, fdm_len); -} - -static struct bbbt *scan_bmt(u16 block) -{ - u8 fdm[4]; - - if (block < bmtd.pool_lba) - return NULL; - - if (read_bmt(block, bmtd.bbt_buf, fdm, sizeof(fdm))) - return scan_bmt(block - 1); - - if (is_valid_bmt(bmtd.bbt_buf, fdm)) { - bmtd.bmt_blk_idx = get_bmt_index(bmt_tbl((struct bbbt *)bmtd.bbt_buf)); - if (bmtd.bmt_blk_idx == 0) { - pr_info("[BBT] FATAL ERR: bmt block index is wrong!\n"); - return NULL; - } - pr_info("[BBT] BMT.v2 is found at 0x%x\n", block); - return (struct bbbt *)bmtd.bbt_buf; - } else - return scan_bmt(block - 1); -} - /* Write the Burner Bad Block Table to Nand Flash * n - write BMT to bmt_tbl[n] */ @@ -472,7 +442,30 @@ static int mtk_bmt_init_v2(struct device_node *np) /* Scanning start from the first page of the last block * of whole flash */ - bmtd.bbt = scan_bmt(bmtd.total_blks - 1); + bmtd.bbt = NULL; + for (u16 block = bmtd.total_blks - 1; !bmtd.bbt && block >= bmtd.pool_lba; block--) { + u8 fdm[4]; + + if (bbt_nand_read(blk_pg(block), bmtd.bbt_buf, bufsz, fdm, sizeof(fdm))) { + /* Read failed, try the previous block */ + continue; + } + + if (!is_valid_bmt(bmtd.bbt_buf, fdm)) { + /* No valid BMT found, try the previous block */ + continue; + } + + bmtd.bmt_blk_idx = get_bmt_index(bmt_tbl((struct bbbt *)bmtd.bbt_buf)); + if (bmtd.bmt_blk_idx == 0) { + pr_info("[BBT] FATAL ERR: bmt block index is wrong!\n"); + break; + } + + pr_info("[BBT] BMT.v2 is found at 0x%x\n", block); + bmtd.bbt = (struct bbbt *)bmtd.bbt_buf; + } + if (!bmtd.bbt) { /* BMT not found */ if (bmtd.total_blks > BB_TABLE_MAX + BMT_TABLE_MAX) { diff --git a/lede/target/linux/generic/files/drivers/mtd/parsers/routerbootpart.c b/lede/target/linux/generic/files/drivers/mtd/parsers/routerbootpart.c index f9bba0f3ba..aa786cd895 100644 --- a/lede/target/linux/generic/files/drivers/mtd/parsers/routerbootpart.c +++ b/lede/target/linux/generic/files/drivers/mtd/parsers/routerbootpart.c @@ -167,7 +167,7 @@ static void routerboot_find_dynparts(struct mtd_info *master) while (offset < master->size) { err = mtd_read(master, offset, sizeof(buf), &bytes_read, (u8 *)&buf); if (err) { - pr_err("%s: mtd_read error while parsing (offset: 0x%X): %d\n", + pr_err("%s: mtd_read error while parsing (offset: 0x%zX): %d\n", master->name, offset, err); continue; } diff --git a/lede/target/linux/generic/files/drivers/net/phy/ar8216.c b/lede/target/linux/generic/files/drivers/net/phy/ar8216.c index 11cb18e4f3..850bcefb74 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/lede/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -891,11 +891,7 @@ ar8216_phy_write(struct ar8xxx_priv *priv, int addr, int regnum, u16 val) static int ar8229_hw_init(struct ar8xxx_priv *priv) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0) phy_interface_t phy_if_mode; -#else - int phy_if_mode; -#endif if (priv->initialized) return 0; @@ -903,11 +899,7 @@ ar8229_hw_init(struct ar8xxx_priv *priv) ar8xxx_write(priv, AR8216_REG_CTRL, AR8216_CTRL_RESET); ar8xxx_reg_wait(priv, AR8216_REG_CTRL, AR8216_CTRL_RESET, 0, 1000); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0) of_get_phy_mode(priv->pdev->of_node, &phy_if_mode); -#else - phy_if_mode = of_get_phy_mode(priv->pdev->of_node); -#endif if (phy_if_mode == PHY_INTERFACE_MODE_GMII) { ar8xxx_write(priv, AR8229_REG_OPER_MODE0, @@ -1427,8 +1419,7 @@ ar8xxx_sw_reset_switch(struct switch_dev *dev) int i; mutex_lock(&priv->reg_mutex); - memset(&priv->vlan, 0, sizeof(struct ar8xxx_priv) - - offsetof(struct ar8xxx_priv, vlan)); + memset(&priv->ar8xxx_priv_volatile, 0, sizeof(priv->ar8xxx_priv_volatile)); for (i = 0; i < dev->vlans; i++) priv->vlan_id[i] = i; @@ -2433,7 +2424,9 @@ static int ar8xxx_phy_config_init(struct phy_device *phydev) { struct ar8xxx_priv *priv = phydev->priv; +#ifdef CONFIG_ETHERNET_PACKET_MANGLE struct net_device *dev = phydev->attached_dev; +#endif int ret; if (WARN_ON(!priv)) @@ -2465,7 +2458,11 @@ ar8xxx_phy_config_init(struct phy_device *phydev) /* VID fixup only needed on ar8216 */ if (chip_is_ar8216(priv)) { dev->phy_ptr = priv; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0) dev->priv_flags |= IFF_NO_IP_ALIGN; +#else + dev->extra_priv_flags |= IFF_NO_IP_ALIGN; +#endif dev->eth_mangle_rx = ar8216_mangle_rx; dev->eth_mangle_tx = ar8216_mangle_tx; } @@ -2700,7 +2697,11 @@ ar8xxx_phy_detach(struct phy_device *phydev) #ifdef CONFIG_ETHERNET_PACKET_MANGLE dev->phy_ptr = NULL; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0) dev->priv_flags &= ~IFF_NO_IP_ALIGN; +#else + dev->extra_priv_flags &= ~IFF_NO_IP_ALIGN; +#endif dev->eth_mangle_rx = NULL; dev->eth_mangle_tx = NULL; #endif diff --git a/lede/target/linux/generic/files/drivers/net/phy/ar8216.h b/lede/target/linux/generic/files/drivers/net/phy/ar8216.h index d62cf60f57..f046b35f43 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/ar8216.h +++ b/lede/target/linux/generic/files/drivers/net/phy/ar8216.h @@ -506,20 +506,22 @@ struct ar8xxx_priv { unsigned int use_count; /* all fields below are cleared on reset */ - bool vlan; + struct_group(ar8xxx_priv_volatile, + bool vlan; - u16 vlan_id[AR8XXX_MAX_VLANS]; - u8 vlan_table[AR8XXX_MAX_VLANS]; - u8 vlan_tagged; - u16 pvid[AR8X16_MAX_PORTS]; - int arl_age_time; + u16 vlan_id[AR8XXX_MAX_VLANS]; + u8 vlan_table[AR8XXX_MAX_VLANS]; + u8 vlan_tagged; + u16 pvid[AR8X16_MAX_PORTS]; + int arl_age_time; - /* mirroring */ - bool mirror_rx; - bool mirror_tx; - int source_port; - int monitor_port; - u8 port_vlan_prio[AR8X16_MAX_PORTS]; + /* mirroring */ + bool mirror_rx; + bool mirror_tx; + int source_port; + int monitor_port; + u8 port_vlan_prio[AR8X16_MAX_PORTS]; + ); }; u32 diff --git a/lede/target/linux/generic/files/drivers/net/phy/ar8327.c b/lede/target/linux/generic/files/drivers/net/phy/ar8327.c index dce52ce0e4..3313149559 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/ar8327.c +++ b/lede/target/linux/generic/files/drivers/net/phy/ar8327.c @@ -183,7 +183,7 @@ ar8327_phy_fixup(struct ar8xxx_priv *priv, int phy) case 2: ar8xxx_phy_mmd_write(priv, phy, 0x7, 0x3c, 0x0); - /* fallthrough */ + fallthrough; case 4: ar8xxx_phy_mmd_write(priv, phy, 0x3, 0x800d, 0x803f); ar8xxx_phy_dbg_write(priv, phy, 0x3d, 0x6860); diff --git a/lede/target/linux/generic/files/drivers/net/phy/b53/b53_common.c b/lede/target/linux/generic/files/drivers/net/phy/b53/b53_common.c index a6dab255cc..d5f9bfc2f0 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/b53/b53_common.c +++ b/lede/target/linux/generic/files/drivers/net/phy/b53/b53_common.c @@ -506,15 +506,9 @@ static int b53_configure_ports_of(struct b53_device *dev) if (fixed_link) { u32 spd; u8 po = GMII_PO_LINK; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0) phy_interface_t mode; -#else - int mode = of_get_phy_mode(pn); -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0) of_get_phy_mode(pn, &mode); -#endif if (!of_property_read_u32(fixed_link, "speed", &spd)) { switch (spd) { @@ -529,7 +523,7 @@ static int b53_configure_ports_of(struct b53_device *dev) po |= PORT_OVERRIDE_SPEED_2000M; else po |= GMII_PO_SPEED_2000M; - __attribute__((__fallthrough__)); + fallthrough; case 1000: po |= GMII_PO_SPEED_1000M; break; @@ -1617,8 +1611,8 @@ static int b53_switch_init(struct b53_device *dev) return b53_switch_reset(dev); } -struct b53_device *b53_switch_alloc(struct device *base, struct b53_io_ops *ops, - void *priv) +struct b53_device *b53_swconfig_switch_alloc(struct device *base, struct b53_io_ops *ops, + void *priv) { struct b53_device *dev; @@ -1633,9 +1627,9 @@ struct b53_device *b53_switch_alloc(struct device *base, struct b53_io_ops *ops, return dev; } -EXPORT_SYMBOL(b53_switch_alloc); +EXPORT_SYMBOL(b53_swconfig_switch_alloc); -int b53_switch_detect(struct b53_device *dev) +int b53_swconfig_switch_detect(struct b53_device *dev) { u32 id32; u16 tmp; @@ -1700,9 +1694,9 @@ int b53_switch_detect(struct b53_device *dev) return b53_read8(dev, B53_MGMT_PAGE, B53_REV_ID, &dev->core_rev); } -EXPORT_SYMBOL(b53_switch_detect); +EXPORT_SYMBOL(b53_swconfig_switch_detect); -int b53_switch_register(struct b53_device *dev) +int b53_swconfig_switch_register(struct b53_device *dev) { int ret; @@ -1712,7 +1706,7 @@ int b53_switch_register(struct b53_device *dev) dev->sw_dev.alias = dev->pdata->alias; } - if (!dev->chip_id && b53_switch_detect(dev)) + if (!dev->chip_id && b53_swconfig_switch_detect(dev)) return -EINVAL; ret = b53_switch_init(dev); @@ -1723,7 +1717,7 @@ int b53_switch_register(struct b53_device *dev) return register_switch(&dev->sw_dev, NULL); } -EXPORT_SYMBOL(b53_switch_register); +EXPORT_SYMBOL(b53_swconfig_switch_register); MODULE_AUTHOR("Jonas Gorski "); MODULE_DESCRIPTION("B53 switch library"); diff --git a/lede/target/linux/generic/files/drivers/net/phy/b53/b53_mdio.c b/lede/target/linux/generic/files/drivers/net/phy/b53/b53_mdio.c index 98cdbffe73..c85df1f305 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/b53/b53_mdio.c +++ b/lede/target/linux/generic/files/drivers/net/phy/b53/b53_mdio.c @@ -280,7 +280,7 @@ static int b53_phy_probe(struct phy_device *phydev) if (phydev->mdio.addr != B53_PSEUDO_PHY && phydev->mdio.addr != 0) return -ENODEV; - dev = b53_switch_alloc(&phydev->mdio.dev, &b53_mdio_ops, phydev->mdio.bus); + dev = b53_swconfig_switch_alloc(&phydev->mdio.dev, &b53_mdio_ops, phydev->mdio.bus); if (!dev) return -ENOMEM; @@ -290,7 +290,7 @@ static int b53_phy_probe(struct phy_device *phydev) dev->pdata = NULL; mutex_init(&dev->reg_mutex); - ret = b53_switch_detect(dev); + ret = b53_swconfig_switch_detect(dev); if (ret) return ret; @@ -302,7 +302,7 @@ static int b53_phy_probe(struct phy_device *phydev) linkmode_copy(phydev->advertising, phydev->supported); - ret = b53_switch_register(dev); + ret = b53_swconfig_switch_register(dev); if (ret) { dev_err(dev->dev, "failed to register switch: %i\n", ret); return ret; @@ -361,26 +361,6 @@ static int b53_phy_read_status(struct phy_device *phydev) return 0; } -static const struct of_device_id b53_of_match_1[] = { - { .compatible = "brcm,bcm5325" }, - { .compatible = "brcm,bcm5395" }, - { .compatible = "brcm,bcm5397" }, - { .compatible = "brcm,bcm5398" }, - { /* sentinel */ }, -}; - -static const struct of_device_id b53_of_match_2[] = { - { .compatible = "brcm,bcm53115" }, - { .compatible = "brcm,bcm53125" }, - { .compatible = "brcm,bcm53128" }, - { /* sentinel */ }, -}; - -static const struct of_device_id b53_of_match_3[] = { - { .compatible = "brcm,bcm5365" }, - { /* sentinel */ }, -}; - /* BCM5325, BCM539x */ static struct phy_driver b53_phy_driver_id1 = { .phy_id = 0x0143bc00, @@ -392,10 +372,6 @@ static struct phy_driver b53_phy_driver_id1 = { .config_aneg = b53_phy_config_aneg, .config_init = b53_phy_config_init, .read_status = b53_phy_read_status, - .mdiodrv.driver = { - .name = "bcm539x", - .of_match_table = b53_of_match_1, - }, }; /* BCM53125, BCM53128 */ @@ -409,10 +385,6 @@ static struct phy_driver b53_phy_driver_id2 = { .config_aneg = b53_phy_config_aneg, .config_init = b53_phy_config_init, .read_status = b53_phy_read_status, - .mdiodrv.driver = { - .name = "bcm531xx", - .of_match_table = b53_of_match_2, - }, }; /* BCM5365 */ @@ -426,10 +398,6 @@ static struct phy_driver b53_phy_driver_id3 = { .config_aneg = b53_phy_config_aneg, .config_init = b53_phy_config_init, .read_status = b53_phy_read_status, - .mdiodrv.driver = { - .name = "bcm5365", - .of_match_table = b53_of_match_3, - }, }; int __init b53_phy_driver_register(void) diff --git a/lede/target/linux/generic/files/drivers/net/phy/b53/b53_mmap.c b/lede/target/linux/generic/files/drivers/net/phy/b53/b53_mmap.c index ab1895e9b5..0a21ff1de5 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/b53/b53_mmap.c +++ b/lede/target/linux/generic/files/drivers/net/phy/b53/b53_mmap.c @@ -205,7 +205,7 @@ static int b53_mmap_probe(struct platform_device *pdev) if (!pdata) return -EINVAL; - dev = b53_switch_alloc(&pdev->dev, &b53_mmap_ops, pdata->regs); + dev = b53_swconfig_switch_alloc(&pdev->dev, &b53_mmap_ops, pdata->regs); if (!dev) return -ENOMEM; @@ -214,7 +214,7 @@ static int b53_mmap_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); - return b53_switch_register(dev); + return b53_swconfig_switch_register(dev); } static int b53_mmap_remove(struct platform_device *pdev) diff --git a/lede/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h b/lede/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h index 37c17aeb25..e455c755bf 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h +++ b/lede/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h @@ -183,12 +183,12 @@ static inline struct b53_device *sw_to_b53(struct switch_dev *sw) return container_of(sw, struct b53_device, sw_dev); } -struct b53_device *b53_switch_alloc(struct device *base, struct b53_io_ops *ops, - void *priv); +struct b53_device *b53_swconfig_switch_alloc(struct device *base, struct b53_io_ops *ops, + void *priv); -int b53_switch_detect(struct b53_device *dev); +int b53_swconfig_switch_detect(struct b53_device *dev); -int b53_switch_register(struct b53_device *dev); +int b53_swconfig_switch_register(struct b53_device *dev); static inline void b53_switch_remove(struct b53_device *dev) { diff --git a/lede/target/linux/generic/files/drivers/net/phy/b53/b53_spi.c b/lede/target/linux/generic/files/drivers/net/phy/b53/b53_spi.c index efc8f7ee89..400454df18 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/b53/b53_spi.c +++ b/lede/target/linux/generic/files/drivers/net/phy/b53/b53_spi.c @@ -288,14 +288,14 @@ static int b53_spi_probe(struct spi_device *spi) struct b53_device *dev; int ret; - dev = b53_switch_alloc(&spi->dev, &b53_spi_ops, spi); + dev = b53_swconfig_switch_alloc(&spi->dev, &b53_spi_ops, spi); if (!dev) return -ENOMEM; if (spi->dev.platform_data) dev->pdata = spi->dev.platform_data; - ret = b53_switch_register(dev); + ret = b53_swconfig_switch_register(dev); if (ret) return ret; diff --git a/lede/target/linux/generic/files/drivers/net/phy/b53/b53_srab.c b/lede/target/linux/generic/files/drivers/net/phy/b53/b53_srab.c index 012daa3a51..ead5209cf0 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/b53/b53_srab.c +++ b/lede/target/linux/generic/files/drivers/net/phy/b53/b53_srab.c @@ -342,7 +342,7 @@ static int b53_srab_probe(struct platform_device *pdev) if (!pdata) return -EINVAL; - dev = b53_switch_alloc(&pdev->dev, &b53_srab_ops, pdata->regs); + dev = b53_swconfig_switch_alloc(&pdev->dev, &b53_srab_ops, pdata->regs); if (!dev) return -ENOMEM; @@ -351,7 +351,7 @@ static int b53_srab_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); - return b53_switch_register(dev); + return b53_swconfig_switch_register(dev); } static int b53_srab_remove(struct platform_device *pdev) diff --git a/lede/target/linux/generic/files/drivers/net/phy/psb6970.c b/lede/target/linux/generic/files/drivers/net/phy/psb6970.c index fb6ed0e204..2587b99913 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/psb6970.c +++ b/lede/target/linux/generic/files/drivers/net/phy/psb6970.c @@ -60,11 +60,13 @@ struct psb6970_priv { struct mutex reg_mutex; /* all fields below are cleared on reset */ - bool vlan; - u16 vlan_id[PSB6970_MAX_VLANS]; - u8 vlan_table[PSB6970_MAX_VLANS]; - u8 vlan_tagged; - u16 pvid[PSB6970_NUM_PORTS]; + struct_group(psb6970_priv_volatile, + bool vlan; + u16 vlan_id[PSB6970_MAX_VLANS]; + u8 vlan_table[PSB6970_MAX_VLANS]; + u8 vlan_tagged; + u16 pvid[PSB6970_NUM_PORTS]; + ); }; #define to_psb6970(_dev) container_of(_dev, struct psb6970_priv, dev) @@ -272,8 +274,8 @@ static int psb6970_reset_switch(struct switch_dev *dev) mutex_lock(&priv->reg_mutex); - memset(&priv->vlan, 0, sizeof(struct psb6970_priv) - - offsetof(struct psb6970_priv, vlan)); + memset(&priv->psb6970_priv_volatile, 0, + sizeof(priv->psb6970_priv_volatile)); for (i = 0; i < PSB6970_MAX_VLANS; i++) priv->vlan_id[i] = i; @@ -307,7 +309,6 @@ static const struct switch_dev_ops psb6970_ops = { static int psb6970_config_init(struct phy_device *pdev) { struct psb6970_priv *priv; - struct net_device *dev = pdev->attached_dev; struct switch_dev *swdev; int ret; diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c b/lede/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c index e8375e5147..a26fd204cb 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c @@ -256,7 +256,7 @@ static int __rtl8366_smi_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data) int __rtl8366_mdio_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data) { - u32 phy_id = MDC_REALTEK_PHY_ADDR; + u32 phy_id = smi->phy_id; struct mii_bus *mbus = smi->ext_mbus; BUG_ON(in_interrupt()); @@ -293,7 +293,7 @@ int __rtl8366_mdio_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data) static int __rtl8366_mdio_write_reg(struct rtl8366_smi *smi, u32 addr, u32 data) { - u32 phy_id = MDC_REALTEK_PHY_ADDR; + u32 phy_id = smi->phy_id; struct mii_bus *mbus = smi->ext_mbus; BUG_ON(in_interrupt()); @@ -590,7 +590,7 @@ static int rtl8366_set_pvid(struct rtl8366_smi *smi, unsigned port, return -ENOSPC; } -int rtl8366_enable_vlan(struct rtl8366_smi *smi, int enable) +static int rtl8366_smi_enable_vlan(struct rtl8366_smi *smi, int enable) { int err; @@ -607,9 +607,8 @@ int rtl8366_enable_vlan(struct rtl8366_smi *smi, int enable) return err; } -EXPORT_SYMBOL_GPL(rtl8366_enable_vlan); -static int rtl8366_enable_vlan4k(struct rtl8366_smi *smi, int enable) +static int rtl8366_smi_enable_vlan4k(struct rtl8366_smi *smi, int enable) { int err; @@ -629,7 +628,7 @@ static int rtl8366_enable_vlan4k(struct rtl8366_smi *smi, int enable) return 0; } -int rtl8366_enable_all_ports(struct rtl8366_smi *smi, int enable) +static int rtl8366_smi_enable_all_ports(struct rtl8366_smi *smi, int enable) { int port; int err; @@ -642,16 +641,15 @@ int rtl8366_enable_all_ports(struct rtl8366_smi *smi, int enable) return 0; } -EXPORT_SYMBOL_GPL(rtl8366_enable_all_ports); -int rtl8366_reset_vlan(struct rtl8366_smi *smi) +static int rtl8366_smi_reset_vlan(struct rtl8366_smi *smi) { struct rtl8366_vlan_mc vlanmc; int err; int i; - rtl8366_enable_vlan(smi, 0); - rtl8366_enable_vlan4k(smi, 0); + rtl8366_smi_enable_vlan(smi, 0); + rtl8366_smi_enable_vlan4k(smi, 0); /* clear VLAN member configurations */ vlanmc.vid = 0; @@ -667,14 +665,13 @@ int rtl8366_reset_vlan(struct rtl8366_smi *smi) return 0; } -EXPORT_SYMBOL_GPL(rtl8366_reset_vlan); static int rtl8366_init_vlan(struct rtl8366_smi *smi) { int port; int err; - err = rtl8366_reset_vlan(smi); + err = rtl8366_smi_reset_vlan(smi); if (err) return err; @@ -695,7 +692,7 @@ static int rtl8366_init_vlan(struct rtl8366_smi *smi) return err; } - return rtl8366_enable_vlan(smi, 1); + return rtl8366_smi_enable_vlan(smi, 1); } #ifdef CONFIG_RTL8366_SMI_DEBUG_FS @@ -1073,15 +1070,15 @@ int rtl8366_sw_reset_switch(struct switch_dev *dev) if (err) return err; - err = rtl8366_reset_vlan(smi); + err = rtl8366_smi_reset_vlan(smi); if (err) return err; - err = rtl8366_enable_vlan(smi, 1); + err = rtl8366_smi_enable_vlan(smi, 1); if (err) return err; - return rtl8366_enable_all_ports(smi, 1); + return rtl8366_smi_enable_all_ports(smi, 1); } EXPORT_SYMBOL_GPL(rtl8366_sw_reset_switch); @@ -1343,9 +1340,9 @@ int rtl8366_sw_set_vlan_enable(struct switch_dev *dev, return -EINVAL; if (attr->ofs == 1) - err = rtl8366_enable_vlan(smi, val->value.i); + err = rtl8366_smi_enable_vlan(smi, val->value.i); else - err = rtl8366_enable_vlan4k(smi, val->value.i); + err = rtl8366_smi_enable_vlan4k(smi, val->value.i); return err; } @@ -1494,7 +1491,7 @@ int rtl8366_smi_init(struct rtl8366_smi *smi) goto err_free_sck; } - err = rtl8366_enable_all_ports(smi, 1); + err = rtl8366_smi_enable_all_ports(smi, 1); if (err) goto err_free_sck; @@ -1550,6 +1547,9 @@ int rtl8366_smi_probe_of(struct platform_device *pdev, struct rtl8366_smi *smi) goto try_gpio; } + if (of_property_read_u32(np, "phy-id", &smi->phy_id)) + smi->phy_id = MDC_REALTEK_PHY_ADDR; + return 0; try_gpio: @@ -1589,6 +1589,7 @@ int rtl8366_smi_probe_plat(struct platform_device *pdev, struct rtl8366_smi *smi smi->gpio_sda = pdata->gpio_sda; smi->gpio_sck = pdata->gpio_sck; smi->hw_reset = pdata->hw_reset; + smi->phy_id = MDC_REALTEK_PHY_ADDR; return 0; } diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h b/lede/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h index d1d988a372..3fcae81fa4 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h @@ -63,6 +63,7 @@ struct rtl8366_smi { u16 dbg_reg; u8 dbg_vlan_4k_page; #endif + u32 phy_id; struct mii_bus *ext_mbus; }; @@ -115,10 +116,6 @@ int rtl8366_smi_write_reg_noack(struct rtl8366_smi *smi, u32 addr, u32 data); int rtl8366_smi_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data); int rtl8366_smi_rmwr(struct rtl8366_smi *smi, u32 addr, u32 mask, u32 data); -int rtl8366_reset_vlan(struct rtl8366_smi *smi); -int rtl8366_enable_vlan(struct rtl8366_smi *smi, int enable); -int rtl8366_enable_all_ports(struct rtl8366_smi *smi, int enable); - #ifdef CONFIG_RTL8366_SMI_DEBUG_FS int rtl8366_debugfs_open(struct inode *inode, struct file *file); #endif diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8367.c b/lede/target/linux/generic/files/drivers/net/phy/rtl8367.c index 7f0569d038..b14b63e036 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/rtl8367.c +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8367.c @@ -1641,7 +1641,7 @@ static int rtl8367_switch_init(struct rtl8366_smi *smi) int err; dev->name = "RTL8367"; - dev->cpu_port = RTL8367_CPU_PORT_NUM; + dev->cpu_port = smi->cpu_port; dev->ports = RTL8367_NUM_PORTS; dev->vlans = RTL8367_NUM_VIDS; dev->ops = &rtl8367_sw_ops; @@ -1722,6 +1722,11 @@ static int rtl8367_detect(struct rtl8366_smi *smi) dev_info(smi->parent, "RTL%s ver. %u chip found\n", chip_name, rtl_ver & RTL8367_RTL_VER_MASK); + if (of_property_present(smi->parent->of_node, "realtek,extif1")) + smi->cpu_port = RTL8367_CPU_PORT_NUM - 1; + + dev_info(smi->parent, "CPU port: %u\n", smi->cpu_port); + return 0; } diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8367b.c b/lede/target/linux/generic/files/drivers/net/phy/rtl8367b.c index cd0d58cbfa..04c790e924 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/rtl8367b.c +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8367b.c @@ -1583,6 +1583,13 @@ static int rtl8367b_detect(struct rtl8366_smi *smi) dev_info(smi->parent, "RTL%s chip found\n", chip_name); + if (of_property_present(smi->parent->of_node, "realtek,extif2")) + smi->cpu_port = RTL8367B_CPU_PORT_NUM + 2; + else if (of_property_present(smi->parent->of_node, "realtek,extif1") && (chip_ver != 0x1010)) /* for the RTL8367R-VB chip, extif1 corresponds to cpu_port 5 */ + smi->cpu_port = RTL8367B_CPU_PORT_NUM + 1; + + dev_info(smi->parent, "CPU port: %u\n", smi->cpu_port); + return 0; } @@ -1621,9 +1628,7 @@ static int rtl8367b_probe(struct platform_device *pdev) smi->cmd_write = 0xb8; smi->ops = &rtl8367b_smi_ops; smi->num_ports = RTL8367B_NUM_PORTS; - if (of_property_read_u32(pdev->dev.of_node, "cpu_port", &smi->cpu_port) - || smi->cpu_port >= smi->num_ports) - smi->cpu_port = RTL8367B_CPU_PORT_NUM; + smi->cpu_port = RTL8367B_CPU_PORT_NUM; smi->num_vlan_mc = RTL8367B_NUM_VLANS; smi->mib_counters = rtl8367b_mib_counters; smi->num_mib_counters = ARRAY_SIZE(rtl8367b_mib_counters); diff --git a/lede/target/linux/generic/files/drivers/net/phy/swconfig.c b/lede/target/linux/generic/files/drivers/net/phy/swconfig.c index a734e57608..5fa2b147c6 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/swconfig.c +++ b/lede/target/linux/generic/files/drivers/net/phy/swconfig.c @@ -1054,6 +1054,9 @@ static struct genl_family switch_fam = { .module = THIS_MODULE, .ops = swconfig_ops, .n_ops = ARRAY_SIZE(swconfig_ops), +#if LINUX_VERSION_CODE > KERNEL_VERSION(6,0,0) + .resv_start_op = SWITCH_CMD_SET_VLAN + 1, +#endif }; #ifdef CONFIG_OF diff --git a/lede/target/linux/generic/files/drivers/net/phy/swconfig_leds.c b/lede/target/linux/generic/files/drivers/net/phy/swconfig_leds.c index 767d9221b4..1d309c046c 100644 --- a/lede/target/linux/generic/files/drivers/net/phy/swconfig_leds.c +++ b/lede/target/linux/generic/files/drivers/net/phy/swconfig_leds.c @@ -85,7 +85,7 @@ swconfig_trig_update_port_mask(struct led_trigger *trigger) sw_trig = (void *) trigger; port_mask = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,16,0) spin_lock(&trigger->leddev_list_lock); #else read_lock(&trigger->leddev_list_lock); @@ -102,11 +102,12 @@ swconfig_trig_update_port_mask(struct led_trigger *trigger) read_unlock(&trig_data->lock); } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,16,0) spin_unlock(&trigger->leddev_list_lock); #else read_unlock(&trigger->leddev_list_lock); #endif + sw_trig->port_mask = port_mask; if (port_mask) @@ -425,7 +426,7 @@ swconfig_trig_update_leds(struct switch_led_trigger *sw_trig) struct led_trigger *trigger; trigger = &sw_trig->trig; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,16,0) spin_lock(&trigger->leddev_list_lock); #else read_lock(&trigger->leddev_list_lock); @@ -436,7 +437,7 @@ swconfig_trig_update_leds(struct switch_led_trigger *sw_trig) led_cdev = list_entry(entry, struct led_classdev, trig_list); swconfig_trig_led_event(sw_trig, led_cdev); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,16,0) spin_unlock(&trigger->leddev_list_lock); #else read_unlock(&trigger->leddev_list_lock); diff --git a/lede/target/linux/generic/files/drivers/platform/mikrotik/Kconfig b/lede/target/linux/generic/files/drivers/platform/mikrotik/Kconfig index 7499ba1e1c..32ef8f29de 100644 --- a/lede/target/linux/generic/files/drivers/platform/mikrotik/Kconfig +++ b/lede/target/linux/generic/files/drivers/platform/mikrotik/Kconfig @@ -1,6 +1,5 @@ menuconfig MIKROTIK bool "Platform support for MikroTik RouterBoard virtual devices" - default n help Say Y here to get to see options for the MikroTik RouterBoard platform. This option alone does not add any kernel code. @@ -16,4 +15,10 @@ config MIKROTIK_RB_SYSFS help This driver exposes RouterBoot configuration in sysfs. +config NVMEM_LAYOUT_MIKROTIK + tristate "RouterBoot NVMEM layout support" + depends on NVMEM_LAYOUTS + help + This driver exposes MikroTik hard_config via NVMEM layout. + endif # MIKROTIK diff --git a/lede/target/linux/generic/files/drivers/platform/mikrotik/Makefile b/lede/target/linux/generic/files/drivers/platform/mikrotik/Makefile index a232e1a9e8..164b23b701 100644 --- a/lede/target/linux/generic/files/drivers/platform/mikrotik/Makefile +++ b/lede/target/linux/generic/files/drivers/platform/mikrotik/Makefile @@ -2,3 +2,4 @@ # Makefile for MikroTik RouterBoard platform specific drivers # obj-$(CONFIG_MIKROTIK_RB_SYSFS) += routerboot.o rb_hardconfig.o rb_softconfig.o +obj-$(CONFIG_NVMEM_LAYOUT_MIKROTIK) += rb_nvmem.o diff --git a/lede/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c b/lede/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c index e6a6928896..78e39a7f94 100644 --- a/lede/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c +++ b/lede/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c @@ -37,29 +37,12 @@ #include #include +#include "rb_hardconfig.h" #include "routerboot.h" -#define RB_HARDCONFIG_VER "0.06" +#define RB_HARDCONFIG_VER "0.07" #define RB_HC_PR_PFX "[rb_hardconfig] " -/* ID values for hardware settings */ -#define RB_ID_FLASH_INFO 0x03 -#define RB_ID_MAC_ADDRESS_PACK 0x04 -#define RB_ID_BOARD_PRODUCT_CODE 0x05 -#define RB_ID_BIOS_VERSION 0x06 -#define RB_ID_SDRAM_TIMINGS 0x08 -#define RB_ID_DEVICE_TIMINGS 0x09 -#define RB_ID_SOFTWARE_ID 0x0A -#define RB_ID_SERIAL_NUMBER 0x0B -#define RB_ID_MEMORY_SIZE 0x0D -#define RB_ID_MAC_ADDRESS_COUNT 0x0E -#define RB_ID_HW_OPTIONS 0x15 -#define RB_ID_WLAN_DATA 0x16 -#define RB_ID_BOARD_IDENTIFIER 0x17 -#define RB_ID_PRODUCT_NAME 0x21 -#define RB_ID_DEFCONF 0x26 -#define RB_ID_BOARD_REVISION 0x27 - /* Bit definitions for hardware options */ #define RB_HW_OPT_NO_UART BIT(0) #define RB_HW_OPT_HAS_VOLTAGE BIT(1) @@ -676,10 +659,9 @@ static ssize_t hc_wlan_data_bin_read(struct file *filp, struct kobject *kobj, return count; } -int __init rb_hardconfig_init(struct kobject *rb_kobj) +int rb_hardconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd) { struct kobject *hc_wlan_kobj; - struct mtd_info *mtd; size_t bytes_read, buflen, outlen; const u8 *buf; void *outbuf; @@ -690,20 +672,19 @@ int __init rb_hardconfig_init(struct kobject *rb_kobj) hc_kobj = NULL; hc_wlan_kobj = NULL; - // TODO allow override - mtd = get_mtd_device_nm(RB_MTD_HARD_CONFIG); - if (IS_ERR(mtd)) + ret = __get_mtd_device(mtd); + if (ret) return -ENODEV; hc_buflen = mtd->size; hc_buf = kmalloc(hc_buflen, GFP_KERNEL); if (!hc_buf) { - put_mtd_device(mtd); + __put_mtd_device(mtd); return -ENOMEM; } ret = mtd_read(mtd, 0, hc_buflen, &bytes_read, hc_buf); - put_mtd_device(mtd); + __put_mtd_device(mtd); if (ret) goto fail; @@ -818,8 +799,10 @@ fail: return ret; } -void __exit rb_hardconfig_exit(void) +void rb_hardconfig_exit(void) { kobject_put(hc_kobj); + hc_kobj = NULL; kfree(hc_buf); + hc_buf = NULL; } diff --git a/lede/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.h b/lede/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.h new file mode 100644 index 0000000000..328f4fe3c3 --- /dev/null +++ b/lede/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.h @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Common definitions for MikroTik RouterBoot hard config data. + * + * Copyright (C) 2020 Thibaut VARÈNE + * + * Some constant defines extracted from routerboot.{c,h} by Gabor Juhos + * + */ + +#ifndef _ROUTERBOOT_HARD_CONFIG_H_ +#define _ROUTERBOOT_HARD_CONFIG_H_ + +/* ID values for hardware settings */ +#define RB_ID_FLASH_INFO 0x03 +#define RB_ID_MAC_ADDRESS_PACK 0x04 +#define RB_ID_BOARD_PRODUCT_CODE 0x05 +#define RB_ID_BIOS_VERSION 0x06 +#define RB_ID_SDRAM_TIMINGS 0x08 +#define RB_ID_DEVICE_TIMINGS 0x09 +#define RB_ID_SOFTWARE_ID 0x0A +#define RB_ID_SERIAL_NUMBER 0x0B +#define RB_ID_MEMORY_SIZE 0x0D +#define RB_ID_MAC_ADDRESS_COUNT 0x0E +#define RB_ID_HW_OPTIONS 0x15 +#define RB_ID_WLAN_DATA 0x16 +#define RB_ID_BOARD_IDENTIFIER 0x17 +#define RB_ID_PRODUCT_NAME 0x21 +#define RB_ID_DEFCONF 0x26 +#define RB_ID_BOARD_REVISION 0x27 + +#endif /* _ROUTERBOOT_HARD_CONFIG_H_ */ diff --git a/lede/target/linux/generic/files/drivers/platform/mikrotik/rb_nvmem.c b/lede/target/linux/generic/files/drivers/platform/mikrotik/rb_nvmem.c new file mode 100644 index 0000000000..6f785ce7d1 --- /dev/null +++ b/lede/target/linux/generic/files/drivers/platform/mikrotik/rb_nvmem.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NVMEM layout driver for MikroTik Routerboard hard config cells + * + * Copyright (C) 2024 Robert Marko + * Based on the sysfs hard config driver by Thibaut VARÈNE + * Comments documenting the format carried over from routerboot.c + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "rb_hardconfig.h" +#include "routerboot.h" + +#define TLV_TAG_MASK GENMASK(15, 0) +#define TLV_LEN_MASK GENMASK(31, 16) + +static const char *rb_tlv_cell_name(u16 tag) +{ + switch (tag) { + case RB_ID_FLASH_INFO: + return "flash-info"; + case RB_ID_MAC_ADDRESS_PACK: + return "base-mac-address"; + case RB_ID_BOARD_PRODUCT_CODE: + return "board-product-code"; + case RB_ID_BIOS_VERSION: + return "booter-version"; + case RB_ID_SERIAL_NUMBER: + return "board-serial"; + case RB_ID_MEMORY_SIZE: + return "mem-size"; + case RB_ID_MAC_ADDRESS_COUNT: + return "mac-count"; + case RB_ID_HW_OPTIONS: + return "hw-options"; + case RB_ID_WLAN_DATA: + return "wlan-data"; + case RB_ID_BOARD_IDENTIFIER: + return "board-identifier"; + case RB_ID_PRODUCT_NAME: + return "product-name"; + case RB_ID_DEFCONF: + return "defconf"; + case RB_ID_BOARD_REVISION: + return "board-revision"; + default: + break; + } + + return NULL; +} + +static int rb_tlv_mac_read_cb(void *priv, const char *id, int index, + unsigned int offset, void *buf, + size_t bytes) +{ + if (index < 0) + return -EINVAL; + + if (!is_valid_ether_addr(buf)) + return -EINVAL; + + eth_addr_add(buf, index); + + return 0; +} + +static nvmem_cell_post_process_t rb_tlv_read_cb(u16 tag) +{ + switch (tag) { + case RB_ID_MAC_ADDRESS_PACK: + return &rb_tlv_mac_read_cb; + default: + break; + } + + return NULL; +} + +static int rb_add_cells(struct device *dev, struct nvmem_device *nvmem, + const size_t data_len, u8 *data) +{ + u32 node, offset = sizeof(RB_MAGIC_HARD); + struct nvmem_cell_info cell = {}; + struct device_node *layout; + u16 tlv_tag, tlv_len; + int ret; + + layout = of_nvmem_layout_get_container(nvmem); + if (!layout) + return -ENOENT; + + /* + * Routerboot tag nodes are u32 values: + * - The low nibble is the tag identification number, + * - The high nibble is the tag payload length (node excluded) in bytes. + * Tag nodes are CPU-endian. + * Tag nodes are 32bit-aligned. + * + * The payload immediately follows the tag node. + * Payload offset will always be aligned. while length may not end on 32bit + * boundary (the only known case is when parsing ERD data). + * The payload is CPU-endian when applicable. + * Tag nodes are not ordered (by ID) on flash. + */ + while ((offset + sizeof(node)) <= data_len) { + node = *((const u32 *) (data + offset)); + /* Tag list ends with null node */ + if (!node) + break; + + tlv_tag = FIELD_GET(TLV_TAG_MASK, node); + tlv_len = FIELD_GET(TLV_LEN_MASK, node); + + offset += sizeof(node); + if (offset + tlv_len > data_len) { + dev_err(dev, "Out of bounds field (0x%x bytes at 0x%x)\n", + tlv_len, offset); + break; + } + + cell.name = rb_tlv_cell_name(tlv_tag); + if (!cell.name) + goto skip; + + cell.offset = offset; + /* + * MikroTik stores MAC-s with length of 8 bytes, + * but kernel expects it to be ETH_ALEN (6 bytes), + * so we need to make sure that is the case. + */ + if (tlv_tag == RB_ID_MAC_ADDRESS_PACK) + cell.bytes = ETH_ALEN; + else + cell.bytes = tlv_len; + cell.np = of_get_child_by_name(layout, cell.name); + cell.read_post_process = rb_tlv_read_cb(tlv_tag); + + ret = nvmem_add_one_cell(nvmem, &cell); + if (ret) { + of_node_put(layout); + return ret; + } + + /* + * The only known situation where len may not end on 32bit + * boundary is within ERD data. Since we're only extracting + * one tag (the first and only one) from that data, we should + * never need to forcefully ALIGN(). Do it anyway, this is not a + * performance path. + */ +skip: + offset += ALIGN(tlv_len, sizeof(offset)); + } + + of_node_put(layout); + + return 0; +} + +static int rb_parse_table(struct nvmem_layout *layout) +{ + struct nvmem_device *nvmem = layout->nvmem; + struct device *dev = &layout->dev; + size_t mtd_size; + u8 *data; + u32 hdr; + int ret; + + ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr); + if (ret < 0) + return ret; + + if (hdr != RB_MAGIC_HARD) { + dev_err(dev, "Invalid header\n"); + return -EINVAL; + } + + mtd_size = nvmem_dev_size(nvmem); + + data = devm_kmalloc(dev, mtd_size, GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = nvmem_device_read(nvmem, 0, mtd_size, data); + if (ret != mtd_size) + return ret; + + return rb_add_cells(dev, nvmem, mtd_size, data); +} + +static int rb_nvmem_probe(struct nvmem_layout *layout) +{ + layout->add_cells = rb_parse_table; + + return nvmem_layout_register(layout); +} + +static void rb_nvmem_remove(struct nvmem_layout *layout) +{ + nvmem_layout_unregister(layout); +} + +static const struct of_device_id rb_nvmem_of_match_table[] = { + { .compatible = "mikrotik,routerboot-nvmem", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rb_nvmem_of_match_table); + +static struct nvmem_layout_driver rb_nvmem_layout = { + .probe = rb_nvmem_probe, + .remove = rb_nvmem_remove, + .driver = { + .owner = THIS_MODULE, + .name = "rb_nvmem", + .of_match_table = rb_nvmem_of_match_table, + }, +}; +module_nvmem_layout_driver(rb_nvmem_layout); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Robert Marko "); +MODULE_DESCRIPTION("NVMEM layout driver for MikroTik Routerboard hard config cells"); diff --git a/lede/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c b/lede/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c index 070bd32d5a..5acff6aa91 100644 --- a/lede/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c +++ b/lede/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c @@ -56,23 +56,12 @@ #include "routerboot.h" -#define RB_SOFTCONFIG_VER "0.03" +#define RB_SOFTCONFIG_VER "0.05" #define RB_SC_PR_PFX "[rb_softconfig] " -/* - * mtd operations before 4.17 are asynchronous, not handled by this code - * Also make the driver act read-only if 4K_SECTORS are not enabled, since they - * are require to handle partial erasing of the small soft_config partition. - */ -#if defined(CONFIG_MTD_SPI_NOR_USE_4K_SECTORS) - #define RB_SC_HAS_WRITE_SUPPORT true - #define RB_SC_WMODE S_IWUSR - #define RB_SC_RMODE S_IRUSR -#else - #define RB_SC_HAS_WRITE_SUPPORT false - #define RB_SC_WMODE 0 - #define RB_SC_RMODE S_IRUSR -#endif +#define RB_SC_HAS_WRITE_SUPPORT true +#define RB_SC_WMODE S_IWUSR +#define RB_SC_RMODE S_IRUSR /* ID values for software settings */ #define RB_SCID_UART_SPEED 0x01 // u32*1 @@ -705,9 +694,8 @@ mtdfail: static struct kobj_attribute sc_kattrcommit = __ATTR(commit, RB_SC_RMODE|RB_SC_WMODE, sc_commit_show, sc_commit_store); -int __init rb_softconfig_init(struct kobject *rb_kobj) +int rb_softconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd) { - struct mtd_info *mtd; size_t bytes_read, buflen; const u8 *buf; int i, ret; @@ -716,20 +704,19 @@ int __init rb_softconfig_init(struct kobject *rb_kobj) sc_buf = NULL; sc_kobj = NULL; - // TODO allow override - mtd = get_mtd_device_nm(RB_MTD_SOFT_CONFIG); - if (IS_ERR(mtd)) + ret = __get_mtd_device(mtd); + if (ret) return -ENODEV; sc_buflen = mtd->size; sc_buf = kmalloc(sc_buflen, GFP_KERNEL); if (!sc_buf) { - put_mtd_device(mtd); + __put_mtd_device(mtd); return -ENOMEM; } ret = mtd_read(mtd, 0, sc_buflen, &bytes_read, sc_buf); - put_mtd_device(mtd); + __put_mtd_device(mtd); if (ret) goto fail; @@ -799,8 +786,10 @@ fail: return ret; } -void __exit rb_softconfig_exit(void) +void rb_softconfig_exit(void) { kobject_put(sc_kobj); + sc_kobj = NULL; kfree(sc_buf); + sc_buf = NULL; } diff --git a/lede/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c b/lede/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c index 4c8c0bfac5..96f2460916 100644 --- a/lede/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c +++ b/lede/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "routerboot.h" @@ -160,25 +161,57 @@ fail: return ret; } +static void routerboot_mtd_notifier_add(struct mtd_info *mtd) +{ + /* Currently routerboot is only known to live on NOR flash */ + if (mtd->type != MTD_NORFLASH) + return; + + /* + * We ignore the following return values and always register. + * These init() routines are designed so that their failed state is + * always manageable by the corresponding exit() calls. + * Notifier is called with MTD mutex held: use __get/__put variants. + * TODO: allow partition names override + */ + if (!strcmp(mtd->name, RB_MTD_HARD_CONFIG)) + rb_hardconfig_init(rb_kobj, mtd); + else if (!strcmp(mtd->name, RB_MTD_SOFT_CONFIG)) + rb_softconfig_init(rb_kobj, mtd); +} + +static void routerboot_mtd_notifier_remove(struct mtd_info *mtd) +{ + if (mtd->type != MTD_NORFLASH) + return; + + if (!strcmp(mtd->name, RB_MTD_HARD_CONFIG)) + rb_hardconfig_exit(); + else if (!strcmp(mtd->name, RB_MTD_SOFT_CONFIG)) + rb_softconfig_exit(); +} + +/* Note: using a notifier prevents qualifying init()/exit() functions with __init/__exit */ +static struct mtd_notifier routerboot_mtd_notifier = { + .add = routerboot_mtd_notifier_add, + .remove = routerboot_mtd_notifier_remove, +}; + static int __init routerboot_init(void) { rb_kobj = kobject_create_and_add("mikrotik", firmware_kobj); if (!rb_kobj) return -ENOMEM; - /* - * We ignore the following return values and always register. - * These init() routines are designed so that their failed state is - * always manageable by the corresponding exit() calls. - */ - rb_hardconfig_init(rb_kobj); - rb_softconfig_init(rb_kobj); + register_mtd_user(&routerboot_mtd_notifier); return 0; } static void __exit routerboot_exit(void) { + unregister_mtd_user(&routerboot_mtd_notifier); + /* Exit routines are idempotent */ rb_softconfig_exit(); rb_hardconfig_exit(); kobject_put(rb_kobj); // recursive afaict diff --git a/lede/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h b/lede/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h index 67d89808d5..e858a524af 100644 --- a/lede/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h +++ b/lede/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h @@ -25,11 +25,11 @@ int routerboot_tag_find(const u8 *bufhead, const size_t buflen, const u16 tag_id, u16 *pld_ofs, u16 *pld_len); int routerboot_rle_decode(const u8 *in, size_t inlen, u8 *out, size_t *outlen); -int __init rb_hardconfig_init(struct kobject *rb_kobj); -void __exit rb_hardconfig_exit(void); +int rb_hardconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd); +void rb_hardconfig_exit(void); -int __init rb_softconfig_init(struct kobject *rb_kobj); -void __exit rb_softconfig_exit(void); +int rb_softconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd); +void rb_softconfig_exit(void); ssize_t routerboot_tag_show_string(const u8 *pld, u16 pld_len, char *buf); ssize_t routerboot_tag_show_u32s(const u8 *pld, u16 pld_len, char *buf); diff --git a/lede/target/linux/generic/hack-6.1/205-kconfig-abort-configuration-on-unset-symbol.patch b/lede/target/linux/generic/hack-6.1/205-kconfig-abort-configuration-on-unset-symbol.patch new file mode 100644 index 0000000000..df18507041 --- /dev/null +++ b/lede/target/linux/generic/hack-6.1/205-kconfig-abort-configuration-on-unset-symbol.patch @@ -0,0 +1,41 @@ +From 310e8e04a05d9eb43fa9dd7f00143300afcaa37a Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Fri, 11 Nov 2022 13:33:44 +0100 +Subject: [PATCH] kconfig: abort configuration on unset symbol + +When a target configuration has unset Kconfig symbols, the build will +fail when OpenWrt is compiled with V=s and stdin is connected to a tty. + +In case OpenWrt is compiled without either of these preconditions, the +build will succeed with the symbols in question being unset. + +Modify the kernel configuration in a way it fails on unset symbols +regardless of the aforementioned preconditions. + +Signed-off-by: David Bauer +--- + scripts/kconfig/conf.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/scripts/kconfig/conf.c ++++ b/scripts/kconfig/conf.c +@@ -338,6 +338,9 @@ static int conf_askvalue(struct symbol * + } + /* fall through */ + default: ++ if (!tty_stdio && getenv("FAIL_ON_UNCONFIGURED")) { ++ exit(1); ++ } + fflush(stdout); + xfgets(line, sizeof(line), stdin); + break; +@@ -520,6 +523,9 @@ static int conf_choice(struct menu *menu + } + /* fall through */ + case oldaskconfig: ++ if (!tty_stdio && getenv("FAIL_ON_UNCONFIGURED")) { ++ exit(1); ++ } + fflush(stdout); + xfgets(line, sizeof(line), stdin); + strip(line); diff --git a/lede/target/linux/generic/hack-6.1/205-kconfig-exit.patch b/lede/target/linux/generic/hack-6.1/205-kconfig-exit.patch deleted file mode 100644 index 2c69895781..0000000000 --- a/lede/target/linux/generic/hack-6.1/205-kconfig-exit.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 300d26562ce4dc427154cb247beb75db4b1f0774 Mon Sep 17 00:00:00 2001 -From: OpenWrt community -Date: Wed, 13 Jul 2022 13:29:57 +0200 -Subject: [PATCH] scripts/Kconfig: Kconfig exit - ---- - scripts/kconfig/conf.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/scripts/kconfig/conf.c -+++ b/scripts/kconfig/conf.c -@@ -432,6 +432,8 @@ static int conf_sym(struct menu *menu) - break; - continue; - case 0: -+ if (!sym_has_value(sym) && !tty_stdio && getenv("FAIL_ON_UNCONFIGURED")) -+ exit(1); - newval = oldval; - break; - case '?': diff --git a/lede/target/linux/generic/hack-6.1/212-tools_portability.patch b/lede/target/linux/generic/hack-6.1/212-tools_portability.patch index 4b1c6c4983..3ee4393006 100644 --- a/lede/target/linux/generic/hack-6.1/212-tools_portability.patch +++ b/lede/target/linux/generic/hack-6.1/212-tools_portability.patch @@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau static inline uint16_t __get_unaligned_le16(const uint8_t *p) --- /dev/null +++ b/tools/include/tools/linux_types.h -@@ -0,0 +1,26 @@ +@@ -0,0 +1,18 @@ +#ifndef __LINUX_TYPES_H +#define __LINUX_TYPES_H + @@ -47,23 +47,15 @@ Signed-off-by: Felix Fietkau + +typedef int8_t __s8; +typedef uint8_t __u8; -+typedef uint8_t __be8; -+typedef uint8_t __le8; + +typedef int16_t __s16; +typedef uint16_t __u16; -+typedef uint16_t __be16; -+typedef uint16_t __le16; + +typedef int32_t __s32; +typedef uint32_t __u32; -+typedef uint32_t __be32; -+typedef uint32_t __le32; + +typedef int64_t __s64; +typedef uint64_t __u64; -+typedef uint64_t __be64; -+typedef uint64_t __le64; + +#endif --- a/tools/include/linux/types.h @@ -81,6 +73,16 @@ Signed-off-by: Felix Fietkau struct page; struct kmem_cache; +@@ -51,7 +55,9 @@ typedef __s8 s8; + #define __force + #define __user + #define __must_check ++#ifndef __cold + #define __cold ++#endif + + typedef __u16 __bitwise __le16; + typedef __u16 __bitwise __be16; --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -684,6 +684,7 @@ def main() -> None: @@ -91,3 +93,268 @@ Signed-off-by: Felix Fietkau #include struct compact_pmu_event { +--- a/tools/arch/x86/include/asm/insn.h ++++ b/tools/arch/x86/include/asm/insn.h +@@ -7,8 +7,8 @@ + * Copyright (C) IBM Corporation, 2009 + */ + +-#include + /* insn_attr_t is defined in inat.h */ ++#include + #include "inat.h" /* __ignore_sync_check__ */ + + #if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN) +--- a/tools/arch/x86/include/asm/orc_types.h ++++ b/tools/arch/x86/include/asm/orc_types.h +@@ -40,7 +40,6 @@ + #define ORC_REG_MAX 15 + + #ifndef __ASSEMBLY__ +-#include + + /* + * This struct is more or less a vastly simplified version of the DWARF Call +@@ -53,12 +52,12 @@ + struct orc_entry { + s16 sp_offset; + s16 bp_offset; +-#if defined(__LITTLE_ENDIAN_BITFIELD) ++#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned sp_reg:4; + unsigned bp_reg:4; + unsigned type:2; + unsigned end:1; +-#elif defined(__BIG_ENDIAN_BITFIELD) ++#elif __BYTE_ORDER == __BIG_ENDIAN + unsigned bp_reg:4; + unsigned sp_reg:4; + unsigned unused:5; +--- a/tools/arch/x86/lib/insn.c ++++ b/tools/arch/x86/lib/insn.c +@@ -15,7 +15,11 @@ + #include "../include/asm/insn.h" /* __ignore_sync_check__ */ + #include "../include/asm-generic/unaligned.h" /* __ignore_sync_check__ */ + ++#ifdef __KERNEL__ + #include ++#else ++#include ++#endif + #include + + #include "../include/asm/emulate_prefix.h" /* __ignore_sync_check__ */ +--- a/tools/include/asm-generic/bitops/fls.h ++++ b/tools/include/asm-generic/bitops/fls.h +@@ -2,6 +2,8 @@ + #ifndef _ASM_GENERIC_BITOPS_FLS_H_ + #define _ASM_GENERIC_BITOPS_FLS_H_ + ++#include ++ + /** + * fls - find last (most-significant) bit set + * @x: the word to search +@@ -10,7 +12,7 @@ + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ + +-static __always_inline int fls(unsigned int x) ++static __always_inline int __generic_fls(unsigned int x) + { + int r = 32; + +@@ -38,5 +40,6 @@ static __always_inline int fls(unsigned + } + return r; + } ++#define fls __generic_fls + + #endif /* _ASM_GENERIC_BITOPS_FLS_H_ */ +--- a/tools/include/asm-generic/bitsperlong.h ++++ b/tools/include/asm-generic/bitsperlong.h +@@ -4,11 +4,13 @@ + + #include + ++#ifndef BITS_PER_LONG + #ifdef __SIZEOF_LONG__ + #define BITS_PER_LONG (__CHAR_BIT__ * __SIZEOF_LONG__) + #else + #define BITS_PER_LONG __WORDSIZE + #endif ++#endif + + #if BITS_PER_LONG != __BITS_PER_LONG + #error Inconsistent word size. Check asm/bitsperlong.h +--- a/tools/include/linux/rbtree.h ++++ b/tools/include/linux/rbtree.h +@@ -18,7 +18,6 @@ + #define __TOOLS_LINUX_PERF_RBTREE_H + + #include +-#include + + struct rb_node { + unsigned long __rb_parent_color; +--- a/tools/objtool/Makefile ++++ b/tools/objtool/Makefile +@@ -4,7 +4,7 @@ include ../scripts/Makefile.arch + + # always use the host compiler + AR = $(HOSTAR) +-CC = $(HOSTCC) ++CC = $(HOSTCC) $(HOST_EXTRACFLAGS) + LD = $(HOSTLD) + + ifeq ($(srctree),) +@@ -43,6 +43,7 @@ BUILD_ORC := n + + ifeq ($(SRCARCH),x86) + BUILD_ORC := y ++ CFLAGS += -DBUILD_ORC + endif + + export BUILD_ORC +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -1164,11 +1164,12 @@ static int add_ignore_alternatives(struc + return 0; + } + ++#ifndef BUILD_ORC + /* + * Symbols that replace INSN_CALL_DYNAMIC, every (tail) call to such a symbol + * will be added to the .retpoline_sites section. + */ +-__weak bool arch_is_retpoline(struct symbol *sym) ++bool arch_is_retpoline(struct symbol *sym) + { + return false; + } +@@ -1177,7 +1178,7 @@ __weak bool arch_is_retpoline(struct sym + * Symbols that replace INSN_RETURN, every (tail) call to such a symbol + * will be added to the .return_sites section. + */ +-__weak bool arch_is_rethunk(struct symbol *sym) ++bool arch_is_rethunk(struct symbol *sym) + { + return false; + } +@@ -1186,10 +1187,11 @@ __weak bool arch_is_rethunk(struct symbo + * Symbols that are embedded inside other instructions, because sometimes crazy + * code exists. These are mostly ignored for validation purposes. + */ +-__weak bool arch_is_embedded_insn(struct symbol *sym) ++bool arch_is_embedded_insn(struct symbol *sym) + { + return false; + } ++#endif + + #define NEGATIVE_RELOC ((void *)-1L) + +--- a/tools/objtool/include/objtool/objtool.h ++++ b/tools/objtool/include/objtool/objtool.h +@@ -12,7 +12,9 @@ + + #include + ++#ifndef __weak + #define __weak __attribute__((weak)) ++#endif + + struct pv_state { + bool clean; +--- a/tools/objtool/orc_dump.c ++++ b/tools/objtool/orc_dump.c +@@ -5,10 +5,10 @@ + + #include + #include +-#include + #include + #include + #include ++#include + + static const char *reg_name(unsigned int reg) + { +--- a/tools/objtool/orc_gen.c ++++ b/tools/objtool/orc_gen.c +@@ -7,11 +7,11 @@ + #include + + #include +-#include + + #include + #include + #include ++#include + + static int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, + struct instruction *insn) +--- a/tools/objtool/special.c ++++ b/tools/objtool/special.c +@@ -54,9 +54,11 @@ struct special_entry entries[] = { + {}, + }; + +-void __weak arch_handle_alternative(unsigned short feature, struct special_alt *alt) ++#ifndef BUILD_ORC ++void arch_handle_alternative(unsigned short feature, struct special_alt *alt) + { + } ++#endif + + static void reloc_to_sec_off(struct reloc *reloc, struct section **sec, + unsigned long *off) +--- a/tools/objtool/weak.c ++++ b/tools/objtool/weak.c +@@ -15,12 +15,14 @@ + return ENOSYS; \ + }) + +-int __weak orc_dump(const char *_objname) ++#ifndef BUILD_ORC ++int orc_dump(const char *_objname) + { + UNSUPPORTED("ORC"); + } + +-int __weak orc_create(struct objtool_file *file) ++int orc_create(struct objtool_file *file) + { + UNSUPPORTED("ORC"); + } ++#endif +--- a/tools/scripts/Makefile.include ++++ b/tools/scripts/Makefile.include +@@ -92,7 +92,7 @@ LLVM_OBJCOPY ?= llvm-objcopy + LLVM_STRIP ?= llvm-strip + + ifeq ($(CC_NO_CLANG), 1) +-EXTRA_WARNINGS += -Wstrict-aliasing=3 ++# EXTRA_WARNINGS += -Wstrict-aliasing=3 + + else ifneq ($(CROSS_COMPILE),) + # Allow userspace to override CLANG_CROSS_FLAGS to specify their own +--- a/tools/lib/string.c ++++ b/tools/lib/string.c +@@ -100,6 +100,7 @@ int strtobool(const char *s, bool *res) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wignored-attributes" + #endif ++#ifndef __APPLE__ + size_t __weak strlcpy(char *dest, const char *src, size_t size) + { + size_t ret = strlen(src); +@@ -111,6 +112,7 @@ size_t __weak strlcpy(char *dest, const + } + return ret; + } ++#endif + #ifdef __clang__ + #pragma clang diagnostic pop + #endif diff --git a/lede/target/linux/generic/hack-6.1/251-kconfig.patch b/lede/target/linux/generic/hack-6.1/251-kconfig.patch index e1ecbca6fe..fcf4eaf6e8 100644 --- a/lede/target/linux/generic/hack-6.1/251-kconfig.patch +++ b/lede/target/linux/generic/hack-6.1/251-kconfig.patch @@ -124,59 +124,6 @@ Signed-off-by: John Crispin config NETFILTER_FAMILY_BRIDGE bool ---- a/net/wireless/Kconfig -+++ b/net/wireless/Kconfig -@@ -1,6 +1,6 @@ - # SPDX-License-Identifier: GPL-2.0-only - config WIRELESS_EXT -- bool -+ bool "Wireless extensions" - - config WEXT_CORE - def_bool y -@@ -12,10 +12,10 @@ config WEXT_PROC - depends on WEXT_CORE - - config WEXT_SPY -- bool -+ bool "WEXT_SPY" - - config WEXT_PRIV -- bool -+ bool "WEXT_PRIV" - - config CFG80211 - tristate "cfg80211 - wireless configuration API" -@@ -208,7 +208,7 @@ config CFG80211_WEXT_EXPORT - endif # CFG80211 - - config LIB80211 -- tristate -+ tristate "LIB80211" - default n - help - This options enables a library of common routines used -@@ -217,17 +217,17 @@ config LIB80211 - Drivers should select this themselves if needed. - - config LIB80211_CRYPT_WEP -- tristate -+ tristate "LIB80211_CRYPT_WEP" - select CRYPTO_LIB_ARC4 - - config LIB80211_CRYPT_CCMP -- tristate -+ tristate "LIB80211_CRYPT_CCMP" - select CRYPTO - select CRYPTO_AES - select CRYPTO_CCM - - config LIB80211_CRYPT_TKIP -- tristate -+ tristate "LIB80211_CRYPT_TKIP" - select CRYPTO_LIB_ARC4 - - config LIB80211_DEBUG --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -17,7 +17,7 @@ config SND_DMAENGINE_PCM diff --git a/lede/target/linux/generic/hack-6.1/402-mtd-blktrans-call-add-disks-after-mtd-device.patch b/lede/target/linux/generic/hack-6.1/402-mtd-blktrans-call-add-disks-after-mtd-device.patch index 7b8ae7680a..a87b41370e 100644 --- a/lede/target/linux/generic/hack-6.1/402-mtd-blktrans-call-add-disks-after-mtd-device.patch +++ b/lede/target/linux/generic/hack-6.1/402-mtd-blktrans-call-add-disks-after-mtd-device.patch @@ -91,7 +91,7 @@ Signed-off-by: Daniel Golle #include "mtdcore.h" -@@ -1076,6 +1077,8 @@ int mtd_device_parse_register(struct mtd +@@ -1100,6 +1101,8 @@ int mtd_device_parse_register(struct mtd register_reboot_notifier(&mtd->reboot_notifier); } diff --git a/lede/target/linux/generic/hack-6.1/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch b/lede/target/linux/generic/hack-6.1/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch index 8e8e5cea8d..7c7e4c814e 100644 --- a/lede/target/linux/generic/hack-6.1/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch +++ b/lede/target/linux/generic/hack-6.1/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch @@ -12,7 +12,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c -@@ -750,7 +750,8 @@ int add_mtd_device(struct mtd_info *mtd) +@@ -773,7 +773,8 @@ int add_mtd_device(struct mtd_info *mtd) mutex_unlock(&mtd_table_mutex); diff --git a/lede/target/linux/generic/hack-6.1/700-swconfig_switch_drivers.patch b/lede/target/linux/generic/hack-6.1/700-swconfig_switch_drivers.patch index 5f49678a34..673082d840 100644 --- a/lede/target/linux/generic/hack-6.1/700-swconfig_switch_drivers.patch +++ b/lede/target/linux/generic/hack-6.1/700-swconfig_switch_drivers.patch @@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -69,6 +69,80 @@ config SFP +@@ -67,6 +67,80 @@ config SFP depends on HWMON || HWMON=n select MDIO_I2C @@ -92,7 +92,7 @@ Signed-off-by: Felix Fietkau + comment "MII PHY device drivers" - config AMD_PHY + config AIR_EN8811H_PHY --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -24,6 +24,21 @@ libphy-$(CONFIG_LED_TRIGGER_PHY) += phy_ diff --git a/lede/target/linux/generic/hack-6.1/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch b/lede/target/linux/generic/hack-6.1/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch index 696009d396..75907bf472 100644 --- a/lede/target/linux/generic/hack-6.1/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch +++ b/lede/target/linux/generic/hack-6.1/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch @@ -9,7 +9,7 @@ Subject: [PATCH] net/dsa/mv88e6xxx: disable ATU violation --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -3492,6 +3492,9 @@ static int mv88e6xxx_setup_port(struct m +@@ -3510,6 +3510,9 @@ static int mv88e6xxx_setup_port(struct m else reg = 1 << port; diff --git a/lede/target/linux/generic/hack-6.1/720-net-phy-add-aqr-phys.patch b/lede/target/linux/generic/hack-6.1/720-net-phy-add-aqr-phys.patch deleted file mode 100644 index fd2687d8ba..0000000000 --- a/lede/target/linux/generic/hack-6.1/720-net-phy-add-aqr-phys.patch +++ /dev/null @@ -1,120 +0,0 @@ -From: Birger Koblitz -Date: Sun, 5 Sep 2021 15:13:10 +0200 -Subject: [PATCH] kernel: Add AQR113C and AQR813 support - -This hack adds support for the Aquantia 4th generation, 10GBit -PHYs AQR113C and AQR813. - -Signed-off-by: Birger Koblitz - ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -23,6 +23,7 @@ - #define PHY_ID_AQCS109 0x03a1b5c2 - #define PHY_ID_AQR405 0x03a1b4b0 - #define PHY_ID_AQR113C 0x31c31c12 -+#define PHY_ID_AQR813 0x31c31cb2 - - #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 - #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -415,6 +416,49 @@ static int aqr107_read_rate(struct phy_d - return 0; - } - -+static int aqr113c_read_status(struct phy_device *phydev) -+{ -+ int val, ret; -+ -+ ret = aqr_read_status(phydev); -+ if (ret) -+ return ret; -+ -+ if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE) -+ return 0; -+ -+ // On AQR113C, the speed returned by aqr_read_status is wrong -+ aqr107_read_rate(phydev); -+ -+ val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_VEND_IF_STATUS); -+ if (val < 0) -+ return val; -+ -+ switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) { -+ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR: -+ phydev->interface = PHY_INTERFACE_MODE_10GKR; -+ break; -+ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI: -+ phydev->interface = PHY_INTERFACE_MODE_10GBASER; -+ break; -+ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII: -+ phydev->interface = PHY_INTERFACE_MODE_USXGMII; -+ break; -+ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII: -+ phydev->interface = PHY_INTERFACE_MODE_SGMII; -+ break; -+ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII: -+ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; -+ break; -+ default: -+ phydev->interface = PHY_INTERFACE_MODE_NA; -+ break; -+ } -+ -+ /* Read downshifted rate from vendor register */ -+ return aqr107_read_rate(phydev); -+} -+ - static int aqr107_read_status(struct phy_device *phydev) - { - int val, ret; -@@ -554,7 +598,7 @@ static void aqr107_chip_info(struct phy_ - build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); - prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); - -- phydev_dbg(phydev, "FW %u.%u, Build %u, Provisioning %u\n", -+ phydev_info(phydev, "FW %u.%u, Build %u, Provisioning %u\n", - fw_major, fw_minor, build_id, prov_id); - } - -@@ -809,7 +853,7 @@ static struct phy_driver aqr_driver[] = - .config_aneg = aqr_config_aneg, - .config_intr = aqr_config_intr, - .handle_interrupt = aqr_handle_interrupt, -- .read_status = aqr107_read_status, -+ .read_status = aqr113c_read_status, - .get_tunable = aqr107_get_tunable, - .set_tunable = aqr107_set_tunable, - .suspend = aqr107_suspend, -@@ -819,6 +863,24 @@ static struct phy_driver aqr_driver[] = - .get_stats = aqr107_get_stats, - .link_change_notify = aqr107_link_change_notify, - }, -+{ -+ PHY_ID_MATCH_MODEL(PHY_ID_AQR813), -+ .name = "Aquantia AQR813", -+ .probe = aqr107_probe, -+ .config_init = aqr107_config_init, -+ .config_aneg = aqr_config_aneg, -+ .config_intr = aqr_config_intr, -+ .handle_interrupt = aqr_handle_interrupt, -+ .read_status = aqr113c_read_status, -+ .get_tunable = aqr107_get_tunable, -+ .set_tunable = aqr107_set_tunable, -+ .suspend = aqr107_suspend, -+ .resume = aqr107_resume, -+ .get_sset_count = aqr107_get_sset_count, -+ .get_strings = aqr107_get_strings, -+ .get_stats = aqr107_get_stats, -+ .link_change_notify = aqr107_link_change_notify, -+}, - }; - - module_phy_driver(aqr_driver); -@@ -832,6 +894,7 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, - { } - }; - diff --git a/lede/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch b/lede/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch index 435f390eab..c6306c85cc 100644 --- a/lede/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch +++ b/lede/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch @@ -19,23 +19,23 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -1707,6 +1707,7 @@ enum netdev_priv_flags { - IFF_LIVE_RENAME_OK = 1<<30, +@@ -1730,6 +1730,7 @@ enum netdev_priv_flags { + /* was IFF_LIVE_RENAME_OK */ IFF_TX_SKB_NO_LINEAR = BIT_ULL(31), IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), + IFF_NO_IP_ALIGN = BIT_ULL(33), }; #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN -@@ -1741,6 +1742,7 @@ enum netdev_priv_flags { +@@ -1763,6 +1764,7 @@ enum netdev_priv_flags { + #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER - #define IFF_LIVE_RENAME_OK IFF_LIVE_RENAME_OK #define IFF_TX_SKB_NO_LINEAR IFF_TX_SKB_NO_LINEAR +#define IFF_NO_IP_ALIGN IFF_NO_IP_ALIGN /* Specifies the type of the struct net_device::ml_priv pointer */ enum netdev_ml_priv_type { -@@ -2109,6 +2111,11 @@ struct net_device { +@@ -2131,6 +2133,11 @@ struct net_device { const struct tlsdev_ops *tlsdev_ops; #endif @@ -47,7 +47,7 @@ Signed-off-by: Felix Fietkau const struct header_ops *header_ops; unsigned char operstate; -@@ -2182,6 +2189,10 @@ struct net_device { +@@ -2204,6 +2211,10 @@ struct net_device { struct mctp_dev __rcu *mctp_ptr; #endif @@ -105,7 +105,7 @@ Signed-off-by: Felix Fietkau help --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -3622,6 +3622,11 @@ static int xmit_one(struct sk_buff *skb, +@@ -3607,6 +3607,11 @@ static int xmit_one(struct sk_buff *skb, if (dev_nit_active(dev)) dev_queue_xmit_nit(skb, dev); diff --git a/lede/target/linux/generic/hack-6.1/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch b/lede/target/linux/generic/hack-6.1/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch index 77b190464c..faaa40f9bd 100644 --- a/lede/target/linux/generic/hack-6.1/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch +++ b/lede/target/linux/generic/hack-6.1/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch @@ -10,13 +10,13 @@ different firmware on the PHY. Signed-off-by: Alex Marginean --- - drivers/net/phy/aquantia_main.c | 88 +++++++++++++++++++++++++++++++++++++++++ + drivers/net/phy/aquantia/aquantia_main.c | 88 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -24,6 +24,8 @@ - #define PHY_ID_AQR405 0x03a1b4b0 +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -27,6 +27,8 @@ + #define PHY_ID_AQR113 0x31c31c40 #define PHY_ID_AQR113C 0x31c31c12 #define PHY_ID_AQR813 0x31c31cb2 +#define PHY_ID_AQR112 0x03a1b662 @@ -24,7 +24,7 @@ Signed-off-by: Alex Marginean #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -151,6 +153,29 @@ +@@ -99,6 +101,29 @@ #define AQR107_OP_IN_PROG_SLEEP 1000 #define AQR107_OP_IN_PROG_TIMEOUT 100000 @@ -54,7 +54,7 @@ Signed-off-by: Alex Marginean struct aqr107_hw_stat { const char *name; int reg; -@@ -282,6 +307,51 @@ static int aqr_config_aneg(struct phy_de +@@ -230,6 +255,51 @@ static int aqr_config_aneg(struct phy_de return genphy_c45_check_and_restart_aneg(phydev, changed); } @@ -106,7 +106,7 @@ Signed-off-by: Alex Marginean static int aqr_config_intr(struct phy_device *phydev) { bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; -@@ -881,6 +951,30 @@ static struct phy_driver aqr_driver[] = +@@ -860,6 +930,30 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, .link_change_notify = aqr107_link_change_notify, }, @@ -137,8 +137,8 @@ Signed-off-by: Alex Marginean }; module_phy_driver(aqr_driver); -@@ -895,6 +989,8 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, +@@ -877,6 +971,8 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, diff --git a/lede/target/linux/generic/hack-6.1/723-net-phy-aquantia-fix-system-side-protocol-mi.patch b/lede/target/linux/generic/hack-6.1/723-net-phy-aquantia-fix-system-side-protocol-mi.patch index 8e204cb146..72a70ebc14 100644 --- a/lede/target/linux/generic/hack-6.1/723-net-phy-aquantia-fix-system-side-protocol-mi.patch +++ b/lede/target/linux/generic/hack-6.1/723-net-phy-aquantia-fix-system-side-protocol-mi.patch @@ -9,12 +9,12 @@ these protocols leads to link issues on system side. Signed-off-by: Alex Marginean --- - drivers/net/phy/aquantia_main.c | 8 +++++++- + drivers/net/phy/aquantia/aquantia_main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -340,10 +340,16 @@ static int aqr_config_aneg_set_prot(stru +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -288,10 +288,16 @@ static int aqr_config_aneg_set_prot(stru phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GSTART_RATE, aquantia_syscfg[if_type].start_rate); diff --git a/lede/target/linux/generic/hack-6.1/724-net-phy-aquantia-Add-AQR113-driver-support.patch b/lede/target/linux/generic/hack-6.1/724-net-phy-aquantia-Add-AQR113-driver-support.patch deleted file mode 100644 index 0a1e970623..0000000000 --- a/lede/target/linux/generic/hack-6.1/724-net-phy-aquantia-Add-AQR113-driver-support.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 2e677e4ae8f8330f68013163b060d0fda3a43095 Mon Sep 17 00:00:00 2001 -From: "Langer, Thomas" -Date: Fri, 9 Jul 2021 17:36:46 +0200 -Subject: [PATCH] PONRTSYS-8842: aquantia: Add AQR113 driver support - -Add a new entry for AQR113 PHY_ID ---- - drivers/net/phy/aquantia_main.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -26,6 +26,7 @@ - #define PHY_ID_AQR813 0x31c31cb2 - #define PHY_ID_AQR112 0x03a1b662 - #define PHY_ID_AQR412 0x03a1b712 -+#define PHY_ID_AQR113 0x31c31c40 - - #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 - #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -981,6 +982,14 @@ static struct phy_driver aqr_driver[] = - .get_strings = aqr107_get_strings, - .get_stats = aqr107_get_stats, - }, -+{ -+ PHY_ID_MATCH_MODEL(PHY_ID_AQR113), -+ .name = "Aquantia AQR113", -+ .config_aneg = aqr_config_aneg, -+ .config_intr = aqr_config_intr, -+ .handle_interrupt = aqr_handle_interrupt, -+ .read_status = aqr107_read_status, -+}, - }; - - module_phy_driver(aqr_driver); -@@ -997,6 +1006,7 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, - { } - }; - diff --git a/lede/target/linux/generic/hack-6.1/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch b/lede/target/linux/generic/hack-6.1/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch index 654fea5661..d83cc48a33 100644 --- a/lede/target/linux/generic/hack-6.1/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch +++ b/lede/target/linux/generic/hack-6.1/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch @@ -7,23 +7,23 @@ As advised by Ian Chang this PHY is used in Puzzle devices. Signed-off-by: Daniel Golle --- - drivers/net/phy/aquantia_main.c | 10 ++++++++++ + drivers/net/phy/aquantia/aquantia_main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -27,6 +27,8 @@ +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -29,6 +29,8 @@ + #define PHY_ID_AQR813 0x31c31cb2 #define PHY_ID_AQR112 0x03a1b662 #define PHY_ID_AQR412 0x03a1b712 - #define PHY_ID_AQR113 0x31c31c40 +#define PHY_ID_AQR112C 0x03a1b790 +#define PHY_ID_AQR112R 0x31c31d12 #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -990,6 +992,30 @@ static struct phy_driver aqr_driver[] = - .handle_interrupt = aqr_handle_interrupt, - .read_status = aqr107_read_status, +@@ -960,6 +962,30 @@ static struct phy_driver aqr_driver[] = + .get_strings = aqr107_get_strings, + .get_stats = aqr107_get_stats, }, +{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR112C), @@ -52,10 +52,10 @@ Signed-off-by: Daniel Golle }; module_phy_driver(aqr_driver); -@@ -1007,6 +1033,8 @@ static struct mdio_device_id __maybe_unu +@@ -979,6 +1005,8 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR112C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR112R) }, { } diff --git a/lede/target/linux/generic/hack-6.1/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch b/lede/target/linux/generic/hack-6.1/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch index 8b7f2f0955..a2bd3a3dbb 100644 --- a/lede/target/linux/generic/hack-6.1/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch +++ b/lede/target/linux/generic/hack-6.1/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch @@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/pcs/pcs-mtk-lynxi.c +++ b/drivers/net/pcs/pcs-mtk-lynxi.c -@@ -92,14 +92,23 @@ static void mtk_pcs_lynxi_get_state(stru +@@ -114,14 +114,23 @@ static void mtk_pcs_lynxi_get_state(stru struct phylink_link_state *state) { struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); @@ -40,14 +40,14 @@ Signed-off-by: Daniel Golle + phylink_mii_c22_pcs_decode_state(state, bmsr, FIELD_GET(SGMII_LPA, adv)); } - static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode, -@@ -134,7 +143,8 @@ static int mtk_pcs_lynxi_config(struct p - /* 1000base-X or 2500base-X autoneg */ - sgm_mode = SGMII_REMOTE_FAULT_DIS; - use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -- advertising); -+ advertising) && -+ !(interface == PHY_INTERFACE_MODE_2500BASEX); - } else { - /* 1000base-X or 2500base-X without autoneg */ - sgm_mode = 0; + static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs) +@@ -163,7 +172,8 @@ static int mtk_pcs_lynxi_config(struct p + if (neg_mode & PHYLINK_PCS_NEG_INBAND) + sgm_mode |= SGMII_REMOTE_FAULT_DIS; + +- if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED && ++ interface != PHY_INTERFACE_MODE_2500BASEX) { + if (interface == PHY_INTERFACE_MODE_SGMII) + sgm_mode |= SGMII_SPEED_DUPLEX_AN; + bmcr = BMCR_ANENABLE; diff --git a/lede/target/linux/generic/hack-6.1/765-mxl-gpy-control-LED-reg-from-DT.patch b/lede/target/linux/generic/hack-6.1/765-mxl-gpy-control-LED-reg-from-DT.patch index d7165cb30a..2724efa15e 100644 --- a/lede/target/linux/generic/hack-6.1/765-mxl-gpy-control-LED-reg-from-DT.patch +++ b/lede/target/linux/generic/hack-6.1/765-mxl-gpy-control-LED-reg-from-DT.patch @@ -55,7 +55,7 @@ Signed-off-by: David Bauer /* SGMII */ #define VSPEC1_SGMII_CTRL 0x08 #define VSPEC1_SGMII_CTRL_ANEN BIT(12) /* Aneg enable */ -@@ -241,6 +248,31 @@ out: +@@ -241,6 +248,35 @@ out: return ret; } @@ -64,6 +64,7 @@ Signed-off-by: David Bauer + struct device_node *node = phydev->mdio.dev.of_node; + u32 led_regs[PHY_LED_NUM_LEDS]; + int i, ret; ++ u16 val = 0xff00; + + if (!IS_ENABLED(CONFIG_OF_MDIO)) + return 0; @@ -71,8 +72,11 @@ Signed-off-by: David Bauer + if (of_property_read_u32_array(node, "mxl,led-config", led_regs, PHY_LED_NUM_LEDS)) + return 0; + ++ if (of_property_read_bool(node, "mxl,led-drive-vdd")) ++ val &= 0x0fff; ++ + /* Enable LED function handling on all ports*/ -+ phy_write(phydev, PHY_LED, 0xFF00); ++ phy_write(phydev, PHY_LED, val); + + /* Write LED register values */ + for (i = 0; i < PHY_LED_NUM_LEDS; i++) { @@ -87,7 +91,7 @@ Signed-off-by: David Bauer static int gpy_config_init(struct phy_device *phydev) { int ret; -@@ -252,7 +284,10 @@ static int gpy_config_init(struct phy_de +@@ -252,7 +288,10 @@ static int gpy_config_init(struct phy_de /* Clear all pending interrupts */ ret = phy_read(phydev, PHY_ISTAT); diff --git a/lede/target/linux/generic/hack-6.1/781-usb-net-rndis-support-asr.patch b/lede/target/linux/generic/hack-6.1/781-usb-net-rndis-support-asr.patch index 9934bb8078..47339b6c22 100644 --- a/lede/target/linux/generic/hack-6.1/781-usb-net-rndis-support-asr.patch +++ b/lede/target/linux/generic/hack-6.1/781-usb-net-rndis-support-asr.patch @@ -1,3 +1,16 @@ +From 9fabf60187f1fa19e6f6bb5441587d485bd534b0 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 9 Apr 2024 17:06:38 +0100 +Subject: [PATCH] rndis_host: add a bunch of USB IDs + +Add a bunch of USB IDs found in various places online to the +RNDIS USB network driver. + +Signed-off-by: Daniel Golle +--- + drivers/net/usb/rndis_host.c | 40 ++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -630,6 +630,16 @@ static const struct driver_info zte_rndi diff --git a/lede/target/linux/generic/hack-6.1/790-SFP-GE-T-ignore-TX_FAULT.patch b/lede/target/linux/generic/hack-6.1/790-SFP-GE-T-ignore-TX_FAULT.patch index 16d5c12dd2..53f199d09b 100644 --- a/lede/target/linux/generic/hack-6.1/790-SFP-GE-T-ignore-TX_FAULT.patch +++ b/lede/target/linux/generic/hack-6.1/790-SFP-GE-T-ignore-TX_FAULT.patch @@ -46,7 +46,7 @@ Signed-off-by: Daniel Golle } else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) { init_done: /* Create mdiobus and start trying for PHY */ -@@ -2572,10 +2576,12 @@ static void sfp_check_state(struct sfp * +@@ -2577,10 +2581,12 @@ static void sfp_check_state(struct sfp * mutex_lock(&sfp->st_mutex); state = sfp_get_state(sfp); changed = state ^ sfp->state; diff --git a/lede/target/linux/generic/hack-6.1/800-GPIO-add-named-gpio-exports.patch b/lede/target/linux/generic/hack-6.1/800-GPIO-add-named-gpio-exports.patch index a892195e68..b60b428dc8 100644 --- a/lede/target/linux/generic/hack-6.1/800-GPIO-add-named-gpio-exports.patch +++ b/lede/target/linux/generic/hack-6.1/800-GPIO-add-named-gpio-exports.patch @@ -15,7 +15,7 @@ Signed-off-by: John Crispin #include "gpiolib.h" #include "gpiolib-of.h" -@@ -1030,3 +1032,72 @@ void of_gpio_dev_init(struct gpio_chip * +@@ -1030,3 +1032,100 @@ void of_gpio_dev_init(struct gpio_chip * else gc->of_node = gdev->dev.of_node; } @@ -47,6 +47,7 @@ Signed-off-by: John Crispin + max_gpio = of_gpio_count(cnp); + + for (i = 0; i < max_gpio; i++) { ++ struct gpio_desc *desc; + unsigned flags = 0; + enum of_gpio_flags of_flags; + @@ -54,17 +55,44 @@ Signed-off-by: John Crispin + if (!gpio_is_valid(gpio)) + return gpio; + -+ if (of_flags == OF_GPIO_ACTIVE_LOW) ++ if (of_flags & OF_GPIO_ACTIVE_LOW) + flags |= GPIOF_ACTIVE_LOW; + -+ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) -+ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; -+ else ++ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) { ++ if (of_flags & OF_GPIO_SINGLE_ENDED) { ++ /* ++ * As gpiod_direction_output_raw() is used, we ++ * need to emulate open drain or open source here. ++ */ ++ if (of_flags & OF_GPIO_OPEN_DRAIN) { ++ flags |= GPIOF_OPEN_DRAIN; ++ flags |= val ? GPIOF_IN : GPIOF_OUT_INIT_LOW; ++ } else { ++ flags |= GPIOF_OPEN_SOURCE; ++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_IN; ++ } ++ } else { ++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; ++ } ++ } else { + flags |= GPIOF_IN; ++ } + + if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) + continue; + ++ /* ++ * When emulating open-source or open-drain functionalities by not ++ * actively driving the line (setting mode to input) we still need to ++ * set the IS_OUT flag or otherwise we won't be able to set the line ++ * value anymore. ++ */ ++ if ((flags & GPIOF_IN) && ++ ((flags & GPIOF_OPEN_DRAIN) || (flags & GPIOF_OPEN_SOURCE))) { ++ desc = gpio_to_desc(gpio); ++ set_bit(FLAG_IS_OUT, &desc->flags); ++ } ++ + dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); + gpio_export_with_name(gpio, dmc, name); + nb++; diff --git a/lede/target/linux/generic/hack-6.1/901-debloat_sock_diag.patch b/lede/target/linux/generic/hack-6.1/901-debloat_sock_diag.patch index c1a36b613f..09b59478aa 100644 --- a/lede/target/linux/generic/hack-6.1/901-debloat_sock_diag.patch +++ b/lede/target/linux/generic/hack-6.1/901-debloat_sock_diag.patch @@ -162,3 +162,13 @@ Signed-off-by: Felix Fietkau default n help Support for UNIX socket monitoring interface used by the ss tool. +--- a/net/xdp/Kconfig ++++ b/net/xdp/Kconfig +@@ -10,6 +10,7 @@ config XDP_SOCKETS + config XDP_SOCKETS_DIAG + tristate "XDP sockets: monitoring interface" + depends on XDP_SOCKETS ++ select SOCK_DIAG + default n + help + Support for PF_XDP sockets monitoring interface used by the ss tool. diff --git a/lede/target/linux/generic/hack-6.1/902-debloat_proc.patch b/lede/target/linux/generic/hack-6.1/902-debloat_proc.patch index eaf524dc5d..06b3a04f7a 100644 --- a/lede/target/linux/generic/hack-6.1/902-debloat_proc.patch +++ b/lede/target/linux/generic/hack-6.1/902-debloat_proc.patch @@ -406,3 +406,14 @@ Signed-off-by: Felix Fietkau return register_pernet_subsys(&ip_rt_proc_ops); } +--- a/net/ipv4/inet_timewait_sock.c ++++ b/net/ipv4/inet_timewait_sock.c +@@ -269,7 +269,7 @@ void __inet_twsk_schedule(struct inet_ti + */ + + if (!rearm) { +- bool kill = timeo <= 4*HZ; ++ bool __maybe_unused kill = timeo <= 4*HZ; + + __NET_INC_STATS(twsk_net(tw), kill ? LINUX_MIB_TIMEWAITKILLED : + LINUX_MIB_TIMEWAITED); diff --git a/lede/target/linux/generic/hack-6.1/930-usb-net-for-fm350.patch b/lede/target/linux/generic/hack-6.1/931-usb-net-for-fm350.patch similarity index 100% rename from lede/target/linux/generic/hack-6.1/930-usb-net-for-fm350.patch rename to lede/target/linux/generic/hack-6.1/931-usb-net-for-fm350.patch diff --git a/lede/target/linux/generic/pending-6.1/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch b/lede/target/linux/generic/pending-6.1/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch new file mode 100644 index 0000000000..f420d210c2 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch @@ -0,0 +1,37 @@ +From: Felix Fietkau +Date: Thu, 4 Jan 2024 15:21:21 +0100 +Subject: [PATCH] net: bridge: do not send arp replies if src and target hw + addr is the same + +There are broken devices in the wild that handle duplicate IP address +detection by sending out ARP requests for the IP that they received from a +DHCP server and refuse the address if they get a reply. +When proxyarp is enabled, they would go into a loop of requesting an address +and then NAKing it again. + +Link: https://github.com/openwrt/openwrt/issues/14309 +Signed-off-by: Felix Fietkau +--- + +--- a/net/bridge/br_arp_nd_proxy.c ++++ b/net/bridge/br_arp_nd_proxy.c +@@ -204,7 +204,10 @@ void br_do_proxy_suppress_arp(struct sk_ + if ((p && (p->flags & BR_PROXYARP)) || + (f->dst && (f->dst->flags & (BR_PROXYARP_WIFI | + BR_NEIGH_SUPPRESS)))) { +- if (!vid) ++ replied = true; ++ if (!memcmp(n->ha, sha, dev->addr_len)) ++ replied = false; ++ else if (!vid) + br_arp_send(br, p, skb->dev, sip, tip, + sha, n->ha, sha, 0, 0); + else +@@ -212,7 +215,6 @@ void br_do_proxy_suppress_arp(struct sk_ + sha, n->ha, sha, + skb->vlan_proto, + skb_vlan_tag_get(skb)); +- replied = true; + } + + /* If we have replied or as long as we know the diff --git a/lede/target/linux/generic/pending-6.1/307-mips_highmem_offset.patch b/lede/target/linux/generic/pending-6.1/307-mips_highmem_offset.patch deleted file mode 100644 index 0529b0c5c8..0000000000 --- a/lede/target/linux/generic/pending-6.1/307-mips_highmem_offset.patch +++ /dev/null @@ -1,19 +0,0 @@ -From: Felix Fietkau -Subject: kernel: adjust mips highmem offset to avoid the need for -mlong-calls on systems with >256M RAM - -Signed-off-by: Felix Fietkau ---- - arch/mips/include/asm/mach-generic/spaces.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/mips/include/asm/mach-generic/spaces.h -+++ b/arch/mips/include/asm/mach-generic/spaces.h -@@ -46,7 +46,7 @@ - * Memory above this physical address will be considered highmem. - */ - #ifndef HIGHMEM_START --#define HIGHMEM_START _AC(0x20000000, UL) -+#define HIGHMEM_START _AC(0x10000000, UL) - #endif - - #endif /* CONFIG_32BIT */ diff --git a/lede/target/linux/generic/pending-6.1/350-mips-kernel-fix-detect_memory_region-function.patch b/lede/target/linux/generic/pending-6.1/350-mips-kernel-fix-detect_memory_region-function.patch new file mode 100644 index 0000000000..3bf7ae98bf --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/350-mips-kernel-fix-detect_memory_region-function.patch @@ -0,0 +1,74 @@ +From: Shiji Yang +Date: Wed, 13 Mar 2024 20:28:37 +0800 +Subject: [PATCH] mips: kernel: fix detect_memory_region() function + +1. Do not use memcmp() on unallocated memory, as the new introduced + fortify dynamic object size check[1] will report unexpected result. +2. Use a fixed pattern instead of a random function pointer as the + magic value. +3. Flip magic value and double check it. +4. Enable this feature only for 32-bit CPUs. Currently, only ath79 and + ralink CPUs are using it. + +[1] 439a1bcac648 ("fortify: Use __builtin_dynamic_object_size() when available") +Signed-off-by: Shiji Yang +--- + arch/mips/include/asm/bootinfo.h | 2 ++ + arch/mips/kernel/setup.c | 17 ++++++++++++----- + 2 files changed, 14 insertions(+), 5 deletions(-) + +--- a/arch/mips/include/asm/bootinfo.h ++++ b/arch/mips/include/asm/bootinfo.h +@@ -93,7 +93,9 @@ const char *get_system_type(void); + + extern unsigned long mips_machtype; + ++#ifndef CONFIG_64BIT + extern void detect_memory_region(phys_addr_t start, phys_addr_t sz_min, phys_addr_t sz_max); ++#endif + + extern void prom_init(void); + extern void prom_free_prom_memory(void); +--- a/arch/mips/kernel/setup.c ++++ b/arch/mips/kernel/setup.c +@@ -90,21 +90,27 @@ static struct resource bss_resource = { + unsigned long __kaslr_offset __ro_after_init; + EXPORT_SYMBOL(__kaslr_offset); + +-static void *detect_magic __initdata = detect_memory_region; +- + #ifdef CONFIG_MIPS_AUTO_PFN_OFFSET + unsigned long ARCH_PFN_OFFSET; + EXPORT_SYMBOL(ARCH_PFN_OFFSET); + #endif + ++#ifndef CONFIG_64BIT ++static u32 detect_magic __initdata; ++#define MIPS_MEM_TEST_PATTERN 0xaa5555aa ++ + void __init detect_memory_region(phys_addr_t start, phys_addr_t sz_min, phys_addr_t sz_max) + { +- void *dm = &detect_magic; ++ void *dm = (void *)KSEG1ADDR(&detect_magic); + phys_addr_t size; + + for (size = sz_min; size < sz_max; size <<= 1) { +- if (!memcmp(dm, dm + size, sizeof(detect_magic))) +- break; ++ __raw_writel(MIPS_MEM_TEST_PATTERN, dm); ++ if (__raw_readl(dm) == __raw_readl(dm + size)) { ++ __raw_writel(~MIPS_MEM_TEST_PATTERN, dm); ++ if (__raw_readl(dm) == __raw_readl(dm + size)) ++ break; ++ } + } + + pr_debug("Memory: %lluMB of RAM detected at 0x%llx (min: %lluMB, max: %lluMB)\n", +@@ -115,6 +121,7 @@ void __init detect_memory_region(phys_ad + + memblock_add(start, size); + } ++#endif /* CONFIG_64BIT */ + + /* + * Manage initrd diff --git a/lede/target/linux/generic/pending-6.1/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch b/lede/target/linux/generic/pending-6.1/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch new file mode 100644 index 0000000000..42b5a564b1 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch @@ -0,0 +1,48 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 31 Oct 2023 15:51:01 +0100 +Subject: [PATCH] mtd: don't register NVMEM devices for partitions with custom + drivers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This fixes issue exposed by upstream commit f4cf4e5db331 ("Revert +"nvmem: add new config option""). + +Signed-off-by: Rafał Miłecki +--- + drivers/mtd/mtdcore.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -519,6 +519,29 @@ static int mtd_nvmem_add(struct mtd_info + struct device_node *node = mtd_get_of_node(mtd); + struct nvmem_config config = {}; + ++ /* ++ * Do NOT register NVMEM device for any partition that is meant to be ++ * handled by a U-Boot env driver. That would result in associating two ++ * different NVMEM devices with the same OF node. ++ * ++ * An example of unwanted behaviour of above (forwardtrace): ++ * of_get_mac_addr_nvmem() ++ * of_nvmem_cell_get() ++ * __nvmem_device_get() ++ * ++ * We can't have __nvmem_device_get() return "mtdX" NVMEM device instead ++ * of U-Boot env NVMEM device. That would result in failing to find ++ * NVMEM cell. ++ * ++ * This issue seems to affect U-Boot env case only and will go away with ++ * switch to NVMEM layouts. ++ */ ++ if (of_device_is_compatible(node, "u-boot,env") || ++ of_device_is_compatible(node, "u-boot,env-redundant-bool") || ++ of_device_is_compatible(node, "u-boot,env-redundant-count") || ++ of_device_is_compatible(node, "brcm,env")) ++ return 0; ++ + config.id = -1; + config.dev = &mtd->dev; + config.name = dev_name(&mtd->dev); diff --git a/lede/target/linux/generic/pending-6.1/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch b/lede/target/linux/generic/pending-6.1/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch index c7da2f8834..66a6feff60 100644 --- a/lede/target/linux/generic/pending-6.1/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch +++ b/lede/target/linux/generic/pending-6.1/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch @@ -202,7 +202,7 @@ Reported-by: Dan Carpenter return !!nor->params->erase_map.uniform_erase_type; } -@@ -2158,6 +2160,7 @@ static int spi_nor_select_erase(struct s +@@ -2180,6 +2182,7 @@ static int spi_nor_select_erase(struct s { struct spi_nor_erase_map *map = &nor->params->erase_map; const struct spi_nor_erase_type *erase = NULL; @@ -210,7 +210,7 @@ Reported-by: Dan Carpenter struct mtd_info *mtd = &nor->mtd; u32 wanted_size = nor->info->sector_size; int i; -@@ -2190,8 +2193,9 @@ static int spi_nor_select_erase(struct s +@@ -2212,8 +2215,9 @@ static int spi_nor_select_erase(struct s */ for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { if (map->erase_type[i].size) { @@ -222,7 +222,7 @@ Reported-by: Dan Carpenter } } -@@ -2199,6 +2203,9 @@ static int spi_nor_select_erase(struct s +@@ -2221,6 +2225,9 @@ static int spi_nor_select_erase(struct s return -EINVAL; mtd->erasesize = erase->size; diff --git a/lede/target/linux/generic/pending-6.1/430-mtd-add-myloader-partition-parser.patch b/lede/target/linux/generic/pending-6.1/430-mtd-add-myloader-partition-parser.patch index c8cf3f5d3b..35e80d6dcc 100644 --- a/lede/target/linux/generic/pending-6.1/430-mtd-add-myloader-partition-parser.patch +++ b/lede/target/linux/generic/pending-6.1/430-mtd-add-myloader-partition-parser.patch @@ -16,7 +16,7 @@ Signed-off-by: Adrian Schmutzler +config MTD_MYLOADER_PARTS + tristate "MyLoader partition parsing" -+ depends on ADM5120 || ATH25 || ATH79 ++ depends on ADM5120 || ATH79 + help + MyLoader is a bootloader which allows the user to define partitions + in flash devices, by putting a table in the second erase block diff --git a/lede/target/linux/generic/pending-6.1/450-01-dt-bindings-mtd-add-basic-bindings-for-UBI.patch b/lede/target/linux/generic/pending-6.1/450-01-dt-bindings-mtd-add-basic-bindings-for-UBI.patch new file mode 100644 index 0000000000..063d3fa79c --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-01-dt-bindings-mtd-add-basic-bindings-for-UBI.patch @@ -0,0 +1,121 @@ +From ffbbe7d66872ff8957dad2136133e28a1fd5d437 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 7 Aug 2023 22:51:05 +0100 +Subject: [PATCH 01/15] dt-bindings: mtd: add basic bindings for UBI + +Add basic bindings for UBI devices and volumes. + +Signed-off-by: Daniel Golle +--- + .../bindings/mtd/partitions/linux,ubi.yaml | 65 +++++++++++++++++++ + .../bindings/mtd/partitions/ubi-volume.yaml | 35 ++++++++++ + 2 files changed, 100 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mtd/partitions/linux,ubi.yaml + create mode 100644 Documentation/devicetree/bindings/mtd/partitions/ubi-volume.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/mtd/partitions/linux,ubi.yaml +@@ -0,0 +1,65 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mtd/partitions/linux,ubi.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Unsorted Block Images ++ ++description: | ++ UBI ("Unsorted Block Images") is a volume management system for raw ++ flash devices which manages multiple logical volumes on a single ++ physical flash device and spreads the I/O load (i.e wear-leveling) ++ across the whole flash chip. ++ ++maintainers: ++ - Daniel Golle ++ ++allOf: ++ - $ref: partition.yaml# ++ ++properties: ++ compatible: ++ const: linux,ubi ++ ++ volumes: ++ type: object ++ description: UBI Volumes ++ ++ patternProperties: ++ "^ubi-volume-.*$": ++ $ref: /schemas/mtd/partitions/ubi-volume.yaml# ++ ++ unevaluatedProperties: false ++ ++required: ++ - compatible ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ reg = <0x0 0x100000>; ++ label = "bootloader"; ++ read-only; ++ }; ++ ++ partition@100000 { ++ reg = <0x100000 0x1ff00000>; ++ label = "ubi"; ++ compatible = "linux,ubi"; ++ ++ volumes { ++ ubi-volume-caldata { ++ volid = <2>; ++ volname = "rf"; ++ }; ++ }; ++ }; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/mtd/partitions/ubi-volume.yaml +@@ -0,0 +1,35 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mtd/partitions/ubi-volume.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: UBI volume ++ ++description: | ++ This binding describes a single UBI volume. Volumes can be matches either ++ by their ID or their name, or both. ++ ++maintainers: ++ - Daniel Golle ++ ++properties: ++ volid: ++ $ref: "/schemas/types.yaml#/definitions/uint32" ++ description: ++ Match UBI volume ID ++ ++ volname: ++ $ref: "/schemas/types.yaml#/definitions/string" ++ description: ++ Match UBI volume ID ++ ++anyOf: ++ - required: ++ - volid ++ ++ - required: ++ - volname ++ ++# This is a generic file other binding inherit from and extend ++additionalProperties: true diff --git a/lede/target/linux/generic/pending-6.1/450-02-dt-bindings-mtd-ubi-volume-allow-UBI-volumes-to-prov.patch b/lede/target/linux/generic/pending-6.1/450-02-dt-bindings-mtd-ubi-volume-allow-UBI-volumes-to-prov.patch new file mode 100644 index 0000000000..823c8e83b7 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-02-dt-bindings-mtd-ubi-volume-allow-UBI-volumes-to-prov.patch @@ -0,0 +1,48 @@ +From e4dad3aa5c3ab9c553555dd23c0b85f725f2eb51 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 7 Aug 2023 22:53:01 +0100 +Subject: [PATCH 02/15] dt-bindings: mtd: ubi-volume: allow UBI volumes to + provide NVMEM + +UBI volumes may be used to contain NVMEM bits, typically device MAC +addresses or wireless radio calibration data. + +Signed-off-by: Daniel Golle +--- + .../devicetree/bindings/mtd/partitions/linux,ubi.yaml | 10 ++++++++++ + .../devicetree/bindings/mtd/partitions/ubi-volume.yaml | 5 +++++ + 2 files changed, 15 insertions(+) + +--- a/Documentation/devicetree/bindings/mtd/partitions/linux,ubi.yaml ++++ b/Documentation/devicetree/bindings/mtd/partitions/linux,ubi.yaml +@@ -59,6 +59,16 @@ examples: + ubi-volume-caldata { + volid = <2>; + volname = "rf"; ++ ++ nvmem-layout { ++ compatible = "fixed-layout"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ eeprom@0 { ++ reg = <0x0 0x1000>; ++ }; ++ }; + }; + }; + }; +--- a/Documentation/devicetree/bindings/mtd/partitions/ubi-volume.yaml ++++ b/Documentation/devicetree/bindings/mtd/partitions/ubi-volume.yaml +@@ -24,6 +24,11 @@ properties: + description: + Match UBI volume ID + ++ nvmem-layout: ++ $ref: /schemas/nvmem/layouts/nvmem-layout.yaml# ++ description: ++ This container may reference an NVMEM layout parser. ++ + anyOf: + - required: + - volid diff --git a/lede/target/linux/generic/pending-6.1/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch b/lede/target/linux/generic/pending-6.1/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch new file mode 100644 index 0000000000..eda3b108da --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-03-mtd-ubi-block-use-notifier-to-create-ubiblock-from-p.patch @@ -0,0 +1,225 @@ +From e5cf19bd8204925f3bd2067df9e867313eac388b Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 1 May 2023 11:57:51 +0100 +Subject: [PATCH 03/15] mtd: ubi: block: use notifier to create ubiblock from + parameter + +Use UBI_VOLUME_ADDED notification to create ubiblock device specified +on kernel cmdline or module parameter. +This makes thing more simple and has the advantage that ubiblock devices +on volumes which are not present at the time the ubi module is probed +will still be created. + +Suggested-by: Zhihao Cheng +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/block.c | 154 ++++++++++++++++++++++------------------ + 1 file changed, 85 insertions(+), 69 deletions(-) + +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -67,10 +68,10 @@ struct ubiblock_pdu { + }; + + /* Numbers of elements set in the @ubiblock_param array */ +-static int ubiblock_devs __initdata; ++static int ubiblock_devs; + + /* MTD devices specification parameters */ +-static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES] __initdata; ++static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES]; + + struct ubiblock { + struct ubi_volume_desc *desc; +@@ -504,7 +505,7 @@ int ubiblock_remove(struct ubi_volume_in + } + + /* Found a device, let's lock it so we can check if it's busy */ +- mutex_lock(&dev->dev_mutex); ++ mutex_lock_nested(&dev->dev_mutex, SINGLE_DEPTH_NESTING); + if (dev->refcnt > 0) { + ret = -EBUSY; + goto out_unlock_dev; +@@ -567,6 +568,85 @@ static int ubiblock_resize(struct ubi_vo + return 0; + } + ++static bool ++match_volume_desc(struct ubi_volume_info *vi, const char *name, int ubi_num, int vol_id) ++{ ++ int err, len; ++ struct path path; ++ struct kstat stat; ++ ++ if (ubi_num == -1) { ++ /* No ubi num, name must be a vol device path */ ++ err = kern_path(name, LOOKUP_FOLLOW, &path); ++ if (err) ++ return false; ++ ++ err = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT); ++ path_put(&path); ++ if (err) ++ return false; ++ ++ if (!S_ISCHR(stat.mode)) ++ return false; ++ ++ if (vi->ubi_num != ubi_major2num(MAJOR(stat.rdev))) ++ return false; ++ ++ if (vi->vol_id != MINOR(stat.rdev) - 1) ++ return false; ++ ++ return true; ++ } ++ ++ if (vol_id == -1) { ++ if (vi->ubi_num != ubi_num) ++ return false; ++ ++ len = strnlen(name, UBI_VOL_NAME_MAX + 1); ++ if (len < 1 || vi->name_len != len) ++ return false; ++ ++ if (strcmp(name, vi->name)) ++ return false; ++ ++ return true; ++ } ++ ++ if (vi->ubi_num != ubi_num) ++ return false; ++ ++ if (vi->vol_id != vol_id) ++ return false; ++ ++ return true; ++} ++ ++static void ++ubiblock_create_from_param(struct ubi_volume_info *vi) ++{ ++ int i, ret = 0; ++ struct ubiblock_param *p; ++ ++ /* ++ * Iterate over ubiblock cmdline parameters. If a parameter matches the ++ * newly added volume create the ubiblock device for it. ++ */ ++ for (i = 0; i < ubiblock_devs; i++) { ++ p = &ubiblock_param[i]; ++ ++ if (!match_volume_desc(vi, p->name, p->ubi_num, p->vol_id)) ++ continue; ++ ++ ret = ubiblock_create(vi); ++ if (ret) { ++ pr_err( ++ "UBI: block: can't add '%s' volume on ubi%d_%d, err=%d\n", ++ vi->name, p->ubi_num, p->vol_id, ret); ++ } ++ break; ++ } ++} ++ + static int ubiblock_notify(struct notifier_block *nb, + unsigned long notification_type, void *ns_ptr) + { +@@ -574,10 +654,7 @@ static int ubiblock_notify(struct notifi + + switch (notification_type) { + case UBI_VOLUME_ADDED: +- /* +- * We want to enforce explicit block device creation for +- * volumes, so when a volume is added we do nothing. +- */ ++ ubiblock_create_from_param(&nt->vi); + break; + case UBI_VOLUME_REMOVED: + ubiblock_remove(&nt->vi); +@@ -603,56 +680,6 @@ static struct notifier_block ubiblock_no + .notifier_call = ubiblock_notify, + }; + +-static struct ubi_volume_desc * __init +-open_volume_desc(const char *name, int ubi_num, int vol_id) +-{ +- if (ubi_num == -1) +- /* No ubi num, name must be a vol device path */ +- return ubi_open_volume_path(name, UBI_READONLY); +- else if (vol_id == -1) +- /* No vol_id, must be vol_name */ +- return ubi_open_volume_nm(ubi_num, name, UBI_READONLY); +- else +- return ubi_open_volume(ubi_num, vol_id, UBI_READONLY); +-} +- +-static void __init ubiblock_create_from_param(void) +-{ +- int i, ret = 0; +- struct ubiblock_param *p; +- struct ubi_volume_desc *desc; +- struct ubi_volume_info vi; +- +- /* +- * If there is an error creating one of the ubiblocks, continue on to +- * create the following ubiblocks. This helps in a circumstance where +- * the kernel command-line specifies multiple block devices and some +- * may be broken, but we still want the working ones to come up. +- */ +- for (i = 0; i < ubiblock_devs; i++) { +- p = &ubiblock_param[i]; +- +- desc = open_volume_desc(p->name, p->ubi_num, p->vol_id); +- if (IS_ERR(desc)) { +- pr_err( +- "UBI: block: can't open volume on ubi%d_%d, err=%ld\n", +- p->ubi_num, p->vol_id, PTR_ERR(desc)); +- continue; +- } +- +- ubi_get_volume_info(desc, &vi); +- ubi_close_volume(desc); +- +- ret = ubiblock_create(&vi); +- if (ret) { +- pr_err( +- "UBI: block: can't add '%s' volume on ubi%d_%d, err=%d\n", +- vi.name, p->ubi_num, p->vol_id, ret); +- continue; +- } +- } +-} +- + static void ubiblock_remove_all(void) + { + struct ubiblock *next; +@@ -678,18 +705,7 @@ int __init ubiblock_init(void) + if (ubiblock_major < 0) + return ubiblock_major; + +- /* +- * Attach block devices from 'block=' module param. +- * Even if one block device in the param list fails to come up, +- * still allow the module to load and leave any others up. +- */ +- ubiblock_create_from_param(); +- +- /* +- * Block devices are only created upon user requests, so we ignore +- * existing volumes. +- */ +- ret = ubi_register_volume_notifier(&ubiblock_notifier, 1); ++ ret = ubi_register_volume_notifier(&ubiblock_notifier, 0); + if (ret) + goto err_unreg; + return 0; diff --git a/lede/target/linux/generic/pending-6.1/450-04-mtd-ubi-attach-from-device-tree.patch b/lede/target/linux/generic/pending-6.1/450-04-mtd-ubi-attach-from-device-tree.patch new file mode 100644 index 0000000000..6e10e5ebed --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-04-mtd-ubi-attach-from-device-tree.patch @@ -0,0 +1,264 @@ +From 471a17d8d1b838092d1a76e48cdce8b5b67ff809 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 27 Nov 2023 01:54:28 +0000 +Subject: [PATCH 04/15] mtd: ubi: attach from device tree + +Introduce device tree compatible 'linux,ubi' and attach compatible MTD +devices using the MTD add notifier. This is needed for a UBI device to +be available early at boot (and not only after late_initcall), so +volumes on them can be used eg. as NVMEM providers for other drivers. + +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/build.c | 146 ++++++++++++++++++++++++++++------------ + drivers/mtd/ubi/cdev.c | 2 +- + drivers/mtd/ubi/ubi.h | 2 +- + 3 files changed, 106 insertions(+), 44 deletions(-) + +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #include "ubi.h" +@@ -1071,6 +1072,7 @@ out_free: + * ubi_detach_mtd_dev - detach an MTD device. + * @ubi_num: UBI device number to detach from + * @anyway: detach MTD even if device reference count is not zero ++ * @have_lock: called by MTD notifier holding mtd_table_mutex + * + * This function destroys an UBI device number @ubi_num and detaches the + * underlying MTD device. Returns zero in case of success and %-EBUSY if the +@@ -1080,7 +1082,7 @@ out_free: + * Note, the invocations of this function has to be serialized by the + * @ubi_devices_mutex. + */ +-int ubi_detach_mtd_dev(int ubi_num, int anyway) ++int ubi_detach_mtd_dev(int ubi_num, int anyway, bool have_lock) + { + struct ubi_device *ubi; + +@@ -1136,7 +1138,11 @@ int ubi_detach_mtd_dev(int ubi_num, int + vfree(ubi->peb_buf); + vfree(ubi->fm_buf); + ubi_msg(ubi, "mtd%d is detached", ubi->mtd->index); +- put_mtd_device(ubi->mtd); ++ if (have_lock) ++ __put_mtd_device(ubi->mtd); ++ else ++ put_mtd_device(ubi->mtd); ++ + put_device(&ubi->dev); + return 0; + } +@@ -1213,43 +1219,43 @@ static struct mtd_info * __init open_mtd + return mtd; + } + +-static int __init ubi_init(void) ++static void ubi_notify_add(struct mtd_info *mtd) + { +- int err, i, k; ++ struct device_node *np = mtd_get_of_node(mtd); ++ int err; + +- /* Ensure that EC and VID headers have correct size */ +- BUILD_BUG_ON(sizeof(struct ubi_ec_hdr) != 64); +- BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64); ++ if (!of_device_is_compatible(np, "linux,ubi")) ++ return; + +- if (mtd_devs > UBI_MAX_DEVICES) { +- pr_err("UBI error: too many MTD devices, maximum is %d\n", +- UBI_MAX_DEVICES); +- return -EINVAL; +- } ++ /* ++ * we are already holding &mtd_table_mutex, but still need ++ * to bump refcount ++ */ ++ err = __get_mtd_device(mtd); ++ if (err) ++ return; + +- /* Create base sysfs directory and sysfs files */ +- err = class_register(&ubi_class); ++ /* called while holding mtd_table_mutex */ ++ mutex_lock_nested(&ubi_devices_mutex, SINGLE_DEPTH_NESTING); ++ err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 0, false); ++ mutex_unlock(&ubi_devices_mutex); + if (err < 0) +- return err; +- +- err = misc_register(&ubi_ctrl_cdev); +- if (err) { +- pr_err("UBI error: cannot register device\n"); +- goto out; +- } ++ __put_mtd_device(mtd); ++} + +- ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", +- sizeof(struct ubi_wl_entry), +- 0, 0, NULL); +- if (!ubi_wl_entry_slab) { +- err = -ENOMEM; +- goto out_dev_unreg; +- } ++static void ubi_notify_remove(struct mtd_info *mtd) ++{ ++ WARN(1, "mtd%d removed despite UBI still being attached", mtd->index); ++} + +- err = ubi_debugfs_init(); +- if (err) +- goto out_slab; ++static struct mtd_notifier ubi_mtd_notifier = { ++ .add = ubi_notify_add, ++ .remove = ubi_notify_remove, ++}; + ++static int __init ubi_init_attach(void) ++{ ++ int err, i, k; + + /* Attach MTD devices */ + for (i = 0; i < mtd_devs; i++) { +@@ -1297,25 +1303,79 @@ static int __init ubi_init(void) + } + } + ++ return 0; ++ ++out_detach: ++ for (k = 0; k < i; k++) ++ if (ubi_devices[k]) { ++ mutex_lock(&ubi_devices_mutex); ++ ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1, false); ++ mutex_unlock(&ubi_devices_mutex); ++ } ++ return err; ++} ++#ifndef CONFIG_MTD_UBI_MODULE ++late_initcall(ubi_init_attach); ++#endif ++ ++static int __init ubi_init(void) ++{ ++ int err; ++ ++ /* Ensure that EC and VID headers have correct size */ ++ BUILD_BUG_ON(sizeof(struct ubi_ec_hdr) != 64); ++ BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64); ++ ++ if (mtd_devs > UBI_MAX_DEVICES) { ++ pr_err("UBI error: too many MTD devices, maximum is %d\n", ++ UBI_MAX_DEVICES); ++ return -EINVAL; ++ } ++ ++ /* Create base sysfs directory and sysfs files */ ++ err = class_register(&ubi_class); ++ if (err < 0) ++ return err; ++ ++ err = misc_register(&ubi_ctrl_cdev); ++ if (err) { ++ pr_err("UBI error: cannot register device\n"); ++ goto out; ++ } ++ ++ ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", ++ sizeof(struct ubi_wl_entry), ++ 0, 0, NULL); ++ if (!ubi_wl_entry_slab) { ++ err = -ENOMEM; ++ goto out_dev_unreg; ++ } ++ ++ err = ubi_debugfs_init(); ++ if (err) ++ goto out_slab; ++ + err = ubiblock_init(); + if (err) { + pr_err("UBI error: block: cannot initialize, error %d\n", err); + + /* See comment above re-ubi_is_module(). */ + if (ubi_is_module()) +- goto out_detach; ++ goto out_slab; ++ } ++ ++ register_mtd_user(&ubi_mtd_notifier); ++ ++ if (ubi_is_module()) { ++ err = ubi_init_attach(); ++ if (err) ++ goto out_mtd_notifier; + } + + return 0; + +-out_detach: +- for (k = 0; k < i; k++) +- if (ubi_devices[k]) { +- mutex_lock(&ubi_devices_mutex); +- ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1); +- mutex_unlock(&ubi_devices_mutex); +- } +- ubi_debugfs_exit(); ++out_mtd_notifier: ++ unregister_mtd_user(&ubi_mtd_notifier); + out_slab: + kmem_cache_destroy(ubi_wl_entry_slab); + out_dev_unreg: +@@ -1325,18 +1385,20 @@ out: + pr_err("UBI error: cannot initialize UBI, error %d\n", err); + return err; + } +-late_initcall(ubi_init); ++device_initcall(ubi_init); ++ + + static void __exit ubi_exit(void) + { + int i; + + ubiblock_exit(); ++ unregister_mtd_user(&ubi_mtd_notifier); + + for (i = 0; i < UBI_MAX_DEVICES; i++) + if (ubi_devices[i]) { + mutex_lock(&ubi_devices_mutex); +- ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1); ++ ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1, false); + mutex_unlock(&ubi_devices_mutex); + } + ubi_debugfs_exit(); +--- a/drivers/mtd/ubi/cdev.c ++++ b/drivers/mtd/ubi/cdev.c +@@ -1065,7 +1065,7 @@ static long ctrl_cdev_ioctl(struct file + } + + mutex_lock(&ubi_devices_mutex); +- err = ubi_detach_mtd_dev(ubi_num, 0); ++ err = ubi_detach_mtd_dev(ubi_num, 0, false); + mutex_unlock(&ubi_devices_mutex); + break; + } +--- a/drivers/mtd/ubi/ubi.h ++++ b/drivers/mtd/ubi/ubi.h +@@ -939,7 +939,7 @@ int ubi_io_write_vid_hdr(struct ubi_devi + int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, + int vid_hdr_offset, int max_beb_per1024, + bool disable_fm); +-int ubi_detach_mtd_dev(int ubi_num, int anyway); ++int ubi_detach_mtd_dev(int ubi_num, int anyway, bool have_lock); + struct ubi_device *ubi_get_device(int ubi_num); + void ubi_put_device(struct ubi_device *ubi); + struct ubi_device *ubi_get_by_major(int major); diff --git a/lede/target/linux/generic/pending-6.1/450-05-mtd-ubi-introduce-pre-removal-notification-for-UBI-v.patch b/lede/target/linux/generic/pending-6.1/450-05-mtd-ubi-introduce-pre-removal-notification-for-UBI-v.patch new file mode 100644 index 0000000000..d5da37b856 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-05-mtd-ubi-introduce-pre-removal-notification-for-UBI-v.patch @@ -0,0 +1,226 @@ +From 2d664266cfdd114cc7a1fa28dd64275e99222455 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 8 Jun 2023 17:18:09 +0100 +Subject: [PATCH 05/15] mtd: ubi: introduce pre-removal notification for UBI + volumes + +Introduce a new notification type UBI_VOLUME_SHUTDOWN to inform users +that a volume is just about to be removed. +This is needed because users (such as the NVMEM subsystem) expect that +at the time their removal function is called, the parenting device is +still available (for removal of sysfs nodes, for example, in case of +NVMEM which otherwise WARNs on volume removal). + +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/block.c | 26 ++++++++++++++++++++++++++ + drivers/mtd/ubi/build.c | 20 +++++++++++++++----- + drivers/mtd/ubi/kapi.c | 2 +- + drivers/mtd/ubi/ubi.h | 2 ++ + drivers/mtd/ubi/vmt.c | 17 +++++++++++++++-- + include/linux/mtd/ubi.h | 2 ++ + 6 files changed, 61 insertions(+), 8 deletions(-) + +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -568,6 +568,29 @@ static int ubiblock_resize(struct ubi_vo + return 0; + } + ++static int ubiblock_shutdown(struct ubi_volume_info *vi) ++{ ++ struct ubiblock *dev; ++ struct gendisk *disk; ++ int ret = 0; ++ ++ mutex_lock(&devices_mutex); ++ dev = find_dev_nolock(vi->ubi_num, vi->vol_id); ++ if (!dev) { ++ ret = -ENODEV; ++ goto out_unlock; ++ } ++ disk = dev->gd; ++ ++out_unlock: ++ mutex_unlock(&devices_mutex); ++ ++ if (!ret) ++ blk_mark_disk_dead(disk); ++ ++ return ret; ++}; ++ + static bool + match_volume_desc(struct ubi_volume_info *vi, const char *name, int ubi_num, int vol_id) + { +@@ -659,6 +682,9 @@ static int ubiblock_notify(struct notifi + case UBI_VOLUME_REMOVED: + ubiblock_remove(&nt->vi); + break; ++ case UBI_VOLUME_SHUTDOWN: ++ ubiblock_shutdown(&nt->vi); ++ break; + case UBI_VOLUME_RESIZED: + ubiblock_resize(&nt->vi); + break; +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -89,7 +89,7 @@ static struct ubi_device *ubi_devices[UB + /* Serializes UBI devices creations and removals */ + DEFINE_MUTEX(ubi_devices_mutex); + +-/* Protects @ubi_devices and @ubi->ref_count */ ++/* Protects @ubi_devices, @ubi->ref_count and @ubi->is_dead */ + static DEFINE_SPINLOCK(ubi_devices_lock); + + /* "Show" method for files in '//class/ubi/' */ +@@ -258,6 +258,9 @@ struct ubi_device *ubi_get_device(int ub + + spin_lock(&ubi_devices_lock); + ubi = ubi_devices[ubi_num]; ++ if (ubi && ubi->is_dead) ++ ubi = NULL; ++ + if (ubi) { + ubi_assert(ubi->ref_count >= 0); + ubi->ref_count += 1; +@@ -295,7 +298,7 @@ struct ubi_device *ubi_get_by_major(int + spin_lock(&ubi_devices_lock); + for (i = 0; i < UBI_MAX_DEVICES; i++) { + ubi = ubi_devices[i]; +- if (ubi && MAJOR(ubi->cdev.dev) == major) { ++ if (ubi && !ubi->is_dead && MAJOR(ubi->cdev.dev) == major) { + ubi_assert(ubi->ref_count >= 0); + ubi->ref_count += 1; + get_device(&ubi->dev); +@@ -324,7 +327,7 @@ int ubi_major2num(int major) + for (i = 0; i < UBI_MAX_DEVICES; i++) { + struct ubi_device *ubi = ubi_devices[i]; + +- if (ubi && MAJOR(ubi->cdev.dev) == major) { ++ if (ubi && !ubi->is_dead && MAJOR(ubi->cdev.dev) == major) { + ubi_num = ubi->ubi_num; + break; + } +@@ -511,7 +514,7 @@ static void ubi_free_volumes_from(struct + int i; + + for (i = from; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { +- if (!ubi->volumes[i]) ++ if (!ubi->volumes[i] || ubi->volumes[i]->is_dead) + continue; + ubi_eba_replace_table(ubi->volumes[i], NULL); + ubi_fastmap_destroy_checkmap(ubi->volumes[i]); +@@ -1094,10 +1097,10 @@ int ubi_detach_mtd_dev(int ubi_num, int + return -EINVAL; + + spin_lock(&ubi_devices_lock); +- put_device(&ubi->dev); + ubi->ref_count -= 1; + if (ubi->ref_count) { + if (!anyway) { ++ ubi->ref_count += 1; + spin_unlock(&ubi_devices_lock); + return -EBUSY; + } +@@ -1105,6 +1108,13 @@ int ubi_detach_mtd_dev(int ubi_num, int + ubi_err(ubi, "%s reference count %d, destroy anyway", + ubi->ubi_name, ubi->ref_count); + } ++ ubi->is_dead = true; ++ spin_unlock(&ubi_devices_lock); ++ ++ ubi_notify_all(ubi, UBI_VOLUME_SHUTDOWN, NULL); ++ ++ spin_lock(&ubi_devices_lock); ++ put_device(&ubi->dev); + ubi_devices[ubi_num] = NULL; + spin_unlock(&ubi_devices_lock); + +--- a/drivers/mtd/ubi/kapi.c ++++ b/drivers/mtd/ubi/kapi.c +@@ -152,7 +152,7 @@ struct ubi_volume_desc *ubi_open_volume( + + spin_lock(&ubi->volumes_lock); + vol = ubi->volumes[vol_id]; +- if (!vol) ++ if (!vol || vol->is_dead) + goto out_unlock; + + err = -EBUSY; +--- a/drivers/mtd/ubi/ubi.h ++++ b/drivers/mtd/ubi/ubi.h +@@ -345,6 +345,7 @@ struct ubi_volume { + int writers; + int exclusive; + int metaonly; ++ bool is_dead; + + int reserved_pebs; + int vol_type; +@@ -564,6 +565,7 @@ struct ubi_device { + spinlock_t volumes_lock; + int ref_count; + int image_seq; ++ bool is_dead; + + int rsvd_pebs; + int avail_pebs; +--- a/drivers/mtd/ubi/vmt.c ++++ b/drivers/mtd/ubi/vmt.c +@@ -59,7 +59,7 @@ static ssize_t vol_attribute_show(struct + struct ubi_device *ubi = vol->ubi; + + spin_lock(&ubi->volumes_lock); +- if (!ubi->volumes[vol->vol_id]) { ++ if (!ubi->volumes[vol->vol_id] || ubi->volumes[vol->vol_id]->is_dead) { + spin_unlock(&ubi->volumes_lock); + return -ENODEV; + } +@@ -189,7 +189,7 @@ int ubi_create_volume(struct ubi_device + + /* Ensure that the name is unique */ + for (i = 0; i < ubi->vtbl_slots; i++) +- if (ubi->volumes[i] && ++ if (ubi->volumes[i] && !ubi->volumes[i]->is_dead && + ubi->volumes[i]->name_len == req->name_len && + !strcmp(ubi->volumes[i]->name, req->name)) { + ubi_err(ubi, "volume \"%s\" exists (ID %d)", +@@ -352,6 +352,19 @@ int ubi_remove_volume(struct ubi_volume_ + err = -EBUSY; + goto out_unlock; + } ++ ++ /* ++ * Mark volume as dead at this point to prevent that anyone ++ * can take a reference to the volume from now on. ++ * This is necessary as we have to release the spinlock before ++ * calling ubi_volume_notify. ++ */ ++ vol->is_dead = true; ++ spin_unlock(&ubi->volumes_lock); ++ ++ ubi_volume_notify(ubi, vol, UBI_VOLUME_SHUTDOWN); ++ ++ spin_lock(&ubi->volumes_lock); + ubi->volumes[vol_id] = NULL; + spin_unlock(&ubi->volumes_lock); + +--- a/include/linux/mtd/ubi.h ++++ b/include/linux/mtd/ubi.h +@@ -192,6 +192,7 @@ struct ubi_device_info { + * or a volume was removed) + * @UBI_VOLUME_RESIZED: a volume has been re-sized + * @UBI_VOLUME_RENAMED: a volume has been re-named ++ * @UBI_VOLUME_SHUTDOWN: a volume is going to removed, shutdown users + * @UBI_VOLUME_UPDATED: data has been written to a volume + * + * These constants define which type of event has happened when a volume +@@ -202,6 +203,7 @@ enum { + UBI_VOLUME_REMOVED, + UBI_VOLUME_RESIZED, + UBI_VOLUME_RENAMED, ++ UBI_VOLUME_SHUTDOWN, + UBI_VOLUME_UPDATED, + }; + diff --git a/lede/target/linux/generic/pending-6.1/450-06-mtd-ubi-populate-ubi-volume-fwnode.patch b/lede/target/linux/generic/pending-6.1/450-06-mtd-ubi-populate-ubi-volume-fwnode.patch new file mode 100644 index 0000000000..1322766965 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-06-mtd-ubi-populate-ubi-volume-fwnode.patch @@ -0,0 +1,65 @@ +From 3a041ee543cdf2e707a1dd72946cd6a583509b28 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Fri, 21 Jul 2023 19:26:37 +0100 +Subject: [PATCH 06/15] mtd: ubi: populate ubi volume fwnode + +Look for the 'volumes' subnode of an MTD partition attached to a UBI +device and attach matching child nodes to UBI volumes. +This allows UBI volumes to be referenced in device tree, e.g. for use +as NVMEM providers. + +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/vmt.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +--- a/drivers/mtd/ubi/vmt.c ++++ b/drivers/mtd/ubi/vmt.c +@@ -124,6 +124,31 @@ static void vol_release(struct device *d + kfree(vol); + } + ++static struct fwnode_handle *find_volume_fwnode(struct ubi_volume *vol) ++{ ++ struct fwnode_handle *fw_vols, *fw_vol; ++ const char *volname; ++ u32 volid; ++ ++ fw_vols = device_get_named_child_node(vol->dev.parent->parent, "volumes"); ++ if (!fw_vols) ++ return NULL; ++ ++ fwnode_for_each_child_node(fw_vols, fw_vol) { ++ if (!fwnode_property_read_string(fw_vol, "volname", &volname) && ++ strncmp(volname, vol->name, vol->name_len)) ++ continue; ++ ++ if (!fwnode_property_read_u32(fw_vol, "volid", &volid) && ++ vol->vol_id != volid) ++ continue; ++ ++ return fw_vol; ++ } ++ ++ return NULL; ++} ++ + /** + * ubi_create_volume - create volume. + * @ubi: UBI device description object +@@ -223,6 +248,7 @@ int ubi_create_volume(struct ubi_device + vol->name_len = req->name_len; + memcpy(vol->name, req->name, vol->name_len); + vol->ubi = ubi; ++ device_set_node(&vol->dev, find_volume_fwnode(vol)); + + /* + * Finish all pending erases because there may be some LEBs belonging +@@ -605,6 +631,7 @@ int ubi_add_volume(struct ubi_device *ub + vol->dev.class = &ubi_class; + vol->dev.groups = volume_dev_groups; + dev_set_name(&vol->dev, "%s_%d", ubi->ubi_name, vol->vol_id); ++ device_set_node(&vol->dev, find_volume_fwnode(vol)); + err = device_register(&vol->dev); + if (err) { + cdev_del(&vol->cdev); diff --git a/lede/target/linux/generic/pending-6.1/450-07-mtd-ubi-provide-NVMEM-layer-over-UBI-volumes.patch b/lede/target/linux/generic/pending-6.1/450-07-mtd-ubi-provide-NVMEM-layer-over-UBI-volumes.patch new file mode 100644 index 0000000000..59a1eb9374 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-07-mtd-ubi-provide-NVMEM-layer-over-UBI-volumes.patch @@ -0,0 +1,246 @@ +From 7eb6666348f3f2d1f7308c712fa5903cbe189401 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 8 Jun 2023 17:22:04 +0100 +Subject: [PATCH 07/15] mtd: ubi: provide NVMEM layer over UBI volumes + +In an ideal world we would like UBI to be used where ever possible on a +NAND chip. And with UBI support in ARM Trusted Firmware and U-Boot it +is possible to achieve an (almost-)all-UBI flash layout. Hence the need +for a way to also use UBI volumes to store board-level constants, such +as MAC addresses and calibration data of wireless interfaces. + +Add UBI volume NVMEM driver module exposing UBI volumes as NVMEM +providers. Allow UBI devices to have a "volumes" firmware subnode with +volumes which may be compatible with "nvmem-cells". +Access to UBI volumes via the NVMEM interface at this point is +read-only, and it is slow, opening and closing the UBI volume for each +access due to limitations of the NVMEM provider API. + +Signed-off-by: Daniel Golle +--- + drivers/mtd/ubi/Kconfig | 12 +++ + drivers/mtd/ubi/Makefile | 1 + + drivers/mtd/ubi/nvmem.c | 188 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 201 insertions(+) + create mode 100644 drivers/mtd/ubi/nvmem.c + +--- a/drivers/mtd/ubi/Kconfig ++++ b/drivers/mtd/ubi/Kconfig +@@ -104,4 +104,16 @@ config MTD_UBI_BLOCK + + If in doubt, say "N". + ++config MTD_UBI_NVMEM ++ tristate "UBI virtual NVMEM" ++ default n ++ depends on NVMEM ++ help ++ This option enabled an additional driver exposing UBI volumes as NVMEM ++ providers, intended for platforms where UBI is part of the firmware ++ specification and used to store also e.g. MAC addresses or board- ++ specific Wi-Fi calibration data. ++ ++ If in doubt, say "N". ++ + endif # MTD_UBI +--- a/drivers/mtd/ubi/Makefile ++++ b/drivers/mtd/ubi/Makefile +@@ -7,3 +7,4 @@ ubi-$(CONFIG_MTD_UBI_FASTMAP) += fastmap + ubi-$(CONFIG_MTD_UBI_BLOCK) += block.o + + obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o ++obj-$(CONFIG_MTD_UBI_NVMEM) += nvmem.o +--- /dev/null ++++ b/drivers/mtd/ubi/nvmem.c +@@ -0,0 +1,191 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (c) 2023 Daniel Golle ++ */ ++ ++/* UBI NVMEM provider */ ++#include "ubi.h" ++#include ++#include ++ ++/* List of all NVMEM devices */ ++static LIST_HEAD(nvmem_devices); ++static DEFINE_MUTEX(devices_mutex); ++ ++struct ubi_nvmem { ++ struct nvmem_device *nvmem; ++ int ubi_num; ++ int vol_id; ++ int usable_leb_size; ++ struct list_head list; ++}; ++ ++static int ubi_nvmem_reg_read(void *priv, unsigned int from, ++ void *val, size_t bytes) ++{ ++ uint32_t offs, to_read, bytes_left; ++ struct ubi_nvmem *unv = priv; ++ struct ubi_volume_desc *desc; ++ uint64_t lnum = from; ++ int err = 0; ++ ++ desc = ubi_open_volume(unv->ubi_num, unv->vol_id, UBI_READONLY); ++ if (IS_ERR(desc)) ++ return PTR_ERR(desc); ++ ++ bytes_left = bytes; ++ offs = do_div(lnum, unv->usable_leb_size); ++ while (bytes_left) { ++ to_read = unv->usable_leb_size - offs; ++ ++ if (to_read > bytes_left) ++ to_read = bytes_left; ++ ++ err = ubi_read(desc, lnum, val, offs, to_read); ++ if (err) ++ break; ++ ++ lnum += 1; ++ offs = 0; ++ bytes_left -= to_read; ++ val += to_read; ++ } ++ ubi_close_volume(desc); ++ ++ if (err) ++ return err; ++ ++ return bytes_left == 0 ? 0 : -EIO; ++} ++ ++static int ubi_nvmem_add(struct ubi_volume_info *vi) ++{ ++ struct device_node *np = dev_of_node(vi->dev); ++ struct nvmem_config config = {}; ++ struct ubi_nvmem *unv; ++ int ret; ++ ++ if (!np) ++ return 0; ++ ++ if (!of_get_child_by_name(np, "nvmem-layout")) ++ return 0; ++ ++ if (WARN_ON_ONCE(vi->usable_leb_size <= 0) || ++ WARN_ON_ONCE(vi->size <= 0)) ++ return -EINVAL; ++ ++ unv = kzalloc(sizeof(struct ubi_nvmem), GFP_KERNEL); ++ if (!unv) ++ return -ENOMEM; ++ ++ config.id = NVMEM_DEVID_NONE; ++ config.dev = vi->dev; ++ config.name = dev_name(vi->dev); ++ config.owner = THIS_MODULE; ++ config.priv = unv; ++ config.reg_read = ubi_nvmem_reg_read; ++ config.size = vi->usable_leb_size * vi->size; ++ config.word_size = 1; ++ config.stride = 1; ++ config.read_only = true; ++ config.root_only = true; ++ config.ignore_wp = true; ++ config.of_node = np; ++ ++ unv->ubi_num = vi->ubi_num; ++ unv->vol_id = vi->vol_id; ++ unv->usable_leb_size = vi->usable_leb_size; ++ unv->nvmem = nvmem_register(&config); ++ if (IS_ERR(unv->nvmem)) { ++ ret = dev_err_probe(vi->dev, PTR_ERR(unv->nvmem), ++ "Failed to register NVMEM device\n"); ++ kfree(unv); ++ return ret; ++ } ++ ++ mutex_lock(&devices_mutex); ++ list_add_tail(&unv->list, &nvmem_devices); ++ mutex_unlock(&devices_mutex); ++ ++ return 0; ++} ++ ++static void ubi_nvmem_remove(struct ubi_volume_info *vi) ++{ ++ struct ubi_nvmem *unv_c, *unv = NULL; ++ ++ mutex_lock(&devices_mutex); ++ list_for_each_entry(unv_c, &nvmem_devices, list) ++ if (unv_c->ubi_num == vi->ubi_num && unv_c->vol_id == vi->vol_id) { ++ unv = unv_c; ++ break; ++ } ++ ++ if (!unv) { ++ mutex_unlock(&devices_mutex); ++ return; ++ } ++ ++ list_del(&unv->list); ++ mutex_unlock(&devices_mutex); ++ nvmem_unregister(unv->nvmem); ++ kfree(unv); ++} ++ ++/** ++ * nvmem_notify - UBI notification handler. ++ * @nb: registered notifier block ++ * @l: notification type ++ * @ns_ptr: pointer to the &struct ubi_notification object ++ */ ++static int nvmem_notify(struct notifier_block *nb, unsigned long l, ++ void *ns_ptr) ++{ ++ struct ubi_notification *nt = ns_ptr; ++ ++ switch (l) { ++ case UBI_VOLUME_RESIZED: ++ ubi_nvmem_remove(&nt->vi); ++ fallthrough; ++ case UBI_VOLUME_ADDED: ++ ubi_nvmem_add(&nt->vi); ++ break; ++ case UBI_VOLUME_SHUTDOWN: ++ ubi_nvmem_remove(&nt->vi); ++ break; ++ default: ++ break; ++ } ++ return NOTIFY_OK; ++} ++ ++static struct notifier_block nvmem_notifier = { ++ .notifier_call = nvmem_notify, ++}; ++ ++static int __init ubi_nvmem_init(void) ++{ ++ return ubi_register_volume_notifier(&nvmem_notifier, 0); ++} ++ ++static void __exit ubi_nvmem_exit(void) ++{ ++ struct ubi_nvmem *unv, *tmp; ++ ++ mutex_lock(&devices_mutex); ++ list_for_each_entry_safe(unv, tmp, &nvmem_devices, list) { ++ nvmem_unregister(unv->nvmem); ++ list_del(&unv->list); ++ kfree(unv); ++ } ++ mutex_unlock(&devices_mutex); ++ ++ ubi_unregister_volume_notifier(&nvmem_notifier); ++} ++ ++module_init(ubi_nvmem_init); ++module_exit(ubi_nvmem_exit); ++MODULE_DESCRIPTION("NVMEM layer over UBI volumes"); ++MODULE_AUTHOR("Daniel Golle"); ++MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/generic/pending-6.1/450-08-dt-bindings-block-add-basic-bindings-for-block-devic.patch b/lede/target/linux/generic/pending-6.1/450-08-dt-bindings-block-add-basic-bindings-for-block-devic.patch new file mode 100644 index 0000000000..d0727faf3d --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-08-dt-bindings-block-add-basic-bindings-for-block-devic.patch @@ -0,0 +1,120 @@ +From 9ffc1d7d73609a89eb264d6066340f8b7b3b0ebe Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 7 Aug 2023 21:19:45 +0100 +Subject: [PATCH 08/15] dt-bindings: block: add basic bindings for block + devices + +Add bindings for block devices which are used to allow referencing +nvmem bits on them. + +Signed-off-by: Daniel Golle +--- + .../bindings/block/block-device.yaml | 22 ++++++++ + .../devicetree/bindings/block/partition.yaml | 50 +++++++++++++++++++ + .../devicetree/bindings/block/partitions.yaml | 20 ++++++++ + 3 files changed, 92 insertions(+) + create mode 100644 Documentation/devicetree/bindings/block/block-device.yaml + create mode 100644 Documentation/devicetree/bindings/block/partition.yaml + create mode 100644 Documentation/devicetree/bindings/block/partitions.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/block/block-device.yaml +@@ -0,0 +1,22 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/block/block-device.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: block storage device ++ ++description: | ++ This binding is generic and describes a block-oriented storage device. ++ ++maintainers: ++ - Daniel Golle ++ ++properties: ++ partitions: ++ $ref: /schemas/block/partitions.yaml ++ ++ nvmem-layout: ++ $ref: /schemas/nvmem/layouts/nvmem-layout.yaml# ++ ++unevaluatedProperties: false +--- /dev/null ++++ b/Documentation/devicetree/bindings/block/partition.yaml +@@ -0,0 +1,50 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/block/partition.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Partition on a block device ++ ++description: | ++ This binding describes a partition on a block device. ++ Partitions may be matched by a combination of partition number, name, ++ and UUID. ++ ++maintainers: ++ - Daniel Golle ++ ++properties: ++ $nodename: ++ pattern: '^block-partition-.+$' ++ ++ partnum: ++ description: ++ Matches partition by number if present. ++ ++ partname: ++ "$ref": "/schemas/types.yaml#/definitions/string" ++ description: ++ Matches partition by PARTNAME if present. ++ ++ uuid: ++ "$ref": "/schemas/types.yaml#/definitions/string" ++ description: ++ Matches partition by PARTUUID if present. ++ ++ nvmem-layout: ++ $ref: /schemas/nvmem/layouts/nvmem-layout.yaml# ++ description: ++ This container may reference an NVMEM layout parser. ++ ++anyOf: ++ - required: ++ - partnum ++ ++ - required: ++ - partname ++ ++ - required: ++ - uuid ++ ++unevaluatedProperties: false +--- /dev/null ++++ b/Documentation/devicetree/bindings/block/partitions.yaml +@@ -0,0 +1,20 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/block/partitions.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Partitions on block devices ++ ++description: | ++ This binding is generic and describes the content of the partitions container ++ node. ++ ++maintainers: ++ - Daniel Golle ++ ++patternProperties: ++ "^block-partition-.+$": ++ $ref: partition.yaml ++ ++unevaluatedProperties: false diff --git a/lede/target/linux/generic/pending-6.1/450-09-block-partitions-populate-fwnode.patch b/lede/target/linux/generic/pending-6.1/450-09-block-partitions-populate-fwnode.patch new file mode 100644 index 0000000000..8aa5cba678 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-09-block-partitions-populate-fwnode.patch @@ -0,0 +1,77 @@ +From 614f4f6fdda09e30ecf7ef6c8091579db15018cb Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Fri, 21 Jul 2023 17:51:03 +0100 +Subject: [PATCH 09/15] block: partitions: populate fwnode + +Let block partitions to be represented by a firmware node and hence +allow them to being referenced e.g. for use with blk-nvmem. + +Signed-off-by: Daniel Golle +--- + block/partitions/core.c | 41 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 41 insertions(+) + +--- a/block/partitions/core.c ++++ b/block/partitions/core.c +@@ -10,6 +10,8 @@ + #include + #include + #include ++#include ++ + #include "check.h" + + static int (*check_part[])(struct parsed_partitions *) = { +@@ -298,6 +300,43 @@ static ssize_t whole_disk_show(struct de + } + static DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL); + ++static struct fwnode_handle *find_partition_fwnode(struct block_device *bdev) ++{ ++ struct fwnode_handle *fw_parts, *fw_part; ++ struct device *ddev = disk_to_dev(bdev->bd_disk); ++ const char *partname, *uuid; ++ u32 partno; ++ ++ fw_parts = device_get_named_child_node(ddev, "partitions"); ++ if (!fw_parts) ++ fw_parts = device_get_named_child_node(ddev->parent, "partitions"); ++ ++ if (!fw_parts) ++ return NULL; ++ ++ fwnode_for_each_child_node(fw_parts, fw_part) { ++ if (!fwnode_property_read_string(fw_part, "uuid", &uuid) && ++ (!bdev->bd_meta_info || strncmp(uuid, ++ bdev->bd_meta_info->uuid, ++ PARTITION_META_INFO_UUIDLTH))) ++ continue; ++ ++ if (!fwnode_property_read_string(fw_part, "partname", &partname) && ++ (!bdev->bd_meta_info || strncmp(partname, ++ bdev->bd_meta_info->volname, ++ PARTITION_META_INFO_VOLNAMELTH))) ++ continue; ++ ++ if (!fwnode_property_read_u32(fw_part, "partno", &partno) && ++ bdev->bd_partno != partno) ++ continue; ++ ++ return fw_part; ++ } ++ ++ return NULL; ++} ++ + /* + * Must be called either with open_mutex held, before a disk can be opened or + * after all disk users are gone. +@@ -380,6 +419,8 @@ static struct block_device *add_partitio + goto out_put; + } + ++ device_set_node(pdev, find_partition_fwnode(bdev)); ++ + /* delay uevent until 'holders' subdir is created */ + dev_set_uevent_suppress(pdev, 1); + err = device_add(pdev); diff --git a/lede/target/linux/generic/pending-6.1/450-10-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch b/lede/target/linux/generic/pending-6.1/450-10-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch new file mode 100644 index 0000000000..4cbec14f5c --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-10-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch @@ -0,0 +1,29 @@ +From 65f3ff9672ccd5ee78937047e7a2fc696eee1c8f Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 13 Jul 2023 04:07:16 +0100 +Subject: [PATCH 10/15] block: add new genhd flag GENHD_FL_NVMEM + +Add new flag to destinguish block devices which may act as an NVMEM +provider. + +Signed-off-by: Daniel Golle +--- + include/linux/blkdev.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -87,11 +87,13 @@ struct partition_meta_info { + * ``GENHD_FL_NO_PART``: partition support is disabled. The kernel will not + * scan for partitions from add_disk, and users can't add partitions manually. + * ++ * ``GENHD_FL_NVMEM``: the block device should be considered as NVMEM provider. + */ + enum { + GENHD_FL_REMOVABLE = 1 << 0, + GENHD_FL_HIDDEN = 1 << 1, + GENHD_FL_NO_PART = 1 << 2, ++ GENHD_FL_NVMEM = 1 << 3, + }; + + enum { diff --git a/lede/target/linux/generic/pending-6.1/450-11-block-implement-NVMEM-provider.patch b/lede/target/linux/generic/pending-6.1/450-11-block-implement-NVMEM-provider.patch new file mode 100644 index 0000000000..e18b0c3a5c --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-11-block-implement-NVMEM-provider.patch @@ -0,0 +1,235 @@ +From b9936aa8a3775c2027f655d91a206d0e6e1c7ec0 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 11 Jul 2023 00:17:31 +0100 +Subject: [PATCH 11/15] block: implement NVMEM provider + +On embedded devices using an eMMC it is common that one or more partitions +on the eMMC are used to store MAC addresses and Wi-Fi calibration EEPROM +data. Allow referencing the partition in device tree for the kernel and +Wi-Fi drivers accessing it via the NVMEM layer. + +Signed-off-by: Daniel Golle +--- + block/Kconfig | 9 +++ + block/Makefile | 1 + + block/blk-nvmem.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 196 insertions(+) + create mode 100644 block/blk-nvmem.c + +--- a/block/Kconfig ++++ b/block/Kconfig +@@ -203,6 +203,15 @@ config BLK_INLINE_ENCRYPTION_FALLBACK + by falling back to the kernel crypto API when inline + encryption hardware is not present. + ++config BLK_NVMEM ++ bool "Block device NVMEM provider" ++ depends on OF ++ depends on NVMEM ++ help ++ Allow block devices (or partitions) to act as NVMEM prodivers, ++ typically used with eMMC to store MAC addresses or Wi-Fi ++ calibration data on embedded devices. ++ + source "block/partitions/Kconfig" + + config BLOCK_COMPAT +--- a/block/Makefile ++++ b/block/Makefile +@@ -35,6 +35,7 @@ obj-$(CONFIG_BLK_DEV_ZONED) += blk-zoned + obj-$(CONFIG_BLK_WBT) += blk-wbt.o + obj-$(CONFIG_BLK_DEBUG_FS) += blk-mq-debugfs.o + obj-$(CONFIG_BLK_DEBUG_FS_ZONED)+= blk-mq-debugfs-zoned.o ++obj-$(CONFIG_BLK_NVMEM) += blk-nvmem.o + obj-$(CONFIG_BLK_SED_OPAL) += sed-opal.o + obj-$(CONFIG_BLK_PM) += blk-pm.o + obj-$(CONFIG_BLK_INLINE_ENCRYPTION) += blk-crypto.o blk-crypto-profile.o \ +--- /dev/null ++++ b/block/blk-nvmem.c +@@ -0,0 +1,186 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * block device NVMEM provider ++ * ++ * Copyright (c) 2023 Daniel Golle ++ * ++ * Useful on devices using a partition on an eMMC for MAC addresses or ++ * Wi-Fi calibration EEPROM data. ++ */ ++ ++#include "blk.h" ++#include ++#include ++#include ++#include ++ ++/* List of all NVMEM devices */ ++static LIST_HEAD(nvmem_devices); ++static DEFINE_MUTEX(devices_mutex); ++ ++struct blk_nvmem { ++ struct nvmem_device *nvmem; ++ struct block_device *bdev; ++ struct list_head list; ++}; ++ ++static int blk_nvmem_reg_read(void *priv, unsigned int from, ++ void *val, size_t bytes) ++{ ++ unsigned long offs = from & ~PAGE_MASK, to_read; ++ pgoff_t f_index = from >> PAGE_SHIFT; ++ struct address_space *mapping; ++ struct blk_nvmem *bnv = priv; ++ size_t bytes_left = bytes; ++ struct folio *folio; ++ void *p; ++ int ret; ++ ++ if (!bnv->bdev) ++ return -ENODEV; ++ ++ if (!bnv->bdev->bd_disk) ++ return -EINVAL; ++ ++ if (!bnv->bdev->bd_disk->fops) ++ return -EIO; ++ ++ if (!bnv->bdev->bd_disk->fops->open) ++ return -EIO; ++ ++ ret = bnv->bdev->bd_disk->fops->open(bnv->bdev, FMODE_READ); ++ if (ret) ++ return ret; ++ ++ mapping = bnv->bdev->bd_inode->i_mapping; ++ ++ while (bytes_left) { ++ folio = read_mapping_folio(mapping, f_index++, NULL); ++ if (IS_ERR(folio)) { ++ ret = PTR_ERR(folio); ++ goto err_release_bdev; ++ } ++ to_read = min_t(unsigned long, bytes_left, PAGE_SIZE - offs); ++ p = folio_address(folio) + offset_in_folio(folio, offs); ++ memcpy(val, p, to_read); ++ offs = 0; ++ bytes_left -= to_read; ++ val += to_read; ++ folio_put(folio); ++ } ++ ++err_release_bdev: ++ bnv->bdev->bd_disk->fops->release(bnv->bdev->bd_disk, FMODE_READ); ++ ++ return ret; ++} ++ ++static int blk_nvmem_register(struct device *dev, struct class_interface *iface) ++{ ++ struct device_node *np = dev_of_node(dev); ++ struct block_device *bdev = dev_to_bdev(dev); ++ struct nvmem_config config = {}; ++ struct blk_nvmem *bnv; ++ ++ /* skip devices which do not have a device tree node */ ++ if (!np) ++ return 0; ++ ++ /* skip devices without an nvmem layout defined */ ++ if (!of_get_child_by_name(np, "nvmem-layout")) ++ return 0; ++ ++ /* ++ * skip devices which don't have GENHD_FL_NVMEM set ++ * ++ * This flag is used for mtdblock and ubiblock devices because ++ * both, MTD and UBI already implement their own NVMEM provider. ++ * To avoid registering multiple NVMEM providers for the same ++ * device node, don't register the block NVMEM provider for them. ++ */ ++ if (!(bdev->bd_disk->flags & GENHD_FL_NVMEM)) ++ return 0; ++ ++ /* ++ * skip block device too large to be represented as NVMEM devices ++ * which are using an 'int' as address ++ */ ++ if (bdev_nr_bytes(bdev) > INT_MAX) ++ return -EFBIG; ++ ++ bnv = kzalloc(sizeof(struct blk_nvmem), GFP_KERNEL); ++ if (!bnv) ++ return -ENOMEM; ++ ++ config.id = NVMEM_DEVID_NONE; ++ config.dev = &bdev->bd_device; ++ config.name = dev_name(&bdev->bd_device); ++ config.owner = THIS_MODULE; ++ config.priv = bnv; ++ config.reg_read = blk_nvmem_reg_read; ++ config.size = bdev_nr_bytes(bdev); ++ config.word_size = 1; ++ config.stride = 1; ++ config.read_only = true; ++ config.root_only = true; ++ config.ignore_wp = true; ++ config.of_node = to_of_node(dev->fwnode); ++ ++ bnv->bdev = bdev; ++ bnv->nvmem = nvmem_register(&config); ++ if (IS_ERR(bnv->nvmem)) { ++ dev_err_probe(&bdev->bd_device, PTR_ERR(bnv->nvmem), ++ "Failed to register NVMEM device\n"); ++ ++ kfree(bnv); ++ return PTR_ERR(bnv->nvmem); ++ } ++ ++ mutex_lock(&devices_mutex); ++ list_add_tail(&bnv->list, &nvmem_devices); ++ mutex_unlock(&devices_mutex); ++ ++ return 0; ++} ++ ++static void blk_nvmem_unregister(struct device *dev, struct class_interface *iface) ++{ ++ struct block_device *bdev = dev_to_bdev(dev); ++ struct blk_nvmem *bnv_c, *bnv = NULL; ++ ++ mutex_lock(&devices_mutex); ++ list_for_each_entry(bnv_c, &nvmem_devices, list) { ++ if (bnv_c->bdev == bdev) { ++ bnv = bnv_c; ++ break; ++ } ++ } ++ ++ if (!bnv) { ++ mutex_unlock(&devices_mutex); ++ return; ++ } ++ ++ list_del(&bnv->list); ++ mutex_unlock(&devices_mutex); ++ nvmem_unregister(bnv->nvmem); ++ kfree(bnv); ++} ++ ++static struct class_interface blk_nvmem_bus_interface __refdata = { ++ .class = &block_class, ++ .add_dev = &blk_nvmem_register, ++ .remove_dev = &blk_nvmem_unregister, ++}; ++ ++static int __init blk_nvmem_init(void) ++{ ++ int ret; ++ ++ ret = class_interface_register(&blk_nvmem_bus_interface); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++device_initcall(blk_nvmem_init); diff --git a/lede/target/linux/generic/pending-6.1/450-12-dt-bindings-mmc-mmc-card-add-block-device-nodes.patch b/lede/target/linux/generic/pending-6.1/450-12-dt-bindings-mmc-mmc-card-add-block-device-nodes.patch new file mode 100644 index 0000000000..77c9bf91a5 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-12-dt-bindings-mmc-mmc-card-add-block-device-nodes.patch @@ -0,0 +1,74 @@ +From 86864bf8f40e84dc881c197ef470a88668329dbf Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 7 Aug 2023 21:21:45 +0100 +Subject: [PATCH 12/15] dt-bindings: mmc: mmc-card: add block device nodes + +Add nodes representing the block devices exposed by an MMC device +including an example involving nvmem-cells. + +Signed-off-by: Daniel Golle +--- + .../devicetree/bindings/mmc/mmc-card.yaml | 45 +++++++++++++++++++ + 1 file changed, 45 insertions(+) + +--- a/Documentation/devicetree/bindings/mmc/mmc-card.yaml ++++ b/Documentation/devicetree/bindings/mmc/mmc-card.yaml +@@ -26,6 +26,18 @@ properties: + Use this to indicate that the mmc-card has a broken hpi + implementation, and that hpi should not be used. + ++ block: ++ $ref: /schemas/block/block-device.yaml# ++ description: ++ Represents the block storage provided by an SD card or the ++ main hardware partition of an eMMC. ++ ++patternProperties: ++ '^boot[0-9]+': ++ $ref: /schemas/block/block-device.yaml# ++ description: ++ Represents a boot hardware partition on an eMMC. ++ + required: + - compatible + - reg +@@ -42,6 +54,39 @@ examples: + compatible = "mmc-card"; + reg = <0>; + broken-hpi; ++ ++ block { ++ partitions { ++ cal_data: block-partition-rf { ++ partnum = <3>; ++ partname = "rf"; ++ ++ nvmem-layout { ++ compatible = "fixed-layout"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ eeprom@0 { ++ reg = <0x0 0x1000>; ++ }; ++ }; ++ }; ++ }; ++ }; ++ ++ boot1 { ++ nvmem-layout { ++ compatible = "fixed-layout"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ macaddr: macaddr@a { ++ compatible = "mac-base"; ++ reg = <0xa 0x6>; ++ #nvmem-cell-cells = <1>; ++ }; ++ }; ++ }; + }; + }; + diff --git a/lede/target/linux/generic/pending-6.1/450-13-mmc-core-set-card-fwnode_handle.patch b/lede/target/linux/generic/pending-6.1/450-13-mmc-core-set-card-fwnode_handle.patch new file mode 100644 index 0000000000..fada280437 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-13-mmc-core-set-card-fwnode_handle.patch @@ -0,0 +1,23 @@ +From 644942a31719de674e2aa68f83d66bd8ae7e4fb7 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 13 Jul 2023 04:12:21 +0100 +Subject: [PATCH 13/15] mmc: core: set card fwnode_handle + +Set fwnode in case it isn't set yet and of_node is present. + +Signed-off-by: Daniel Golle +--- + drivers/mmc/core/bus.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/mmc/core/bus.c ++++ b/drivers/mmc/core/bus.c +@@ -363,6 +363,8 @@ int mmc_add_card(struct mmc_card *card) + mmc_add_card_debugfs(card); + #endif + card->dev.of_node = mmc_of_find_child_device(card->host, 0); ++ if (card->dev.of_node && !card->dev.fwnode) ++ card->dev.fwnode = &card->dev.of_node->fwnode; + + device_enable_async_suspend(&card->dev); + diff --git a/lede/target/linux/generic/pending-6.1/450-14-mmc-block-set-fwnode-of-disk-devices.patch b/lede/target/linux/generic/pending-6.1/450-14-mmc-block-set-fwnode-of-disk-devices.patch new file mode 100644 index 0000000000..386282459b --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-14-mmc-block-set-fwnode-of-disk-devices.patch @@ -0,0 +1,39 @@ +From d9143f86330dd038fc48878558dd287ceee5d3d4 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 13 Jul 2023 04:13:04 +0100 +Subject: [PATCH 14/15] mmc: block: set fwnode of disk devices + +Set fwnode of disk devices to 'block', 'boot0' and 'boot1' subnodes of +the mmc-card. This is done in preparation for having the eMMC act as +NVMEM provider. + +Signed-off-by: Daniel Golle +--- + drivers/mmc/core/block.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -2486,6 +2486,8 @@ static struct mmc_blk_data *mmc_blk_allo + int area_type, + unsigned int part_type) + { ++ struct fwnode_handle *fwnode; ++ struct device *ddev; + struct mmc_blk_data *md; + int devidx, ret; + char cap_str[10]; +@@ -2582,6 +2584,13 @@ static struct mmc_blk_data *mmc_blk_allo + + blk_queue_write_cache(md->queue.queue, cache_enabled, fua_enabled); + ++ ddev = disk_to_dev(md->disk); ++ fwnode = device_get_named_child_node(subname ? md->parent->parent : ++ md->parent, ++ subname ? subname : "block"); ++ if (fwnode) ++ device_set_node(ddev, fwnode); ++ + string_get_size((u64)size, 512, STRING_UNITS_2, + cap_str, sizeof(cap_str)); + pr_info("%s: %s %s %s %s\n", diff --git a/lede/target/linux/generic/pending-6.1/450-15-mmc-block-set-GENHD_FL_NVMEM.patch b/lede/target/linux/generic/pending-6.1/450-15-mmc-block-set-GENHD_FL_NVMEM.patch new file mode 100644 index 0000000000..41c257cdeb --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/450-15-mmc-block-set-GENHD_FL_NVMEM.patch @@ -0,0 +1,22 @@ +From 322035ab2b0113d98b6c0ea788d971e0df2952a4 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 20 Jul 2023 17:36:44 +0100 +Subject: [PATCH 15/15] mmc: block: set GENHD_FL_NVMEM + +Set flag to consider MMC block devices as NVMEM providers. + +Signed-off-by: Daniel Golle +--- + drivers/mmc/core/block.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -2540,6 +2540,7 @@ static struct mmc_blk_data *mmc_blk_allo + md->disk->major = MMC_BLOCK_MAJOR; + md->disk->minors = perdev_minors; + md->disk->first_minor = devidx * perdev_minors; ++ md->disk->flags = GENHD_FL_NVMEM; + md->disk->fops = &mmc_bdops; + md->disk->private_data = md; + md->parent = parent; diff --git a/lede/target/linux/generic/pending-6.1/479-mtd-spi-nor-add-xtx-xt25f128b.patch b/lede/target/linux/generic/pending-6.1/479-mtd-spi-nor-add-xtx-xt25f128b.patch index d2a9fb3436..371f1a7276 100644 --- a/lede/target/linux/generic/pending-6.1/479-mtd-spi-nor-add-xtx-xt25f128b.patch +++ b/lede/target/linux/generic/pending-6.1/479-mtd-spi-nor-add-xtx-xt25f128b.patch @@ -68,7 +68,7 @@ Signed-off-by: Felix Fietkau + &spi_nor_xtx, }; - static const struct flash_info *spi_nor_match_id(struct spi_nor *nor, + static const struct flash_info spi_nor_generic_flash = { --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -633,6 +633,7 @@ extern const struct spi_nor_manufacturer diff --git a/lede/target/linux/generic/pending-6.1/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch b/lede/target/linux/generic/pending-6.1/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch index 765eecd9d7..2eccb9d3bb 100644 --- a/lede/target/linux/generic/pending-6.1/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch +++ b/lede/target/linux/generic/pending-6.1/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch @@ -8,10 +8,11 @@ Signed-off-by: Daniel Golle --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c -@@ -1212,6 +1212,73 @@ static struct mtd_info * __init open_mtd - return mtd; - } +@@ -1263,6 +1263,74 @@ static struct mtd_notifier ubi_mtd_notif + .remove = ubi_notify_remove, + }; ++ +/* + * This function tries attaching mtd partitions named either "ubi" or "data" + * during boot. @@ -79,10 +80,10 @@ Signed-off-by: Daniel Golle + put_mtd_device(mtd); +} + - static int __init ubi_init(void) + static int __init ubi_init_attach(void) { int err, i, k; -@@ -1296,6 +1363,12 @@ static int __init ubi_init(void) +@@ -1313,6 +1381,12 @@ static int __init ubi_init_attach(void) } } @@ -92,6 +93,6 @@ Signed-off-by: Daniel Golle + !ubi_is_module() && !mtd_devs) + ubi_auto_attach(); + - err = ubiblock_init(); - if (err) { - pr_err("UBI error: block: cannot initialize, error %d\n", err); + return 0; + + out_detach: diff --git a/lede/target/linux/generic/pending-6.1/491-ubi-auto-create-ubiblock-device-for-rootfs.patch b/lede/target/linux/generic/pending-6.1/491-ubi-auto-create-ubiblock-device-for-rootfs.patch index 17e8d8bedb..a43da2a572 100644 --- a/lede/target/linux/generic/pending-6.1/491-ubi-auto-create-ubiblock-device-for-rootfs.patch +++ b/lede/target/linux/generic/pending-6.1/491-ubi-auto-create-ubiblock-device-for-rootfs.patch @@ -8,8 +8,8 @@ Signed-off-by: Daniel Golle --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c -@@ -653,6 +653,47 @@ static void __init ubiblock_create_from_ - } +@@ -644,10 +644,47 @@ match_volume_desc(struct ubi_volume_info + return true; } +#define UBIFS_NODE_MAGIC 0x06101831 @@ -24,46 +24,54 @@ Signed-off-by: Daniel Golle + return magic == UBIFS_NODE_MAGIC; +} + -+static void __init ubiblock_create_auto_rootfs(void) ++static void __init ubiblock_create_auto_rootfs(struct ubi_volume_info *vi) +{ -+ int ubi_num, ret, is_ubifs; ++ int ret, is_ubifs; + struct ubi_volume_desc *desc; -+ struct ubi_volume_info vi; + -+ for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) { -+ desc = ubi_open_volume_nm(ubi_num, "rootfs", UBI_READONLY); -+ if (IS_ERR(desc)) -+ desc = ubi_open_volume_nm(ubi_num, "fit", UBI_READONLY);; ++ if (strcmp(vi->name, "rootfs") && ++ strcmp(vi->name, "fit")) ++ return; + -+ if (IS_ERR(desc)) -+ continue; ++ desc = ubi_open_volume(vi->ubi_num, vi->vol_id, UBI_READONLY); ++ if (IS_ERR(desc)) ++ return; + -+ ubi_get_volume_info(desc, &vi); -+ is_ubifs = ubi_vol_is_ubifs(desc); -+ ubi_close_volume(desc); -+ if (is_ubifs) -+ break; ++ is_ubifs = ubi_vol_is_ubifs(desc); ++ ubi_close_volume(desc); ++ if (is_ubifs) ++ return; + -+ ret = ubiblock_create(&vi); -+ if (ret) -+ pr_err("UBI error: block: can't add '%s' volume, err=%d\n", -+ vi.name, ret); -+ /* always break if we get here */ -+ break; -+ } ++ ret = ubiblock_create(vi); ++ if (ret) ++ pr_err("UBI error: block: can't add '%s' volume, err=%d\n", ++ vi->name, ret); +} + - static void ubiblock_remove_all(void) + static void + ubiblock_create_from_param(struct ubi_volume_info *vi) { - struct ubiblock *next; -@@ -685,6 +726,10 @@ int __init ubiblock_init(void) - */ - ubiblock_create_from_param(); + int i, ret = 0; ++ bool got_param = false; + struct ubiblock_param *p; -+ /* auto-attach "rootfs" volume if existing and non-ubifs */ -+ if (IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV)) -+ ubiblock_create_auto_rootfs(); -+ /* - * Block devices are only created upon user requests, so we ignore - * existing volumes. +@@ -660,6 +697,7 @@ ubiblock_create_from_param(struct ubi_vo + if (!match_volume_desc(vi, p->name, p->ubi_num, p->vol_id)) + continue; + ++ got_param = true; + ret = ubiblock_create(vi); + if (ret) { + pr_err( +@@ -668,6 +706,10 @@ ubiblock_create_from_param(struct ubi_vo + } + break; + } ++ ++ /* auto-attach "rootfs" volume if existing and non-ubifs */ ++ if (!got_param && IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV)) ++ ubiblock_create_auto_rootfs(vi); + } + + static int ubiblock_notify(struct notifier_block *nb, diff --git a/lede/target/linux/generic/pending-6.1/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch b/lede/target/linux/generic/pending-6.1/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch index e3493ef19e..5357c7e15d 100644 --- a/lede/target/linux/generic/pending-6.1/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch +++ b/lede/target/linux/generic/pending-6.1/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch @@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c -@@ -42,6 +42,7 @@ +@@ -43,6 +43,7 @@ #include #include #include @@ -16,7 +16,7 @@ Signed-off-by: Daniel Golle #include "ubi-media.h" #include "ubi.h" -@@ -459,6 +460,15 @@ int ubiblock_create(struct ubi_volume_in +@@ -460,6 +461,15 @@ int ubiblock_create(struct ubi_volume_in dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)", dev->ubi_num, dev->vol_id, vi->name); mutex_unlock(&devices_mutex); diff --git a/lede/target/linux/generic/pending-6.1/494-mtd-ubi-add-EOF-marker-support.patch b/lede/target/linux/generic/pending-6.1/494-mtd-ubi-add-EOF-marker-support.patch index 413431755f..fc48146221 100644 --- a/lede/target/linux/generic/pending-6.1/494-mtd-ubi-add-EOF-marker-support.patch +++ b/lede/target/linux/generic/pending-6.1/494-mtd-ubi-add-EOF-marker-support.patch @@ -50,7 +50,7 @@ Signed-off-by: Gabor Juhos break; --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h -@@ -778,6 +778,7 @@ struct ubi_attach_info { +@@ -780,6 +780,7 @@ struct ubi_attach_info { int mean_ec; uint64_t ec_sum; int ec_count; diff --git a/lede/target/linux/generic/pending-6.1/510-block-add-uImage.FIT-subimage-block-driver.patch b/lede/target/linux/generic/pending-6.1/510-block-add-uImage.FIT-subimage-block-driver.patch index 7ee66b318c..f88136541f 100644 --- a/lede/target/linux/generic/pending-6.1/510-block-add-uImage.FIT-subimage-block-driver.patch +++ b/lede/target/linux/generic/pending-6.1/510-block-add-uImage.FIT-subimage-block-driver.patch @@ -36,7 +36,7 @@ Signed-off-by: Daniel Golle --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -21052,6 +21052,12 @@ F: Documentation/filesystems/ubifs-authe +@@ -21059,6 +21059,12 @@ F: Documentation/filesystems/ubifs-authe F: Documentation/filesystems/ubifs.rst F: fs/ubifs/ @@ -81,7 +81,7 @@ Signed-off-by: Daniel Golle swim_mod-y := swim.o swim_asm.o --- /dev/null +++ b/drivers/block/fitblk.c -@@ -0,0 +1,635 @@ +@@ -0,0 +1,636 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * uImage.FIT virtual block device driver. @@ -454,7 +454,8 @@ Signed-off-by: Daniel Golle + bytes_left = size; + fit_c = fit; + while (bytes_left > 0) { -+ bytes_to_copy = min(bytes_left, folio_size(folio) - offset_in_folio(folio, 0)); ++ bytes_to_copy = min_t(size_t, bytes_left, ++ folio_size(folio) - offset_in_folio(folio, 0)); + memcpy(fit_c, pre_fit, bytes_to_copy); + fit_c += bytes_to_copy; + bytes_left -= bytes_to_copy; diff --git a/lede/target/linux/generic/pending-6.1/530-jffs2_make_lzma_available.patch b/lede/target/linux/generic/pending-6.1/530-jffs2_make_lzma_available.patch index f17216c52b..27a673399a 100644 --- a/lede/target/linux/generic/pending-6.1/530-jffs2_make_lzma_available.patch +++ b/lede/target/linux/generic/pending-6.1/530-jffs2_make_lzma_available.patch @@ -351,7 +351,7 @@ Signed-off-by: Alexandros C. Couloumbis + LZMA_FREE(address); +} + -+static ISzAlloc lzma_alloc = {p_lzma_malloc, p_lzma_free}; ++static ISzAlloc lzma_alloc = { .Alloc = p_lzma_malloc, .Free = p_lzma_free }; + +#endif --- /dev/null diff --git a/lede/target/linux/generic/pending-6.1/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch b/lede/target/linux/generic/pending-6.1/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch new file mode 100644 index 0000000000..9f8c3d6ff5 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch @@ -0,0 +1,29 @@ +From: Felix Fietkau +Date: Thu, 31 Aug 2023 21:48:38 +0200 +Subject: [PATCH] netfilter: nf_tables: ignore -EOPNOTSUPP on flowtable device + offload setup + +On many embedded devices, it is common to configure flowtable offloading for +a mix of different devices, some of which have hardware offload support and +some of which don't. +The current code limits the ability of user space to properly set up such a +configuration by only allowing adding devices with hardware offload support to +a offload-enabled flowtable. +Given that offload-enabled flowtables also imply fallback to pure software +offloading, this limitation makes little sense. +Fix it by not bailing out when the offload setup returns -EOPNOTSUPP + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -7959,7 +7959,7 @@ static int nft_register_flowtable_net_ho + err = flowtable->data.type->setup(&flowtable->data, + hook->ops.dev, + FLOW_BLOCK_BIND); +- if (err < 0) ++ if (err < 0 && err != -EOPNOTSUPP) + goto err_unregister_net_hooks; + + err = nf_register_net_hook(net, &hook->ops); diff --git a/lede/target/linux/generic/pending-6.1/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch b/lede/target/linux/generic/pending-6.1/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch index 77a94dae85..90b60def6b 100644 --- a/lede/target/linux/generic/pending-6.1/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch +++ b/lede/target/linux/generic/pending-6.1/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4939,6 +4939,8 @@ static int mtk_probe(struct platform_dev +@@ -4940,6 +4940,8 @@ static int mtk_probe(struct platform_dev * for NAPI to work */ init_dummy_netdev(ð->dummy_dev); diff --git a/lede/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch b/lede/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch index 8d2803158e..d50bc9cd4c 100644 --- a/lede/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/lede/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1753,6 +1753,9 @@ void phy_detach(struct phy_device *phyde +@@ -1852,6 +1852,9 @@ void phy_detach(struct phy_device *phyde struct module *ndev_owner = NULL; struct mii_bus *bus; @@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos sysfs_remove_link(&dev->dev.kobj, "phydev"); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -878,6 +878,12 @@ struct phy_driver { +@@ -903,6 +903,12 @@ struct phy_driver { /** @handle_interrupt: Override default interrupt handling */ irqreturn_t (*handle_interrupt)(struct phy_device *phydev); diff --git a/lede/target/linux/generic/pending-6.1/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch b/lede/target/linux/generic/pending-6.1/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch new file mode 100644 index 0000000000..629b141572 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch @@ -0,0 +1,86 @@ +From 3b4329230db8750bea7a56ef07f07cbbf5fc6c5a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 4 Jul 2023 22:50:12 +0200 +Subject: [PATCH 19/20] net: dsa: qca8k: implement lag_fdb_add/del ops + +Implement lag_fdb_add/del ops to correctly support using LAG interface. +Qca8k switch supports declaring fdb entry for link aggregation by simply +setting the DES_PORT bits to all the LAG member. + +Signed-off-by: Christian Marangi +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 2 ++ + drivers/net/dsa/qca/qca8k-common.c | 48 ++++++++++++++++++++++++++++++ + drivers/net/dsa/qca/qca8k.h | 6 ++++ + 3 files changed, 56 insertions(+) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -2015,6 +2015,8 @@ static const struct dsa_switch_ops qca8k + .port_fdb_add = qca8k_port_fdb_add, + .port_fdb_del = qca8k_port_fdb_del, + .port_fdb_dump = qca8k_port_fdb_dump, ++ .lag_fdb_add = qca8k_lag_fdb_add, ++ .lag_fdb_del = qca8k_lag_fdb_del, + .port_mdb_add = qca8k_port_mdb_add, + .port_mdb_del = qca8k_port_mdb_del, + .port_mirror_add = qca8k_port_mirror_add, +--- a/drivers/net/dsa/qca/qca8k-common.c ++++ b/drivers/net/dsa/qca/qca8k-common.c +@@ -1215,6 +1215,42 @@ int qca8k_port_lag_leave(struct dsa_swit + return qca8k_lag_refresh_portmap(ds, port, lag, true); + } + ++int qca8k_lag_fdb_add(struct dsa_switch *ds, struct dsa_lag lag, ++ const unsigned char *addr, u16 vid, ++ struct dsa_db db) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ struct dsa_port *dp; ++ u16 port_mask = 0; ++ ++ /* Set the vid to the port vlan id if no vid is set */ ++ if (!vid) ++ vid = QCA8K_PORT_VID_DEF; ++ ++ dsa_lag_foreach_port(dp, ds->dst, &lag) ++ port_mask |= BIT(dp->index); ++ ++ return qca8k_port_fdb_insert(priv, addr, port_mask, vid); ++} ++ ++int qca8k_lag_fdb_del(struct dsa_switch *ds, struct dsa_lag lag, ++ const unsigned char *addr, u16 vid, ++ struct dsa_db db) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ struct dsa_port *dp; ++ u16 port_mask = 0; ++ ++ /* Set the vid to the port vlan id if no vid is set */ ++ if (!vid) ++ vid = QCA8K_PORT_VID_DEF; ++ ++ dsa_lag_foreach_port(dp, ds->dst, &lag) ++ port_mask |= BIT(dp->index); ++ ++ return qca8k_fdb_del(priv, addr, port_mask, vid); ++} ++ + int qca8k_read_switch_id(struct qca8k_priv *priv) + { + u32 val; +--- a/drivers/net/dsa/qca/qca8k.h ++++ b/drivers/net/dsa/qca/qca8k.h +@@ -590,5 +590,11 @@ int qca8k_port_lag_join(struct dsa_switc + struct netlink_ext_ack *extack); + int qca8k_port_lag_leave(struct dsa_switch *ds, int port, + struct dsa_lag lag); ++int qca8k_lag_fdb_add(struct dsa_switch *ds, struct dsa_lag lag, ++ const unsigned char *addr, u16 vid, ++ struct dsa_db db); ++int qca8k_lag_fdb_del(struct dsa_switch *ds, struct dsa_lag lag, ++ const unsigned char *addr, u16 vid, ++ struct dsa_db db); + + #endif /* __QCA8K_H */ diff --git a/lede/target/linux/generic/pending-6.1/711-02-net-dsa-qca8k-enable-flooding-to-both-CPU-port.patch b/lede/target/linux/generic/pending-6.1/711-02-net-dsa-qca8k-enable-flooding-to-both-CPU-port.patch new file mode 100644 index 0000000000..24243468a8 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/711-02-net-dsa-qca8k-enable-flooding-to-both-CPU-port.patch @@ -0,0 +1,37 @@ +From b954d61d9ecfa64450fc178586719dc2a95b92a7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 20 Jun 2023 21:48:24 +0200 +Subject: [PATCH 3/4] net: dsa: qca8k: enable flooding to both CPU port + +To permit a multi-CPU setup, flood all unknown frames to all CPU ports. +Each CPU port should have correct LOOKUP MEMBER configuration to +prevent receiving duplicate packets from user ports. + +Signed-off-by: Christian Marangi +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -1904,15 +1904,12 @@ qca8k_setup(struct dsa_switch *ds) + } + } + +- /* Forward all unknown frames to CPU port for Linux processing +- * Notice that in multi-cpu config only one port should be set +- * for igmp, unknown, multicast and broadcast packet +- */ ++ /* Forward all unknown frames to CPU port for Linux processing */ + ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1, +- FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_MASK, BIT(cpu_port)) | +- FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_BC_DP_MASK, BIT(cpu_port)) | +- FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_MC_DP_MASK, BIT(cpu_port)) | +- FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_UC_DP_MASK, BIT(cpu_port))); ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_MASK, dsa_cpu_ports(ds)) | ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_BC_DP_MASK, dsa_cpu_ports(ds)) | ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_MC_DP_MASK, dsa_cpu_ports(ds)) | ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_UC_DP_MASK, dsa_cpu_ports(ds))); + if (ret) + return ret; + diff --git a/lede/target/linux/generic/pending-6.1/711-03-net-dsa-qca8k-add-support-for-port_change_master.patch b/lede/target/linux/generic/pending-6.1/711-03-net-dsa-qca8k-add-support-for-port_change_master.patch new file mode 100644 index 0000000000..8a58e0f76e --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/711-03-net-dsa-qca8k-add-support-for-port_change_master.patch @@ -0,0 +1,158 @@ +From b2d6ebf2f92f8695c83fa6979f4ab579c588df76 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 20 Jun 2023 07:57:38 +0200 +Subject: [PATCH 4/4] net: dsa: qca8k: add support for port_change_master + +Add support for port_change_master to permit assigning an alternative +CPU port if the switch have both CPU port connected or create a LAG on +both CPU port and assign the LAG as DSA master. + +On port change master request, we check if the master is a LAG. +With LAG we compose the cpu_port_mask with the CPU port in the LAG, if +master is a simple dsa_port, we derive the index. + +Finally we apply the new cpu_port_mask to the LOOKUP MEMBER to permit +the port to receive packet by the new CPU port setup for the port and we +refresh the CPU ports LOOKUP MEMBER configuration to reflect the new +user port state. + +port_lag_join/leave is updated to refresh the user ports if we detect +that the LAG is a DSA master and we have user port using it as a master. + +Signed-off-by: Christian Marangi +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 116 ++++++++++++++++++++++++++++++- + 1 file changed, 114 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -1741,6 +1741,117 @@ qca8k_get_tag_protocol(struct dsa_switch + return DSA_TAG_PROTO_QCA; + } + ++static int qca8k_port_change_master(struct dsa_switch *ds, int port, ++ struct net_device *master, ++ struct netlink_ext_ack *extack) ++{ ++ struct dsa_switch_tree *dst = ds->dst; ++ struct qca8k_priv *priv = ds->priv; ++ u8 cpu_port_mask = 0; ++ struct dsa_port *dp; ++ u32 val; ++ int ret; ++ ++ /* With LAG of CPU port, compose the mask for port LOOKUP MEMBER */ ++ if (netif_is_lag_master(master)) { ++ struct dsa_lag *lag; ++ int id; ++ ++ id = dsa_lag_id(dst, master); ++ lag = dsa_lag_by_id(dst, id); ++ ++ dsa_lag_foreach_port(dp, dst, lag) ++ if (dsa_port_is_cpu(dp)) ++ cpu_port_mask |= BIT(dp->index); ++ } else { ++ dp = master->dsa_ptr; ++ cpu_port_mask |= BIT(dp->index); ++ } ++ ++ /* Connect port to new cpu port */ ++ ret = regmap_read(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port), &val); ++ if (ret) ++ return ret; ++ ++ /* Reset connected CPU port in port LOOKUP MEMBER */ ++ val &= ~dsa_cpu_ports(ds); ++ /* Assign the new CPU port in port LOOKUP MEMBER */ ++ val |= cpu_port_mask; ++ ++ ret = regmap_update_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_MEMBER, ++ val); ++ if (ret) ++ return ret; ++ ++ /* Refresh CPU port LOOKUP MEMBER with new port */ ++ dsa_tree_for_each_cpu_port(dp, ds->dst) { ++ u32 reg = QCA8K_PORT_LOOKUP_CTRL(dp->index); ++ ++ /* If CPU port in mask assign port, else remove port */ ++ if (BIT(dp->index) & cpu_port_mask) ++ ret = regmap_set_bits(priv->regmap, reg, BIT(port)); ++ else ++ ret = regmap_clear_bits(priv->regmap, reg, BIT(port)); ++ ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int qca8k_port_lag_refresh_user_ports(struct dsa_switch *ds, ++ struct dsa_lag lag) ++{ ++ struct net_device *lag_dev = lag.dev; ++ struct dsa_port *dp; ++ int ret; ++ ++ /* Ignore if LAG is not a DSA master */ ++ if (!netif_is_lag_master(lag_dev)) ++ return 0; ++ ++ dsa_switch_for_each_user_port(dp, ds) { ++ /* Skip if assigned master is not the LAG */ ++ if (dsa_port_to_master(dp) != lag_dev) ++ continue; ++ ++ ret = qca8k_port_change_master(ds, dp->index, ++ lag_dev, NULL); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int qca8xxx_port_lag_join(struct dsa_switch *ds, int port, ++ struct dsa_lag lag, ++ struct netdev_lag_upper_info *info, ++ struct netlink_ext_ack *extack) ++{ ++ int ret; ++ ++ ret = qca8k_port_lag_join(ds, port, lag, info, extack); ++ if (ret) ++ return ret; ++ ++ return qca8k_port_lag_refresh_user_ports(ds, lag); ++} ++ ++static int qca8xxx_port_lag_leave(struct dsa_switch *ds, int port, ++ struct dsa_lag lag) ++{ ++ int ret; ++ ++ ret = qca8k_port_lag_leave(ds, port, lag); ++ if (ret) ++ return ret; ++ ++ return qca8k_port_lag_refresh_user_ports(ds, lag); ++} ++ + static void + qca8k_master_change(struct dsa_switch *ds, const struct net_device *master, + bool operational) +@@ -2027,8 +2138,9 @@ static const struct dsa_switch_ops qca8k + .phylink_mac_link_down = qca8k_phylink_mac_link_down, + .phylink_mac_link_up = qca8k_phylink_mac_link_up, + .get_phy_flags = qca8k_get_phy_flags, +- .port_lag_join = qca8k_port_lag_join, +- .port_lag_leave = qca8k_port_lag_leave, ++ .port_lag_join = qca8xxx_port_lag_join, ++ .port_lag_leave = qca8xxx_port_lag_leave, ++ .port_change_master = qca8k_port_change_master, + .master_state_change = qca8k_master_change, + .connect_tag_protocol = qca8k_connect_tag_protocol, + }; diff --git a/lede/target/linux/generic/pending-6.1/712-net-dsa-qca8k-enable-assisted-learning-on-CPU-port.patch b/lede/target/linux/generic/pending-6.1/712-net-dsa-qca8k-enable-assisted-learning-on-CPU-port.patch new file mode 100644 index 0000000000..23816fe366 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/712-net-dsa-qca8k-enable-assisted-learning-on-CPU-port.patch @@ -0,0 +1,57 @@ +From 0f6599167c126ce32c85d4f8a1f3d1775a268572 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 6 Oct 2023 12:44:00 +0200 +Subject: [PATCH] net: dsa: qca8k: enable assisted learning on CPU port + +Enable assisted learning on CPU port. + +It has been verified that there is a problem in packet roaming +from one BSS to another in the same security settings from one +physical R7800 to another physical R7800 where they are in the +same L2 broadcast domain backhauled/linked together via one +of the ethernet ports. +DHCP will fail to complete and traffic cannot flow for around 300 +seconds. + +Signed-off-by: Christian Marangi +--- + drivers/net/dsa/qca/qca8k-8xxx.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -2013,6 +2013,12 @@ qca8k_setup(struct dsa_switch *ds) + dev_err(priv->dev, "failed enabling QCA header mode on port %d", dp->index); + return ret; + } ++ ++ /* Disable learning by default on all ports */ ++ ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(dp->index), ++ QCA8K_PORT_LOOKUP_LEARN); ++ if (ret) ++ return ret; + } + + /* Forward all unknown frames to CPU port for Linux processing */ +@@ -2042,11 +2048,6 @@ qca8k_setup(struct dsa_switch *ds) + if (ret) + return ret; + +- ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port), +- QCA8K_PORT_LOOKUP_LEARN); +- if (ret) +- return ret; +- + /* For port based vlans to work we need to set the + * default egress vid + */ +@@ -2098,6 +2099,9 @@ qca8k_setup(struct dsa_switch *ds) + /* Set max number of LAGs supported */ + ds->num_lag_ids = QCA8K_NUM_LAGS; + ++ /* HW learn on CPU port is limited and require manual setting */ ++ ds->assisted_learning_on_cpu_port = true; ++ + return 0; + } + diff --git a/lede/target/linux/generic/pending-6.1/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch b/lede/target/linux/generic/pending-6.1/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch new file mode 100644 index 0000000000..55f116ec5f --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch @@ -0,0 +1,25 @@ +From 3b5a603bf66236b956287909556fd7ad4904450c Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 24 Jan 2024 19:38:01 +0100 +Subject: [PATCH 3/3] arm64: dts: qcom: ipq8074: add clock-frequency to MDIO + node + +Add clock-frequency to MDIO node to set the MDC rate to 6.25Mhz instead +of using the default value of 390KHz from MDIO default divider. + +Signed-off-by: Christian Marangi +--- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -263,6 +263,8 @@ + clocks = <&gcc GCC_MDIO_AHB_CLK>; + clock-names = "gcc_mdio_ahb_clk"; + ++ clock-frequency = <6250000>; ++ + status = "disabled"; + }; + diff --git a/lede/target/linux/generic/pending-6.1/722-net-phy-realtek-support-switching-between-SGMII-and-.patch b/lede/target/linux/generic/pending-6.1/722-net-phy-realtek-support-switching-between-SGMII-and-.patch index f3c850f7b2..abe31e66af 100644 --- a/lede/target/linux/generic/pending-6.1/722-net-phy-realtek-support-switching-between-SGMII-and-.patch +++ b/lede/target/linux/generic/pending-6.1/722-net-phy-realtek-support-switching-between-SGMII-and-.patch @@ -1,3 +1,19 @@ +From 312753d0aadba0f58841ae513b80fdbabc887523 Mon Sep 17 00:00:00 2001 +From: Chukun Pan +Date: Wed, 8 Feb 2023 16:32:18 +0800 +Subject: [PATCH] net: phy: realtek: support switching between SGMII and + 2500BASE-X for RTL822x series + +After commit ace6aba ("net: phy: realtek: rtl8221: allow to configure +SERDES mode"), the rtl8221 phy can work in SGMII and 2500base-x modes +respectively. So add interface automatic switching for rtl8221 phy to +match various wire speeds. + +Signed-off-by: Chukun Pan +--- + drivers/net/phy/realtek.c | 26 ++++++++++++++++++++++++-- + 1 file changed, 24 insertions(+), 2 deletions(-) + --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -686,6 +686,25 @@ static int rtl822x_config_aneg(struct ph diff --git a/lede/target/linux/generic/pending-6.1/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch b/lede/target/linux/generic/pending-6.1/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch deleted file mode 100644 index d8440d7aaf..0000000000 --- a/lede/target/linux/generic/pending-6.1/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 3fb8841513c4ec3a2e5d366df86230c45f239a57 Mon Sep 17 00:00:00 2001 -From: Alexander Couzens -Date: Sat, 13 Aug 2022 13:08:22 +0200 -Subject: [PATCH 03/10] net: mt7531: ensure all MACs are powered down before - reset - -The datasheet [1] explicit describes it as requirement for a reset. - -[1] MT7531 Reference Manual for Development Board rev 1.0, page 735 - -Signed-off-by: Alexander Couzens ---- - drivers/net/dsa/mt7530.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -2470,6 +2470,10 @@ mt7530_setup(struct dsa_switch *ds) - return -ENODEV; - } - -+ /* all MACs must be forced link-down before sw reset */ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) -+ mt7530_write(priv, MT7530_PMCR_P(i), MT7531_FORCE_LNK); -+ - /* Reset the switch through internal reset */ - mt7530_write(priv, MT7530_SYS_CTRL, - SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | diff --git a/lede/target/linux/generic/pending-6.1/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch b/lede/target/linux/generic/pending-6.1/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch index 2bea60803d..babaa47aed 100644 --- a/lede/target/linux/generic/pending-6.1/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch +++ b/lede/target/linux/generic/pending-6.1/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch @@ -9,6 +9,7 @@ access a PHY, in-band-status is unneeded as we have link-status via MDIO. Switch off SGMII in-band autonegotiation using magic values. Reported-by: Chen Minqiang +Reported-by: Chukun Pan Reported-by: Yevhen Kolomeiko Tested-by: Yevhen Kolomeiko Signed-off-by: Daniel Golle diff --git a/lede/target/linux/generic/pending-6.1/729-net-phy-realtek-introduce-rtl822x_probe.patch b/lede/target/linux/generic/pending-6.1/729-net-phy-realtek-introduce-rtl822x_probe.patch index 0167792647..92e7a8742a 100644 --- a/lede/target/linux/generic/pending-6.1/729-net-phy-realtek-introduce-rtl822x_probe.patch +++ b/lede/target/linux/generic/pending-6.1/729-net-phy-realtek-introduce-rtl822x_probe.patch @@ -50,23 +50,7 @@ Signed-off-by: Daniel Golle static int rtlgen_resume(struct phy_device *phydev) { int ret = genphy_resume(phydev); -@@ -1035,6 +1058,7 @@ static struct phy_driver realtek_drvs[] - .match_phy_device = rtl8226_match_phy_device, - .get_features = rtl822x_get_features, - .config_aneg = rtl822x_config_aneg, -+ .probe = rtl822x_probe, - .read_status = rtl822x_read_status, - .suspend = genphy_suspend, - .resume = rtlgen_resume, -@@ -1048,6 +1072,7 @@ static struct phy_driver realtek_drvs[] - .name = "RTL8226B_RTL8221B 2.5Gbps PHY", - .get_features = rtl822x_get_features, - .config_aneg = rtl822x_config_aneg, -+ .probe = rtl822x_probe, - .read_status = rtl822x_read_status, - .suspend = genphy_suspend, - .resume = rtlgen_resume, -@@ -1061,6 +1086,7 @@ static struct phy_driver realtek_drvs[] +@@ -1061,6 +1084,7 @@ static struct phy_driver realtek_drvs[] .name = "RTL8226-CG 2.5Gbps PHY", .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, @@ -74,7 +58,7 @@ Signed-off-by: Daniel Golle .read_status = rtl822x_read_status, .suspend = genphy_suspend, .resume = rtlgen_resume, -@@ -1072,6 +1098,7 @@ static struct phy_driver realtek_drvs[] +@@ -1072,6 +1096,7 @@ static struct phy_driver realtek_drvs[] .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, @@ -82,7 +66,7 @@ Signed-off-by: Daniel Golle .read_status = rtl822x_read_status, .suspend = genphy_suspend, .resume = rtlgen_resume, -@@ -1084,6 +1111,7 @@ static struct phy_driver realtek_drvs[] +@@ -1084,6 +1109,7 @@ static struct phy_driver realtek_drvs[] .get_features = rtl822x_get_features, .config_init = rtl8221b_config_init, .config_aneg = rtl822x_config_aneg, @@ -90,7 +74,7 @@ Signed-off-by: Daniel Golle .read_status = rtl822x_read_status, .suspend = genphy_suspend, .resume = rtlgen_resume, -@@ -1096,6 +1124,7 @@ static struct phy_driver realtek_drvs[] +@@ -1096,6 +1122,7 @@ static struct phy_driver realtek_drvs[] .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .config_init = rtl8221b_config_init, diff --git a/lede/target/linux/generic/pending-6.1/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch b/lede/target/linux/generic/pending-6.1/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch index 8a4ea137ac..05edcc8bf4 100644 --- a/lede/target/linux/generic/pending-6.1/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch +++ b/lede/target/linux/generic/pending-6.1/730-net-phy-realtek-detect-early-version-of-RTL8221B.patch @@ -13,7 +13,15 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -754,6 +754,38 @@ static int rtl8226_match_phy_device(stru +@@ -80,6 +80,7 @@ + + #define RTL_GENERIC_PHYID 0x001cc800 + #define RTL_8211FVD_PHYID 0x001cc878 ++#define RTL_8221B_VB_CG_PHYID 0x001cc849 + + MODULE_DESCRIPTION("Realtek PHY driver"); + MODULE_AUTHOR("Johnson Leung"); +@@ -754,6 +755,38 @@ static int rtl8226_match_phy_device(stru rtlgen_supports_2_5gbps(phydev); } @@ -46,13 +54,13 @@ Signed-off-by: Daniel Golle + id |= val; + } + -+ return (id == 0x001cc849); ++ return (id == RTL_8221B_VB_CG_PHYID); +} + static int rtl822x_probe(struct phy_device *phydev) { struct device *dev = &phydev->mdio.dev; -@@ -1106,7 +1138,7 @@ static struct phy_driver realtek_drvs[] +@@ -1104,7 +1137,7 @@ static struct phy_driver realtek_drvs[] .write_page = rtl821x_write_page, .soft_reset = genphy_soft_reset, }, { diff --git a/lede/target/linux/generic/pending-6.1/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch b/lede/target/linux/generic/pending-6.1/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch index 2c1ec55d09..f3725bf7d3 100644 --- a/lede/target/linux/generic/pending-6.1/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch +++ b/lede/target/linux/generic/pending-6.1/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch @@ -17,7 +17,7 @@ Signed-off-by: Christian Marangi --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -2168,7 +2168,7 @@ struct net_device { +@@ -2190,7 +2190,7 @@ struct net_device { #if IS_ENABLED(CONFIG_AX25) void *ax25_ptr; #endif diff --git a/lede/target/linux/generic/pending-6.1/732-03-net-ethernet-mtk_eth_soc-fix-remaining-throughput-re.patch b/lede/target/linux/generic/pending-6.1/732-03-net-ethernet-mtk_eth_soc-fix-remaining-throughput-re.patch index 1a3f56e94f..aa86075417 100644 --- a/lede/target/linux/generic/pending-6.1/732-03-net-ethernet-mtk_eth_soc-fix-remaining-throughput-re.patch +++ b/lede/target/linux/generic/pending-6.1/732-03-net-ethernet-mtk_eth_soc-fix-remaining-throughput-re.patch @@ -22,7 +22,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -765,6 +765,7 @@ static void mtk_mac_link_up(struct phyli +@@ -766,6 +766,7 @@ static void mtk_mac_link_up(struct phyli MAC_MCR_FORCE_RX_FC); /* Configure speed */ @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau switch (speed) { case SPEED_2500: case SPEED_1000: -@@ -3346,6 +3347,9 @@ found: +@@ -3347,6 +3348,9 @@ found: if (dp->index >= MTK_QDMA_NUM_QUEUES) return NOTIFY_DONE; diff --git a/lede/target/linux/generic/pending-6.1/734-net-ethernet-mtk_eth_soc-ppe-fix-L2-offloading-with-.patch b/lede/target/linux/generic/pending-6.1/734-net-ethernet-mtk_eth_soc-ppe-fix-L2-offloading-with-.patch index 72d5743402..61042c1ad0 100644 --- a/lede/target/linux/generic/pending-6.1/734-net-ethernet-mtk_eth_soc-ppe-fix-L2-offloading-with-.patch +++ b/lede/target/linux/generic/pending-6.1/734-net-ethernet-mtk_eth_soc-ppe-fix-L2-offloading-with-.patch @@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau #include #include "mtk_eth_soc.h" #include "mtk_ppe.h" -@@ -775,7 +776,9 @@ void __mtk_ppe_check_skb(struct mtk_ppe +@@ -829,7 +830,9 @@ void __mtk_ppe_check_skb(struct mtk_ppe skb->dev->dsa_ptr->tag_ops->proto != DSA_TAG_PROTO_MTK) goto out; diff --git a/lede/target/linux/generic/pending-6.1/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch b/lede/target/linux/generic/pending-6.1/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch index 519ece669e..2b379c9158 100644 --- a/lede/target/linux/generic/pending-6.1/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch +++ b/lede/target/linux/generic/pending-6.1/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch @@ -1,8 +1,8 @@ -From 1e25ca1147579bda8b941be1b9851f5911d44eb0 Mon Sep 17 00:00:00 2001 +From d5e337e7aecc2e1cc9e96768062610adb95f8f72 Mon Sep 17 00:00:00 2001 From: Daniel Golle -Date: Tue, 22 Aug 2023 19:04:42 +0100 -Subject: [PATCH 098/125] net: ethernet: mtk_eth_soc: add paths and SerDes - modes for MT7988 +Date: Tue, 12 Dec 2023 03:51:14 +0000 +Subject: [PATCH] net: ethernet: mtk_eth_soc: add paths and SerDes modes for + MT7988 MT7988 comes with a built-in 2.5G PHY as well as SerDes lanes to connect external PHYs or transceivers in USXGMII, 10GBase-R, 5GBase-R, @@ -18,50 +18,11 @@ modes. Signed-off-by: Daniel Golle --- - drivers/net/ethernet/mediatek/Kconfig | 16 + - drivers/net/ethernet/mediatek/Makefile | 1 + - drivers/net/ethernet/mediatek/mtk_eth_path.c | 123 +++- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 182 ++++- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 232 ++++++- - drivers/net/ethernet/mediatek/mtk_usxgmii.c | 692 +++++++++++++++++++ - 6 files changed, 1215 insertions(+), 31 deletions(-) - create mode 100644 drivers/net/ethernet/mediatek/mtk_usxgmii.c + drivers/net/ethernet/mediatek/mtk_eth_path.c | 122 +++++++- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 292 +++++++++++++++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 107 ++++++- + 3 files changed, 470 insertions(+), 51 deletions(-) ---- a/drivers/net/ethernet/mediatek/Kconfig -+++ b/drivers/net/ethernet/mediatek/Kconfig -@@ -25,6 +25,22 @@ config NET_MEDIATEK_SOC - This driver supports the gigabit ethernet MACs in the - MediaTek SoC family. - -+config NET_MEDIATEK_SOC_USXGMII -+ bool "Support USXGMII SerDes on MT7988" -+ depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST -+ def_bool NET_MEDIATEK_SOC != n -+ help -+ Include support for 10GE SerDes which can be found on MT7988. -+ If this kernel should run on SoCs with 10 GBit/s Ethernet you -+ will need to select this option to use GMAC2 and GMAC3 with -+ external PHYs, SFP(+) cages in 10GBase-R, 5GBase-R or USXGMII -+ interface modes. -+ -+ Note that as the 2500Base-X/1000Base-X/Cisco SGMII SerDes PCS -+ unit (MediaTek LynxI) in MT7988 is connected via the new 10GE -+ SerDes, you will also need to select this option in case you -+ want to use any of those SerDes modes. -+ - config NET_MEDIATEK_STAR_EMAC - tristate "MediaTek STAR Ethernet MAC support" - select PHYLIB ---- a/drivers/net/ethernet/mediatek/Makefile -+++ b/drivers/net/ethernet/mediatek/Makefile -@@ -5,6 +5,7 @@ - - obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o - mtk_eth-y := mtk_eth_soc.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o -+mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_USXGMII) += mtk_usxgmii.o - mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o mtk_wed_wo.o - ifdef CONFIG_DEBUG_FS - mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o --- a/drivers/net/ethernet/mediatek/mtk_eth_path.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c @@ -31,10 +31,20 @@ static const char *mtk_eth_path_name(u64 @@ -242,14 +203,31 @@ Signed-off-by: Daniel Golle /* Setup proper MUXes along the path */ return mtk_eth_mux_setup(eth, path); -@@ -284,4 +398,3 @@ int mtk_gmac_rgmii_path_setup(struct mtk - /* Setup proper MUXes along the path */ - return mtk_eth_mux_setup(eth, path); - } -- --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -474,6 +474,30 @@ static void mtk_setup_bridge_switch(stru +@@ -21,6 +21,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -258,12 +260,8 @@ static const char * const mtk_clks_sourc + "ethwarp_wocpu2", + "ethwarp_wocpu1", + "ethwarp_wocpu0", +- "top_usxgmii0_sel", +- "top_usxgmii1_sel", + "top_sgm0_sel", + "top_sgm1_sel", +- "top_xfi_phy0_xtal_sel", +- "top_xfi_phy1_xtal_sel", + "top_eth_gmii_sel", + "top_eth_refck_50m_sel", + "top_eth_sys_200m_sel", +@@ -475,6 +473,30 @@ static void mtk_setup_bridge_switch(stru MTK_GSW_CFG); } @@ -280,34 +258,29 @@ Signed-off-by: Daniel Golle static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, phy_interface_t interface) { -@@ -482,12 +506,20 @@ static struct phylink_pcs *mtk_mac_selec +@@ -483,6 +505,21 @@ static struct phylink_pcs *mtk_mac_selec struct mtk_eth *eth = mac->hw; unsigned int sid; -- if (interface == PHY_INTERFACE_MODE_SGMII || -- phy_interface_mode_is_8023z(interface)) { -- sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? -- 0 : mac->id; -- -- return eth->sgmii_pcs[sid]; -+ if ((interface == PHY_INTERFACE_MODE_SGMII || -+ phy_interface_mode_is_8023z(interface)) && -+ MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { -+ sid = mtk_mac2xgmii_id(eth, mac->id); -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_USXGMII)) -+ return mtk_sgmii_wrapper_select_pcs(eth, mac->id); -+ else -+ return eth->sgmii_pcs[sid]; -+ } else if ((interface == PHY_INTERFACE_MODE_USXGMII || -+ interface == PHY_INTERFACE_MODE_10GBASER || -+ interface == PHY_INTERFACE_MODE_5GBASER) && -+ MTK_HAS_CAPS(eth->soc->caps, MTK_USXGMII) && -+ mac->id != MTK_GMAC1_ID) { -+ return mtk_usxgmii_select_pcs(eth, mac->id); - } - - return NULL; -@@ -543,7 +575,22 @@ static void mtk_mac_config(struct phylin ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ switch (interface) { ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ case PHY_INTERFACE_MODE_SGMII: ++ return mac->sgmii_pcs; ++ case PHY_INTERFACE_MODE_5GBASER: ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_USXGMII: ++ return mac->usxgmii_pcs; ++ default: ++ return NULL; ++ } ++ } ++ + if (interface == PHY_INTERFACE_MODE_SGMII || + phy_interface_mode_is_8023z(interface)) { + sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? +@@ -544,7 +581,22 @@ static void mtk_mac_config(struct phylin goto init_err; } break; @@ -330,7 +303,7 @@ Signed-off-by: Daniel Golle break; default: goto err_phy; -@@ -598,8 +645,6 @@ static void mtk_mac_config(struct phylin +@@ -599,8 +651,6 @@ static void mtk_mac_config(struct phylin val &= ~SYSCFG0_GE_MODE(SYSCFG0_GE_MASK, mac->id); val |= SYSCFG0_GE_MODE(ge_mode, mac->id); regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val); @@ -339,7 +312,7 @@ Signed-off-by: Daniel Golle } /* SGMII */ -@@ -616,21 +661,40 @@ static void mtk_mac_config(struct phylin +@@ -617,21 +667,40 @@ static void mtk_mac_config(struct phylin /* Save the syscfg0 value for mac_finish */ mac->syscfg0 = val; @@ -387,7 +360,37 @@ Signed-off-by: Daniel Golle return; err_phy: -@@ -675,10 +739,13 @@ static void mtk_mac_link_down(struct phy +@@ -644,6 +713,18 @@ init_err: + mac->id, phy_modes(state->interface), err); + } + ++static int mtk_mac_prepare(struct phylink_config *config, unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct mtk_mac *mac = container_of(config, struct mtk_mac, ++ phylink_config); ++ ++ if (mac->pextp && mac->interface != interface) ++ phy_reset(mac->pextp); ++ ++ return 0; ++} ++ + static int mtk_mac_finish(struct phylink_config *config, unsigned int mode, + phy_interface_t interface) + { +@@ -652,6 +733,10 @@ static int mtk_mac_finish(struct phylink + struct mtk_eth *eth = mac->hw; + u32 mcr_cur, mcr_new; + ++ /* Setup PMA/PMD */ ++ if (mac->pextp) ++ phy_set_mode_ext(mac->pextp, PHY_MODE_ETHERNET, interface); ++ + /* Enable SGMII */ + if (interface == PHY_INTERFACE_MODE_SGMII || + phy_interface_mode_is_8023z(interface)) +@@ -676,10 +761,14 @@ static void mtk_mac_link_down(struct phy { struct mtk_mac *mac = container_of(config, struct mtk_mac, phylink_config); @@ -396,15 +399,16 @@ Signed-off-by: Daniel Golle - mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK); - mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + if (!mtk_interface_mode_is_xgmii(interface)) { -+ mtk_m32(mac->hw, MAC_MCR_TX_EN | MAC_MCR_RX_EN, 0, MTK_MAC_MCR(mac->id)); -+ mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), 0, MTK_XGMAC_STS(mac->id)); -+ } else if (mac->id != MTK_GMAC1_ID) { ++ mtk_m32(mac->hw, MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK, 0, MTK_MAC_MCR(mac->id)); ++ if (mtk_is_netsys_v3_or_greater(mac->hw)) ++ mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), 0, MTK_XGMAC_STS(mac->id)); ++ } else if (mtk_is_netsys_v3_or_greater(mac->hw) && mac->id != MTK_GMAC1_ID) { + mtk_m32(mac->hw, XMAC_MCR_TRX_DISABLE, XMAC_MCR_TRX_DISABLE, MTK_XMAC_MCR(mac->id)); + } } static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, -@@ -750,13 +817,11 @@ static void mtk_set_queue_speed(struct m +@@ -751,13 +840,11 @@ static void mtk_set_queue_speed(struct m mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); } @@ -422,7 +426,7 @@ Signed-off-by: Daniel Golle u32 mcr; mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); -@@ -790,6 +855,55 @@ static void mtk_mac_link_up(struct phyli +@@ -791,9 +878,63 @@ static void mtk_mac_link_up(struct phyli mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); } @@ -467,18 +471,104 @@ Signed-off-by: Daniel Golle + struct mtk_mac *mac = container_of(config, struct mtk_mac, + phylink_config); + -+ if (mtk_interface_mode_is_xgmii(interface)) ++ if (mtk_is_netsys_v3_or_greater(mac->hw) && mtk_interface_mode_is_xgmii(interface)) + mtk_xgdm_mac_link_up(mac, phy, mode, interface, speed, duplex, + tx_pause, rx_pause); + else + mtk_gdm_mac_link_up(mac, phy, mode, interface, speed, duplex, + tx_pause, rx_pause); ++ ++ /* Repeat pextp setup to tune link */ ++ if (mac->pextp) ++ phy_set_mode_ext(mac->pextp, PHY_MODE_ETHERNET, interface); +} + static const struct phylink_mac_ops mtk_phylink_ops = { - .validate = phylink_generic_validate, .mac_select_pcs = mtk_mac_select_pcs, -@@ -4614,8 +4728,21 @@ static int mtk_add_mac(struct mtk_eth *e + .mac_config = mtk_mac_config, ++ .mac_prepare = mtk_mac_prepare, + .mac_finish = mtk_mac_finish, + .mac_link_down = mtk_mac_link_down, + .mac_link_up = mtk_mac_link_up, +@@ -3372,6 +3513,9 @@ static int mtk_open(struct net_device *d + struct mtk_eth *eth = mac->hw; + int i, err; + ++ if (mac->pextp) ++ phy_power_on(mac->pextp); ++ + err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); + if (err) { + netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, +@@ -3500,6 +3644,9 @@ static int mtk_stop(struct net_device *d + for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) + mtk_ppe_stop(eth->ppe[i]); + ++ if (mac->pextp) ++ phy_power_off(mac->pextp); ++ + return 0; + } + +@@ -4497,6 +4644,7 @@ static const struct net_device_ops mtk_n + static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) + { + const __be32 *_id = of_get_property(np, "reg", NULL); ++ struct device_node *pcs_np; + phy_interface_t phy_mode; + struct phylink *phylink; + struct mtk_mac *mac; +@@ -4532,16 +4680,41 @@ static int mtk_add_mac(struct mtk_eth *e + mac->id = id; + mac->hw = eth; + mac->of_node = np; ++ pcs_np = of_parse_phandle(mac->of_node, "pcs-handle", 0); ++ if (pcs_np) { ++ mac->sgmii_pcs = mtk_pcs_lynxi_get(eth->dev, pcs_np); ++ if (IS_ERR(mac->sgmii_pcs)) { ++ if (PTR_ERR(mac->sgmii_pcs) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; + +- err = of_get_ethdev_address(mac->of_node, eth->netdev[id]); +- if (err == -EPROBE_DEFER) +- return err; ++ dev_err(eth->dev, "cannot select SGMII PCS, error %ld\n", ++ PTR_ERR(mac->sgmii_pcs)); ++ return PTR_ERR(mac->sgmii_pcs); ++ } ++ } + +- if (err) { +- /* If the mac address is invalid, use random mac address */ +- eth_hw_addr_random(eth->netdev[id]); +- dev_err(eth->dev, "generated random MAC address %pM\n", +- eth->netdev[id]->dev_addr); ++ pcs_np = of_parse_phandle(mac->of_node, "pcs-handle", 1); ++ if (pcs_np) { ++ mac->usxgmii_pcs = mtk_usxgmii_pcs_get(eth->dev, pcs_np); ++ if (IS_ERR(mac->usxgmii_pcs)) { ++ if (PTR_ERR(mac->usxgmii_pcs) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ ++ dev_err(eth->dev, "cannot select USXGMII PCS, error %ld\n", ++ PTR_ERR(mac->usxgmii_pcs)); ++ return PTR_ERR(mac->usxgmii_pcs); ++ } ++ } ++ ++ if (mtk_is_netsys_v3_or_greater(eth) && (mac->sgmii_pcs || mac->usxgmii_pcs)) { ++ mac->pextp = devm_of_phy_get(eth->dev, mac->of_node, NULL); ++ if (IS_ERR(mac->pextp)) { ++ if (PTR_ERR(mac->pextp) != -EPROBE_DEFER) ++ dev_err(eth->dev, "cannot get PHY, error %ld\n", ++ PTR_ERR(mac->pextp)); ++ ++ return PTR_ERR(mac->pextp); ++ } + } + + memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip)); +@@ -4615,8 +4788,21 @@ static int mtk_add_mac(struct mtk_eth *e phy_interface_zero(mac->phylink_config.supported_interfaces); __set_bit(PHY_INTERFACE_MODE_INTERNAL, mac->phylink_config.supported_interfaces); @@ -500,23 +590,91 @@ Signed-off-by: Daniel Golle phylink = phylink_create(&mac->phylink_config, of_fwnode_handle(mac->of_node), phy_mode, &mtk_phylink_ops); -@@ -4808,6 +4935,13 @@ static int mtk_probe(struct platform_dev +@@ -4661,6 +4847,26 @@ free_netdev: + return err; + } - if (err) - return err; ++static int mtk_mac_assign_address(struct mtk_eth *eth, int i, bool test_defer_only) ++{ ++ int err = of_get_ethdev_address(eth->mac[i]->of_node, eth->netdev[i]); ++ ++ if (err == -EPROBE_DEFER) ++ return err; ++ ++ if (test_defer_only) ++ return 0; ++ ++ if (err) { ++ /* If the mac address is invalid, use random mac address */ ++ eth_hw_addr_random(eth->netdev[i]); ++ dev_err(eth->dev, "generated random MAC address %pM\n", ++ eth->netdev[i]); + } + -+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_USXGMII)) { -+ err = mtk_usxgmii_init(eth); ++ return 0; ++} + -+ if (err) -+ return err; + void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev) + { + struct net_device *dev, *tmp; +@@ -4804,7 +5010,8 @@ static int mtk_probe(struct platform_dev + regmap_write(cci, 0, 3); } - if (eth->soc->required_pctl) { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII) && ++ !mtk_is_netsys_v3_or_greater(eth)) { + err = mtk_sgmii_init(eth); + + if (err) +@@ -4915,6 +5122,24 @@ static int mtk_probe(struct platform_dev + } + } + ++ for (i = 0; i < MTK_MAX_DEVS; i++) { ++ if (!eth->netdev[i]) ++ continue; ++ ++ err = mtk_mac_assign_address(eth, i, true); ++ if (err) ++ goto err_deinit_hw; ++ } ++ ++ for (i = 0; i < MTK_MAX_DEVS; i++) { ++ if (!eth->netdev[i]) ++ continue; ++ ++ err = mtk_mac_assign_address(eth, i, false); ++ if (err) ++ goto err_deinit_hw; ++ } ++ + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) { + err = devm_request_irq(eth->dev, eth->irq[0], + mtk_handle_irq, 0, +@@ -5017,6 +5242,11 @@ static int mtk_remove(struct platform_de + mtk_stop(eth->netdev[i]); + mac = netdev_priv(eth->netdev[i]); + phylink_disconnect_phy(mac->phylink); ++ if (mac->sgmii_pcs) ++ mtk_pcs_lynxi_put(mac->sgmii_pcs); ++ ++ if (mac->usxgmii_pcs) ++ mtk_usxgmii_pcs_put(mac->usxgmii_pcs); + } + + mtk_wed_exit(); --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -502,6 +502,21 @@ +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -502,6 +503,21 @@ #define INTF_MODE_RGMII_1000 (TRGMII_MODE | TRGMII_CENTRAL_ALIGNED) #define INTF_MODE_RGMII_10_100 0 @@ -538,7 +696,7 @@ Signed-off-by: Daniel Golle /* GPIO port control registers for GMAC 2*/ #define GPIO_OD33_CTRL8 0x4c0 #define GPIO_BIAS_CTRL 0xed0 -@@ -527,6 +542,7 @@ +@@ -527,6 +543,7 @@ #define SYSCFG0_SGMII_GMAC2 ((3 << 8) & SYSCFG0_SGMII_MASK) #define SYSCFG0_SGMII_GMAC1_V2 BIT(9) #define SYSCFG0_SGMII_GMAC2_V2 BIT(8) @@ -546,72 +704,9 @@ Signed-off-by: Daniel Golle /* ethernet subsystem clock register */ -@@ -559,12 +575,74 @@ - #define ETHSYS_DMA_AG_MAP_QDMA BIT(1) - #define ETHSYS_DMA_AG_MAP_PPE BIT(2) - -+/* USXGMII subsystem config registers */ -+/* Register to control speed */ -+#define RG_PHY_TOP_SPEED_CTRL1 0x80C -+#define USXGMII_RATE_UPDATE_MODE BIT(31) -+#define USXGMII_MAC_CK_GATED BIT(29) -+#define USXGMII_IF_FORCE_EN BIT(28) -+#define USXGMII_RATE_ADAPT_MODE GENMASK(10, 8) -+#define USXGMII_RATE_ADAPT_MODE_X1 0 -+#define USXGMII_RATE_ADAPT_MODE_X2 1 -+#define USXGMII_RATE_ADAPT_MODE_X4 2 -+#define USXGMII_RATE_ADAPT_MODE_X10 3 -+#define USXGMII_RATE_ADAPT_MODE_X100 4 -+#define USXGMII_RATE_ADAPT_MODE_X5 5 -+#define USXGMII_RATE_ADAPT_MODE_X50 6 -+#define USXGMII_XFI_RX_MODE GENMASK(6, 4) -+#define USXGMII_XFI_RX_MODE_10G 0 -+#define USXGMII_XFI_RX_MODE_5G 1 -+#define USXGMII_XFI_TX_MODE GENMASK(2, 0) -+#define USXGMII_XFI_TX_MODE_10G 0 -+#define USXGMII_XFI_TX_MODE_5G 1 -+ -+/* Register to control PCS AN */ -+#define RG_PCS_AN_CTRL0 0x810 -+#define USXGMII_AN_RESTART BIT(31) -+#define USXGMII_AN_SYNC_CNT GENMASK(30, 11) -+#define USXGMII_AN_ENABLE BIT(0) -+ -+#define RG_PCS_AN_CTRL2 0x818 -+#define USXGMII_LINK_TIMER_IDLE_DETECT GENMASK(29, 20) -+#define USXGMII_LINK_TIMER_COMP_ACK_DETECT GENMASK(19, 10) -+#define USXGMII_LINK_TIMER_AN_RESTART GENMASK(9, 0) -+ -+/* Register to read PCS AN status */ -+#define RG_PCS_AN_STS0 0x81c -+#define USXGMII_PCS_AN_WORD GENMASK(15, 0) -+#define USXGMII_LPA_LATCH BIT(31) -+ -+/* Register to control USXGMII XFI PLL digital */ -+#define XFI_PLL_DIG_GLB8 0x08 -+#define RG_XFI_PLL_EN BIT(31) -+ -+/* Register to control USXGMII XFI PLL analog */ -+#define XFI_PLL_ANA_GLB8 0x108 -+#define RG_XFI_PLL_ANA_SWWA 0x02283248 -+ - /* Infrasys subsystem config registers */ - #define INFRA_MISC2 0x70c - #define CO_QPHY_SEL BIT(0) +@@ -565,6 +582,11 @@ #define GEPHY_MAC_SEL BIT(1) -+/* Toprgu subsystem config registers */ -+#define TOPRGU_SWSYSRST 0x18 -+#define SWSYSRST_UNLOCK_KEY GENMASK(31, 24) -+#define SWSYSRST_XFI_PLL_GRST BIT(16) -+#define SWSYSRST_XFI_PEXPT1_GRST BIT(15) -+#define SWSYSRST_XFI_PEXPT0_GRST BIT(14) -+#define SWSYSRST_XFI1_GRST BIT(13) -+#define SWSYSRST_XFI0_GRST BIT(12) -+#define SWSYSRST_SGMII1_GRST BIT(2) -+#define SWSYSRST_SGMII0_GRST BIT(1) -+#define TOPRGU_SWSYSRST_EN 0xFC -+ /* Top misc registers */ +#define TOP_MISC_NETSYS_PCS_MUX 0x84 +#define NETSYS_PCS_MUX_MASK GENMASK(1, 0) @@ -621,7 +716,7 @@ Signed-off-by: Daniel Golle #define USB_PHY_SWITCH_REG 0x218 #define QPHY_SEL_MASK GENMASK(1, 0) #define SGMII_QPHY_SEL 0x2 -@@ -589,6 +667,8 @@ +@@ -589,6 +611,8 @@ #define MT7628_SDM_RBCNT (MT7628_SDM_OFFSET + 0x10c) #define MT7628_SDM_CS_ERR (MT7628_SDM_OFFSET + 0x110) @@ -630,7 +725,7 @@ Signed-off-by: Daniel Golle #define MTK_FE_CDM1_FSM 0x220 #define MTK_FE_CDM2_FSM 0x224 #define MTK_FE_CDM3_FSM 0x238 -@@ -597,6 +677,11 @@ +@@ -597,6 +621,11 @@ #define MTK_FE_CDM6_FSM 0x328 #define MTK_FE_GDM1_FSM 0x228 #define MTK_FE_GDM2_FSM 0x22C @@ -642,7 +737,40 @@ Signed-off-by: Daniel Golle #define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100)) -@@ -943,6 +1028,8 @@ enum mkt_eth_capabilities { +@@ -721,12 +750,8 @@ enum mtk_clks_map { + MTK_CLK_ETHWARP_WOCPU2, + MTK_CLK_ETHWARP_WOCPU1, + MTK_CLK_ETHWARP_WOCPU0, +- MTK_CLK_TOP_USXGMII_SBUS_0_SEL, +- MTK_CLK_TOP_USXGMII_SBUS_1_SEL, + MTK_CLK_TOP_SGM_0_SEL, + MTK_CLK_TOP_SGM_1_SEL, +- MTK_CLK_TOP_XFI_PHY_0_XTAL_SEL, +- MTK_CLK_TOP_XFI_PHY_1_XTAL_SEL, + MTK_CLK_TOP_ETH_GMII_SEL, + MTK_CLK_TOP_ETH_REFCK_50M_SEL, + MTK_CLK_TOP_ETH_SYS_200M_SEL, +@@ -797,19 +822,9 @@ enum mtk_clks_map { + BIT_ULL(MTK_CLK_GP3) | BIT_ULL(MTK_CLK_XGP1) | \ + BIT_ULL(MTK_CLK_XGP2) | BIT_ULL(MTK_CLK_XGP3) | \ + BIT_ULL(MTK_CLK_CRYPTO) | \ +- BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ +- BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ +- BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \ +- BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ + BIT_ULL(MTK_CLK_ETHWARP_WOCPU2) | \ + BIT_ULL(MTK_CLK_ETHWARP_WOCPU1) | \ + BIT_ULL(MTK_CLK_ETHWARP_WOCPU0) | \ +- BIT_ULL(MTK_CLK_TOP_USXGMII_SBUS_0_SEL) | \ +- BIT_ULL(MTK_CLK_TOP_USXGMII_SBUS_1_SEL) | \ +- BIT_ULL(MTK_CLK_TOP_SGM_0_SEL) | \ +- BIT_ULL(MTK_CLK_TOP_SGM_1_SEL) | \ +- BIT_ULL(MTK_CLK_TOP_XFI_PHY_0_XTAL_SEL) | \ +- BIT_ULL(MTK_CLK_TOP_XFI_PHY_1_XTAL_SEL) | \ + BIT_ULL(MTK_CLK_TOP_ETH_GMII_SEL) | \ + BIT_ULL(MTK_CLK_TOP_ETH_REFCK_50M_SEL) | \ + BIT_ULL(MTK_CLK_TOP_ETH_SYS_200M_SEL) | \ +@@ -943,6 +958,8 @@ enum mkt_eth_capabilities { MTK_RGMII_BIT = 0, MTK_TRGMII_BIT, MTK_SGMII_BIT, @@ -651,7 +779,7 @@ Signed-off-by: Daniel Golle MTK_ESW_BIT, MTK_GEPHY_BIT, MTK_MUX_BIT, -@@ -963,8 +1050,11 @@ enum mkt_eth_capabilities { +@@ -963,8 +980,11 @@ enum mkt_eth_capabilities { MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT, MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT, MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT, @@ -663,7 +791,7 @@ Signed-off-by: Daniel Golle /* PATH BITS */ MTK_ETH_PATH_GMAC1_RGMII_BIT, -@@ -972,14 +1062,21 @@ enum mkt_eth_capabilities { +@@ -972,14 +992,21 @@ enum mkt_eth_capabilities { MTK_ETH_PATH_GMAC1_SGMII_BIT, MTK_ETH_PATH_GMAC2_RGMII_BIT, MTK_ETH_PATH_GMAC2_SGMII_BIT, @@ -685,7 +813,7 @@ Signed-off-by: Daniel Golle #define MTK_ESW BIT_ULL(MTK_ESW_BIT) #define MTK_GEPHY BIT_ULL(MTK_GEPHY_BIT) #define MTK_MUX BIT_ULL(MTK_MUX_BIT) -@@ -1002,10 +1099,16 @@ enum mkt_eth_capabilities { +@@ -1002,10 +1029,16 @@ enum mkt_eth_capabilities { BIT_ULL(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT) #define MTK_ETH_MUX_U3_GMAC2_TO_QPHY \ BIT_ULL(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT) @@ -702,7 +830,7 @@ Signed-off-by: Daniel Golle /* Supported path present on SoCs */ #define MTK_ETH_PATH_GMAC1_RGMII BIT_ULL(MTK_ETH_PATH_GMAC1_RGMII_BIT) -@@ -1013,8 +1116,13 @@ enum mkt_eth_capabilities { +@@ -1013,8 +1046,13 @@ enum mkt_eth_capabilities { #define MTK_ETH_PATH_GMAC1_SGMII BIT_ULL(MTK_ETH_PATH_GMAC1_SGMII_BIT) #define MTK_ETH_PATH_GMAC2_RGMII BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT) #define MTK_ETH_PATH_GMAC2_SGMII BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT) @@ -716,7 +844,7 @@ Signed-off-by: Daniel Golle #define MTK_GMAC1_RGMII (MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII) #define MTK_GMAC1_TRGMII (MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII) -@@ -1022,7 +1130,12 @@ enum mkt_eth_capabilities { +@@ -1022,7 +1060,12 @@ enum mkt_eth_capabilities { #define MTK_GMAC2_RGMII (MTK_ETH_PATH_GMAC2_RGMII | MTK_RGMII) #define MTK_GMAC2_SGMII (MTK_ETH_PATH_GMAC2_SGMII | MTK_SGMII) #define MTK_GMAC2_GEPHY (MTK_ETH_PATH_GMAC2_GEPHY | MTK_GEPHY) @@ -729,7 +857,7 @@ Signed-off-by: Daniel Golle /* MUXes present on SoCs */ /* 0: GDM1 -> GMAC1, 1: GDM1 -> ESW */ -@@ -1041,10 +1154,20 @@ enum mkt_eth_capabilities { +@@ -1041,10 +1084,20 @@ enum mkt_eth_capabilities { (MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_MUX | \ MTK_SHARED_SGMII) @@ -750,7 +878,7 @@ Signed-off-by: Daniel Golle #define MTK_HAS_CAPS(caps, _x) (((caps) & (_x)) == (_x)) #define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \ -@@ -1076,8 +1199,12 @@ enum mkt_eth_capabilities { +@@ -1076,8 +1129,12 @@ enum mkt_eth_capabilities { MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ MTK_RSTCTRL_PPE1 | MTK_SRAM) @@ -765,56 +893,17 @@ Signed-off-by: Daniel Golle struct mtk_tx_dma_desc_info { dma_addr_t addr; -@@ -1187,6 +1314,24 @@ struct mtk_soc_data { - /* currently no SoC has more than 3 macs */ - #define MTK_MAX_DEVS 3 - -+/* struct mtk_usxgmii_pcs - This structure holds each usxgmii regmap and -+ * associated data -+ * @regmap: The register map pointing at the range used to setup -+ * USXGMII modes -+ * @interface: Currently selected interface mode -+ * @id: The element is used to record the index of PCS -+ * @pcs: Phylink PCS structure -+ */ -+struct mtk_usxgmii_pcs { -+ struct mtk_eth *eth; -+ struct regmap *regmap; -+ struct phylink_pcs *wrapped_sgmii_pcs; -+ phy_interface_t interface; -+ u8 id; -+ unsigned int mode; -+ struct phylink_pcs pcs; -+}; -+ - /* struct mtk_eth - This is the main datasructure for holding the state - * of the driver - * @dev: The device pointer -@@ -1207,6 +1352,12 @@ struct mtk_soc_data { - * @infra: The register map pointing at the range used to setup - * SGMII and GePHY path - * @sgmii_pcs: Pointers to mtk-pcs-lynxi phylink_pcs instances -+ * @sgmii_wrapped_pcs: Pointers to NETSYSv3 wrapper PCS instances -+ * @usxgmii_pll: The register map pointing at the range used to control -+ * the USXGMII SerDes PLL -+ * @regmap_pextp: The register map pointing at the range used to setup -+ * PHYA -+ * @usxgmii_pcs: Pointer to array of pointers to struct for USXGMII PCS - * @pctl: The register map pointing at the range used to setup - * GMAC port drive/slew values - * @dma_refcnt: track how many netdevs are using the DMA engine -@@ -1250,6 +1401,10 @@ struct mtk_eth { - struct regmap *ethsys; - struct regmap *infra; - struct phylink_pcs *sgmii_pcs[MTK_MAX_DEVS]; -+ struct regmap *toprgu; -+ struct regmap *usxgmii_pll; -+ struct regmap *regmap_pextp[MTK_MAX_DEVS]; -+ struct mtk_usxgmii_pcs *usxgmii_pcs[MTK_MAX_DEVS]; - struct regmap *pctl; - bool hwlro; - refcount_t dma_refcnt; -@@ -1437,6 +1592,19 @@ static inline u32 mtk_get_ib2_multicast_ +@@ -1314,6 +1371,9 @@ struct mtk_mac { + struct device_node *of_node; + struct phylink *phylink; + struct phylink_config phylink_config; ++ struct phylink_pcs *sgmii_pcs; ++ struct phylink_pcs *usxgmii_pcs; ++ struct phy *pextp; + struct mtk_eth *hw; + struct mtk_hw_stats *hw_stats; + __be32 hwlro_ip[MTK_MAX_LRO_IP_CNT]; +@@ -1437,6 +1497,19 @@ static inline u32 mtk_get_ib2_multicast_ return MTK_FOE_IB2_MULTICAST; } @@ -834,7 +923,7 @@ Signed-off-by: Daniel Golle /* read the hardware status register */ void mtk_stats_update_mac(struct mtk_mac *mac); -@@ -1445,8 +1613,10 @@ u32 mtk_r32(struct mtk_eth *eth, unsigne +@@ -1445,8 +1518,10 @@ u32 mtk_r32(struct mtk_eth *eth, unsigne u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg); int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id); @@ -845,760 +934,3 @@ Signed-off-by: Daniel Golle int mtk_eth_offload_init(struct mtk_eth *eth); int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, -@@ -1456,5 +1626,63 @@ int mtk_flow_offload_cmd(struct mtk_eth - void mtk_flow_offload_cleanup(struct mtk_eth *eth, struct list_head *list); - void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev); - -+static inline int mtk_mac2xgmii_id(struct mtk_eth *eth, int mac_id) -+{ -+ int xgmii_id = mac_id; -+ -+ if (mtk_is_netsys_v3_or_greater(eth)) { -+ switch (mac_id) { -+ case MTK_GMAC1_ID: -+ case MTK_GMAC2_ID: -+ xgmii_id = 1; -+ break; -+ case MTK_GMAC3_ID: -+ xgmii_id = 0; -+ break; -+ default: -+ xgmii_id = -1; -+ } -+ } -+ -+ return MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII) ? 0 : xgmii_id; -+} -+ -+static inline int mtk_xgmii2mac_id(struct mtk_eth *eth, int xgmii_id) -+{ -+ int mac_id = xgmii_id; -+ -+ if (mtk_is_netsys_v3_or_greater(eth)) { -+ switch (xgmii_id) { -+ case 0: -+ mac_id = 2; -+ break; -+ case 1: -+ mac_id = 1; -+ break; -+ default: -+ mac_id = -1; -+ } -+ } -+ -+ return mac_id; -+} -+ -+#ifdef CONFIG_NET_MEDIATEK_SOC_USXGMII -+struct phylink_pcs *mtk_sgmii_wrapper_select_pcs(struct mtk_eth *eth, int id); -+struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_eth *eth, int id); -+int mtk_usxgmii_init(struct mtk_eth *eth); -+#else -+static inline struct phylink_pcs *mtk_sgmii_wrapper_select_pcs(struct mtk_eth *eth, int id) -+{ -+ return NULL; -+} -+ -+static inline struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_eth *eth, int id) -+{ -+ return NULL; -+} -+ -+static inline int mtk_usxgmii_init(struct mtk_eth *eth) { return 0; } -+#endif /* NET_MEDIATEK_SOC_USXGMII */ - - #endif /* MTK_ETH_H */ ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mtk_usxgmii.c -@@ -0,0 +1,690 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2023 MediaTek Inc. -+ * Author: Henry Yen -+ * Daniel Golle -+ */ -+ -+#include -+#include -+#include -+#include "mtk_eth_soc.h" -+ -+static struct mtk_usxgmii_pcs *pcs_to_mtk_usxgmii_pcs(struct phylink_pcs *pcs) -+{ -+ return container_of(pcs, struct mtk_usxgmii_pcs, pcs); -+} -+ -+static int mtk_xfi_pextp_init(struct mtk_eth *eth) -+{ -+ struct device *dev = eth->dev; -+ struct device_node *r = dev->of_node; -+ struct device_node *np; -+ int i; -+ -+ for (i = 0; i < MTK_MAX_DEVS; i++) { -+ np = of_parse_phandle(r, "mediatek,xfi-pextp", i); -+ if (!np) -+ break; -+ -+ eth->regmap_pextp[i] = syscon_node_to_regmap(np); -+ if (IS_ERR(eth->regmap_pextp[i])) -+ return PTR_ERR(eth->regmap_pextp[i]); -+ } -+ -+ return 0; -+} -+ -+static int mtk_xfi_pll_init(struct mtk_eth *eth) -+{ -+ struct device_node *r = eth->dev->of_node; -+ struct device_node *np; -+ -+ np = of_parse_phandle(r, "mediatek,xfi-pll", 0); -+ if (!np) -+ return -1; -+ -+ eth->usxgmii_pll = syscon_node_to_regmap(np); -+ if (IS_ERR(eth->usxgmii_pll)) -+ return PTR_ERR(eth->usxgmii_pll); -+ -+ return 0; -+} -+ -+static int mtk_toprgu_init(struct mtk_eth *eth) -+{ -+ struct device_node *r = eth->dev->of_node; -+ struct device_node *np; -+ -+ np = of_parse_phandle(r, "mediatek,toprgu", 0); -+ if (!np) -+ return -1; -+ -+ eth->toprgu = syscon_node_to_regmap(np); -+ if (IS_ERR(eth->toprgu)) -+ return PTR_ERR(eth->toprgu); -+ -+ return 0; -+} -+ -+static int mtk_xfi_pll_enable(struct mtk_eth *eth) -+{ -+ u32 val = 0; -+ -+ if (!eth->usxgmii_pll) -+ return -EINVAL; -+ -+ /* Add software workaround for USXGMII PLL TCL issue */ -+ regmap_write(eth->usxgmii_pll, XFI_PLL_ANA_GLB8, RG_XFI_PLL_ANA_SWWA); -+ -+ regmap_read(eth->usxgmii_pll, XFI_PLL_DIG_GLB8, &val); -+ val |= RG_XFI_PLL_EN; -+ regmap_write(eth->usxgmii_pll, XFI_PLL_DIG_GLB8, val); -+ -+ return 0; -+} -+ -+static void mtk_usxgmii_setup_phya(struct regmap *pextp, phy_interface_t interface, int id) -+{ -+ bool is_10g = (interface == PHY_INTERFACE_MODE_10GBASER || -+ interface == PHY_INTERFACE_MODE_USXGMII); -+ bool is_2p5g = (interface == PHY_INTERFACE_MODE_2500BASEX); -+ bool is_5g = (interface == PHY_INTERFACE_MODE_5GBASER); -+ -+ /* Setup operation mode */ -+ if (is_10g) -+ regmap_write(pextp, 0x9024, 0x00C9071C); -+ else -+ regmap_write(pextp, 0x9024, 0x00D9071C); -+ -+ if (is_5g) -+ regmap_write(pextp, 0x2020, 0xAAA5A5AA); -+ else -+ regmap_write(pextp, 0x2020, 0xAA8585AA); -+ -+ if (is_2p5g || is_5g || is_10g) { -+ regmap_write(pextp, 0x2030, 0x0C020707); -+ regmap_write(pextp, 0x2034, 0x0E050F0F); -+ regmap_write(pextp, 0x2040, 0x00140032); -+ } else { -+ regmap_write(pextp, 0x2030, 0x0C020207); -+ regmap_write(pextp, 0x2034, 0x0E05050F); -+ regmap_write(pextp, 0x2040, 0x00200032); -+ } -+ -+ if (is_2p5g || is_10g) -+ regmap_write(pextp, 0x50F0, 0x00C014AA); -+ else if (is_5g) -+ regmap_write(pextp, 0x50F0, 0x00C018AA); -+ else -+ regmap_write(pextp, 0x50F0, 0x00C014BA); -+ -+ if (is_5g) { -+ regmap_write(pextp, 0x50E0, 0x3777812B); -+ regmap_write(pextp, 0x506C, 0x005C9CFF); -+ regmap_write(pextp, 0x5070, 0x9DFAFAFA); -+ regmap_write(pextp, 0x5074, 0x273F3F3F); -+ regmap_write(pextp, 0x5078, 0xA8883868); -+ regmap_write(pextp, 0x507C, 0x14661466); -+ } else { -+ regmap_write(pextp, 0x50E0, 0x3777C12B); -+ regmap_write(pextp, 0x506C, 0x005F9CFF); -+ regmap_write(pextp, 0x5070, 0x9D9DFAFA); -+ regmap_write(pextp, 0x5074, 0x27273F3F); -+ regmap_write(pextp, 0x5078, 0xA7883C68); -+ regmap_write(pextp, 0x507C, 0x11661166); -+ } -+ -+ if (is_2p5g || is_10g) { -+ regmap_write(pextp, 0x5080, 0x0E000AAF); -+ regmap_write(pextp, 0x5084, 0x08080D0D); -+ regmap_write(pextp, 0x5088, 0x02030909); -+ } else if (is_5g) { -+ regmap_write(pextp, 0x5080, 0x0E001ABF); -+ regmap_write(pextp, 0x5084, 0x080B0D0D); -+ regmap_write(pextp, 0x5088, 0x02050909); -+ } else { -+ regmap_write(pextp, 0x5080, 0x0E000EAF); -+ regmap_write(pextp, 0x5084, 0x08080E0D); -+ regmap_write(pextp, 0x5088, 0x02030B09); -+ } -+ -+ if (is_5g) { -+ regmap_write(pextp, 0x50E4, 0x0C000000); -+ regmap_write(pextp, 0x50E8, 0x04000000); -+ } else { -+ regmap_write(pextp, 0x50E4, 0x0C0C0000); -+ regmap_write(pextp, 0x50E8, 0x04040000); -+ } -+ -+ if (is_2p5g || mtk_interface_mode_is_xgmii(interface)) -+ regmap_write(pextp, 0x50EC, 0x0F0F0C06); -+ else -+ regmap_write(pextp, 0x50EC, 0x0F0F0606); -+ -+ if (is_5g) { -+ regmap_write(pextp, 0x50A8, 0x50808C8C); -+ regmap_write(pextp, 0x6004, 0x18000000); -+ } else { -+ regmap_write(pextp, 0x50A8, 0x506E8C8C); -+ regmap_write(pextp, 0x6004, 0x18190000); -+ } -+ -+ if (is_10g) -+ regmap_write(pextp, 0x00F8, 0x01423342); -+ else if (is_5g) -+ regmap_write(pextp, 0x00F8, 0x00A132A1); -+ else if (is_2p5g) -+ regmap_write(pextp, 0x00F8, 0x009C329C); -+ else -+ regmap_write(pextp, 0x00F8, 0x00FA32FA); -+ -+ /* Force SGDT_OUT off and select PCS */ -+ if (mtk_interface_mode_is_xgmii(interface)) -+ regmap_write(pextp, 0x00F4, 0x80201F20); -+ else -+ regmap_write(pextp, 0x00F4, 0x80201F21); -+ -+ /* Force GLB_CKDET_OUT */ -+ regmap_write(pextp, 0x0030, 0x00050C00); -+ -+ /* Force AEQ on */ -+ regmap_write(pextp, 0x0070, 0x02002800); -+ ndelay(1020); -+ -+ /* Setup DA default value */ -+ regmap_write(pextp, 0x30B0, 0x00000020); -+ regmap_write(pextp, 0x3028, 0x00008A01); -+ regmap_write(pextp, 0x302C, 0x0000A884); -+ regmap_write(pextp, 0x3024, 0x00083002); -+ if (mtk_interface_mode_is_xgmii(interface)) { -+ regmap_write(pextp, 0x3010, 0x00022220); -+ regmap_write(pextp, 0x5064, 0x0F020A01); -+ regmap_write(pextp, 0x50B4, 0x06100600); -+ if (interface == PHY_INTERFACE_MODE_USXGMII) -+ regmap_write(pextp, 0x3048, 0x40704000); -+ else -+ regmap_write(pextp, 0x3048, 0x47684100); -+ } else { -+ regmap_write(pextp, 0x3010, 0x00011110); -+ regmap_write(pextp, 0x3048, 0x40704000); -+ } -+ -+ if (!mtk_interface_mode_is_xgmii(interface) && !is_2p5g) -+ regmap_write(pextp, 0x3064, 0x0000C000); -+ -+ if (interface == PHY_INTERFACE_MODE_USXGMII) { -+ regmap_write(pextp, 0x3050, 0xA8000000); -+ regmap_write(pextp, 0x3054, 0x000000AA); -+ } else if (mtk_interface_mode_is_xgmii(interface)) { -+ regmap_write(pextp, 0x3050, 0x00000000); -+ regmap_write(pextp, 0x3054, 0x00000000); -+ } else { -+ regmap_write(pextp, 0x3050, 0xA8000000); -+ regmap_write(pextp, 0x3054, 0x000000AA); -+ } -+ -+ if (mtk_interface_mode_is_xgmii(interface)) -+ regmap_write(pextp, 0x306C, 0x00000F00); -+ else if (is_2p5g) -+ regmap_write(pextp, 0x306C, 0x22000F00); -+ else -+ regmap_write(pextp, 0x306C, 0x20200F00); -+ -+ if (interface == PHY_INTERFACE_MODE_10GBASER && id == 0) -+ regmap_write(pextp, 0xA008, 0x0007B400); -+ -+ if (mtk_interface_mode_is_xgmii(interface)) -+ regmap_write(pextp, 0xA060, 0x00040000); -+ else -+ regmap_write(pextp, 0xA060, 0x00050000); -+ -+ if (is_10g) -+ regmap_write(pextp, 0x90D0, 0x00000001); -+ else if (is_5g) -+ regmap_write(pextp, 0x90D0, 0x00000003); -+ else if (is_2p5g) -+ regmap_write(pextp, 0x90D0, 0x00000005); -+ else -+ regmap_write(pextp, 0x90D0, 0x00000007); -+ -+ /* Release reset */ -+ regmap_write(pextp, 0x0070, 0x0200E800); -+ usleep_range(150, 500); -+ -+ /* Switch to P0 */ -+ regmap_write(pextp, 0x0070, 0x0200C111); -+ ndelay(1020); -+ regmap_write(pextp, 0x0070, 0x0200C101); -+ usleep_range(15, 50); -+ -+ if (mtk_interface_mode_is_xgmii(interface)) { -+ /* Switch to Gen3 */ -+ regmap_write(pextp, 0x0070, 0x0202C111); -+ } else { -+ /* Switch to Gen2 */ -+ regmap_write(pextp, 0x0070, 0x0201C111); -+ } -+ ndelay(1020); -+ if (mtk_interface_mode_is_xgmii(interface)) -+ regmap_write(pextp, 0x0070, 0x0202C101); -+ else -+ regmap_write(pextp, 0x0070, 0x0201C101); -+ usleep_range(100, 500); -+ regmap_write(pextp, 0x30B0, 0x00000030); -+ if (mtk_interface_mode_is_xgmii(interface)) -+ regmap_write(pextp, 0x00F4, 0x80201F00); -+ else -+ regmap_write(pextp, 0x00F4, 0x80201F01); -+ -+ regmap_write(pextp, 0x3040, 0x30000000); -+ usleep_range(400, 1000); -+} -+ -+static void mtk_usxgmii_reset(struct mtk_eth *eth, int id) -+{ -+ u32 toggle, val; -+ -+ if (id >= MTK_MAX_DEVS || !eth->toprgu) -+ return; -+ -+ switch (id) { -+ case 0: -+ toggle = SWSYSRST_XFI_PEXPT0_GRST | SWSYSRST_XFI0_GRST | -+ SWSYSRST_SGMII0_GRST; -+ break; -+ case 1: -+ toggle = SWSYSRST_XFI_PEXPT1_GRST | SWSYSRST_XFI1_GRST | -+ SWSYSRST_SGMII1_GRST; -+ break; -+ default: -+ return; -+ } -+ -+ /* Enable software reset */ -+ regmap_set_bits(eth->toprgu, TOPRGU_SWSYSRST_EN, toggle); -+ -+ /* Assert USXGMII reset */ -+ regmap_set_bits(eth->toprgu, TOPRGU_SWSYSRST, -+ FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) | toggle); -+ -+ usleep_range(100, 500); -+ -+ /* De-assert USXGMII reset */ -+ regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val); -+ val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88); -+ val &= ~toggle; -+ regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val); -+ -+ /* Disable software reset */ -+ regmap_clear_bits(eth->toprgu, TOPRGU_SWSYSRST_EN, toggle); -+ -+ mdelay(10); -+} -+ -+/* As the USXGMII PHYA is shared with the 1000Base-X/2500Base-X/Cisco SGMII unit -+ * the psc-mtk-lynxi instance needs to be wrapped, so that calls to .pcs_config -+ * also trigger an initial reset and subsequent configuration of the PHYA. -+ */ -+struct mtk_sgmii_wrapper_pcs { -+ struct mtk_eth *eth; -+ struct phylink_pcs *wrapped_pcs; -+ u8 id; -+ struct phylink_pcs pcs; -+}; -+ -+static int mtk_sgmii_wrapped_pcs_config(struct phylink_pcs *pcs, -+ unsigned int mode, -+ phy_interface_t interface, -+ const unsigned long *advertising, -+ bool permit_pause_to_mac) -+{ -+ struct mtk_sgmii_wrapper_pcs *wp = container_of(pcs, struct mtk_sgmii_wrapper_pcs, pcs); -+ bool full_reconf; -+ int ret; -+ -+ full_reconf = interface != wp->eth->usxgmii_pcs[wp->id]->interface; -+ if (full_reconf) { -+ mtk_xfi_pll_enable(wp->eth); -+ mtk_usxgmii_reset(wp->eth, wp->id); -+ } -+ -+ ret = wp->wrapped_pcs->ops->pcs_config(wp->wrapped_pcs, mode, interface, -+ advertising, permit_pause_to_mac); -+ -+ if (full_reconf) -+ mtk_usxgmii_setup_phya(wp->eth->regmap_pextp[wp->id], interface, wp->id); -+ -+ wp->eth->usxgmii_pcs[wp->id]->interface = interface; -+ -+ return ret; -+} -+ -+static void mtk_sgmii_wrapped_pcs_get_state(struct phylink_pcs *pcs, -+ struct phylink_link_state *state) -+{ -+ struct mtk_sgmii_wrapper_pcs *wp = container_of(pcs, struct mtk_sgmii_wrapper_pcs, pcs); -+ -+ return wp->wrapped_pcs->ops->pcs_get_state(wp->wrapped_pcs, state); -+} -+ -+static void mtk_sgmii_wrapped_pcs_an_restart(struct phylink_pcs *pcs) -+{ -+ struct mtk_sgmii_wrapper_pcs *wp = container_of(pcs, struct mtk_sgmii_wrapper_pcs, pcs); -+ -+ wp->wrapped_pcs->ops->pcs_an_restart(wp->wrapped_pcs); -+} -+ -+static void mtk_sgmii_wrapped_pcs_link_up(struct phylink_pcs *pcs, -+ unsigned int mode, -+ phy_interface_t interface, int speed, -+ int duplex) -+{ -+ struct mtk_sgmii_wrapper_pcs *wp = container_of(pcs, struct mtk_sgmii_wrapper_pcs, pcs); -+ -+ wp->wrapped_pcs->ops->pcs_link_up(wp->wrapped_pcs, mode, interface, speed, duplex); -+} -+ -+static void mtk_sgmii_wrapped_pcs_disable(struct phylink_pcs *pcs) -+{ -+ struct mtk_sgmii_wrapper_pcs *wp = container_of(pcs, struct mtk_sgmii_wrapper_pcs, pcs); -+ -+ wp->wrapped_pcs->ops->pcs_disable(wp->wrapped_pcs); -+ -+ wp->eth->usxgmii_pcs[wp->id]->interface = PHY_INTERFACE_MODE_NA; -+} -+ -+static const struct phylink_pcs_ops mtk_sgmii_wrapped_pcs_ops = { -+ .pcs_get_state = mtk_sgmii_wrapped_pcs_get_state, -+ .pcs_config = mtk_sgmii_wrapped_pcs_config, -+ .pcs_an_restart = mtk_sgmii_wrapped_pcs_an_restart, -+ .pcs_link_up = mtk_sgmii_wrapped_pcs_link_up, -+ .pcs_disable = mtk_sgmii_wrapped_pcs_disable, -+}; -+ -+static int mtk_sgmii_wrapper_init(struct mtk_eth *eth) -+{ -+ struct mtk_sgmii_wrapper_pcs *wp; -+ int i; -+ -+ for (i = 0; i < MTK_MAX_DEVS; i++) { -+ if (!eth->sgmii_pcs[i]) -+ continue; -+ -+ if (!eth->usxgmii_pcs[i]) -+ continue; -+ -+ /* Make sure all PCS ops are supported by wrapped PCS */ -+ if (!eth->sgmii_pcs[i]->ops->pcs_get_state || -+ !eth->sgmii_pcs[i]->ops->pcs_config || -+ !eth->sgmii_pcs[i]->ops->pcs_an_restart || -+ !eth->sgmii_pcs[i]->ops->pcs_link_up || -+ !eth->sgmii_pcs[i]->ops->pcs_disable) -+ return -EOPNOTSUPP; -+ -+ wp = devm_kzalloc(eth->dev, sizeof(*wp), GFP_KERNEL); -+ if (!wp) -+ return -ENOMEM; -+ -+ wp->wrapped_pcs = eth->sgmii_pcs[i]; -+ wp->id = i; -+ wp->pcs.poll = true; -+ wp->pcs.ops = &mtk_sgmii_wrapped_pcs_ops; -+ wp->eth = eth; -+ -+ eth->usxgmii_pcs[i]->wrapped_sgmii_pcs = &wp->pcs; -+ } -+ -+ return 0; -+} -+ -+struct phylink_pcs *mtk_sgmii_wrapper_select_pcs(struct mtk_eth *eth, int mac_id) -+{ -+ u32 xgmii_id = mtk_mac2xgmii_id(eth, mac_id); -+ -+ if (!eth->usxgmii_pcs[xgmii_id]) -+ return NULL; -+ -+ return eth->usxgmii_pcs[xgmii_id]->wrapped_sgmii_pcs; -+} -+ -+static int mtk_usxgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+ phy_interface_t interface, -+ const unsigned long *advertising, -+ bool permit_pause_to_mac) -+{ -+ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); -+ struct mtk_eth *eth = mpcs->eth; -+ struct regmap *pextp = eth->regmap_pextp[mpcs->id]; -+ unsigned int an_ctrl = 0, link_timer = 0, xfi_mode = 0, adapt_mode = 0; -+ bool mode_changed = false; -+ -+ if (!pextp) -+ return -ENODEV; -+ -+ if (interface == PHY_INTERFACE_MODE_USXGMII) { -+ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF) | USXGMII_AN_ENABLE; -+ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) | -+ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) | -+ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B); -+ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_10G) | -+ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_10G); -+ } else if (interface == PHY_INTERFACE_MODE_10GBASER) { -+ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF); -+ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) | -+ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) | -+ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B); -+ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_10G) | -+ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_10G); -+ adapt_mode = USXGMII_RATE_UPDATE_MODE; -+ } else if (interface == PHY_INTERFACE_MODE_5GBASER) { -+ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0xFF); -+ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x3D) | -+ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x3D) | -+ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x3D); -+ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_5G) | -+ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_5G); -+ adapt_mode = USXGMII_RATE_UPDATE_MODE; -+ } else { -+ return -EINVAL; -+ } -+ -+ adapt_mode |= FIELD_PREP(USXGMII_RATE_ADAPT_MODE, USXGMII_RATE_ADAPT_MODE_X1); -+ -+ if (mpcs->interface != interface) { -+ mpcs->interface = interface; -+ mode_changed = true; -+ } -+ -+ mtk_xfi_pll_enable(eth); -+ mtk_usxgmii_reset(eth, mpcs->id); -+ -+ /* Setup USXGMII AN ctrl */ -+ regmap_update_bits(mpcs->regmap, RG_PCS_AN_CTRL0, -+ USXGMII_AN_SYNC_CNT | USXGMII_AN_ENABLE, -+ an_ctrl); -+ -+ regmap_update_bits(mpcs->regmap, RG_PCS_AN_CTRL2, -+ USXGMII_LINK_TIMER_IDLE_DETECT | -+ USXGMII_LINK_TIMER_COMP_ACK_DETECT | -+ USXGMII_LINK_TIMER_AN_RESTART, -+ link_timer); -+ -+ mpcs->mode = mode; -+ -+ /* Gated MAC CK */ -+ regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, -+ USXGMII_MAC_CK_GATED, USXGMII_MAC_CK_GATED); -+ -+ /* Enable interface force mode */ -+ regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, -+ USXGMII_IF_FORCE_EN, USXGMII_IF_FORCE_EN); -+ -+ /* Setup USXGMII adapt mode */ -+ regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, -+ USXGMII_RATE_UPDATE_MODE | USXGMII_RATE_ADAPT_MODE, -+ adapt_mode); -+ -+ /* Setup USXGMII speed */ -+ regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, -+ USXGMII_XFI_RX_MODE | USXGMII_XFI_TX_MODE, -+ xfi_mode); -+ -+ usleep_range(1, 10); -+ -+ /* Un-gated MAC CK */ -+ regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, -+ USXGMII_MAC_CK_GATED, 0); -+ -+ usleep_range(1, 10); -+ -+ /* Disable interface force mode for the AN mode */ -+ if (an_ctrl & USXGMII_AN_ENABLE) -+ regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, -+ USXGMII_IF_FORCE_EN, 0); -+ -+ /* Setup USXGMIISYS with the determined property */ -+ mtk_usxgmii_setup_phya(pextp, interface, mpcs->id); -+ -+ return mode_changed; -+} -+ -+static void mtk_usxgmii_pcs_get_state(struct phylink_pcs *pcs, -+ struct phylink_link_state *state) -+{ -+ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); -+ struct mtk_eth *eth = mpcs->eth; -+ struct mtk_mac *mac = eth->mac[mtk_xgmii2mac_id(eth, mpcs->id)]; -+ u32 val = 0; -+ -+ regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val); -+ if (FIELD_GET(USXGMII_AN_ENABLE, val)) { -+ /* Refresh LPA by inverting LPA_LATCH */ -+ regmap_read(mpcs->regmap, RG_PCS_AN_STS0, &val); -+ regmap_update_bits(mpcs->regmap, RG_PCS_AN_STS0, -+ USXGMII_LPA_LATCH, -+ !(val & USXGMII_LPA_LATCH)); -+ -+ regmap_read(mpcs->regmap, RG_PCS_AN_STS0, &val); -+ -+ phylink_decode_usxgmii_word(state, FIELD_GET(USXGMII_PCS_AN_WORD, -+ val)); -+ -+ state->interface = mpcs->interface; -+ } else { -+ val = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id)); -+ -+ if (mac->id == MTK_GMAC2_ID) -+ val >>= 16; -+ -+ switch (FIELD_GET(MTK_USXGMII_PCS_MODE, val)) { -+ case 0: -+ state->speed = SPEED_10000; -+ break; -+ case 1: -+ state->speed = SPEED_5000; -+ break; -+ case 2: -+ state->speed = SPEED_2500; -+ break; -+ case 3: -+ state->speed = SPEED_1000; -+ break; -+ } -+ -+ state->interface = mpcs->interface; -+ state->link = FIELD_GET(MTK_USXGMII_PCS_LINK, val); -+ state->duplex = DUPLEX_FULL; -+ } -+ -+ /* Continuously repeat re-configuration sequence until link comes up */ -+ if (state->link == 0) -+ mtk_usxgmii_pcs_config(pcs, mpcs->mode, -+ state->interface, NULL, false); -+} -+ -+static void mtk_usxgmii_pcs_restart_an(struct phylink_pcs *pcs) -+{ -+ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); -+ unsigned int val = 0; -+ -+ if (!mpcs->regmap) -+ return; -+ -+ regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val); -+ val |= USXGMII_AN_RESTART; -+ regmap_write(mpcs->regmap, RG_PCS_AN_CTRL0, val); -+} -+ -+static void mtk_usxgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, -+ phy_interface_t interface, -+ int speed, int duplex) -+{ -+ /* Reconfiguring USXGMII to ensure the quality of the RX signal -+ * after the line side link up. -+ */ -+ mtk_usxgmii_pcs_config(pcs, mode, -+ interface, NULL, false); -+} -+ -+static const struct phylink_pcs_ops mtk_usxgmii_pcs_ops = { -+ .pcs_config = mtk_usxgmii_pcs_config, -+ .pcs_get_state = mtk_usxgmii_pcs_get_state, -+ .pcs_an_restart = mtk_usxgmii_pcs_restart_an, -+ .pcs_link_up = mtk_usxgmii_pcs_link_up, -+}; -+ -+int mtk_usxgmii_init(struct mtk_eth *eth) -+{ -+ struct device_node *r = eth->dev->of_node; -+ struct device *dev = eth->dev; -+ struct device_node *np; -+ int i, ret; -+ -+ for (i = 0; i < MTK_MAX_DEVS; i++) { -+ np = of_parse_phandle(r, "mediatek,usxgmiisys", i); -+ if (!np) -+ break; -+ -+ eth->usxgmii_pcs[i] = devm_kzalloc(dev, sizeof(*eth->usxgmii_pcs[i]), GFP_KERNEL); -+ if (!eth->usxgmii_pcs[i]) -+ return -ENOMEM; -+ -+ eth->usxgmii_pcs[i]->id = i; -+ eth->usxgmii_pcs[i]->eth = eth; -+ eth->usxgmii_pcs[i]->regmap = syscon_node_to_regmap(np); -+ if (IS_ERR(eth->usxgmii_pcs[i]->regmap)) -+ return PTR_ERR(eth->usxgmii_pcs[i]->regmap); -+ -+ eth->usxgmii_pcs[i]->pcs.ops = &mtk_usxgmii_pcs_ops; -+ eth->usxgmii_pcs[i]->pcs.poll = true; -+ eth->usxgmii_pcs[i]->interface = PHY_INTERFACE_MODE_NA; -+ eth->usxgmii_pcs[i]->mode = -1; -+ -+ of_node_put(np); -+ } -+ -+ ret = mtk_xfi_pextp_init(eth); -+ if (ret) -+ return ret; -+ -+ ret = mtk_xfi_pll_init(eth); -+ if (ret) -+ return ret; -+ -+ ret = mtk_toprgu_init(eth); -+ if (ret) -+ return ret; -+ -+ return mtk_sgmii_wrapper_init(eth); -+} -+ -+struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_eth *eth, int mac_id) -+{ -+ u32 xgmii_id = mtk_mac2xgmii_id(eth, mac_id); -+ -+ if (!eth->usxgmii_pcs[xgmii_id]->regmap) -+ return NULL; -+ -+ return ð->usxgmii_pcs[xgmii_id]->pcs; -+} diff --git a/lede/target/linux/generic/pending-6.1/738-net-ethernet-mtk_eth_soc-set-coherent-mask-to-get-PP.patch b/lede/target/linux/generic/pending-6.1/738-net-ethernet-mtk_eth_soc-set-coherent-mask-to-get-PP.patch new file mode 100644 index 0000000000..b598d15866 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/738-net-ethernet-mtk_eth_soc-set-coherent-mask-to-get-PP.patch @@ -0,0 +1,46 @@ +From dee3f591103910c8d8b2a6d57879ccd2a4be4b10 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Daniel Golle +Date: Wed, 24 Jan 2024 03:19:49 +0000 +Subject: [PATCH net] net: ethernet: mtk_eth_soc: set coherent mask to get PPE + working +To: Felix Fietkau , + Sean Wang , + Mark Lee , + Lorenzo Bianconi , + David S. Miller , + Eric Dumazet , + Jakub Kicinski , + Paolo Abeni , + Matthias Brugger , + AngeloGioacchino Del Regno , + Daniel Golle , + netdev@vger.kernel.org, + linux-kernel@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, + linux-mediatek@lists.infradead.org + +Set DMA coherent mask to 32-bit which makes PPE offloading engine start +working on BPi-R4 which got 4 GiB of RAM. + +Fixes: 2d75891ebc09 ("net: ethernet: mtk_eth_soc: support 36-bit DMA addressing on MT7988") +Suggested-by: Elad Yifee +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -4963,7 +4963,10 @@ static int mtk_probe(struct platform_dev + } + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) { +- err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36)); ++ err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(36)); ++ if (!err) ++ err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); ++ + if (err) { + dev_err(&pdev->dev, "Wrong DMA config\n"); + return -EINVAL; diff --git a/lede/target/linux/generic/pending-6.1/739-01-dt-bindings-phy-mediatek-xfi-tphy-add-new-bindings.patch b/lede/target/linux/generic/pending-6.1/739-01-dt-bindings-phy-mediatek-xfi-tphy-add-new-bindings.patch new file mode 100644 index 0000000000..1f1c40b1d9 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/739-01-dt-bindings-phy-mediatek-xfi-tphy-add-new-bindings.patch @@ -0,0 +1,136 @@ +From patchwork Thu Feb 1 21:52:20 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 13541842 +Date: Thu, 1 Feb 2024 21:52:20 +0000 +From: Daniel Golle +To: Bc-bocun Chen , + Steven Liu , + John Crispin , + Chunfeng Yun , + Vinod Koul , + Kishon Vijay Abraham I , + Rob Herring , + Krzysztof Kozlowski , + Conor Dooley , + Daniel Golle , + Qingfang Deng , + SkyLake Huang , + Matthias Brugger , + AngeloGioacchino Del Regno , + Philipp Zabel , + linux-arm-kernel@lists.infradead.org, + linux-mediatek@lists.infradead.org, linux-phy@lists.infradead.org, + devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, + netdev@vger.kernel.org +Subject: [PATCH 1/2] dt-bindings: phy: mediatek,xfi-tphy: add new bindings +Message-ID: + <702afb0c1246d95c90b22e57105304028bdd3083.1706823233.git.daniel@makrotopia.org> +MIME-Version: 1.0 +Content-Disposition: inline +List-Id: Linux Phy Mailing list + +Add bindings for the MediaTek XFI T-PHY Ethernet SerDes PHY found in the +MediaTek MT7988 SoC which can operate at various interfaces modes: + +via USXGMII PCS: + * USXGMII + * 10GBase-R + * 5GBase-R + +via LynxI SGMII PCS: + * 2500Base-X + * 1000Base-X + * Cisco SGMII (MAC side) + +Signed-off-by: Daniel Golle +--- + .../bindings/phy/mediatek,xfi-tphy.yaml | 80 +++++++++++++++++++ + 1 file changed, 80 insertions(+) + create mode 100644 Documentation/devicetree/bindings/phy/mediatek,xfi-tphy.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/mediatek,xfi-tphy.yaml +@@ -0,0 +1,80 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/phy/mediatek,xfi-tphy.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: MediaTek XFI T-PHY ++ ++maintainers: ++ - Daniel Golle ++ ++description: ++ The MediaTek XFI SerDes T-PHY provides the physical SerDes lanes ++ used by the (10G/5G) USXGMII PCS and (1G/2.5G) LynxI PCS found in ++ MediaTek's 10G-capabale SoCs. ++ ++properties: ++ $nodename: ++ pattern: "^phy@[0-9a-f]+$" ++ ++ compatible: ++ const: mediatek,mt7988-xfi-tphy ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: XFI PHY clock ++ - description: XFI register clock ++ ++ clock-names: ++ items: ++ - const: xfipll ++ - const: topxtal ++ ++ resets: ++ items: ++ - description: PEXTP reset ++ ++ mediatek,usxgmii-performance-errata: ++ $ref: /schemas/types.yaml#/definitions/flag ++ description: ++ One instance of the T-PHY on MT7988 suffers from a performance ++ problem in 10GBase-R mode which needs a work-around in the driver. ++ The work-around is enabled using this flag. ++ ++ "#phy-cells": ++ const: 0 ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - resets ++ - "#phy-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ soc { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ phy@11f20000 { ++ compatible = "mediatek,mt7988-xfi-tphy"; ++ reg = <0 0x11f20000 0 0x10000>; ++ clocks = <&xfi_pll CLK_XFIPLL_PLL_EN>, ++ <&topckgen CLK_TOP_XFI_PHY_0_XTAL_SEL>; ++ clock-names = "xfipll", "topxtal"; ++ resets = <&watchdog 14>; ++ mediatek,usxgmii-performance-errata; ++ #phy-cells = <0>; ++ }; ++ }; ++ ++... diff --git a/lede/target/linux/generic/pending-6.1/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch b/lede/target/linux/generic/pending-6.1/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch new file mode 100644 index 0000000000..1aa36fcd3d --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch @@ -0,0 +1,498 @@ +From patchwork Thu Feb 1 21:53:06 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 13541843 +Date: Thu, 1 Feb 2024 21:53:06 +0000 +From: Daniel Golle +To: Bc-bocun Chen , + Chunfeng Yun , + Vinod Koul , + Kishon Vijay Abraham I , + Rob Herring , + Krzysztof Kozlowski , + Conor Dooley , + Daniel Golle , + Qingfang Deng , + SkyLake Huang , + Matthias Brugger , + AngeloGioacchino Del Regno , + Philipp Zabel , + linux-arm-kernel@lists.infradead.org, + linux-mediatek@lists.infradead.org, linux-phy@lists.infradead.org, + devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, + netdev@vger.kernel.org +Subject: [PATCH 2/2] phy: add driver for MediaTek XFI T-PHY +Message-ID: + +References: + <702afb0c1246d95c90b22e57105304028bdd3083.1706823233.git.daniel@makrotopia.org> +MIME-Version: 1.0 +Content-Disposition: inline +In-Reply-To: + <702afb0c1246d95c90b22e57105304028bdd3083.1706823233.git.daniel@makrotopia.org> +List-Id: Linux Phy Mailing list + +Add driver for MediaTek's XFI T-PHY, 10 Gigabit/s Ethernet SerDes PHY +which can be found in the MT7988 SoC. + +The PHY can operates only in PHY_MODE_ETHERNET, the submode is one of +PHY_INTERFACE_MODE_* corresponding to the supported modes: + + * USXGMII \ + * 10GBase-R }- USXGMII PCS - XGDM \ + * 5GBase-R / \ + }- Ethernet MAC + * 2500Base-X \ / + * 1000Base-X }- LynxI PCS - GDM / + * Cisco SGMII (MAC side) / + +In order to work-around a performance issue present on the first of +two XFI T-PHYs present in MT7988, special tuning is applied which can be +selected by adding the 'mediatek,usxgmii-performance-errata' property to +the device tree node. + +There is no documentation for most registers used for the +analog/tuning part, however, most of the registers have been partially +reverse-engineered from MediaTek's SDK implementation (an opaque +sequence of 32-bit register writes) and descriptions for all relevant +digital registers and bits such as resets and muxes have been supplied +by MediaTek. + +Signed-off-by: Daniel Golle +--- + MAINTAINERS | 1 + + drivers/phy/mediatek/Kconfig | 12 + + drivers/phy/mediatek/Makefile | 1 + + drivers/phy/mediatek/phy-mtk-xfi-tphy.c | 392 ++++++++++++++++++++++++ + 4 files changed, 406 insertions(+) + create mode 100644 drivers/phy/mediatek/phy-mtk-xfi-tphy.c + +--- a/drivers/phy/mediatek/Kconfig ++++ b/drivers/phy/mediatek/Kconfig +@@ -13,6 +13,18 @@ config PHY_MTK_PCIE + callback for PCIe GEN3 port, it supports software efuse + initialization. + ++config PHY_MTK_XFI_TPHY ++ tristate "MediaTek XFI T-PHY Driver" ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ depends on OF && OF_ADDRESS ++ depends on HAS_IOMEM ++ select GENERIC_PHY ++ help ++ Say 'Y' here to add support for MediaTek XFI T-PHY driver. ++ The driver provides access to the Ethernet SerDes T-PHY supporting ++ 1GE and 2.5GE modes via the LynxI PCS, and 5GE and 10GE modes ++ via the USXGMII PCS found in MediaTek SoCs with 10G Ethernet. ++ + config PHY_MTK_TPHY + tristate "MediaTek T-PHY Driver" + depends on ARCH_MEDIATEK || COMPILE_TEST +--- a/drivers/phy/mediatek/Makefile ++++ b/drivers/phy/mediatek/Makefile +@@ -8,6 +8,7 @@ obj-$(CONFIG_PHY_MTK_PCIE) += phy-mtk-p + obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o + obj-$(CONFIG_PHY_MTK_UFS) += phy-mtk-ufs.o + obj-$(CONFIG_PHY_MTK_XSPHY) += phy-mtk-xsphy.o ++obj-$(CONFIG_PHY_MTK_XFI_TPHY) += phy-mtk-xfi-tphy.o + + phy-mtk-hdmi-drv-y := phy-mtk-hdmi.o + phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt2701.o +--- /dev/null ++++ b/drivers/phy/mediatek/phy-mtk-xfi-tphy.c +@@ -0,0 +1,393 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* MediaTek 10GE SerDes PHY driver ++ * ++ * Copyright (c) 2024 Daniel Golle ++ * Bc-bocun Chen ++ * based on mtk_usxgmii.c found in MediaTek's SDK released under GPL-2.0 ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Henry Yen ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MTK_XFI_TPHY_NUM_CLOCKS 2 ++ ++#define REG_DIG_GLB_70 0x0070 ++#define XTP_PCS_RX_EQ_IN_PROGRESS(x) FIELD_PREP(GENMASK(25, 24), (x)) ++#define XTP_PCS_MODE_MASK GENMASK(17, 16) ++#define XTP_PCS_MODE(x) FIELD_PREP(GENMASK(17, 16), (x)) ++#define XTP_PCS_RST_B BIT(15) ++#define XTP_FRC_PCS_RST_B BIT(14) ++#define XTP_PCS_PWD_SYNC_MASK GENMASK(13, 12) ++#define XTP_PCS_PWD_SYNC(x) FIELD_PREP(XTP_PCS_PWD_SYNC_MASK, (x)) ++#define XTP_PCS_PWD_ASYNC_MASK GENMASK(11, 10) ++#define XTP_PCS_PWD_ASYNC(x) FIELD_PREP(XTP_PCS_PWD_ASYNC_MASK, (x)) ++#define XTP_FRC_PCS_PWD_ASYNC BIT(8) ++#define XTP_PCS_UPDT BIT(4) ++#define XTP_PCS_IN_FR_RG BIT(0) ++ ++#define REG_DIG_GLB_F4 0x00f4 ++#define XFI_DPHY_PCS_SEL BIT(0) ++#define XFI_DPHY_PCS_SEL_SGMII FIELD_PREP(XFI_DPHY_PCS_SEL, 1) ++#define XFI_DPHY_PCS_SEL_USXGMII FIELD_PREP(XFI_DPHY_PCS_SEL, 0) ++#define XFI_DPHY_AD_SGDT_FRC_EN BIT(5) ++ ++#define REG_DIG_LN_TRX_40 0x3040 ++#define XTP_LN_FRC_TX_DATA_EN BIT(29) ++#define XTP_LN_TX_DATA_EN BIT(28) ++ ++#define REG_DIG_LN_TRX_B0 0x30b0 ++#define XTP_LN_FRC_TX_MACCK_EN BIT(5) ++#define XTP_LN_TX_MACCK_EN BIT(4) ++ ++#define REG_ANA_GLB_D0 0x90d0 ++#define XTP_GLB_USXGMII_SEL_MASK GENMASK(3, 1) ++#define XTP_GLB_USXGMII_SEL(x) FIELD_PREP(GENMASK(3, 1), (x)) ++#define XTP_GLB_USXGMII_EN BIT(0) ++ ++struct mtk_xfi_tphy { ++ void __iomem *base; ++ struct device *dev; ++ struct reset_control *reset; ++ struct clk_bulk_data clocks[MTK_XFI_TPHY_NUM_CLOCKS]; ++ bool da_war; ++}; ++ ++static void mtk_xfi_tphy_write(struct mtk_xfi_tphy *xfi_tphy, u16 reg, ++ u32 value) ++{ ++ iowrite32(value, xfi_tphy->base + reg); ++} ++ ++static void mtk_xfi_tphy_rmw(struct mtk_xfi_tphy *xfi_tphy, u16 reg, ++ u32 clr, u32 set) ++{ ++ u32 val; ++ ++ val = ioread32(xfi_tphy->base + reg); ++ val &= ~clr; ++ val |= set; ++ iowrite32(val, xfi_tphy->base + reg); ++} ++ ++static void mtk_xfi_tphy_set(struct mtk_xfi_tphy *xfi_tphy, u16 reg, ++ u32 set) ++{ ++ mtk_xfi_tphy_rmw(xfi_tphy, reg, 0, set); ++} ++ ++static void mtk_xfi_tphy_clear(struct mtk_xfi_tphy *xfi_tphy, u16 reg, ++ u32 clr) ++{ ++ mtk_xfi_tphy_rmw(xfi_tphy, reg, clr, 0); ++} ++ ++static void mtk_xfi_tphy_setup(struct mtk_xfi_tphy *xfi_tphy, ++ phy_interface_t interface) ++{ ++ bool is_2p5g = (interface == PHY_INTERFACE_MODE_2500BASEX); ++ bool is_1g = (interface == PHY_INTERFACE_MODE_1000BASEX || ++ interface == PHY_INTERFACE_MODE_SGMII); ++ bool is_10g = (interface == PHY_INTERFACE_MODE_10GBASER || ++ interface == PHY_INTERFACE_MODE_USXGMII); ++ bool is_5g = (interface == PHY_INTERFACE_MODE_5GBASER); ++ bool is_xgmii = (is_10g || is_5g); ++ ++ dev_dbg(xfi_tphy->dev, "setting up for mode %s\n", phy_modes(interface)); ++ ++ /* Setup PLL setting */ ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x9024, 0x100000, is_10g ? 0x0 : 0x100000); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x2020, 0x202000, is_5g ? 0x202000 : 0x0); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x2030, 0x500, is_1g ? 0x0 : 0x500); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x2034, 0xa00, is_1g ? 0x0 : 0xa00); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x2040, 0x340000, is_1g ? 0x200000 : ++ 0x140000); ++ ++ /* Setup RXFE BW setting */ ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x50f0, 0xc10, is_1g ? 0x410 : ++ is_5g ? 0x800 : 0x400); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x50e0, 0x4000, is_5g ? 0x0 : 0x4000); ++ ++ /* Setup RX CDR setting */ ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x506c, 0x30000, is_5g ? 0x0 : 0x30000); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x5070, 0x670000, is_5g ? 0x620000 : 0x50000); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x5074, 0x180000, is_5g ? 0x180000 : 0x0); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x5078, 0xf000400, is_5g ? 0x8000000 : ++ 0x7000400); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x507c, 0x5000500, is_5g ? 0x4000400 : ++ 0x1000100); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x5080, 0x1410, is_1g ? 0x400 : ++ is_5g ? 0x1010 : 0x0); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x5084, 0x30300, is_1g ? 0x30300 : ++ is_5g ? 0x30100 : ++ 0x100); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x5088, 0x60200, is_1g ? 0x20200 : ++ is_5g ? 0x40000 : ++ 0x20000); ++ ++ /* Setting RXFE adaptation range setting */ ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x50e4, 0xc0000, is_5g ? 0x0 : 0xc0000); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x50e8, 0x40000, is_5g ? 0x0 : 0x40000); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x50ec, 0xa00, is_1g ? 0x200 : 0x800); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x50a8, 0xee0000, is_5g ? 0x800000 : ++ 0x6e0000); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x6004, 0x190000, is_5g ? 0x0 : 0x190000); ++ if (is_10g) ++ mtk_xfi_tphy_write(xfi_tphy, 0x00f8, 0x01423342); ++ else if (is_5g) ++ mtk_xfi_tphy_write(xfi_tphy, 0x00f8, 0x00a132a1); ++ else if (is_2p5g) ++ mtk_xfi_tphy_write(xfi_tphy, 0x00f8, 0x009c329c); ++ else ++ mtk_xfi_tphy_write(xfi_tphy, 0x00f8, 0x00fa32fa); ++ ++ /* Force SGDT_OUT off and select PCS */ ++ mtk_xfi_tphy_rmw(xfi_tphy, REG_DIG_GLB_F4, ++ XFI_DPHY_AD_SGDT_FRC_EN | XFI_DPHY_PCS_SEL, ++ XFI_DPHY_AD_SGDT_FRC_EN | ++ (is_xgmii ? XFI_DPHY_PCS_SEL_USXGMII : ++ XFI_DPHY_PCS_SEL_SGMII)); ++ ++ ++ /* Force GLB_CKDET_OUT */ ++ mtk_xfi_tphy_set(xfi_tphy, 0x0030, 0xc00); ++ ++ /* Force AEQ on */ ++ mtk_xfi_tphy_write(xfi_tphy, REG_DIG_GLB_70, ++ XTP_PCS_RX_EQ_IN_PROGRESS(2) | ++ XTP_PCS_PWD_SYNC(2) | ++ XTP_PCS_PWD_ASYNC(2)); ++ ++ usleep_range(1, 5); ++ writel(XTP_LN_FRC_TX_DATA_EN, xfi_tphy->base + REG_DIG_LN_TRX_40); ++ ++ /* Setup TX DA default value */ ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x30b0, 0x30, 0x20); ++ mtk_xfi_tphy_write(xfi_tphy, 0x3028, 0x00008a01); ++ mtk_xfi_tphy_write(xfi_tphy, 0x302c, 0x0000a884); ++ mtk_xfi_tphy_write(xfi_tphy, 0x3024, 0x00083002); ++ ++ /* Setup RG default value */ ++ if (is_xgmii) { ++ mtk_xfi_tphy_write(xfi_tphy, 0x3010, 0x00022220); ++ mtk_xfi_tphy_write(xfi_tphy, 0x5064, 0x0f020a01); ++ mtk_xfi_tphy_write(xfi_tphy, 0x50b4, 0x06100600); ++ if (interface == PHY_INTERFACE_MODE_USXGMII) ++ mtk_xfi_tphy_write(xfi_tphy, 0x3048, 0x40704000); ++ else ++ mtk_xfi_tphy_write(xfi_tphy, 0x3048, 0x47684100); ++ } else { ++ mtk_xfi_tphy_write(xfi_tphy, 0x3010, 0x00011110); ++ mtk_xfi_tphy_write(xfi_tphy, 0x3048, 0x40704000); ++ } ++ ++ if (is_1g) ++ mtk_xfi_tphy_write(xfi_tphy, 0x3064, 0x0000c000); ++ ++ /* Setup RX EQ initial value */ ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x3050, 0xa8000000, ++ (interface != PHY_INTERFACE_MODE_10GBASER) ? ++ 0xa8000000 : 0x0); ++ mtk_xfi_tphy_rmw(xfi_tphy, 0x3054, 0xaa, ++ (interface != PHY_INTERFACE_MODE_10GBASER) ? ++ 0xaa : 0x0); ++ ++ if (is_xgmii) ++ mtk_xfi_tphy_write(xfi_tphy, 0x306c, 0x00000f00); ++ else if (is_2p5g) ++ mtk_xfi_tphy_write(xfi_tphy, 0x306c, 0x22000f00); ++ else ++ mtk_xfi_tphy_write(xfi_tphy, 0x306c, 0x20200f00); ++ ++ if (interface == PHY_INTERFACE_MODE_10GBASER && xfi_tphy->da_war) ++ mtk_xfi_tphy_rmw(xfi_tphy, 0xa008, 0x10000, 0x10000); ++ ++ mtk_xfi_tphy_rmw(xfi_tphy, 0xa060, 0x50000, is_xgmii ? 0x40000 : ++ 0x50000); ++ ++ /* Setup PHYA speed */ ++ mtk_xfi_tphy_rmw(xfi_tphy, REG_ANA_GLB_D0, ++ XTP_GLB_USXGMII_SEL_MASK | XTP_GLB_USXGMII_EN, ++ is_10g ? XTP_GLB_USXGMII_SEL(0) : ++ is_5g ? XTP_GLB_USXGMII_SEL(1) : ++ is_2p5g ? XTP_GLB_USXGMII_SEL(2) : ++ XTP_GLB_USXGMII_SEL(3)); ++ mtk_xfi_tphy_set(xfi_tphy, REG_ANA_GLB_D0, XTP_GLB_USXGMII_EN); ++ ++ /* Release reset */ ++ mtk_xfi_tphy_set(xfi_tphy, REG_DIG_GLB_70, ++ XTP_PCS_RST_B | XTP_FRC_PCS_RST_B); ++ usleep_range(150, 500); ++ ++ /* Switch to P0 */ ++ mtk_xfi_tphy_rmw(xfi_tphy, REG_DIG_GLB_70, ++ XTP_PCS_PWD_SYNC_MASK | ++ XTP_PCS_PWD_ASYNC_MASK, ++ XTP_FRC_PCS_PWD_ASYNC | ++ XTP_PCS_UPDT | XTP_PCS_IN_FR_RG); ++ usleep_range(1, 5); ++ ++ mtk_xfi_tphy_clear(xfi_tphy, REG_DIG_GLB_70, XTP_PCS_UPDT); ++ usleep_range(15, 50); ++ ++ if (is_xgmii) { ++ /* Switch to Gen3 */ ++ mtk_xfi_tphy_rmw(xfi_tphy, REG_DIG_GLB_70, ++ XTP_PCS_MODE_MASK | XTP_PCS_UPDT, ++ XTP_PCS_MODE(2) | XTP_PCS_UPDT); ++ } else { ++ /* Switch to Gen2 */ ++ mtk_xfi_tphy_rmw(xfi_tphy, REG_DIG_GLB_70, ++ XTP_PCS_MODE_MASK | XTP_PCS_UPDT, ++ XTP_PCS_MODE(1) | XTP_PCS_UPDT); ++ } ++ usleep_range(1, 5); ++ ++ mtk_xfi_tphy_clear(xfi_tphy, REG_DIG_GLB_70, XTP_PCS_UPDT); ++ ++ usleep_range(100, 500); ++ ++ /* Enable MAC CK */ ++ mtk_xfi_tphy_set(xfi_tphy, REG_DIG_LN_TRX_B0, XTP_LN_TX_MACCK_EN); ++ mtk_xfi_tphy_clear(xfi_tphy, REG_DIG_GLB_F4, XFI_DPHY_AD_SGDT_FRC_EN); ++ ++ /* Enable TX data */ ++ mtk_xfi_tphy_set(xfi_tphy, REG_DIG_LN_TRX_40, ++ XTP_LN_FRC_TX_DATA_EN | XTP_LN_TX_DATA_EN); ++ usleep_range(400, 1000); ++} ++ ++static int mtk_xfi_tphy_set_mode(struct phy *phy, enum phy_mode mode, int ++ submode) ++{ ++ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy); ++ ++ if (mode != PHY_MODE_ETHERNET) ++ return -EINVAL; ++ ++ switch (submode) { ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_5GBASER: ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_USXGMII: ++ mtk_xfi_tphy_setup(xfi_tphy, submode); ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int mtk_xfi_tphy_reset(struct phy *phy) ++{ ++ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy); ++ ++ reset_control_assert(xfi_tphy->reset); ++ usleep_range(100, 500); ++ reset_control_deassert(xfi_tphy->reset); ++ usleep_range(1, 10); ++ ++ return 0; ++} ++ ++static int mtk_xfi_tphy_power_on(struct phy *phy) ++{ ++ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy); ++ ++ return clk_bulk_prepare_enable(MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks); ++} ++ ++static int mtk_xfi_tphy_power_off(struct phy *phy) ++{ ++ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy); ++ ++ clk_bulk_disable_unprepare(MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks); ++ ++ return 0; ++} ++ ++static const struct phy_ops mtk_xfi_tphy_ops = { ++ .power_on = mtk_xfi_tphy_power_on, ++ .power_off = mtk_xfi_tphy_power_off, ++ .set_mode = mtk_xfi_tphy_set_mode, ++ .reset = mtk_xfi_tphy_reset, ++ .owner = THIS_MODULE, ++}; ++ ++static int mtk_xfi_tphy_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct phy_provider *phy_provider; ++ struct mtk_xfi_tphy *xfi_tphy; ++ struct phy *phy; ++ ++ if (!np) ++ return -ENODEV; ++ ++ xfi_tphy = devm_kzalloc(&pdev->dev, sizeof(*xfi_tphy), GFP_KERNEL); ++ if (!xfi_tphy) ++ return -ENOMEM; ++ ++ xfi_tphy->base = devm_of_iomap(&pdev->dev, np, 0, NULL); ++ if (!xfi_tphy->base) ++ return -EIO; ++ ++ xfi_tphy->dev = &pdev->dev; ++ ++ xfi_tphy->clocks[0].id = "topxtal"; ++ xfi_tphy->clocks[0].clk = devm_clk_get(&pdev->dev, xfi_tphy->clocks[0].id); ++ if (IS_ERR(xfi_tphy->clocks[0].clk)) ++ return PTR_ERR(xfi_tphy->clocks[0].clk); ++ ++ xfi_tphy->clocks[1].id = "xfipll"; ++ xfi_tphy->clocks[1].clk = devm_clk_get(&pdev->dev, xfi_tphy->clocks[1].id); ++ if (IS_ERR(xfi_tphy->clocks[1].clk)) ++ return PTR_ERR(xfi_tphy->clocks[1].clk); ++ ++ xfi_tphy->reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); ++ if (IS_ERR(xfi_tphy->reset)) ++ return PTR_ERR(xfi_tphy->reset); ++ ++ xfi_tphy->da_war = of_property_read_bool(np, ++ "mediatek,usxgmii-performance-errata"); ++ ++ phy = devm_phy_create(&pdev->dev, NULL, &mtk_xfi_tphy_ops); ++ if (IS_ERR(phy)) ++ return PTR_ERR(phy); ++ ++ phy_set_drvdata(phy, xfi_tphy); ++ ++ phy_provider = devm_of_phy_provider_register(&pdev->dev, ++ of_phy_simple_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static const struct of_device_id mtk_xfi_tphy_match[] = { ++ { .compatible = "mediatek,mt7988-xfi-tphy", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, mtk_xfi_tphy_match); ++ ++static struct platform_driver mtk_xfi_tphy_driver = { ++ .probe = mtk_xfi_tphy_probe, ++ .driver = { ++ .name = "mtk-xfi-tphy", ++ .of_match_table = mtk_xfi_tphy_match, ++ }, ++}; ++module_platform_driver(mtk_xfi_tphy_driver); ++ ++MODULE_DESCRIPTION("MediaTek XFI T-PHY driver"); ++MODULE_AUTHOR("Daniel Golle "); ++MODULE_AUTHOR("Bc-bocun Chen "); ++MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/generic/pending-6.1/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch b/lede/target/linux/generic/pending-6.1/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch new file mode 100644 index 0000000000..adb95e9587 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch @@ -0,0 +1,371 @@ +From 4b1a2716299c0e96a698044aebf3f80513509ae7 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 12 Dec 2023 03:47:18 +0000 +Subject: [PATCH 3/5] net: pcs: pcs-mtk-lynxi: add platform driver for MT7988 + +Introduce a proper platform MFD driver for the LynxI (H)SGMII PCS which +is going to initially be used for the MT7988 SoC. + +Signed-off-by: Daniel Golle +--- + drivers/net/pcs/pcs-mtk-lynxi.c | 227 ++++++++++++++++++++++++++++-- + include/linux/pcs/pcs-mtk-lynxi.h | 11 ++ + 2 files changed, 227 insertions(+), 11 deletions(-) + +--- a/drivers/net/pcs/pcs-mtk-lynxi.c ++++ b/drivers/net/pcs/pcs-mtk-lynxi.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + // Copyright (c) 2018-2019 MediaTek Inc. +-/* A library for MediaTek SGMII circuit ++/* A library and platform driver for the MediaTek LynxI SGMII circuit + * + * Author: Sean Wang + * Author: Alexander Couzens +@@ -8,11 +8,17 @@ + * + */ + ++#include + #include ++#include ++#include + #include ++#include + #include + #include ++#include + #include ++#include + + /* SGMII subsystem config registers */ + /* BMCR (low 16) BMSR (high 16) */ +@@ -65,6 +71,8 @@ + #define SGMII_PN_SWAP_MASK GENMASK(1, 0) + #define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1)) + ++#define MTK_NETSYS_V3_AMA_RGC3 0x128 ++ + /* struct mtk_pcs_lynxi - This structure holds each sgmii regmap andassociated + * data + * @regmap: The register map pointing at the range used to setup +@@ -74,15 +82,29 @@ + * @interface: Currently configured interface mode + * @pcs: Phylink PCS structure + * @flags: Flags indicating hardware properties ++ * @rstc: Reset controller ++ * @sgmii_sel: SGMII Register Clock ++ * @sgmii_rx: SGMII RX Clock ++ * @sgmii_tx: SGMII TX Clock ++ * @node: List node + */ + struct mtk_pcs_lynxi { + struct regmap *regmap; ++ struct device *dev; + u32 ana_rgc3; + phy_interface_t interface; + struct phylink_pcs pcs; + u32 flags; ++ struct reset_control *rstc; ++ struct clk *sgmii_sel; ++ struct clk *sgmii_rx; ++ struct clk *sgmii_tx; ++ struct list_head node; + }; + ++static LIST_HEAD(mtk_pcs_lynxi_instances); ++static DEFINE_MUTEX(instance_mutex); ++ + static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs) + { + return container_of(pcs, struct mtk_pcs_lynxi, pcs); +@@ -102,6 +124,17 @@ static void mtk_pcs_lynxi_get_state(stru + FIELD_GET(SGMII_LPA, adv)); + } + ++static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs) ++{ ++ if (!mpcs->rstc) ++ return; ++ ++ reset_control_assert(mpcs->rstc); ++ udelay(100); ++ reset_control_deassert(mpcs->rstc); ++ mdelay(1); ++} ++ + static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, +@@ -148,6 +181,7 @@ static int mtk_pcs_lynxi_config(struct p + SGMII_PHYA_PWD); + + /* Reset SGMII PCS state */ ++ mtk_sgmii_reset(mpcs); + regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0, + SGMII_SW_RESET); + +@@ -234,10 +268,29 @@ static void mtk_pcs_lynxi_link_up(struct + } + } + ++static int mtk_pcs_lynxi_enable(struct phylink_pcs *pcs) ++{ ++ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); ++ ++ if (mpcs->sgmii_tx && mpcs->sgmii_rx) { ++ clk_prepare_enable(mpcs->sgmii_rx); ++ clk_prepare_enable(mpcs->sgmii_tx); ++ } ++ ++ return 0; ++} ++ + static void mtk_pcs_lynxi_disable(struct phylink_pcs *pcs) + { + struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); + ++ regmap_set_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD); ++ ++ if (mpcs->sgmii_tx && mpcs->sgmii_rx) { ++ clk_disable_unprepare(mpcs->sgmii_tx); ++ clk_disable_unprepare(mpcs->sgmii_rx); ++ } ++ + mpcs->interface = PHY_INTERFACE_MODE_NA; + } + +@@ -247,11 +300,12 @@ static const struct phylink_pcs_ops mtk_ + .pcs_an_restart = mtk_pcs_lynxi_restart_an, + .pcs_link_up = mtk_pcs_lynxi_link_up, + .pcs_disable = mtk_pcs_lynxi_disable, ++ .pcs_enable = mtk_pcs_lynxi_enable, + }; + +-struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, +- struct regmap *regmap, u32 ana_rgc3, +- u32 flags) ++static struct phylink_pcs *mtk_pcs_lynxi_init(struct device *dev, struct regmap *regmap, ++ u32 ana_rgc3, u32 flags, ++ struct mtk_pcs_lynxi *prealloc) + { + struct mtk_pcs_lynxi *mpcs; + u32 id, ver; +@@ -259,29 +313,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create + + ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id); + if (ret < 0) +- return NULL; ++ return ERR_PTR(ret); + + if (id != SGMII_LYNXI_DEV_ID) { + dev_err(dev, "unknown PCS device id %08x\n", id); +- return NULL; ++ return ERR_PTR(-ENODEV); + } + + ret = regmap_read(regmap, SGMSYS_PCS_SCRATCH, &ver); + if (ret < 0) +- return NULL; ++ return ERR_PTR(ret); + + ver = FIELD_GET(SGMII_DEV_VERSION, ver); + if (ver != 0x1) { + dev_err(dev, "unknown PCS device version %04x\n", ver); +- return NULL; ++ return ERR_PTR(-ENODEV); + } + + dev_dbg(dev, "MediaTek LynxI SGMII PCS (id 0x%08x, ver 0x%04x)\n", id, + ver); + +- mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL); +- if (!mpcs) +- return NULL; ++ if (prealloc) { ++ mpcs = prealloc; ++ } else { ++ mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL); ++ if (!mpcs) ++ return ERR_PTR(-ENOMEM); ++ }; + + mpcs->ana_rgc3 = ana_rgc3; + mpcs->regmap = regmap; +@@ -292,6 +350,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create + mpcs->interface = PHY_INTERFACE_MODE_NA; + + return &mpcs->pcs; ++}; ++ ++struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, ++ struct regmap *regmap, u32 ana_rgc3, ++ u32 flags) ++{ ++ return mtk_pcs_lynxi_init(dev, regmap, ana_rgc3, flags, NULL); + } + EXPORT_SYMBOL(mtk_pcs_lynxi_create); + +@@ -304,4 +369,144 @@ void mtk_pcs_lynxi_destroy(struct phylin + } + EXPORT_SYMBOL(mtk_pcs_lynxi_destroy); + ++static int mtk_pcs_lynxi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct mtk_pcs_lynxi *mpcs; ++ struct phylink_pcs *pcs; ++ struct regmap *regmap; ++ u32 flags = 0; ++ ++ mpcs = devm_kzalloc(dev, sizeof(*mpcs), GFP_KERNEL); ++ if (!mpcs) ++ return -ENOMEM; ++ ++ mpcs->dev = dev; ++ regmap = syscon_node_to_regmap(np->parent); ++ if (IS_ERR(regmap)) ++ return PTR_ERR(regmap); ++ ++ if (of_property_read_bool(np->parent, "mediatek,pnswap")) ++ flags |= MTK_SGMII_FLAG_PN_SWAP; ++ ++ mpcs->rstc = of_reset_control_get_shared(np->parent, NULL); ++ if (IS_ERR(mpcs->rstc)) ++ return PTR_ERR(mpcs->rstc); ++ ++ reset_control_deassert(mpcs->rstc); ++ mpcs->sgmii_sel = devm_clk_get_enabled(dev, "sgmii_sel"); ++ if (IS_ERR(mpcs->sgmii_sel)) ++ return PTR_ERR(mpcs->sgmii_sel); ++ ++ mpcs->sgmii_rx = devm_clk_get(dev, "sgmii_rx"); ++ if (IS_ERR(mpcs->sgmii_rx)) ++ return PTR_ERR(mpcs->sgmii_rx); ++ ++ mpcs->sgmii_tx = devm_clk_get(dev, "sgmii_tx"); ++ if (IS_ERR(mpcs->sgmii_tx)) ++ return PTR_ERR(mpcs->sgmii_tx); ++ ++ pcs = mtk_pcs_lynxi_init(dev, regmap, (uintptr_t)of_device_get_match_data(dev), ++ flags, mpcs); ++ if (IS_ERR(pcs)) ++ return PTR_ERR(pcs); ++ ++ regmap_set_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD); ++ ++ platform_set_drvdata(pdev, mpcs); ++ ++ mutex_lock(&instance_mutex); ++ list_add_tail(&mpcs->node, &mtk_pcs_lynxi_instances); ++ mutex_unlock(&instance_mutex); ++ ++ return 0; ++} ++ ++static int mtk_pcs_lynxi_remove(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct mtk_pcs_lynxi *cur, *tmp; ++ ++ mutex_lock(&instance_mutex); ++ list_for_each_entry_safe(cur, tmp, &mtk_pcs_lynxi_instances, node) ++ if (cur->dev == dev) { ++ list_del(&cur->node); ++ kfree(cur); ++ break; ++ } ++ mutex_unlock(&instance_mutex); ++ ++ return 0; ++} ++ ++static const struct of_device_id mtk_pcs_lynxi_of_match[] = { ++ { .compatible = "mediatek,mt7988-sgmii", .data = (void *)MTK_NETSYS_V3_AMA_RGC3 }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, mtk_pcs_lynxi_of_match); ++ ++struct phylink_pcs *mtk_pcs_lynxi_get(struct device *dev, struct device_node *np) ++{ ++ struct platform_device *pdev; ++ struct mtk_pcs_lynxi *mpcs; ++ ++ if (!np) ++ return NULL; ++ ++ if (!of_device_is_available(np)) ++ return ERR_PTR(-ENODEV); ++ ++ if (!of_match_node(mtk_pcs_lynxi_of_match, np)) ++ return ERR_PTR(-EINVAL); ++ ++ pdev = of_find_device_by_node(np); ++ if (!pdev || !platform_get_drvdata(pdev)) { ++ if (pdev) ++ put_device(&pdev->dev); ++ return ERR_PTR(-EPROBE_DEFER); ++ } ++ ++ mpcs = platform_get_drvdata(pdev); ++ device_link_add(dev, mpcs->dev, DL_FLAG_AUTOREMOVE_CONSUMER); ++ ++ return &mpcs->pcs; ++} ++EXPORT_SYMBOL(mtk_pcs_lynxi_get); ++ ++void mtk_pcs_lynxi_put(struct phylink_pcs *pcs) ++{ ++ struct mtk_pcs_lynxi *cur, *mpcs = NULL; ++ ++ if (!pcs) ++ return; ++ ++ mutex_lock(&instance_mutex); ++ list_for_each_entry(cur, &mtk_pcs_lynxi_instances, node) ++ if (pcs == &cur->pcs) { ++ mpcs = cur; ++ break; ++ } ++ mutex_unlock(&instance_mutex); ++ ++ if (WARN_ON(!mpcs)) ++ return; ++ ++ put_device(mpcs->dev); ++} ++EXPORT_SYMBOL(mtk_pcs_lynxi_put); ++ ++static struct platform_driver mtk_pcs_lynxi_driver = { ++ .driver = { ++ .name = "mtk-pcs-lynxi", ++ .suppress_bind_attrs = true, ++ .of_match_table = mtk_pcs_lynxi_of_match, ++ }, ++ .probe = mtk_pcs_lynxi_probe, ++ .remove = mtk_pcs_lynxi_remove, ++}; ++module_platform_driver(mtk_pcs_lynxi_driver); ++ ++MODULE_AUTHOR("Daniel Golle "); ++MODULE_DESCRIPTION("MediaTek LynxI HSGMII PCS"); + MODULE_LICENSE("GPL"); +--- a/include/linux/pcs/pcs-mtk-lynxi.h ++++ b/include/linux/pcs/pcs-mtk-lynxi.h +@@ -10,4 +10,15 @@ struct phylink_pcs *mtk_pcs_lynxi_create + struct regmap *regmap, + u32 ana_rgc3, u32 flags); + void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs); ++ ++#if IS_ENABLED(CONFIG_PCS_MTK_LYNXI) ++struct phylink_pcs *mtk_pcs_lynxi_get(struct device *dev, struct device_node *np); ++void mtk_pcs_lynxi_put(struct phylink_pcs *pcs); ++#else ++static inline struct phylink_pcs *mtk_pcs_lynxi_get(struct device *dev, struct device_node *np) ++{ ++ return NULL; ++} ++static inline void mtk_pcs_lynxi_put(struct phylink_pcs *pcs) { } ++#endif /* IS_ENABLED(CONFIG_PCS_MTK_LYNXI) */ + #endif diff --git a/lede/target/linux/generic/pending-6.1/739-04-dt-bindings-net-pcs-add-bindings-for-MediaTek-USXGMI.patch b/lede/target/linux/generic/pending-6.1/739-04-dt-bindings-net-pcs-add-bindings-for-MediaTek-USXGMI.patch new file mode 100644 index 0000000000..215bd2ca2e --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/739-04-dt-bindings-net-pcs-add-bindings-for-MediaTek-USXGMI.patch @@ -0,0 +1,81 @@ +From 7d88d79c0f65b27a92754d7547f7af098b3de67b Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 12 Dec 2023 03:47:31 +0000 +Subject: [PATCH 4/5] dt-bindings: net: pcs: add bindings for MediaTek USXGMII + PCS + +MediaTek's USXGMII can be found in the MT7988 SoC. We need to access +it in order to configure and monitor the Ethernet SerDes link in +USXGMII, 10GBase-R and 5GBase-R mode. By including a wrapped +legacy 1000Base-X/2500Base-X/Cisco SGMII LynxI PCS as well, those +interface modes are also available. + +Signed-off-by: Daniel Golle +--- + .../bindings/net/pcs/mediatek,usxgmii.yaml | 60 +++++++++++++++++++ + 1 file changed, 60 insertions(+) + create mode 100644 Documentation/devicetree/bindings/net/pcs/mediatek,usxgmii.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/pcs/mediatek,usxgmii.yaml +@@ -0,0 +1,60 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/net/pcs/mediatek,usxgmii.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: MediaTek USXGMII PCS ++ ++maintainers: ++ - Daniel Golle ++ ++description: ++ The MediaTek USXGMII PCS provides physical link control and status ++ for USXGMII, 10GBase-R and 5GBase-R links on the SerDes interfaces ++ provided by the PEXTP PHY. ++ In order to also support legacy 2500Base-X, 1000Base-X and Cisco ++ SGMII an existing mediatek,*-sgmiisys LynxI PCS is wrapped to ++ provide those interfaces modes on the same SerDes interfaces shared ++ with the USXGMII PCS. ++ ++properties: ++ $nodename: ++ pattern: "^pcs@[0-9a-f]+$" ++ ++ compatible: ++ const: mediatek,mt7988-usxgmiisys ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: USXGMII top-level clock ++ ++ resets: ++ items: ++ - description: XFI reset ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - resets ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #define MT7988_TOPRGU_XFI0_GRST 12 ++ soc { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ usxgmiisys0: pcs@10080000 { ++ compatible = "mediatek,mt7988-usxgmiisys"; ++ reg = <0 0x10080000 0 0x1000>; ++ clocks = <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>; ++ resets = <&watchdog MT7988_TOPRGU_XFI0_GRST>; ++ }; ++ }; diff --git a/lede/target/linux/generic/pending-6.1/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch b/lede/target/linux/generic/pending-6.1/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch new file mode 100644 index 0000000000..fd1bba3089 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch @@ -0,0 +1,547 @@ +From dde0e95fff92e9f5009f3bea75278e0e34a48822 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 12 Dec 2023 03:47:47 +0000 +Subject: [PATCH 5/5] net: pcs: add driver for MediaTek USXGMII PCS + +Add driver for USXGMII PCS found in the MediaTek MT7988 SoC and supporting +USXGMII, 10GBase-R and 5GBase-R interface modes. + +Signed-off-by: Daniel Golle +--- + MAINTAINERS | 2 + + drivers/net/pcs/Kconfig | 11 + + drivers/net/pcs/Makefile | 1 + + drivers/net/pcs/pcs-mtk-usxgmii.c | 456 ++++++++++++++++++++++++++++ + include/linux/pcs/pcs-mtk-usxgmii.h | 27 ++ + 5 files changed, 497 insertions(+) + create mode 100644 drivers/net/pcs/pcs-mtk-usxgmii.c + create mode 100644 include/linux/pcs/pcs-mtk-usxgmii.h + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -12941,7 +12941,9 @@ M: Daniel Golle + L: netdev@vger.kernel.org + S: Maintained + F: drivers/net/pcs/pcs-mtk-lynxi.c ++F: drivers/net/pcs/pcs-mtk-usxgmii.c + F: include/linux/pcs/pcs-mtk-lynxi.h ++F: include/linux/pcs/pcs-mtk-usxgmii.h + + MEDIATEK I2C CONTROLLER DRIVER + M: Qii Wang +--- a/drivers/net/pcs/Kconfig ++++ b/drivers/net/pcs/Kconfig +@@ -18,6 +18,17 @@ config PCS_LYNX + This module provides helpers to phylink for managing the Lynx PCS + which is part of the Layerscape and QorIQ Ethernet SERDES. + ++config PCS_MTK_USXGMII ++ tristate "MediaTek USXGMII PCS" ++ select PCS_MTK_LYNXI ++ select PHY_MTK_PEXTP ++ select PHYLINK ++ help ++ This module provides a driver for MediaTek's USXGMII PCS supporting ++ 10GBase-R, 5GBase-R and USXGMII interface modes. ++ 1000Base-X, 2500Base-X and Cisco SGMII are supported on the same ++ differential pairs via an embedded LynxI PHY. ++ + config PCS_RZN1_MIIC + tristate "Renesas RZ/N1 MII converter" + depends on OF && (ARCH_RZN1 || COMPILE_TEST) +--- a/drivers/net/pcs/Makefile ++++ b/drivers/net/pcs/Makefile +@@ -8,3 +8,4 @@ obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o + obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o + obj-$(CONFIG_PCS_ALTERA_TSE) += pcs-altera-tse.o + obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o ++obj-$(CONFIG_PCS_MTK_USXGMII) += pcs-mtk-usxgmii.o +--- /dev/null ++++ b/drivers/net/pcs/pcs-mtk-usxgmii.c +@@ -0,0 +1,456 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2023 MediaTek Inc. ++ * Author: Henry Yen ++ * Daniel Golle ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* USXGMII subsystem config registers */ ++/* Register to control speed */ ++#define RG_PHY_TOP_SPEED_CTRL1 0x80c ++#define USXGMII_RATE_UPDATE_MODE BIT(31) ++#define USXGMII_MAC_CK_GATED BIT(29) ++#define USXGMII_IF_FORCE_EN BIT(28) ++#define USXGMII_RATE_ADAPT_MODE GENMASK(10, 8) ++#define USXGMII_RATE_ADAPT_MODE_X1 0 ++#define USXGMII_RATE_ADAPT_MODE_X2 1 ++#define USXGMII_RATE_ADAPT_MODE_X4 2 ++#define USXGMII_RATE_ADAPT_MODE_X10 3 ++#define USXGMII_RATE_ADAPT_MODE_X100 4 ++#define USXGMII_RATE_ADAPT_MODE_X5 5 ++#define USXGMII_RATE_ADAPT_MODE_X50 6 ++#define USXGMII_XFI_RX_MODE GENMASK(6, 4) ++#define USXGMII_XFI_TX_MODE GENMASK(2, 0) ++#define USXGMII_XFI_MODE_10G 0 ++#define USXGMII_XFI_MODE_5G 1 ++#define USXGMII_XFI_MODE_2P5G 3 ++ ++/* Register to control PCS AN */ ++#define RG_PCS_AN_CTRL0 0x810 ++#define USXGMII_AN_RESTART BIT(31) ++#define USXGMII_AN_SYNC_CNT GENMASK(30, 11) ++#define USXGMII_AN_ENABLE BIT(0) ++ ++#define RG_PCS_AN_CTRL2 0x818 ++#define USXGMII_LINK_TIMER_IDLE_DETECT GENMASK(29, 20) ++#define USXGMII_LINK_TIMER_COMP_ACK_DETECT GENMASK(19, 10) ++#define USXGMII_LINK_TIMER_AN_RESTART GENMASK(9, 0) ++ ++/* Register to read PCS AN status */ ++#define RG_PCS_AN_STS0 0x81c ++#define USXGMII_LPA GENMASK(15, 0) ++#define USXGMII_LPA_LATCH BIT(31) ++ ++/* Register to read PCS link status */ ++#define RG_PCS_RX_STATUS0 0x904 ++#define RG_PCS_RX_STATUS_UPDATE BIT(16) ++#define RG_PCS_RX_LINK_STATUS BIT(2) ++ ++/* struct mtk_usxgmii_pcs - This structure holds each usxgmii PCS ++ * @pcs: Phylink PCS structure ++ * @dev: Pointer to device structure ++ * @base: IO memory to access PCS hardware ++ * @clk: Pointer to USXGMII clk ++ * @reset: Pointer to USXGMII reset control ++ * @interface: Currently selected interface mode ++ * @neg_mode: Currently used phylink neg_mode ++ * @node: List node ++ */ ++struct mtk_usxgmii_pcs { ++ struct phylink_pcs pcs; ++ struct device *dev; ++ void __iomem *base; ++ struct clk *clk; ++ struct reset_control *reset; ++ phy_interface_t interface; ++ unsigned int neg_mode; ++ struct list_head node; ++}; ++ ++static LIST_HEAD(mtk_usxgmii_pcs_instances); ++static DEFINE_MUTEX(instance_mutex); ++ ++static u32 mtk_r32(struct mtk_usxgmii_pcs *mpcs, unsigned int reg) ++{ ++ return ioread32(mpcs->base + reg); ++} ++ ++static void mtk_m32(struct mtk_usxgmii_pcs *mpcs, unsigned int reg, u32 mask, u32 set) ++{ ++ u32 val; ++ ++ val = ioread32(mpcs->base + reg); ++ val &= ~mask; ++ val |= set; ++ iowrite32(val, mpcs->base + reg); ++} ++ ++static struct mtk_usxgmii_pcs *pcs_to_mtk_usxgmii_pcs(struct phylink_pcs *pcs) ++{ ++ return container_of(pcs, struct mtk_usxgmii_pcs, pcs); ++} ++ ++static void mtk_usxgmii_reset(struct mtk_usxgmii_pcs *mpcs) ++{ ++ reset_control_assert(mpcs->reset); ++ udelay(100); ++ reset_control_deassert(mpcs->reset); ++ ++ mdelay(10); ++} ++ ++static int mtk_usxgmii_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, ++ phy_interface_t interface, ++ const unsigned long *advertising, ++ bool permit_pause_to_mac) ++{ ++ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); ++ unsigned int an_ctrl = 0, link_timer = 0, xfi_mode = 0, adapt_mode = 0; ++ bool mode_changed = false; ++ ++ if (interface == PHY_INTERFACE_MODE_USXGMII) { ++ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF) | USXGMII_AN_ENABLE; ++ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) | ++ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) | ++ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B); ++ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_MODE_10G) | ++ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_MODE_10G); ++ } else if (interface == PHY_INTERFACE_MODE_10GBASER) { ++ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF); ++ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) | ++ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) | ++ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B); ++ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_MODE_10G) | ++ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_MODE_10G); ++ adapt_mode = USXGMII_RATE_UPDATE_MODE; ++ } else if (interface == PHY_INTERFACE_MODE_5GBASER) { ++ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0xFF); ++ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x3D) | ++ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x3D) | ++ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x3D); ++ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_MODE_5G) | ++ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_MODE_5G); ++ adapt_mode = USXGMII_RATE_UPDATE_MODE; ++ } else { ++ return -EINVAL; ++ } ++ ++ adapt_mode |= FIELD_PREP(USXGMII_RATE_ADAPT_MODE, USXGMII_RATE_ADAPT_MODE_X1); ++ ++ if (mpcs->interface != interface) { ++ mpcs->interface = interface; ++ mode_changed = true; ++ } ++ ++ mtk_usxgmii_reset(mpcs); ++ ++ /* Setup USXGMII AN ctrl */ ++ mtk_m32(mpcs, RG_PCS_AN_CTRL0, ++ USXGMII_AN_SYNC_CNT | USXGMII_AN_ENABLE, ++ an_ctrl); ++ ++ mtk_m32(mpcs, RG_PCS_AN_CTRL2, ++ USXGMII_LINK_TIMER_IDLE_DETECT | ++ USXGMII_LINK_TIMER_COMP_ACK_DETECT | ++ USXGMII_LINK_TIMER_AN_RESTART, ++ link_timer); ++ ++ mpcs->neg_mode = neg_mode; ++ ++ /* Gated MAC CK */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, ++ USXGMII_MAC_CK_GATED, USXGMII_MAC_CK_GATED); ++ ++ /* Enable interface force mode */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, ++ USXGMII_IF_FORCE_EN, USXGMII_IF_FORCE_EN); ++ ++ /* Setup USXGMII adapt mode */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, ++ USXGMII_RATE_UPDATE_MODE | USXGMII_RATE_ADAPT_MODE, ++ adapt_mode); ++ ++ /* Setup USXGMII speed */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, ++ USXGMII_XFI_RX_MODE | USXGMII_XFI_TX_MODE, ++ xfi_mode); ++ ++ usleep_range(1, 10); ++ ++ /* Un-gated MAC CK */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, USXGMII_MAC_CK_GATED, 0); ++ ++ usleep_range(1, 10); ++ ++ /* Disable interface force mode for the AN mode */ ++ if (an_ctrl & USXGMII_AN_ENABLE) ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, USXGMII_IF_FORCE_EN, 0); ++ ++ return mode_changed; ++} ++ ++static void mtk_usxgmii_pcs_get_fixed_speed(struct mtk_usxgmii_pcs *mpcs, ++ struct phylink_link_state *state) ++{ ++ u32 val = mtk_r32(mpcs, RG_PHY_TOP_SPEED_CTRL1); ++ int speed; ++ ++ /* Calculate speed from interface speed and rate adapt mode */ ++ switch (FIELD_GET(USXGMII_XFI_RX_MODE, val)) { ++ case USXGMII_XFI_MODE_10G: ++ speed = 10000; ++ break; ++ case USXGMII_XFI_MODE_5G: ++ speed = 5000; ++ break; ++ case USXGMII_XFI_MODE_2P5G: ++ speed = 2500; ++ break; ++ default: ++ state->speed = SPEED_UNKNOWN; ++ return; ++ } ++ ++ switch (FIELD_GET(USXGMII_RATE_ADAPT_MODE, val)) { ++ case USXGMII_RATE_ADAPT_MODE_X100: ++ speed /= 100; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X50: ++ speed /= 50; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X10: ++ speed /= 10; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X5: ++ speed /= 5; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X4: ++ speed /= 4; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X2: ++ speed /= 2; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X1: ++ break; ++ default: ++ state->speed = SPEED_UNKNOWN; ++ return; ++ } ++ ++ state->speed = speed; ++ state->duplex = DUPLEX_FULL; ++} ++ ++static void mtk_usxgmii_pcs_get_an_state(struct mtk_usxgmii_pcs *mpcs, ++ struct phylink_link_state *state) ++{ ++ u16 lpa; ++ ++ /* Refresh LPA by toggling LPA_LATCH */ ++ mtk_m32(mpcs, RG_PCS_AN_STS0, USXGMII_LPA_LATCH, USXGMII_LPA_LATCH); ++ ndelay(1020); ++ mtk_m32(mpcs, RG_PCS_AN_STS0, USXGMII_LPA_LATCH, 0); ++ ndelay(1020); ++ lpa = FIELD_GET(USXGMII_LPA, mtk_r32(mpcs, RG_PCS_AN_STS0)); ++ ++ phylink_decode_usxgmii_word(state, lpa); ++} ++ ++static void mtk_usxgmii_pcs_get_state(struct phylink_pcs *pcs, ++ struct phylink_link_state *state) ++{ ++ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); ++ ++ /* Refresh USXGMII link status by toggling RG_PCS_AN_STATUS_UPDATE */ ++ mtk_m32(mpcs, RG_PCS_RX_STATUS0, RG_PCS_RX_STATUS_UPDATE, ++ RG_PCS_RX_STATUS_UPDATE); ++ ndelay(1020); ++ mtk_m32(mpcs, RG_PCS_RX_STATUS0, RG_PCS_RX_STATUS_UPDATE, 0); ++ ndelay(1020); ++ ++ /* Read USXGMII link status */ ++ state->link = FIELD_GET(RG_PCS_RX_LINK_STATUS, ++ mtk_r32(mpcs, RG_PCS_RX_STATUS0)); ++ ++ /* Continuously repeat re-configuration sequence until link comes up */ ++ if (!state->link) { ++ mtk_usxgmii_pcs_config(pcs, mpcs->neg_mode, ++ state->interface, NULL, false); ++ return; ++ } ++ ++ if (FIELD_GET(USXGMII_AN_ENABLE, mtk_r32(mpcs, RG_PCS_AN_CTRL0))) ++ mtk_usxgmii_pcs_get_an_state(mpcs, state); ++ else ++ mtk_usxgmii_pcs_get_fixed_speed(mpcs, state); ++} ++ ++static void mtk_usxgmii_pcs_restart_an(struct phylink_pcs *pcs) ++{ ++ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); ++ ++ mtk_m32(mpcs, RG_PCS_AN_CTRL0, USXGMII_AN_RESTART, USXGMII_AN_RESTART); ++} ++ ++static void mtk_usxgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, ++ phy_interface_t interface, ++ int speed, int duplex) ++{ ++ /* Reconfiguring USXGMII to ensure the quality of the RX signal ++ * after the line side link up. ++ */ ++ mtk_usxgmii_pcs_config(pcs, neg_mode, interface, NULL, false); ++} ++ ++static void mtk_usxgmii_pcs_disable(struct phylink_pcs *pcs) ++{ ++ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); ++ ++ mpcs->interface = PHY_INTERFACE_MODE_NA; ++ mpcs->neg_mode = -1; ++} ++ ++static const struct phylink_pcs_ops mtk_usxgmii_pcs_ops = { ++ .pcs_config = mtk_usxgmii_pcs_config, ++ .pcs_get_state = mtk_usxgmii_pcs_get_state, ++ .pcs_an_restart = mtk_usxgmii_pcs_restart_an, ++ .pcs_link_up = mtk_usxgmii_pcs_link_up, ++ .pcs_disable = mtk_usxgmii_pcs_disable, ++}; ++ ++static int mtk_usxgmii_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct mtk_usxgmii_pcs *mpcs; ++ ++ mpcs = devm_kzalloc(dev, sizeof(*mpcs), GFP_KERNEL); ++ if (!mpcs) ++ return -ENOMEM; ++ ++ mpcs->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(mpcs->base)) ++ return PTR_ERR(mpcs->base); ++ ++ mpcs->dev = dev; ++ mpcs->pcs.ops = &mtk_usxgmii_pcs_ops; ++ mpcs->pcs.poll = true; ++ mpcs->pcs.neg_mode = true; ++ mpcs->interface = PHY_INTERFACE_MODE_NA; ++ mpcs->neg_mode = -1; ++ ++ mpcs->clk = devm_clk_get_enabled(mpcs->dev, NULL); ++ if (IS_ERR(mpcs->clk)) ++ return PTR_ERR(mpcs->clk); ++ ++ mpcs->reset = devm_reset_control_get_shared(dev, NULL); ++ if (IS_ERR(mpcs->reset)) ++ return PTR_ERR(mpcs->reset); ++ ++ reset_control_deassert(mpcs->reset); ++ ++ platform_set_drvdata(pdev, mpcs); ++ ++ mutex_lock(&instance_mutex); ++ list_add_tail(&mpcs->node, &mtk_usxgmii_pcs_instances); ++ mutex_unlock(&instance_mutex); ++ ++ return 0; ++} ++ ++static int mtk_usxgmii_remove(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct mtk_usxgmii_pcs *cur, *tmp; ++ ++ mutex_lock(&instance_mutex); ++ list_for_each_entry_safe(cur, tmp, &mtk_usxgmii_pcs_instances, node) ++ if (cur->dev == dev) { ++ list_del(&cur->node); ++ break; ++ } ++ mutex_unlock(&instance_mutex); ++ ++ return 0; ++} ++ ++static const struct of_device_id mtk_usxgmii_of_mtable[] = { ++ { .compatible = "mediatek,mt7988-usxgmiisys" }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, mtk_usxgmii_of_mtable); ++ ++struct phylink_pcs *mtk_usxgmii_pcs_get(struct device *dev, struct device_node *np) ++{ ++ struct platform_device *pdev; ++ struct mtk_usxgmii_pcs *mpcs; ++ ++ if (!np) ++ return NULL; ++ ++ if (!of_device_is_available(np)) ++ return ERR_PTR(-ENODEV); ++ ++ if (!of_match_node(mtk_usxgmii_of_mtable, np)) ++ return ERR_PTR(-EINVAL); ++ ++ pdev = of_find_device_by_node(np); ++ if (!pdev || !platform_get_drvdata(pdev)) { ++ if (pdev) ++ put_device(&pdev->dev); ++ return ERR_PTR(-EPROBE_DEFER); ++ } ++ ++ mpcs = platform_get_drvdata(pdev); ++ device_link_add(dev, mpcs->dev, DL_FLAG_AUTOREMOVE_CONSUMER); ++ ++ return &mpcs->pcs; ++} ++EXPORT_SYMBOL(mtk_usxgmii_pcs_get); ++ ++void mtk_usxgmii_pcs_put(struct phylink_pcs *pcs) ++{ ++ struct mtk_usxgmii_pcs *cur, *mpcs = NULL; ++ ++ if (!pcs) ++ return; ++ ++ mutex_lock(&instance_mutex); ++ list_for_each_entry(cur, &mtk_usxgmii_pcs_instances, node) ++ if (pcs == &cur->pcs) { ++ mpcs = cur; ++ break; ++ } ++ mutex_unlock(&instance_mutex); ++ ++ if (WARN_ON(!mpcs)) ++ return; ++ ++ put_device(mpcs->dev); ++} ++EXPORT_SYMBOL(mtk_usxgmii_pcs_put); ++ ++static struct platform_driver mtk_usxgmii_driver = { ++ .driver = { ++ .name = "mtk_usxgmii", ++ .suppress_bind_attrs = true, ++ .of_match_table = mtk_usxgmii_of_mtable, ++ }, ++ .probe = mtk_usxgmii_probe, ++ .remove = mtk_usxgmii_remove, ++}; ++module_platform_driver(mtk_usxgmii_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("MediaTek USXGMII PCS driver"); ++MODULE_AUTHOR("Daniel Golle "); +--- /dev/null ++++ b/include/linux/pcs/pcs-mtk-usxgmii.h +@@ -0,0 +1,27 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __LINUX_PCS_MTK_USXGMII_H ++#define __LINUX_PCS_MTK_USXGMII_H ++ ++#include ++ ++/** ++ * mtk_usxgmii_select_pcs() - Get MediaTek PCS instance ++ * @np: Pointer to device node indentifying a MediaTek USXGMII PCS ++ * @mode: Ethernet PHY interface mode ++ * ++ * Return PCS identified by a device node and the PHY interface mode in use ++ * ++ * Return: Pointer to phylink PCS instance of NULL ++ */ ++#if IS_ENABLED(CONFIG_PCS_MTK_USXGMII) ++struct phylink_pcs *mtk_usxgmii_pcs_get(struct device *dev, struct device_node *np); ++void mtk_usxgmii_pcs_put(struct phylink_pcs *pcs); ++#else ++static inline struct phylink_pcs *mtk_usxgmii_pcs_get(struct device *dev, struct device_node *np) ++{ ++ return NULL; ++} ++static inline void mtk_usxgmii_pcs_put(struct phylink_pcs *pcs) { } ++#endif /* IS_ENABLED(CONFIG_PCS_MTK_USXGMII) */ ++ ++#endif /* __LINUX_PCS_MTK_USXGMII_H */ diff --git a/lede/target/linux/generic/pending-6.1/740-net-phy-motorcomm-Add-missing-include.patch b/lede/target/linux/generic/pending-6.1/740-net-phy-motorcomm-Add-missing-include.patch new file mode 100644 index 0000000000..2a1f908cfb --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/740-net-phy-motorcomm-Add-missing-include.patch @@ -0,0 +1,22 @@ +From 6f291aa7da199c6486cc229b055dcbcd5cee7a21 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 21 May 2023 22:24:56 +0200 +Subject: [PATCH] net: phy: motorcomm: Add missing include + +Directly include linux/bitfield.h which provides FIELD_PREP. + +Signed-off-by: Hauke Mehrtens +--- + drivers/net/phy/motorcomm.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -6,6 +6,7 @@ + * Author: Frank + */ + ++#include + #include + #include + #include diff --git a/lede/target/linux/generic/pending-6.1/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch b/lede/target/linux/generic/pending-6.1/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch index bcace0e956..249ba5c496 100644 --- a/lede/target/linux/generic/pending-6.1/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch +++ b/lede/target/linux/generic/pending-6.1/741-net-phy-realtek-support-interrupt-of-RTL8221B.patch @@ -1,6 +1,18 @@ +From d7943c31d57c11e1a517aa3ce2006fca44866870 Mon Sep 17 00:00:00 2001 +From: Jianhui Zhao +Date: Sun, 24 Sep 2023 22:15:00 +0800 +Subject: [PATCH] net: phy: realtek: add interrupt support for RTL8221B + +This commit introduces interrupt support for RTL8221B. + +Signed-off-by: Jianhui Zhao +--- + drivers/net/phy/realtek.c | 47 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 47 insertions(+) + --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -981,6 +981,51 @@ static int rtl8221b_config_init(struct p +@@ -982,6 +982,51 @@ static int rtl8221b_config_init(struct p return 0; } @@ -52,7 +64,7 @@ static struct phy_driver realtek_drvs[] = { { PHY_ID_MATCH_EXACT(0x00008201), -@@ -1143,6 +1188,8 @@ static struct phy_driver realtek_drvs[] +@@ -1142,6 +1187,8 @@ static struct phy_driver realtek_drvs[] .get_features = rtl822x_get_features, .config_init = rtl8221b_config_init, .config_aneg = rtl822x_config_aneg, diff --git a/lede/target/linux/generic/pending-6.1/742-net-phy-air_en8811h-reset-netdev-rules-when-LED-is-s.patch b/lede/target/linux/generic/pending-6.1/742-net-phy-air_en8811h-reset-netdev-rules-when-LED-is-s.patch new file mode 100644 index 0000000000..500567b4ed --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/742-net-phy-air_en8811h-reset-netdev-rules-when-LED-is-s.patch @@ -0,0 +1,45 @@ +From 9be9a00adfac8118b6d685e71696f83187308c66 Mon Sep 17 00:00:00 2001 +Message-ID: <9be9a00adfac8118b6d685e71696f83187308c66.1715125851.git.daniel@makrotopia.org> +From: Daniel Golle +Date: Tue, 7 May 2024 22:43:30 +0100 +Subject: [PATCH net] net: phy: air_en8811h: reset netdev rules when LED is set + manually +To: Andrew Lunn , + Heiner Kallweit , + Russell King , + David S. Miller , + Eric Dumazet , + Jakub Kicinski , + Paolo Abeni , + SkyLake Huang , + Eric Woudstra , + netdev@vger.kernel.org, + linux-kernel@vger.kernel.org + +Setting LED_OFF via the brightness_set should deactivate hw control, +so make sure netdev trigger rules also get cleared in that case. + +Fixes: 71e79430117d ("net: phy: air_en8811h: Add the Airoha EN8811H PHY driver") +Signed-off-by: Daniel Golle +--- +This is basically a stop-gap measure until unified LED handling has +been implemented accross all MediaTek and Airoha PHYs. +See also +https://patchwork.kernel.org/project/netdevbpf/patch/20240425023325.15586-3-SkyLake.Huang@mediatek.com/ + + drivers/net/phy/air_en8811h.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/phy/air_en8811h.c ++++ b/drivers/net/phy/air_en8811h.c +@@ -544,6 +544,10 @@ static int air_hw_led_on_set(struct phy_ + + changed |= (priv->led[index].rules != 0); + ++ /* clear netdev trigger rules in case LED_OFF has been set */ ++ if (!on) ++ priv->led[index].rules = 0; ++ + if (changed) + return phy_modify_mmd(phydev, MDIO_MMD_VEND2, + AIR_PHY_LED_ON(index), diff --git a/lede/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch b/lede/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch index 558641f7c0..7d5727bda6 100644 --- a/lede/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch +++ b/lede/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch @@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -520,6 +520,7 @@ static inline bool napi_complete(struct +@@ -543,6 +543,7 @@ static inline bool napi_complete(struct } int dev_set_threaded(struct net_device *dev, bool threaded); @@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau /** * napi_disable - prevent NAPI from scheduling -@@ -3128,6 +3129,7 @@ struct softnet_data { +@@ -3150,6 +3151,7 @@ struct softnet_data { unsigned int processed; unsigned int time_squeeze; unsigned int received_rps; @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau #endif --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -4640,7 +4640,7 @@ static int napi_schedule_rps(struct soft +@@ -4625,7 +4625,7 @@ static int napi_schedule_rps(struct soft struct softnet_data *mysd = this_cpu_ptr(&softnet_data); #ifdef CONFIG_RPS @@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau sd->rps_ipi_next = mysd->rps_ipi_list; mysd->rps_ipi_list = sd; -@@ -5821,6 +5821,8 @@ static DEFINE_PER_CPU(struct work_struct +@@ -5806,6 +5806,8 @@ static DEFINE_PER_CPU(struct work_struct /* Network device is going away, flush any packets still pending */ static void flush_backlog(struct work_struct *work) { @@ -48,7 +48,7 @@ Signed-off-by: Felix Fietkau struct sk_buff *skb, *tmp; struct softnet_data *sd; -@@ -5835,8 +5837,17 @@ static void flush_backlog(struct work_st +@@ -5820,8 +5822,17 @@ static void flush_backlog(struct work_st input_queue_head_incr(sd); } } @@ -66,7 +66,7 @@ Signed-off-by: Felix Fietkau skb_queue_walk_safe(&sd->process_queue, skb, tmp) { if (skb->dev->reg_state == NETREG_UNREGISTERING) { __skb_unlink(skb, &sd->process_queue); -@@ -5844,7 +5855,16 @@ static void flush_backlog(struct work_st +@@ -5829,7 +5840,16 @@ static void flush_backlog(struct work_st input_queue_head_incr(sd); } } @@ -83,7 +83,7 @@ Signed-off-by: Felix Fietkau } static bool flush_required(int cpu) -@@ -5976,6 +5996,7 @@ static int process_backlog(struct napi_s +@@ -5961,6 +5981,7 @@ static int process_backlog(struct napi_s } rps_lock_irq_disable(sd); @@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau if (skb_queue_empty(&sd->input_pkt_queue)) { /* * Inline a custom version of __napi_complete(). -@@ -5985,7 +6006,8 @@ static int process_backlog(struct napi_s +@@ -5970,7 +5991,8 @@ static int process_backlog(struct napi_s * We can use a plain write instead of clear_bit(), * and we dont need an smp_mb() memory barrier. */ @@ -101,7 +101,7 @@ Signed-off-by: Felix Fietkau again = false; } else { skb_queue_splice_tail_init(&sd->input_pkt_queue, -@@ -6401,6 +6423,55 @@ int dev_set_threaded(struct net_device * +@@ -6386,6 +6408,55 @@ int dev_set_threaded(struct net_device * } EXPORT_SYMBOL(dev_set_threaded); @@ -157,7 +157,7 @@ Signed-off-by: Felix Fietkau void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct *, int), int weight) { -@@ -11142,6 +11213,9 @@ static int dev_cpu_dead(unsigned int old +@@ -11127,6 +11198,9 @@ static int dev_cpu_dead(unsigned int old raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_enable(); @@ -167,7 +167,7 @@ Signed-off-by: Felix Fietkau #ifdef CONFIG_RPS remsd = oldsd->rps_ipi_list; oldsd->rps_ipi_list = NULL; -@@ -11454,6 +11528,7 @@ static int __init net_dev_init(void) +@@ -11439,6 +11513,7 @@ static int __init net_dev_init(void) INIT_CSD(&sd->defer_csd, trigger_rx_softirq, sd); spin_lock_init(&sd->defer_lock); diff --git a/lede/target/linux/generic/pending-6.1/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch b/lede/target/linux/generic/pending-6.1/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch index 8458f8c1ec..13a4d190ee 100644 --- a/lede/target/linux/generic/pending-6.1/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch +++ b/lede/target/linux/generic/pending-6.1/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch @@ -17,7 +17,7 @@ Signed-off-by: Tobias Waldekranz --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -7032,6 +7032,7 @@ static int mv88e6xxx_register_switch(str +@@ -7079,6 +7079,7 @@ static int mv88e6xxx_register_switch(str ds->ops = &mv88e6xxx_switch_ops; ds->ageing_time_min = chip->info->age_time_coeff; ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX; diff --git a/lede/target/linux/generic/pending-6.1/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch b/lede/target/linux/generic/pending-6.1/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch deleted file mode 100644 index df52a6ac25..0000000000 --- a/lede/target/linux/generic/pending-6.1/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 1d81e51d6d79d9098013b2e8cdd677bae998c5d8 Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Fri, 28 Apr 2023 02:22:59 +0200 -Subject: [PATCH 1/2] mt7530: register OF node for internal MDIO bus - -The MT753x switches provide a switch-internal MDIO bus for the embedded -PHYs. - -Register a OF sub-node on the switch OF-node for this internal MDIO bus. -This allows to configure the embedded PHYs using device-tree. - -Signed-off-by: David Bauer ---- - drivers/net/dsa/mt7530.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -2360,10 +2360,13 @@ mt7530_setup_mdio(struct mt7530_priv *pr - { - struct dsa_switch *ds = priv->ds; - struct device *dev = priv->dev; -+ struct device_node *np, *mnp; - struct mii_bus *bus; - static int idx; - int ret; - -+ np = priv->dev->of_node; -+ - bus = devm_mdiobus_alloc(dev); - if (!bus) - return -ENOMEM; -@@ -2380,7 +2383,9 @@ mt7530_setup_mdio(struct mt7530_priv *pr - if (priv->irq) - mt7530_setup_mdio_irq(priv); - -- ret = devm_mdiobus_register(dev, bus); -+ mnp = of_get_child_by_name(np, "mdio"); -+ ret = devm_of_mdiobus_register(dev, bus, mnp); -+ of_node_put(mnp); - if (ret) { - dev_err(dev, "failed to register MDIO bus: %d\n", ret); - if (priv->irq) diff --git a/lede/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch b/lede/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch index 9b111050ee..d07447bcba 100644 --- a/lede/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch +++ b/lede/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch @@ -36,9 +36,9 @@ Signed-off-by: Srinivas Kandagatla --- a/drivers/nvmem/u-boot-env.c +++ b/drivers/nvmem/u-boot-env.c -@@ -182,7 +182,7 @@ static int u_boot_env_parse(struct u_boo - crc32_data_len = priv->mtd->size - crc32_data_offset; - data_len = priv->mtd->size - data_offset; +@@ -181,7 +181,7 @@ static int u_boot_env_parse(struct u_boo + crc32_data_len = dev_size - crc32_data_offset; + data_len = dev_size - data_offset; - calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; + calc = le32_to_cpu((__le32)crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L); diff --git a/lede/target/linux/generic/pending-6.1/804-nvmem-core-support-mac-base-fixed-layout-cells.patch b/lede/target/linux/generic/pending-6.1/804-nvmem-core-support-mac-base-fixed-layout-cells.patch new file mode 100644 index 0000000000..9bb94a28b5 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/804-nvmem-core-support-mac-base-fixed-layout-cells.patch @@ -0,0 +1,124 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 13 Jul 2023 18:29:19 +0200 +Subject: [PATCH] nvmem: core: support "mac-base" fixed layout cells + +Fixed layout binding allows specifying "mac-base" NVMEM cells. It's used +for base MAC address (that can be used for calculating relative +addresses). It can be stored in a raw binary format or as an ASCII +string. +--- + +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0-only + menuconfig NVMEM + bool "NVMEM Support" ++ select GENERIC_NET_UTILS + imply NVMEM_LAYOUTS + help + Support for NVMEM(Non Volatile Memory) devices like EEPROM, EFUSES... +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -7,9 +7,12 @@ + */ + + #include ++#include ++#include + #include + #include + #include ++#include + #include + #include + #include +@@ -780,6 +783,62 @@ static int nvmem_validate_keepouts(struc + return 0; + } + ++static int nvmem_mac_base_raw_read(void *context, const char *id, int index, unsigned int offset, ++ void *buf, size_t bytes) ++{ ++ if (WARN_ON(bytes != ETH_ALEN)) ++ return -EINVAL; ++ ++ if (index) ++ eth_addr_add(buf, index); ++ ++ return 0; ++} ++ ++static int nvmem_mac_base_ascii_read(void *context, const char *id, int index, unsigned int offset, ++ void *buf, size_t bytes) ++{ ++ u8 mac[ETH_ALEN]; ++ ++ if (WARN_ON(bytes != 3 * ETH_ALEN - 1)) ++ return -EINVAL; ++ ++ if (!mac_pton(buf, mac)) ++ return -EINVAL; ++ ++ if (index) ++ eth_addr_add(mac, index); ++ ++ ether_addr_copy(buf, mac); ++ ++ return 0; ++} ++ ++static int nvmem_mac_base_hex_read(void *context, const char *id, int index, unsigned int offset, ++ void *buf, size_t bytes) ++{ ++ u8 mac[ETH_ALEN], *hexstr; ++ int i; ++ ++ if (WARN_ON(bytes != 2 * ETH_ALEN)) ++ return -EINVAL; ++ ++ hexstr = (u8 *)buf; ++ for (i = 0; i < ETH_ALEN; i++) { ++ if (!isxdigit(hexstr[i * 2]) || !isxdigit(hexstr[i * 2 + 1])) ++ return -EINVAL; ++ ++ mac[i] = (hex_to_bin(hexstr[i * 2]) << 4) | hex_to_bin(hexstr[i * 2 + 1]); ++ } ++ ++ if (index) ++ eth_addr_add(mac, index); ++ ++ ether_addr_copy(buf, mac); ++ ++ return 0; ++} ++ + static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np) + { + struct device *dev = &nvmem->dev; +@@ -814,6 +873,25 @@ static int nvmem_add_cells_from_dt(struc + if (nvmem->fixup_dt_cell_info) + nvmem->fixup_dt_cell_info(nvmem, &info); + ++ if (of_device_is_compatible(np, "fixed-layout")) { ++ if (of_device_is_compatible(child, "mac-base")) { ++ if (info.bytes == ETH_ALEN) { ++ info.raw_len = info.bytes; ++ info.bytes = ETH_ALEN; ++ info.read_post_process = nvmem_mac_base_raw_read; ++ } else if (info.bytes == 2 * ETH_ALEN) { ++ info.raw_len = info.bytes; ++ info.bytes = ETH_ALEN; ++ info.read_post_process = nvmem_mac_base_hex_read; ++ } else if (info.bytes == 3 * ETH_ALEN - 1) { ++ info.raw_len = info.bytes; ++ info.bytes = ETH_ALEN; ++ info.read_post_process = nvmem_mac_base_ascii_read; ++ } ++ ++ } ++ } ++ + ret = nvmem_add_one_cell(nvmem, &info); + kfree(info.name); + if (ret) { diff --git a/lede/target/linux/generic/pending-6.1/870-ARM-dts-nxp-imx7d-pico-add-cpu-supply-nodes.patch b/lede/target/linux/generic/pending-6.1/870-ARM-dts-nxp-imx7d-pico-add-cpu-supply-nodes.patch new file mode 100644 index 0000000000..e25389363f --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/870-ARM-dts-nxp-imx7d-pico-add-cpu-supply-nodes.patch @@ -0,0 +1,43 @@ +From d0562705bcd4cb9849156f095b2af0ec1bb53b56 Mon Sep 17 00:00:00 2001 +From: Lech Perczak +Date: Fri, 17 Nov 2023 21:33:04 +0100 +Subject: [PATCH] ARM: dts: nxp: imx7d-pico: add cpu-supply nodes + +The PICO-IMX7D SoM has the usual power supply configuration using +output sw1a of PF3000 PMIC, which was defined in downstream derivative +of linux-imx (see link) in the sources for "Android Things" devkit. +It is required to support CPU frequency scaling. + +Map the respective "cpu-supply" nodes of each core to sw1a of the PMIC. + +Enabling them causes cpufreq-dt, and imx-thermal drivers to probe +successfully, and CPU frequency scaling to function. + +Link: https://android.googlesource.com/platform/hardware/bsp/kernel/nxp/imx-v4.1/+/o-iot-preview-5/arch/arm/boot/dts/imx7d-pico.dtsi#849 + +Cc: Fabio Estevam +Cc: Shawn Guo +Cc: Sascha Hauer + +Signed-off-by: Lech Perczak +--- + arch/arm/boot/dts/imx7d-pico.dtsi | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/arch/arm/boot/dts/imx7d-pico.dtsi ++++ b/arch/arm/boot/dts/imx7d-pico.dtsi +@@ -108,6 +108,14 @@ + assigned-clock-rates = <0>, <32768>; + }; + ++&cpu0 { ++ cpu-supply = <&sw1a_reg>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&sw1a_reg>; ++}; ++ + &ecspi3 { + cs-gpios = <&gpio4 11 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; diff --git a/lede/target/linux/generic/pending-6.1/880-01-dt-bindings-leds-add-LED_FUNCTION_MOBILE-for-mobile-.patch b/lede/target/linux/generic/pending-6.1/880-01-dt-bindings-leds-add-LED_FUNCTION_MOBILE-for-mobile-.patch new file mode 100644 index 0000000000..3321b03f28 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/880-01-dt-bindings-leds-add-LED_FUNCTION_MOBILE-for-mobile-.patch @@ -0,0 +1,37 @@ +From 38eb5b3370c29515d2ce92adac2d6eba96f276f5 Mon Sep 17 00:00:00 2001 +From: INAGAKI Hiroshi +Date: Wed, 20 Mar 2024 15:32:18 +0900 +Subject: [PATCH v2 1/2] dt-bindings: leds: add LED_FUNCTION_MOBILE for mobile + network + +Add LED_FUNCTION_MOBILE for LEDs that indicate status of mobile network +connection. This is useful to distinguish those LEDs from LEDs that +indicates status of wired "wan" connection. + +example (on stock fw): + +IIJ SA-W2 has "Mobile" LEDs that indicate status (no signal, too low, +low, good) of mobile network connection via dongle connected to USB +port. + +- no signal: (none, turned off) +- too low: green:mobile & red:mobile (amber, blink) +- low: green:mobile & red:mobile (amber, turned on) +- good: green:mobile (turned on) + +Suggested-by: Hauke Mehrtens +Signed-off-by: INAGAKI Hiroshi +--- + include/dt-bindings/leds/common.h | 1 + + 1 file changed, 1 insertion(+) + +--- a/include/dt-bindings/leds/common.h ++++ b/include/dt-bindings/leds/common.h +@@ -90,6 +90,7 @@ + #define LED_FUNCTION_INDICATOR "indicator" + #define LED_FUNCTION_LAN "lan" + #define LED_FUNCTION_MAIL "mail" ++#define LED_FUNCTION_MOBILE "mobile" + #define LED_FUNCTION_MTD "mtd" + #define LED_FUNCTION_PANIC "panic" + #define LED_FUNCTION_PROGRAMMING "programming" diff --git a/lede/target/linux/generic/pending-6.1/880-02-dt-bindings-leds-add-LED_FUNCTION_SPEED_-for-link-sp.patch b/lede/target/linux/generic/pending-6.1/880-02-dt-bindings-leds-add-LED_FUNCTION_SPEED_-for-link-sp.patch new file mode 100644 index 0000000000..ab27cd3399 --- /dev/null +++ b/lede/target/linux/generic/pending-6.1/880-02-dt-bindings-leds-add-LED_FUNCTION_SPEED_-for-link-sp.patch @@ -0,0 +1,37 @@ +From e22afe910afcfb51b6ba6a0ae776939959727f54 Mon Sep 17 00:00:00 2001 +From: INAGAKI Hiroshi +Date: Wed, 20 Mar 2024 15:59:06 +0900 +Subject: [PATCH v2 2/2] dt-bindings: leds: add LED_FUNCTION_SPEED_* for link + speed on LAN/WAN + +Add LED_FUNCTION_SPEED_LAN and LED_FUNCTION_SPEED_WAN for LEDs that +indicate link speed of ethernet ports on LAN/WAN. This is useful to +distinguish those LEDs from LEDs that indicate link status (up/down). + +example: + +Fortinet FortiGate 30E/50E have LEDs that indicate link speed on each +of the ethernet ports in addition to LEDs that indicate link status +(up/down). + +- 1000 Mbps: green:speed-(lan|wan)-N +- 100 Mbps: amber:speed-(lan|wan)-N +- 10 Mbps: (none, turned off) + +Reviewed-by: Rob Herring +Signed-off-by: INAGAKI Hiroshi +--- + include/dt-bindings/leds/common.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/dt-bindings/leds/common.h ++++ b/include/dt-bindings/leds/common.h +@@ -96,6 +96,8 @@ + #define LED_FUNCTION_PROGRAMMING "programming" + #define LED_FUNCTION_RX "rx" + #define LED_FUNCTION_SD "sd" ++#define LED_FUNCTION_SPEED_LAN "speed-lan" ++#define LED_FUNCTION_SPEED_WAN "speed-wan" + #define LED_FUNCTION_STANDBY "standby" + #define LED_FUNCTION_TORCH "torch" + #define LED_FUNCTION_TX "tx" diff --git a/lede/target/linux/generic/pending-6.6/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch b/lede/target/linux/generic/pending-6.6/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch index 6405865c45..defde3f426 100644 --- a/lede/target/linux/generic/pending-6.6/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch +++ b/lede/target/linux/generic/pending-6.6/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch @@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c -@@ -1258,6 +1258,74 @@ static struct mtd_notifier ubi_mtd_notif +@@ -1258,6 +1258,80 @@ static struct mtd_notifier ubi_mtd_notif .remove = ubi_notify_remove, }; @@ -21,6 +21,7 @@ Signed-off-by: Daniel Golle +{ + int err; + struct mtd_info *mtd; ++ struct device_node *np; + loff_t offset = 0; + size_t len; + char magic[4]; @@ -33,6 +34,11 @@ Signed-off-by: Daniel Golle + if (IS_ERR(mtd)) + return; + ++ /* skip "linux,ubi" mtd as it has already been attached */ ++ np = mtd_get_of_node(mtd); ++ if (of_device_is_compatible(np, "linux,ubi")) ++ goto cleanup; ++ + /* get the first not bad block */ + if (mtd_can_have_bb(mtd)) + while (mtd_block_isbad(mtd, offset)) { @@ -83,7 +89,7 @@ Signed-off-by: Daniel Golle static int __init ubi_init_attach(void) { int err, i, k; -@@ -1308,6 +1376,12 @@ static int __init ubi_init_attach(void) +@@ -1308,6 +1382,12 @@ static int __init ubi_init_attach(void) } } diff --git a/lede/target/linux/generic/pending-6.6/734-net-ethernet-mediatek-Allow-gaps-in-MAC-allocation.patch b/lede/target/linux/generic/pending-6.6/734-net-ethernet-mediatek-Allow-gaps-in-MAC-allocation.patch new file mode 100644 index 0000000000..8e1ad54a53 --- /dev/null +++ b/lede/target/linux/generic/pending-6.6/734-net-ethernet-mediatek-Allow-gaps-in-MAC-allocation.patch @@ -0,0 +1,33 @@ +From 379ae584cea112db60f4ada79c7e5ba4f3364a64 Mon Sep 17 00:00:00 2001 +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 13718593 +X-Patchwork-Delegate: kuba@kernel.org +List-Id: +From: Daniel Golle +Date: Mon, 1 Jul 2024 19:26:28 +0100 +Subject: [PATCH] net: ethernet: mediatek: Allow gaps in MAC allocation + +Some devices with MediaTek SoCs don't use the first but only the second +MAC in the chip. Especially with MT7981 which got a built-in 1GE PHY +connected to the second MAC this is quite common. +Make sure to reset and enable PSE also in those cases by skipping gaps +using 'continue' instead of aborting the loop using 'break'. + +Fixes: dee4dd10c79a ("net: ethernet: mtk_eth_soc: ppe: add support for multiple PPEs") +Suggested-by: Elad Yifee +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3431,7 +3431,7 @@ static int mtk_open(struct net_device *d + + for (i = 0; i < MTK_MAX_DEVS; i++) { + if (!eth->netdev[i]) +- break; ++ continue; + + target_mac = netdev_priv(eth->netdev[i]); + if (!soc->offload_version) { diff --git a/lede/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/lede/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh index 52adac9c33..37cba01940 100755 --- a/lede/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/lede/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -1,4 +1,5 @@ REQUIRE_IMAGE_METADATA=1 +RAMFS_COPY_BIN='fitblk' asus_initial_setup() { @@ -23,17 +24,16 @@ platform_do_upgrade() { bananapi,bpi-r3|\ bananapi,bpi-r4|\ bananapi,bpi-r4-poe) - local rootdev="$(cmdline_get_var root)" - rootdev="${rootdev##*/}" - rootdev="${rootdev%p[0-9]*}" - case "$rootdev" in + [ -e /dev/fit0 ] && fitblk /dev/fit0 + [ -e /dev/fitrw ] && fitblk /dev/fitrw + bootdev="$(fitblk_get_bootdev)" + case "$bootdev" in mmc*) - CI_ROOTDEV="$rootdev" - CI_KERNPART="production" + EMMC_KERN_DEV="/dev/$bootdev" emmc_do_upgrade "$1" ;; mtdblock*) - PART_NAME="fit" + PART_NAME="/dev/mtd${bootdev:8}" default_do_upgrade "$1" ;; ubiblock*) diff --git a/lede/target/linux/mediatek/image/filogic.mk b/lede/target/linux/mediatek/image/filogic.mk index 15dc26c4fa..c1ac001c20 100644 --- a/lede/target/linux/mediatek/image/filogic.mk +++ b/lede/target/linux/mediatek/image/filogic.mk @@ -479,9 +479,23 @@ define Device/mediatek_mt7988a-rfb endef TARGET_DEVICES += mediatek_mt7988a-rfb +define Device/hf_m7986r1-emmc + DEVICE_VENDOR := HF + DEVICE_MODEL := M7986R1 (eMMC version) + DEVICE_DTS := mt7986a-hf-m7986r1-emmc + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-usb3 kmod-mt7921e kmod-usb-serial-option kmod-usb-net-rndis f2fsck mkf2fs + SUPPORTED_DEVICES += HF-M7986R1 + KERNEL := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES +=hf_m7986r1-emmc + define Device/hf_m7986r1-nand DEVICE_VENDOR := HF - DEVICE_MODEL := M7986R1 + DEVICE_MODEL := M7986R1 (NAND version) DEVICE_DTS := mt7986a-hf-m7986r1-nand DEVICE_DTS_DIR := ../dts UBINIZE_OPTS := -E 5 diff --git a/lede/target/linux/mediatek/patches-6.1/041-block-fit-partition-parser.patch b/lede/target/linux/mediatek/patches-6.1/041-block-fit-partition-parser.patch index 0bd82e0704..49fc7e638c 100644 --- a/lede/target/linux/mediatek/patches-6.1/041-block-fit-partition-parser.patch +++ b/lede/target/linux/mediatek/patches-6.1/041-block-fit-partition-parser.patch @@ -19,7 +19,7 @@ Subject: [PATCH] kernel: add block fit partition parser --- a/block/blk.h +++ b/block/blk.h -@@ -415,6 +415,8 @@ void blk_free_ext_minor(unsigned int min +@@ -424,6 +424,8 @@ void blk_free_ext_minor(unsigned int min #define ADDPART_FLAG_NONE 0 #define ADDPART_FLAG_RAID 1 #define ADDPART_FLAG_WHOLEDISK 2 @@ -72,18 +72,17 @@ Subject: [PATCH] kernel: add block fit partition parser +int parse_fit_partitions(struct parsed_partitions *state, u64 start_sector, u64 nr_sectors, int *slot, int add_remain); --- a/block/partitions/core.c +++ b/block/partitions/core.c -@@ -10,6 +10,10 @@ - #include +@@ -11,6 +11,9 @@ #include #include + #include +#ifdef CONFIG_FIT_PARTITION +#include +#endif -+ + #include "check.h" - static int (*check_part[])(struct parsed_partitions *) = { -@@ -46,6 +50,9 @@ static int (*check_part[])(struct parsed +@@ -48,6 +51,9 @@ static int (*const check_part[])(struct #ifdef CONFIG_EFI_PARTITION efi_partition, /* this must come before msdos */ #endif @@ -93,7 +92,7 @@ Subject: [PATCH] kernel: add block fit partition parser #ifdef CONFIG_SGI_PARTITION sgi_partition, #endif -@@ -398,6 +405,11 @@ static struct block_device *add_partitio +@@ -430,6 +436,11 @@ static struct block_device *add_partitio goto out_del; } @@ -105,7 +104,7 @@ Subject: [PATCH] kernel: add block fit partition parser /* everything is up and running, commence */ err = xa_insert(&disk->part_tbl, partno, bdev, GFP_KERNEL); if (err) -@@ -590,6 +602,11 @@ static bool blk_add_partition(struct gen +@@ -622,6 +633,11 @@ static bool blk_add_partition(struct gen (state->parts[p].flags & ADDPART_FLAG_RAID)) md_autodetect_dev(part->bd_dev); @@ -194,7 +193,7 @@ Subject: [PATCH] kernel: add block fit partition parser set_capacity(gd, ((u64)new->size * tr->blksize) >> 9); --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c -@@ -431,7 +431,9 @@ int ubiblock_create(struct ubi_volume_in +@@ -410,7 +410,9 @@ int ubiblock_create(struct ubi_volume_in ret = -ENODEV; goto out_cleanup_disk; } diff --git a/lede/target/linux/mediatek/patches-6.1/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch b/lede/target/linux/mediatek/patches-6.1/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch index 2fe565f3b2..465f0eaf27 100644 --- a/lede/target/linux/mediatek/patches-6.1/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch +++ b/lede/target/linux/mediatek/patches-6.1/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch @@ -15,30 +15,23 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -215,8 +215,8 @@ int mtk_wed_mcu_msg_update(struct mtk_we +@@ -234,8 +234,8 @@ int mtk_wed_mcu_msg_update(struct mtk_we } static int --mtk_wed_get_memory_region(struct mtk_wed_wo *wo, +-mtk_wed_get_memory_region(struct mtk_wed_hw *hw, int index, - struct mtk_wed_wo_memory_region *region) -+mtk_wed_get_reserved_memory_region(struct mtk_wed_wo *wo, ++mtk_wed_get_reserved_memory_region(struct mtk_wed_hw *hw, int index, + struct mtk_wed_wo_memory_region *region) { struct reserved_mem *rmem; struct device_node *np; -@@ -311,13 +311,13 @@ mtk_wed_mcu_load_firmware(struct mtk_wed +@@ -325,7 +325,7 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + if (index < 0) + continue; - /* load firmware region metadata */ - for (i = 0; i < ARRAY_SIZE(mem_region); i++) { -- ret = mtk_wed_get_memory_region(wo, &mem_region[i]); -+ ret = mtk_wed_get_reserved_memory_region(wo, &mem_region[i]); +- ret = mtk_wed_get_memory_region(wo->hw, index, &mem_region[i]); ++ ret = mtk_wed_get_reserved_memory_region(wo->hw, index, &mem_region[i]); if (ret) return ret; } - - wo->boot.name = "wo-boot"; -- ret = mtk_wed_get_memory_region(wo, &wo->boot); -+ ret = mtk_wed_get_reserved_memory_region(wo, &wo->boot); - if (ret) - return ret; - diff --git a/lede/target/linux/mediatek/patches-6.1/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch b/lede/target/linux/mediatek/patches-6.1/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch index 9de4ffa433..b4bea2087b 100644 --- a/lede/target/linux/mediatek/patches-6.1/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch +++ b/lede/target/linux/mediatek/patches-6.1/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch @@ -23,15 +23,15 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -18,12 +18,23 @@ +@@ -34,12 +34,23 @@ static struct mtk_wed_wo_memory_region m static u32 wo_r32(struct mtk_wed_wo *wo, u32 reg) { -- return readl(wo->boot.addr + reg); +- return readl(mem_region[MTK_WED_WO_REGION_BOOT].addr + reg); + u32 val; + + if (!wo->boot_regmap) -+ return readl(wo->boot.addr + reg); ++ return readl(mem_region[MTK_WED_WO_REGION_BOOT].addr + reg); + + if (regmap_read(wo->boot_regmap, reg, &val)) + val = ~0; @@ -41,49 +41,41 @@ Signed-off-by: Lorenzo Bianconi static void wo_w32(struct mtk_wed_wo *wo, u32 reg, u32 val) { -- writel(val, wo->boot.addr + reg); +- writel(val, mem_region[MTK_WED_WO_REGION_BOOT].addr + reg); + if (wo->boot_regmap) + regmap_write(wo->boot_regmap, reg, val); + else -+ writel(val, wo->boot.addr + reg); ++ writel(val, mem_region[MTK_WED_WO_REGION_BOOT].addr + reg); } static struct sk_buff * -@@ -316,10 +327,21 @@ mtk_wed_mcu_load_firmware(struct mtk_wed - return ret; - } +@@ -313,6 +324,9 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + u32 val, boot_cr; + int ret, i; -- wo->boot.name = "wo-boot"; -- ret = mtk_wed_get_reserved_memory_region(wo, &wo->boot); -- if (ret) -- return ret; + wo->boot_regmap = syscon_regmap_lookup_by_phandle(wo->hw->node, + "mediatek,wo-cpuboot"); -+ if (IS_ERR(wo->boot_regmap)) { -+ if (wo->boot_regmap != ERR_PTR(-ENODEV)) -+ return PTR_ERR(wo->boot_regmap); + -+ /* For backward compatibility, we need to check if cpu_boot -+ * is defined through reserved memory property. -+ */ -+ wo->boot_regmap = NULL; -+ wo->boot.name = "wo-boot"; -+ ret = mtk_wed_get_reserved_memory_region(wo, &wo->boot); -+ if (ret) -+ return ret; -+ } + /* load firmware region metadata */ + for (i = 0; i < ARRAY_SIZE(mem_region); i++) { + int index = of_property_match_string(wo->hw->node, +@@ -321,6 +335,9 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + if (index < 0) + continue; - /* set dummy cr */ - wed_w32(wo->hw->wed_dev, MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_FWDL, ++ if (index == MTK_WED_WO_REGION_BOOT && !IS_ERR(wo->boot_regmap)) ++ continue; ++ + ret = mtk_wed_get_reserved_memory_region(wo->hw, index, &mem_region[i]); + if (ret) + return ret; --- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h +++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h -@@ -228,7 +228,8 @@ struct mtk_wed_wo_queue { - +@@ -231,6 +231,7 @@ struct mtk_wed_wo_queue { struct mtk_wed_wo { struct mtk_wed_hw *hw; -- struct mtk_wed_wo_memory_region boot; -+ struct mtk_wed_wo_memory_region boot; /* backward compatibility */ -+ struct regmap *boot_regmap; ++ struct regmap *boot_regmap; struct mtk_wed_wo_queue q_tx; struct mtk_wed_wo_queue q_rx; + diff --git a/lede/target/linux/mediatek/patches-6.1/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch b/lede/target/linux/mediatek/patches-6.1/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch index 7b6c5d1e27..b4ba5b0d2d 100644 --- a/lede/target/linux/mediatek/patches-6.1/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch +++ b/lede/target/linux/mediatek/patches-6.1/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch @@ -20,72 +20,67 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -300,6 +300,52 @@ next: +@@ -316,6 +316,39 @@ next: } static int -+mtk_wed_mcu_load_memory_regions(struct mtk_wed_wo *wo, -+ struct mtk_wed_wo_memory_region *region) ++mtk_wed_mcu_load_ilm(struct mtk_wed_wo *wo) +{ ++ struct mtk_wed_wo_memory_region *ilm_region; ++ struct resource res; + struct device_node *np; + int ret; + -+ /* firmware EMI memory region */ -+ ret = mtk_wed_get_reserved_memory_region(wo, -+ ®ion[MTK_WED_WO_REGION_EMI]); -+ if (ret) -+ return ret; -+ -+ /* firmware DATA memory region */ -+ ret = mtk_wed_get_reserved_memory_region(wo, -+ ®ion[MTK_WED_WO_REGION_DATA]); -+ if (ret) -+ return ret; -+ + np = of_parse_phandle(wo->hw->node, "mediatek,wo-ilm", 0); -+ if (np) { -+ struct mtk_wed_wo_memory_region *ilm_region; -+ struct resource res; ++ if (!np) ++ return 0; + -+ ret = of_address_to_resource(np, 0, &res); -+ of_node_put(np); ++ ret = of_address_to_resource(np, 0, &res); ++ of_node_put(np); + -+ if (ret < 0) -+ return ret; ++ if (ret < 0) ++ return ret; + -+ ilm_region = ®ion[MTK_WED_WO_REGION_ILM]; -+ ilm_region->phy_addr = res.start; -+ ilm_region->size = resource_size(&res); -+ ilm_region->addr = devm_ioremap(wo->hw->dev, res.start, -+ resource_size(&res)); ++ ilm_region = &mem_region[MTK_WED_WO_REGION_ILM]; ++ ilm_region->phy_addr = res.start; ++ ilm_region->size = resource_size(&res); ++ ilm_region->addr = devm_ioremap(wo->hw->dev, res.start, ++ resource_size(&res)); + -+ return IS_ERR(ilm_region->addr) ? PTR_ERR(ilm_region->addr) : 0; -+ } ++ if (!IS_ERR(ilm_region->addr)) ++ return 0; + -+ /* For backward compatibility, we need to check if ILM -+ * node is defined through reserved memory property. -+ */ -+ return mtk_wed_get_reserved_memory_region(wo, -+ ®ion[MTK_WED_WO_REGION_ILM]); ++ ret = PTR_ERR(ilm_region->addr); ++ ilm_region->addr = NULL; ++ ++ return ret; +} + +static int mtk_wed_mcu_load_firmware(struct mtk_wed_wo *wo) { - static struct mtk_wed_wo_memory_region mem_region[] = { -@@ -320,12 +366,9 @@ mtk_wed_mcu_load_firmware(struct mtk_wed + const struct mtk_wed_fw_trailer *trailer; +@@ -324,14 +357,20 @@ mtk_wed_mcu_load_firmware(struct mtk_wed u32 val, boot_cr; int ret, i; -- /* load firmware region metadata */ -- for (i = 0; i < ARRAY_SIZE(mem_region); i++) { -- ret = mtk_wed_get_reserved_memory_region(wo, &mem_region[i]); -- if (ret) -- return ret; -- } -+ ret = mtk_wed_mcu_load_memory_regions(wo, mem_region); -+ if (ret) -+ return ret; - ++ mtk_wed_mcu_load_ilm(wo); wo->boot_regmap = syscon_regmap_lookup_by_phandle(wo->hw->node, "mediatek,wo-cpuboot"); + + /* load firmware region metadata */ + for (i = 0; i < ARRAY_SIZE(mem_region); i++) { +- int index = of_property_match_string(wo->hw->node, +- "memory-region-names", +- mem_region[i].name); ++ int index; ++ ++ if (mem_region[i].addr) ++ continue; ++ ++ index = of_property_match_string(wo->hw->node, ++ "memory-region-names", ++ mem_region[i].name); + if (index < 0) + continue; + diff --git a/lede/target/linux/x86/Makefile b/lede/target/linux/x86/Makefile index 2c85929155..441448da59 100644 --- a/lede/target/linux/x86/Makefile +++ b/lede/target/linux/x86/Makefile @@ -17,7 +17,7 @@ KERNELNAME:=bzImage include $(INCLUDE_DIR)/target.mk -DEFAULT_PACKAGES += partx-utils mkf2fs e2fsprogs kmod-button-hotplug kmod-usb-hid kmod-mmc kmod-sdhci kmod-fs-f2fs cfdisk usbutils pciutils \ +DEFAULT_PACKAGES += partx-utils mkf2fs e2fsprogs kmod-button-hotplug kmod-usb-hid kmod-mmc kmod-sdhci kmod-fs-f2fs intel-microcode cfdisk usbutils pciutils \ kmod-alx kmod-e1000e kmod-igb kmod-igc kmod-igbvf kmod-iavf kmod-bnx2x kmod-pcnet32 kmod-tulip kmod-via-velocity kmod-vmxnet3 kmod-i40e kmod-i40evf \ kmod-sound-hda-core kmod-sound-hda-codec-realtek kmod-sound-hda-codec-via kmod-sound-via82xx kmod-sound-hda-intel kmod-sound-hda-codec-hdmi kmod-sound-i8x0 \ kmod-usb-net kmod-usb-net-asix-ax88179 kmod-usb-net-rtl8150 kmod-usb-net-aqc111 kmod-mlx4-core kmod-mlx5-core kmod-drm-i915 kmod-drm-amdgpu kmod-usb-audio \ diff --git a/nekobox-android/.github/workflows/ci.yml b/nekobox-android/.github/workflows/ci.yml deleted file mode 100644 index 14a7a4e24b..0000000000 --- a/nekobox-android/.github/workflows/ci.yml +++ /dev/null @@ -1,74 +0,0 @@ -name: CI -on: - push: - tags-ignore: - - 'v*' - branches: - - '*' - pull_request: -jobs: - libcore: - name: Native Build (LibCore) - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Golang Status - run: find buildScript libcore/*.sh | xargs cat | sha1sum > golang_status - - name: Libcore Status - run: git ls-files libcore | xargs cat | sha1sum > libcore_status - - name: LibCore Cache - id: cache - uses: actions/cache@v4 - with: - path: | - app/libs/libcore.aar - key: ${{ hashFiles('.github/workflows/*', 'golang_status', 'libcore_status') }}-ci - - name: Install Golang - if: steps.cache.outputs.cache-hit != 'true' - uses: actions/setup-go@v5 - with: - go-version: ^1.21 - - name: Native Build - if: steps.cache.outputs.cache-hit != 'true' - run: ./run lib core - build: - name: Build OSS APK - runs-on: ubuntu-latest - needs: - - libcore - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Golang Status - run: find buildScript libcore/*.sh | xargs cat | sha1sum > golang_status - - name: Libcore Status - run: git ls-files libcore | xargs cat | sha1sum > libcore_status - - name: LibCore Cache - uses: actions/cache@v4 - with: - path: | - app/libs/libcore.aar - key: ${{ hashFiles('.github/workflows/*', 'golang_status', 'libcore_status') }}-ci - - name: Gradle cache - uses: actions/cache@v4 - with: - path: ~/.gradle - key: gradle-oss-${{ hashFiles('**/*.gradle.kts') }}-ci - - name: Gradle Build - env: - BUILD_PLUGIN: none - run: | - echo "sdk.dir=${ANDROID_HOME}" > local.properties - echo "ndk.dir=${ANDROID_HOME}/ndk/25.0.8775105" >> local.properties - export LOCAL_PROPERTIES="${{ secrets.LOCAL_PROPERTIES }}" - ./run init action gradle - ./gradlew app:assembleOssDebug - APK=$(find app/build/outputs/apk -name '*arm64-v8a*.apk') - APK=$(dirname $APK) - echo "APK=$APK" >> $GITHUB_ENV - - name: Upload Artifacts - uses: actions/upload-artifact@v4 - with: - name: APKs - path: ${{ env.APK }} diff --git a/nekobox-android/buildScript/lib/core/get_source.sh b/nekobox-android/buildScript/lib/core/get_source.sh index 416ef3ec24..d77947c76f 100755 --- a/nekobox-android/buildScript/lib/core/get_source.sh +++ b/nekobox-android/buildScript/lib/core/get_source.sh @@ -11,16 +11,25 @@ pushd .. ###### #### -if [ ! -d "sing-box-extra" ]; then - git clone --no-checkout https://github.com/MatsuriDayo/sing-box-extra.git + +if [ ! -d "sing-box" ]; then + git clone --no-checkout https://github.com/MatsuriDayo/sing-box.git fi -pushd sing-box-extra -git checkout "$COMMIT_SING_BOX_EXTRA" - -ENV_SING_BOX_EXTRA=1 -source $SRC_ROOT/buildScript/lib/core/get_source_env.sh -NO_ENV=1 ./libs/get_source.sh +pushd sing-box +git checkout "$COMMIT_SING_BOX" popd +#### + +if [ ! -d "libneko" ]; then + git clone --no-checkout https://github.com/MatsuriDayo/libneko.git +fi +pushd libneko +git checkout "$COMMIT_LIBNEKO" + +popd + +#### + popd diff --git a/nekobox-android/buildScript/lib/core/get_source_env.sh b/nekobox-android/buildScript/lib/core/get_source_env.sh index 951974279b..3ccd4a1fa8 100644 --- a/nekobox-android/buildScript/lib/core/get_source_env.sh +++ b/nekobox-android/buildScript/lib/core/get_source_env.sh @@ -1,8 +1,2 @@ -if [ ! -z $ENV_NB4A ]; then - export COMMIT_SING_BOX_EXTRA="73bce610791a373dad29cb80b8ffc05fe87e21ec" -fi - -if [ ! -z $ENV_SING_BOX_EXTRA ]; then - source libs/get_source_env.sh - # export COMMIT_SING_BOX="91495e813068294aae506fdd769437c41dd8d3a3" -fi +export COMMIT_SING_BOX="cf36758f11b7c144e1211801753cc91f06ff2906" +export COMMIT_LIBNEKO="1c47a3af71990a7b2192e03292b4d246c308ef0b" diff --git a/nekobox-android/libcore/box.go b/nekobox-android/libcore/box.go index 4b79dca526..b90b414831 100644 --- a/nekobox-android/libcore/box.go +++ b/nekobox-android/libcore/box.go @@ -10,16 +10,15 @@ import ( "runtime" "runtime/debug" "strings" - "time" - - "github.com/matsuridayo/sing-box-extra/boxbox" - _ "github.com/matsuridayo/sing-box-extra/distro/all" + "github.com/matsuridayo/libneko/neko_log" "github.com/matsuridayo/libneko/protect_server" "github.com/matsuridayo/libneko/speedtest" - "github.com/matsuridayo/sing-box-extra/boxapi" + "github.com/sagernet/sing-box/boxapi" + box "github.com/sagernet/sing-box" "github.com/sagernet/sing-box/common/conntrack" + "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing-box/outbound" "github.com/sagernet/sing/service/pause" @@ -29,7 +28,7 @@ var mainInstance *BoxInstance func VersionBox() string { version := []string{ - "sing-box-extra: " + boxbox.Version, + "sing-box: " + constant.Version, runtime.Version() + "@" + runtime.GOOS + "/" + runtime.GOARCH, } @@ -59,7 +58,7 @@ func ResetAllConnections(system bool) { } type BoxInstance struct { - *boxbox.Box + *box.Box cancel context.CancelFunc state int @@ -85,7 +84,7 @@ func NewSingBoxInstance(config string) (b *BoxInstance, err error) { sleepManager := pause.ManagerFromContext(ctx) //sleepManager := pause.NewDefaultManager(ctx) ctx = pause.ContextWithManager(ctx, sleepManager) - instance, err := boxbox.New(boxbox.Options{ + instance, err := box.New(box.Options{ Options: options, Context: ctx, PlatformInterface: boxPlatformInterfaceInstance, @@ -101,6 +100,8 @@ func NewSingBoxInstance(config string) (b *BoxInstance, err error) { pauseManager: sleepManager, } + b.SetLogWritter(neko_log.LogWriter) + // fuck your sing-box platformFormatter pf := instance.GetLogPlatformFormatter() pf.DisableColors = true @@ -142,7 +143,7 @@ func (b *BoxInstance) Close() (err error) { } // close box - b.CloseWithTimeout(b.cancel, time.Second*2, log.Println) + b.Close() return nil } @@ -191,9 +192,9 @@ func UrlTest(i *BoxInstance, link string, timeout int32) (latency int32, err err defer device.DeferPanicToError("box.UrlTest", func(err_ error) { err = err_ }) if i == nil { // test current - return speedtest.UrlTest(boxapi.CreateProxyHttpClient(mainInstance.Box), link, timeout) + return speedtest.UrlTest(boxapi.CreateProxyHttpClient(mainInstance.Box), link, timeout, speedtest.UrlTestStandard_RTT) } - return speedtest.UrlTest(boxapi.CreateProxyHttpClient(i.Box), link, timeout) + return speedtest.UrlTest(boxapi.CreateProxyHttpClient(i.Box), link, timeout, speedtest.UrlTestStandard_RTT) } var protectCloser io.Closer diff --git a/nekobox-android/libcore/dns_box.go b/nekobox-android/libcore/dns_box.go index 2e25c43725..c7d2447670 100644 --- a/nekobox-android/libcore/dns_box.go +++ b/nekobox-android/libcore/dns_box.go @@ -11,9 +11,7 @@ import ( dns "github.com/sagernet/sing-dns" "github.com/sagernet/sing/common" E "github.com/sagernet/sing/common/exceptions" - "github.com/sagernet/sing/common/logger" M "github.com/sagernet/sing/common/metadata" - N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing/common/task" mDNS "github.com/miekg/dns" @@ -27,9 +25,9 @@ type LocalDNSTransport interface { func RegisterLocalDNSTransport(transport LocalDNSTransport) { if transport == nil { - dns.RegisterTransport([]string{"local"}, dns.CreateLocalTransport) + dns.RegisterTransport([]string{"local"}, dns.CreateTransport) } else { - dns.RegisterTransport([]string{"local"}, func(name string, ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (dns.Transport, error) { + dns.RegisterTransport([]string{"local"}, func(options dns.TransportOptions) (dns.Transport, error) { return &platformLocalDNSTransport{ iif: transport, }, nil diff --git a/nekobox-android/libcore/go.mod b/nekobox-android/libcore/go.mod index ef6e8eba59..6c9b0b6ddf 100644 --- a/nekobox-android/libcore/go.mod +++ b/nekobox-android/libcore/go.mod @@ -4,12 +4,11 @@ go 1.20 require ( github.com/matsuridayo/libneko v1.0.0 // replaced - github.com/matsuridayo/sing-box-extra v1.0.0 // replaced - github.com/miekg/dns v1.1.57 - github.com/sagernet/sing v0.3.0 + github.com/miekg/dns v1.1.59 + github.com/sagernet/sing v0.4.1 github.com/sagernet/sing-box v1.0.0 // replaced - github.com/sagernet/sing-dns v0.1.12 - github.com/sagernet/sing-tun v0.2.0-rc.1 + github.com/sagernet/sing-dns v0.2.1-0.20240624030536-ca4a5f7afb65 + github.com/sagernet/sing-tun v0.3.2 github.com/ulikunitz/xz v0.5.11 golang.org/x/mobile v0.0.0-20231108233038-35478a0c49da ) @@ -23,18 +22,16 @@ require ( github.com/caddyserver/certmagic v0.20.0 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/cretz/bine v0.2.0 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gaukas/godicttls v0.0.4 // indirect - github.com/go-chi/chi/v5 v5.0.11 // indirect + github.com/go-chi/chi/v5 v5.0.12 // indirect github.com/go-chi/cors v1.2.1 // indirect github.com/go-chi/render v1.0.3 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/pool v0.2.1 // indirect - github.com/gofrs/uuid/v5 v5.0.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/gofrs/uuid/v5 v5.2.0 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect github.com/hashicorp/yamux v0.1.1 // indirect @@ -44,8 +41,8 @@ require ( github.com/klauspost/compress v1.17.4 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/libdns/alidns v1.0.3 // indirect - github.com/libdns/cloudflare v0.1.0 // indirect - github.com/libdns/libdns v0.2.1 // indirect + github.com/libdns/cloudflare v0.1.1 // indirect + github.com/libdns/libdns v0.2.2 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/mholt/acmez v1.2.0 // indirect github.com/onsi/ginkgo/v2 v2.9.7 // indirect @@ -53,15 +50,16 @@ require ( github.com/pierrec/lz4/v4 v4.1.14 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-20 v0.4.1 // indirect + github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 // indirect - github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e // indirect - github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect - github.com/sagernet/quic-go v0.40.1-beta.2 // indirect + github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f // indirect + github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba // indirect + github.com/sagernet/quic-go v0.45.1-beta.2 // indirect github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect - github.com/sagernet/sing-mux v0.1.8-rc.1 // indirect - github.com/sagernet/sing-quic v1.0.0 // indirect + github.com/sagernet/sing-mux v0.2.0 // indirect + github.com/sagernet/sing-quic v0.2.0-beta.12 // indirect github.com/sagernet/sing-shadowsocks v0.2.6 // indirect - github.com/sagernet/sing-shadowsocks2 v0.1.6-rc.1 // indirect + github.com/sagernet/sing-shadowsocks2 v0.2.0 // indirect github.com/sagernet/sing-shadowtls v0.1.4 // indirect github.com/sagernet/sing-vmess v0.1.8 // indirect github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect @@ -69,37 +67,35 @@ require ( github.com/sagernet/utls v1.5.4 // indirect github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 // indirect github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 // indirect - github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect github.com/zeebo/blake3 v0.2.3 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect + go.uber.org/zap v1.27.0 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.15.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/crypto v0.23.0 // indirect + golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect + golang.org/x/mod v0.18.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.16.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect - google.golang.org/grpc v1.60.1 // indirect - google.golang.org/protobuf v1.32.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.33.0 // indirect lukechampine.com/blake3 v1.2.1 // indirect ) replace github.com/matsuridayo/libneko => ../../libneko -replace github.com/matsuridayo/sing-box-extra => ../../sing-box-extra - replace github.com/sagernet/sing-box => ../../sing-box -replace github.com/sagernet/sing-quic => ../../sing-quic +// replace github.com/sagernet/sing-quic => ../../sing-quic // replace github.com/sagernet/sing => ../../sing diff --git a/nekobox-android/libcore/go.sum b/nekobox-android/libcore/go.sum index 5283246705..4d1e41565d 100644 --- a/nekobox-android/libcore/go.sum +++ b/nekobox-android/libcore/go.sum @@ -15,14 +15,12 @@ github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbe github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= -github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA= -github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= +github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= @@ -36,15 +34,12 @@ github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M= -github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/gofrs/uuid/v5 v5.2.0 h1:qw1GMx6/y8vhVsx626ImfKMuS5CvJmhIKKtuyvfajMM= +github.com/gofrs/uuid/v5 v5.2.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= @@ -63,17 +58,17 @@ github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/q github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/libdns/alidns v1.0.3 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ= github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE= -github.com/libdns/cloudflare v0.1.0 h1:93WkJaGaiXCe353LHEP36kAWCUw0YjFqwhkBkU2/iic= -github.com/libdns/cloudflare v0.1.0/go.mod h1:a44IP6J1YH6nvcNl1PverfJviADgXUnsozR3a7vBKN8= +github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054= +github.com/libdns/cloudflare v0.1.1/go.mod h1:9VK91idpOjg6v7/WbjkEW49bSCxj00ALesIFDhJ8PBU= github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= -github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis= -github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= +github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s= +github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= -github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= -github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= +github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs= +github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk= github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= @@ -90,31 +85,35 @@ github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1 github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs= github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0= +github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM= github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 h1:YbmpqPQEMdlk9oFSKYWRqVuu9qzNiOayIonKmv1gCXY= github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k= -github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e h1:DOkjByVeAR56dkszjnMZke4wr7yM/1xHaJF3G9olkEE= -github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e/go.mod h1:fLxq/gtp0qzkaEwywlRRiGmjOK5ES/xUzyIKIFP2Asw= -github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE= -github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= -github.com/sagernet/quic-go v0.40.1-beta.2 h1:USRwm36XuAFdcrmv4vDRD+YUOO08DfvLNruXThrVHZU= -github.com/sagernet/quic-go v0.40.1-beta.2/go.mod h1:CcKTpzTAISxrM4PA5M20/wYuz9Tj6Tx4DwGbNl9UQrU= +github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f h1:NkhuupzH5ch7b/Y/6ZHJWrnNLoiNnSJaow6DPb8VW2I= +github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f/go.mod h1:KXmw+ouSJNOsuRpg4wgwwCQuunrGz4yoAqQjsLjc6N0= +github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba h1:EY5AS7CCtfmARNv2zXUOrsEMPFDGYxaw65JzA2p51Vk= +github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= +github.com/sagernet/quic-go v0.45.1-beta.2 h1:zkEeCbhdFFkrxKcuIRBtXNKci/1t2J/39QSG/sPvlmc= +github.com/sagernet/quic-go v0.45.1-beta.2/go.mod h1:+N3FqM9DAzOWfe64uxXuBejVJwX7DeW7BslzLO6N/xI= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= -github.com/sagernet/sing v0.3.0 h1:PIDVFZHnQAAYRL1UYqNM+0k5s8f/tb1lUW6UDcQiOc8= -github.com/sagernet/sing v0.3.0/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g= -github.com/sagernet/sing-dns v0.1.12 h1:1HqZ+ln+Rezx/aJMStaS0d7oPeX2EobSV1NT537kyj4= -github.com/sagernet/sing-dns v0.1.12/go.mod h1:rx/DTOisneQpCgNQ4jbFU/JNEtnz0lYcHXenlVzpjEU= -github.com/sagernet/sing-mux v0.1.8-rc.1 h1:5dsZgWmNr9W6JzQj4fb3xX2pMP0OyJH6kVtlqc2kFKA= -github.com/sagernet/sing-mux v0.1.8-rc.1/go.mod h1:KK5zCbNujj5kn36G+wLFROOXyJhaaXLyaZWY2w7kBNQ= +github.com/sagernet/sing v0.4.1 h1:zVlpE+7k7AFoC2pv6ReqLf0PIHjihL/jsBl5k05PQFk= +github.com/sagernet/sing v0.4.1/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls= +github.com/sagernet/sing-dns v0.2.1-0.20240624030536-ca4a5f7afb65 h1:lcCe7E1csuyUA3RCvpFcIYOy6FIifDthKaCrUjLG4xA= +github.com/sagernet/sing-dns v0.2.1-0.20240624030536-ca4a5f7afb65/go.mod h1:dArgyPZmK8+zDBVRMjV3r12zHgnTara0ahrWwSe/eQE= +github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo= +github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ= +github.com/sagernet/sing-quic v0.2.0-beta.12 h1:BhvA5mmrDFEyDUQB5eeu+9UhF+ieyuNJ5Rsb0dAG3QY= +github.com/sagernet/sing-quic v0.2.0-beta.12/go.mod h1:YVpLfVi8BvYM7NMrjmnvcRm3E8iMETf1gFQmTQDN9jI= github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s= github.com/sagernet/sing-shadowsocks v0.2.6/go.mod h1:j2YZBIpWIuElPFL/5sJAj470bcn/3QQ5lxZUNKLDNAM= -github.com/sagernet/sing-shadowsocks2 v0.1.6-rc.1 h1:E+8OyyVg0YfFNUmxMx9jYBEhjLYMQSAMzJrUmE934bo= -github.com/sagernet/sing-shadowsocks2 v0.1.6-rc.1/go.mod h1:wFkU7sKxyZADS/idtJqBhtc+QBf5iwX9nZO7ymcn6MM= +github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg= +github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k= github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4= -github.com/sagernet/sing-tun v0.2.0-rc.1 h1:CnlxRgrJKAMKYNuJOcKie6TjRz8wremEq1wndLup7cA= -github.com/sagernet/sing-tun v0.2.0-rc.1/go.mod h1:hpbL9jNAbYT9G2EHCpCXVIgSrM/2Wgnrm/Hped+8zdY= +github.com/sagernet/sing-tun v0.3.2 h1:z0bLUT/YXH9RrJS9DsIpB0Bb9afl2hVJOmHd0zA3HJY= +github.com/sagernet/sing-tun v0.3.2/go.mod h1:DxLIyhjWU/HwGYoX0vNGg2c5QgTQIakphU1MuERR5tQ= github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc= github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= @@ -127,8 +126,6 @@ github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 h1:R0OMYASco github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8/go.mod h1:K4J7/npM+VAMUeUmTa2JaA02JmyheP0GpRBOUvn3ecc= github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc= github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA= -github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg= -github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -137,7 +134,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA= github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= @@ -150,28 +147,29 @@ github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg= github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ= github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM= -golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/mobile v0.0.0-20231108233038-35478a0c49da h1:gS9sVMAeHM+gVBmM9bTM6vUi/NHv58O3QzJ3vjjN84M= golang.org/x/mobile v0.0.0-20231108233038-35478a0c49da/go.mod h1:IEceR0jfVklLJXrbUe90rfdAFAYDW0SQwKl4qvO1GBQ= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -181,30 +179,27 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= -golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/nekobox-android/libcore/nb4a.go b/nekobox-android/libcore/nb4a.go index 97ae290d91..1d994b7054 100644 --- a/nekobox-android/libcore/nb4a.go +++ b/nekobox-android/libcore/nb4a.go @@ -12,8 +12,7 @@ import ( "github.com/matsuridayo/libneko/neko_common" "github.com/matsuridayo/libneko/neko_log" - "github.com/matsuridayo/sing-box-extra/boxmain" - "github.com/sagernet/sing-box/nekoutils" + boxmain "github.com/sagernet/sing-box/cmd/sing-box" ) //go:linkname resourcePaths github.com/sagernet/sing-box/constant.resourcePaths @@ -58,10 +57,10 @@ func InitCore(process, cachePath, internalAssets, externalAssets string, neko_log.LogWriterDisable = !logEnable neko_log.TruncateOnStart = isBgProcess neko_log.SetupLog(int(maxLogSizeKb)*1024, filepath.Join(cachePath, "neko.log")) - boxmain.DisableColor() + boxmain.SetDisableColor(true) // nekoutils - nekoutils.Selector_OnProxySelected = intfNB4A.Selector_OnProxySelected + // nekoutils.Selector_OnProxySelected = intfNB4A.Selector_OnProxySelected // Set up some component go func() { diff --git a/nekobox-android/libcore/platform_box.go b/nekobox-android/libcore/platform_box.go index 65068aefff..11ae9217ac 100644 --- a/nekobox-android/libcore/platform_box.go +++ b/nekobox-android/libcore/platform_box.go @@ -90,10 +90,14 @@ func (w *boxPlatformInterfaceWrapper) UsePlatformInterfaceGetter() bool { return false } -func (w *boxPlatformInterfaceWrapper) Interfaces() ([]platform.NetworkInterface, error) { +func (w *boxPlatformInterfaceWrapper) Interfaces() ([]control.Interface, error) { return nil, errors.New("wtf") } +func (w *boxPlatformInterfaceWrapper) IncludeAllNetworks() bool { + return false +} + // Android not using func (w *boxPlatformInterfaceWrapper) UnderNetworkExtension() bool { diff --git a/nekoray/.github/workflows/build-qv2ray-cmake.yml b/nekoray/.github/workflows/build-nekoray-cmake.yml similarity index 98% rename from nekoray/.github/workflows/build-qv2ray-cmake.yml rename to nekoray/.github/workflows/build-nekoray-cmake.yml index 784f8b41c2..1a3438572d 100644 --- a/nekoray/.github/workflows/build-qv2ray-cmake.yml +++ b/nekoray/.github/workflows/build-nekoray-cmake.yml @@ -51,7 +51,7 @@ jobs: if: steps.cache-common.outputs.cache-hit != 'true' run: tar czvf artifacts.tgz ./deployment - name: Uploading Artifact - uses: actions/upload-artifact@master + uses: actions/upload-artifact@v3 with: name: NekoRay-${{ github.sha }}-Common-${{ matrix.cross_os }}-${{ matrix.cross_arch }} path: artifacts.tgz @@ -141,7 +141,7 @@ jobs: shell: bash run: tar czvf artifacts.tgz ./deployment - name: Uploading Artifact - uses: actions/upload-artifact@master + uses: actions/upload-artifact@v3 with: name: NekoRay-${{ github.sha }}-${{ matrix.platform }}-${{ matrix.arch }}-Qt${{ matrix.qt_version }} path: artifacts.tgz @@ -205,7 +205,7 @@ jobs: rm -rf public_res rm -rf *.pdb - name: Uploading Artifact - uses: actions/upload-artifact@master + uses: actions/upload-artifact@v3 with: name: Deployment-${{ github.sha }} path: deployment diff --git a/nekoray/CMakeLists.txt b/nekoray/CMakeLists.txt index 7b03830d80..d8673d4a19 100644 --- a/nekoray/CMakeLists.txt +++ b/nekoray/CMakeLists.txt @@ -267,6 +267,10 @@ set_property(TARGET nekoray PROPERTY AUTOUIC ON) set_property(TARGET nekoray PROPERTY AUTOMOC ON) set_property(TARGET nekoray PROPERTY AUTORCC ON) +set_target_properties(nekoray PROPERTIES + WIN32_EXECUTABLE TRUE +) + # Target Source Translations set(TS_FILES diff --git a/nekoray/db/ConfigBuilder.cpp b/nekoray/db/ConfigBuilder.cpp index 77c27c2a91..aeba840657 100644 --- a/nekoray/db/ConfigBuilder.cpp +++ b/nekoray/db/ConfigBuilder.cpp @@ -7,8 +7,7 @@ #include #include -#define BOX_UNDERLYING_DNS dataStore->core_box_underlying_dns.isEmpty() ? "underlying://0.0.0.0" : dataStore->core_box_underlying_dns -#define BOX_UNDERLYING_DNS_EXPORT dataStore->core_box_underlying_dns.isEmpty() ? (status->forExport ? "local" : "underlying://0.0.0.0") : dataStore->core_box_underlying_dns +#define BOX_UNDERLYING_DNS dataStore->core_box_underlying_dns.isEmpty() ? "local" : dataStore->core_box_underlying_dns namespace NekoGui { @@ -847,7 +846,6 @@ namespace NekoGui { // Direct auto directDNSAddress = dataStore->routing->direct_dns; - if (directDNSAddress == "localhost") directDNSAddress = BOX_UNDERLYING_DNS_EXPORT; if (!status->forTest) { QJsonObject directObj{ {"tag", "dns-direct"}, @@ -883,10 +881,10 @@ namespace NekoGui { }; } - // Underlying 100% Working DNS + // Underlying 100% Working DNS ? dnsServers += QJsonObject{ {"tag", "dns-local"}, - {"address", BOX_UNDERLYING_DNS_EXPORT}, + {"address", BOX_UNDERLYING_DNS}, {"detour", "direct"}, }; diff --git a/nekoray/go/cmd/nekobox_core/core_box.go b/nekoray/go/cmd/nekobox_core/core_box.go index ff31f96f4d..4e5d253eda 100644 --- a/nekoray/go/cmd/nekobox_core/core_box.go +++ b/nekoray/go/cmd/nekobox_core/core_box.go @@ -7,16 +7,16 @@ import ( "github.com/matsuridayo/libneko/neko_common" "github.com/matsuridayo/libneko/neko_log" - "github.com/matsuridayo/sing-box-extra/boxapi" - "github.com/matsuridayo/sing-box-extra/boxbox" - "github.com/matsuridayo/sing-box-extra/boxmain" + box "github.com/sagernet/sing-box" + "github.com/sagernet/sing-box/boxapi" + boxmain "github.com/sagernet/sing-box/cmd/sing-box" ) -var instance *boxbox.Box +var instance *box.Box var instance_cancel context.CancelFunc func setupCore() { - boxmain.DisableColor() + boxmain.SetDisableColor(true) // neko_log.SetupLog(50*1024, "./neko.log") // @@ -24,7 +24,7 @@ func setupCore() { return instance } neko_common.DialContext = func(ctx context.Context, specifiedInstance interface{}, network, addr string) (net.Conn, error) { - if i, ok := specifiedInstance.(*boxbox.Box); ok { + if i, ok := specifiedInstance.(*box.Box); ok { return boxapi.DialContext(ctx, i, network, addr) } if instance != nil { @@ -33,7 +33,7 @@ func setupCore() { return neko_common.DialContextSystem(ctx, network, addr) } neko_common.DialUDP = func(ctx context.Context, specifiedInstance interface{}) (net.PacketConn, error) { - if i, ok := specifiedInstance.(*boxbox.Box); ok { + if i, ok := specifiedInstance.(*box.Box); ok { return boxapi.DialUDP(ctx, i) } if instance != nil { @@ -42,7 +42,7 @@ func setupCore() { return neko_common.DialUDPSystem(ctx) } neko_common.CreateProxyHttpClient = func(specifiedInstance interface{}) *http.Client { - if i, ok := specifiedInstance.(*boxbox.Box); ok { + if i, ok := specifiedInstance.(*box.Box); ok { return boxapi.CreateProxyHttpClient(i) } return boxapi.CreateProxyHttpClient(instance) diff --git a/nekoray/go/cmd/nekobox_core/go.mod b/nekoray/go/cmd/nekobox_core/go.mod index d101edef6e..7afab52083 100644 --- a/nekoray/go/cmd/nekobox_core/go.mod +++ b/nekoray/go/cmd/nekobox_core/go.mod @@ -4,7 +4,6 @@ go 1.19 require ( github.com/matsuridayo/libneko v1.0.0 // replaced - github.com/matsuridayo/sing-box-extra v1.0.0 // replaced github.com/sagernet/sing-box v1.0.0 // replaced // github.com/sagernet/sing-dns v1.0.0 // indirect; replaced grpc_server v1.0.0 @@ -14,82 +13,82 @@ require ( berty.tech/go-libtor v1.0.385 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/ajg/form v1.5.1 // indirect - github.com/andybalholm/brotli v1.0.5 // indirect - github.com/caddyserver/certmagic v0.19.2 // indirect - github.com/cloudflare/circl v1.3.6 // indirect + github.com/andybalholm/brotli v1.0.6 // indirect + github.com/caddyserver/certmagic v0.20.0 // indirect + github.com/cloudflare/circl v1.3.7 // indirect github.com/cretz/bine v0.2.0 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-chi/chi/v5 v5.0.10 // indirect + github.com/gaukas/godicttls v0.0.4 // indirect + github.com/go-chi/chi/v5 v5.0.12 // indirect github.com/go-chi/cors v1.2.1 // indirect github.com/go-chi/render v1.0.3 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect - github.com/gofrs/uuid/v5 v5.0.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/gofrs/uuid/v5 v5.2.0 // indirect github.com/google/btree v1.1.2 // indirect - github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect + github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c // indirect + github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 // indirect github.com/josharian/native v1.1.0 // indirect - github.com/klauspost/compress v1.15.15 // indirect + github.com/klauspost/compress v1.17.4 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/libdns/alidns v1.0.3 // indirect - github.com/libdns/cloudflare v0.1.0 // indirect - github.com/libdns/libdns v0.2.1 // indirect + github.com/libdns/cloudflare v0.1.1 // indirect + github.com/libdns/libdns v0.2.2 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/mholt/acmez v1.2.0 // indirect - github.com/miekg/dns v1.1.56 // indirect - github.com/onsi/ginkgo/v2 v2.9.5 // indirect + github.com/miekg/dns v1.1.59 // indirect + github.com/onsi/ginkgo/v2 v2.9.7 // indirect github.com/ooni/go-libtor v1.1.8 // indirect github.com/oschwald/maxminddb-golang v1.12.0 // indirect github.com/pierrec/lz4/v4 v4.1.14 // indirect github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-20 v0.3.4 // indirect + github.com/quic-go/qtls-go1-20 v0.4.1 // indirect github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect - github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a // indirect - github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect - github.com/sagernet/gvisor v0.0.0-20230930141345-5fef6f2e17ab // indirect - github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect - github.com/sagernet/quic-go v0.0.0-20231008035953-32727fef9460 // indirect + github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 // indirect + github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f // indirect + github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba // indirect + github.com/sagernet/quic-go v0.45.1-beta.2 // indirect github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect - github.com/sagernet/sing v0.2.17 // indirect - github.com/sagernet/sing-dns v0.1.10 // indirect - github.com/sagernet/sing-mux v0.1.4 // indirect - github.com/sagernet/sing-quic v1.0.0 // indirect - github.com/sagernet/sing-shadowsocks v0.2.5 // indirect - github.com/sagernet/sing-shadowsocks2 v0.1.4 // indirect + github.com/sagernet/sing v0.4.1 // indirect + github.com/sagernet/sing-dns v0.2.1-0.20240624030536-ca4a5f7afb65 // indirect + github.com/sagernet/sing-mux v0.2.0 // indirect + github.com/sagernet/sing-quic v0.2.0-beta.12 // indirect + github.com/sagernet/sing-shadowsocks v0.2.6 // indirect + github.com/sagernet/sing-shadowsocks2 v0.2.0 // indirect github.com/sagernet/sing-shadowtls v0.1.4 // indirect - github.com/sagernet/sing-tun v0.1.20-0.20231116102114-958d6a25a41d // indirect + github.com/sagernet/sing-tun v0.3.2 // indirect github.com/sagernet/sing-vmess v0.1.8 // indirect - github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect - github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 // indirect - github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 // indirect - github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e // indirect - github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f // indirect - github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect + github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect + github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6 // indirect + github.com/sagernet/utls v1.5.4 // indirect + github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 // indirect + github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 // indirect github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect github.com/zeebo/blake3 v0.2.3 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - go4.org/netipx v0.0.0-20230824141953-6213f710f925 // indirect - golang.org/x/crypto v0.15.0 // indirect - golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/mod v0.13.0 // indirect - golang.org/x/net v0.18.0 // indirect - golang.org/x/sys v0.14.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.14.0 // indirect + go.uber.org/zap v1.27.0 // indirect + go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect + golang.org/x/crypto v0.23.0 // indirect + golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect + golang.org/x/mod v0.18.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/grpc v1.63.2 // indirect + google.golang.org/protobuf v1.33.0 // indirect lukechampine.com/blake3 v1.2.1 // indirect ) @@ -97,11 +96,9 @@ replace grpc_server => ../../grpc_server replace github.com/matsuridayo/libneko => ../../../../libneko -replace github.com/matsuridayo/sing-box-extra => ../../../../sing-box-extra - replace github.com/sagernet/sing-box => ../../../../sing-box -replace github.com/sagernet/sing-quic => ../../../../sing-quic +// replace github.com/sagernet/sing-quic => ../../../../sing-quic // replace github.com/sagernet/sing => ../../../../sing diff --git a/nekoray/go/cmd/nekobox_core/go.sum b/nekoray/go/cmd/nekobox_core/go.sum index 6045e45de0..0c1f7692ec 100644 --- a/nekoray/go/cmd/nekobox_core/go.sum +++ b/nekoray/go/cmd/nekobox_core/go.sum @@ -2,23 +2,20 @@ berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw= berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw= cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= -github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/caddyserver/certmagic v0.19.2 h1:HZd1AKLx4592MalEGQS39DKs2ZOAJCEM/xYPMQ2/ui0= -github.com/caddyserver/certmagic v0.19.2/go.mod h1:fsL01NomQ6N+kE2j37ZCnig2MFosG+MIO4ztnmG/zz8= +github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= +github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc= +github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.3.6 h1:/xbKIqSHbZXHwkhbrhrt2YOHIwYJlXH94E3tI/gDlUg= -github.com/cloudflare/circl v1.3.6/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw= @@ -27,16 +24,16 @@ github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbe github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= -github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= +github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= +github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= +github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= @@ -49,40 +46,40 @@ github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= -github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M= -github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gofrs/uuid/v5 v5.2.0 h1:qw1GMx6/y8vhVsx626ImfKMuS5CvJmhIKKtuyvfajMM= +github.com/gofrs/uuid/v5 v5.2.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= +github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c h1:PgxFEySCI41sH0mB7/2XswdXbUykQsRUGod8Rn+NubM= -github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI= +github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA= +github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI= github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -90,20 +87,20 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/libdns/alidns v1.0.3 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ= github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE= -github.com/libdns/cloudflare v0.1.0 h1:93WkJaGaiXCe353LHEP36kAWCUw0YjFqwhkBkU2/iic= -github.com/libdns/cloudflare v0.1.0/go.mod h1:a44IP6J1YH6nvcNl1PverfJviADgXUnsozR3a7vBKN8= +github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054= +github.com/libdns/cloudflare v0.1.1/go.mod h1:9VK91idpOjg6v7/WbjkEW49bSCxj00ALesIFDhJ8PBU= github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= -github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis= -github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= +github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s= +github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= -github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= -github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= -github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= -github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= -github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= +github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs= +github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk= +github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= +github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= +github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= github.com/ooni/go-libtor v1.1.8 h1:Wo3V3DVTxl5vZdxtQakqYP+DAHx7pPtAFSl1bnAa08w= github.com/ooni/go-libtor v1.1.8/go.mod h1:q1YyLwRD9GeMyeerVvwc0vJ2YgwDLTp2bdVcrh/JXyI= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -117,53 +114,50 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg= -github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= +github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs= +github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0= github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM= -github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a h1:wZHruBxZCsQLXHAozWpnJBL3wJ/XufDpz0qKtgpSnA4= -github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a/go.mod h1:dNV1ZP9y3qx5ltULeKaQZTZWTLHflgW5DES+Ses7cMI= -github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA= -github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms= -github.com/sagernet/gvisor v0.0.0-20230930141345-5fef6f2e17ab h1:u+xQoi/Yc6bNUvTfrDD6HhGRybn2lzrhf5vmS+wb4Ho= -github.com/sagernet/gvisor v0.0.0-20230930141345-5fef6f2e17ab/go.mod h1:3akUhSHSVtLuJaYcW5JPepUraBOW06Ibz2HKwaK5rOk= -github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE= -github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= -github.com/sagernet/quic-go v0.0.0-20231008035953-32727fef9460 h1:dAe4OIJAtE0nHOzTHhAReQteh3+sa63rvXbuIpbeOTY= -github.com/sagernet/quic-go v0.0.0-20231008035953-32727fef9460/go.mod h1:uJGpmJCOcMQqMlHKc3P1Vz6uygmpz4bPeVIoOhdVQnM= +github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 h1:YbmpqPQEMdlk9oFSKYWRqVuu9qzNiOayIonKmv1gCXY= +github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k= +github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f h1:NkhuupzH5ch7b/Y/6ZHJWrnNLoiNnSJaow6DPb8VW2I= +github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f/go.mod h1:KXmw+ouSJNOsuRpg4wgwwCQuunrGz4yoAqQjsLjc6N0= +github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba h1:EY5AS7CCtfmARNv2zXUOrsEMPFDGYxaw65JzA2p51Vk= +github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= +github.com/sagernet/quic-go v0.45.1-beta.2 h1:zkEeCbhdFFkrxKcuIRBtXNKci/1t2J/39QSG/sPvlmc= +github.com/sagernet/quic-go v0.45.1-beta.2/go.mod h1:+N3FqM9DAzOWfe64uxXuBejVJwX7DeW7BslzLO6N/xI= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= -github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= -github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= -github.com/sagernet/sing v0.2.17 h1:vMPKb3MV0Aa5ws4dCJkRI8XEjrsUcDn810czd0FwmzI= -github.com/sagernet/sing v0.2.17/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= -github.com/sagernet/sing-dns v0.1.10 h1:iIU7nRBlUYj+fF2TaktGIvRiTFFrHwSMedLQsvlTZCI= -github.com/sagernet/sing-dns v0.1.10/go.mod h1:vtUimtf7Nq9EdvD5WTpfCr69KL1M7bcgOVKiYBiAY/c= -github.com/sagernet/sing-mux v0.1.4 h1:BPNPOQr6HkXG3iY/BrfvUKUl+A7gYsGKVSxvoR3PO50= -github.com/sagernet/sing-mux v0.1.4/go.mod h1:dKvcu/sb3fZ88uGv9vzAqUej6J4W+pHu5GqjRuFwAWs= -github.com/sagernet/sing-shadowsocks v0.2.5 h1:qxIttos4xu6ii7MTVJYA8EFQR7Q3KG6xMqmLJIFtBaY= -github.com/sagernet/sing-shadowsocks v0.2.5/go.mod h1:MGWGkcU2xW2G2mfArT9/QqpVLOGU+dBaahZCtPHdt7A= -github.com/sagernet/sing-shadowsocks2 v0.1.4 h1:vht2M8t3m5DTgXR2j24KbYOygG5aOp+MUhpQnAux728= -github.com/sagernet/sing-shadowsocks2 v0.1.4/go.mod h1:Mgdee99NxxNd5Zld3ixIs18yVs4x2dI2VTDDE1N14Wc= +github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= +github.com/sagernet/sing v0.4.1 h1:zVlpE+7k7AFoC2pv6ReqLf0PIHjihL/jsBl5k05PQFk= +github.com/sagernet/sing v0.4.1/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls= +github.com/sagernet/sing-dns v0.2.1-0.20240624030536-ca4a5f7afb65 h1:lcCe7E1csuyUA3RCvpFcIYOy6FIifDthKaCrUjLG4xA= +github.com/sagernet/sing-dns v0.2.1-0.20240624030536-ca4a5f7afb65/go.mod h1:dArgyPZmK8+zDBVRMjV3r12zHgnTara0ahrWwSe/eQE= +github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo= +github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ= +github.com/sagernet/sing-quic v0.2.0-beta.12 h1:BhvA5mmrDFEyDUQB5eeu+9UhF+ieyuNJ5Rsb0dAG3QY= +github.com/sagernet/sing-quic v0.2.0-beta.12/go.mod h1:YVpLfVi8BvYM7NMrjmnvcRm3E8iMETf1gFQmTQDN9jI= +github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s= +github.com/sagernet/sing-shadowsocks v0.2.6/go.mod h1:j2YZBIpWIuElPFL/5sJAj470bcn/3QQ5lxZUNKLDNAM= +github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg= +github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k= github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4= -github.com/sagernet/sing-tun v0.1.20-0.20231116102114-958d6a25a41d h1:c0M01hMieuYwOMk+xzgudn0jNjPLUR15I/QnXk0eLkc= -github.com/sagernet/sing-tun v0.1.20-0.20231116102114-958d6a25a41d/go.mod h1:6kkPL/u9tWcLFfu55VbwMDnO++17cUihSmImkZjdZro= +github.com/sagernet/sing-tun v0.3.2 h1:z0bLUT/YXH9RrJS9DsIpB0Bb9afl2hVJOmHd0zA3HJY= +github.com/sagernet/sing-tun v0.3.2/go.mod h1:DxLIyhjWU/HwGYoX0vNGg2c5QgTQIakphU1MuERR5tQ= github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc= github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA= -github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as= -github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0= -github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 h1:Px+hN4Vzgx+iCGVnWH5A8eR7JhNnIV3rGQmBxA7cw6Q= -github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6/go.mod h1:zovq6vTvEM6ECiqE3Eeb9rpIylPpamPcmrJ9tv0Bt0M= -github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 h1:kDUqhc9Vsk5HJuhfIATJ8oQwBmpOZJuozQG7Vk88lL4= -github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2/go.mod h1:JKQMZq/O2qnZjdrt+B57olmfgEmLtY9iiSIEYtWvoSM= -github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+VpWamge6o56j2RWk4omF6uLKKxMmcWvs= -github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e/go.mod h1:45TUl8+gH4SIKr4ykREbxKWTxkDlSzFENzctB1dVRRY= -github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f h1:Kvo8w8Y9lzFGB/7z09MJ3TR99TFtfI/IuY87Ygcycho= -github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f/go.mod h1:mySs0abhpc/gLlvhoq7HP1RzOaRmIXVeZGCh++zoApk= -github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg= -github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s= +github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= +github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo= +github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6 h1:z3SJQhVyU63FT26Wn/UByW6b7q8QKB0ZkPqsyqcz2PI= +github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6/go.mod h1:73xRZuxwkFk4aiLw28hG8W6o9cr2UPrGL9pdY2UTbvY= +github.com/sagernet/utls v1.5.4 h1:KmsEGbB2dKUtCNC+44NwAdNAqnqQ6GA4pTO0Yik56co= +github.com/sagernet/utls v1.5.4/go.mod h1:CTGxPWExIloRipK3XFpYv0OVyhO8kk3XCGW/ieyTh1s= +github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 h1:R0OMYAScomNAVpTfbHFpxqJpvwuhxSRi+g6z7gZhABs= +github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8/go.mod h1:K4J7/npM+VAMUeUmTa2JaA02JmyheP0GpRBOUvn3ecc= +github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc= +github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= @@ -176,7 +170,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA= github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= @@ -190,32 +184,32 @@ github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvv github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -go4.org/netipx v0.0.0-20230824141953-6213f710f925 h1:eeQDDVKFkx0g4Hyy8pHgmZaK0EqB4SD6rvKbUdN3ziQ= -go4.org/netipx v0.0.0-20230824141953-6213f710f925/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= +go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= -golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -226,41 +220,42 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= +golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -269,8 +264,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -279,23 +274,21 @@ golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvY golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/nekoray/go/cmd/nekobox_core/grpc_box.go b/nekoray/go/cmd/nekobox_core/grpc_box.go index 44f3623d28..aabc0f593e 100644 --- a/nekoray/go/cmd/nekobox_core/grpc_box.go +++ b/nekoray/go/cmd/nekobox_core/grpc_box.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "time" "grpc_server" "grpc_server/gen" @@ -12,9 +11,9 @@ import ( "github.com/matsuridayo/libneko/neko_common" "github.com/matsuridayo/libneko/neko_log" "github.com/matsuridayo/libneko/speedtest" - "github.com/matsuridayo/sing-box-extra/boxapi" - "github.com/matsuridayo/sing-box-extra/boxbox" - "github.com/matsuridayo/sing-box-extra/boxmain" + box "github.com/sagernet/sing-box" + "github.com/sagernet/sing-box/boxapi" + boxmain "github.com/sagernet/sing-box/cmd/sing-box" "log" @@ -76,7 +75,8 @@ func (s *server) Stop(ctx context.Context, in *gen.EmptyReq) (out *gen.ErrorResp return } - instance.CloseWithTimeout(instance_cancel, time.Second*2, log.Println) + instance_cancel() + instance.Close() instance = nil @@ -94,7 +94,7 @@ func (s *server) Test(ctx context.Context, in *gen.TestReq) (out *gen.TestResp, }() if in.Mode == gen.TestMode_UrlTest { - var i *boxbox.Box + var i *box.Box var cancel context.CancelFunc if in.Config != nil { // Test instance @@ -114,7 +114,7 @@ func (s *server) Test(ctx context.Context, in *gen.TestReq) (out *gen.TestResp, } } // Latency - out.Ms, err = speedtest.UrlTest(boxapi.CreateProxyHttpClient(i), in.Url, in.Timeout) + out.Ms, err = speedtest.UrlTest(boxapi.CreateProxyHttpClient(i), in.Url, in.Timeout, speedtest.UrlTestStandard_RTT) } else if in.Mode == gen.TestMode_TcpPing { out.Ms, err = speedtest.TcpPing(in.Address, in.Timeout) } else if in.Mode == gen.TestMode_FullTest { diff --git a/nekoray/go/cmd/nekobox_core/main.go b/nekoray/go/cmd/nekobox_core/main.go index a53f33af07..d2349520f8 100644 --- a/nekoray/go/cmd/nekobox_core/main.go +++ b/nekoray/go/cmd/nekobox_core/main.go @@ -8,13 +8,12 @@ import ( "grpc_server" "github.com/matsuridayo/libneko/neko_common" - "github.com/matsuridayo/sing-box-extra/boxbox" - "github.com/matsuridayo/sing-box-extra/boxmain" - _ "github.com/matsuridayo/sing-box-extra/distro/all" + boxmain "github.com/sagernet/sing-box/cmd/sing-box" + "github.com/sagernet/sing-box/constant" ) func main() { - fmt.Println("sing-box-extra:", boxbox.Version, "NekoBox:", neko_common.Version_neko) + fmt.Println("sing-box:", constant.Version, "NekoBox:", neko_common.Version_neko) fmt.Println() // nekobox_core diff --git a/nekoray/go/grpc_server/fulltest.go b/nekoray/go/grpc_server/fulltest.go index 9bf70eda9b..f888ece5d8 100644 --- a/nekoray/go/grpc_server/fulltest.go +++ b/nekoray/go/grpc_server/fulltest.go @@ -43,7 +43,7 @@ func DoFullTest(ctx context.Context, in *gen.TestReq, instance interface{}) (out // Latency var latency string if in.FullLatency { - t, _ := speedtest.UrlTest(httpClient, in.Url, in.Timeout) + t, _ := speedtest.UrlTest(httpClient, in.Url, in.Timeout, speedtest.UrlTestStandard_RTT) out.Ms = t if t > 0 { latency = fmt.Sprint(t, "ms") diff --git a/nekoray/libs/get_source.sh b/nekoray/libs/get_source.sh index a449f8e56b..9564bd615f 100755 --- a/nekoray/libs/get_source.sh +++ b/nekoray/libs/get_source.sh @@ -7,17 +7,25 @@ source libs/get_source_env.sh pushd .. #### -if [ ! -d "sing-box-extra" ]; then - git clone --no-checkout https://github.com/MatsuriDayo/sing-box-extra.git -fi -pushd sing-box-extra -git checkout "$COMMIT_SING_BOX_EXTRA" -ENV_SING_BOX_EXTRA=1 -source $SRC_ROOT/libs/get_source_env.sh -NO_ENV=1 ./libs/get_source.sh +if [ ! -d "sing-box" ]; then + git clone --no-checkout https://github.com/MatsuriDayo/sing-box.git +fi +pushd sing-box +git checkout "$COMMIT_SING_BOX" popd + +#### + +if [ ! -d "libneko" ]; then + git clone --no-checkout https://github.com/MatsuriDayo/libneko.git +fi +pushd libneko +git checkout "$COMMIT_LIBNEKO" + +popd + #### popd diff --git a/nekoray/libs/get_source_env.sh b/nekoray/libs/get_source_env.sh index c27535eee7..3ccd4a1fa8 100644 --- a/nekoray/libs/get_source_env.sh +++ b/nekoray/libs/get_source_env.sh @@ -1,8 +1,2 @@ -if [ ! -z $ENV_NEKORAY ]; then - export COMMIT_SING_BOX_EXTRA="d31d6da26a51a929349e0d75fd89dccbe20d1268" -fi - -if [ ! -z $ENV_SING_BOX_EXTRA ]; then - source libs/get_source_env.sh -# export COMMIT_LIBNEKO="a26f0dbb1467bd181f76e2560e956633d9637e9d" -fi +export COMMIT_SING_BOX="cf36758f11b7c144e1211801753cc91f06ff2906" +export COMMIT_LIBNEKO="1c47a3af71990a7b2192e03292b4d246c308ef0b" diff --git a/nekoray/main/NekoGui_DataStore.hpp b/nekoray/main/NekoGui_DataStore.hpp index 14ce720038..21ceffc5f2 100644 --- a/nekoray/main/NekoGui_DataStore.hpp +++ b/nekoray/main/NekoGui_DataStore.hpp @@ -14,9 +14,9 @@ namespace NekoGui { QString custom = "{\"rules\": []}"; // DNS - QString remote_dns = "https://8.8.8.8/dns-query"; + QString remote_dns = "https://dns.google/dns-query"; QString remote_dns_strategy = ""; - QString direct_dns = "localhost"; + QString direct_dns = "https://doh.pub/dns-query"; QString direct_dns_strategy = ""; bool dns_routing = true; bool use_dns_object = false; diff --git a/nekoray/nekoray_version.txt b/nekoray/nekoray_version.txt index c703684d43..7cd4543340 100644 --- a/nekoray/nekoray_version.txt +++ b/nekoray/nekoray_version.txt @@ -1 +1 @@ -3.26-2023-12-09 +4.0-beta1-2024-07-02 diff --git a/nekoray/ui/dialog_manage_routes.ui b/nekoray/ui/dialog_manage_routes.ui index 1f2bdbe66b..cfb846e472 100644 --- a/nekoray/ui/dialog_manage_routes.ui +++ b/nekoray/ui/dialog_manage_routes.ui @@ -301,7 +301,12 @@ For more information, see the document "Configuration/DNS". - localhost + local + + + + + tls://120.53.53.53 diff --git a/nekoray/ui/mainwindow_grpc.cpp b/nekoray/ui/mainwindow_grpc.cpp index 55332bd834..d45f1027a7 100644 --- a/nekoray/ui/mainwindow_grpc.cpp +++ b/nekoray/ui/mainwindow_grpc.cpp @@ -150,7 +150,7 @@ void MainWindow::speedtest_current_group(int mode) { // libcore::TestReq req; req.set_mode((libcore::TestMode) mode); - req.set_timeout(3000); + req.set_timeout(5000); req.set_url(NekoGui::dataStore->test_latency_url.toStdString()); // @@ -250,7 +250,7 @@ void MainWindow::speedtest_current() { runOnNewThread([=] { libcore::TestReq req; req.set_mode(libcore::UrlTest); - req.set_timeout(3000); + req.set_timeout(5000); req.set_url(NekoGui::dataStore->test_latency_url.toStdString()); bool rpcOK; diff --git a/openwrt-packages/luci-app-store/API.md b/openwrt-packages/luci-app-store/API.md index 34fce1a5c5..0ccbf9907d 100644 --- a/openwrt-packages/luci-app-store/API.md +++ b/openwrt-packages/luci-app-store/API.md @@ -97,7 +97,7 @@ {"installed":false} ``` -7. 任务状态(日志) +7. 任务状态(日志),已废弃,使用luci-lib-taskd提供的封装 ``` GET /cgi-bin/luci/admin/store/log diff --git a/openwrt-packages/luci-app-store/Makefile b/openwrt-packages/luci-app-store/Makefile index 1ea7580aea..7bbdee446c 100644 --- a/openwrt-packages/luci-app-store/Makefile +++ b/openwrt-packages/luci-app-store/Makefile @@ -11,7 +11,7 @@ LUCI_DEPENDS:=+curl +opkg +luci-base +tar +coreutils +coreutils-stat +libuci-lua LUCI_EXTRA_DEPENDS:=luci-lib-taskd (>=1.0.19) LUCI_PKGARCH:=all -PKG_VERSION:=0.1.21-0 +PKG_VERSION:=0.1.23-0 # PKG_RELEASE MUST be empty for luci.mk PKG_RELEASE:= diff --git a/openwrt-packages/luci-app-store/luasrc/controller/store.lua b/openwrt-packages/luci-app-store/luasrc/controller/store.lua index ea6ac96ee5..b7561e6d85 100644 --- a/openwrt-packages/luci-app-store/luasrc/controller/store.lua +++ b/openwrt-packages/luci-app-store/luasrc/controller/store.lua @@ -29,13 +29,22 @@ function index() entry({"admin", "store", "get_block_devices"}, call("get_block_devices")) entry({"admin", "store", "configured"}, call("configured")) + entry({"admin", "store", "entrysh"}, post("entrysh")) - for _, action in ipairs({"update", "install", "upgrade", "remove"}) do + -- docker + entry({"admin", "store", "docker_check_dir"}, call("docker_check_dir")) + entry({"admin", "store", "docker_check_migrate"}, call("docker_check_migrate")) + entry({"admin", "store", "docker_migrate"}, post("docker_migrate")) + + -- package + for _, action in ipairs({"update", "install", "upgrade", "remove", "autoconf"}) do store_api(action, true) end for _, action in ipairs({"status", "installed"}) do store_api(action, false) end + + -- backup if nixio.fs.access("/usr/libexec/istore/backup") then entry({"admin", "store", "get_support_backup_features"}, call("get_support_backup_features")) entry({"admin", "store", "light_backup"}, post("light_backup")) @@ -294,8 +303,8 @@ function store_action(param) end local metapkg = pkg and (metapkgpre .. pkg) or "" if action == "update" or pkg then - if action == "update" or action == "install" then - if action == "install" and "1" == luci.http.formvalue("autoconf") then + if action == "update" or action == "install" or action == "autoconf" then + if (action == "install" and "1" == luci.http.formvalue("autoconf")) or action == "autoconf" then local autoenv = "AUTOCONF=" .. pkg local autopath = luci.http.formvalue("path") local autoenable = luci.http.formvalue("enable") @@ -408,6 +417,77 @@ function configured() luci.http.write_json({code=200, configured=configured}) end +function entrysh() + local package = luci.http.formvalue("package") + local hostname = luci.http.formvalue("hostname") + if hostname == nil or hostname == "" or not validate_pkgname(package) then + luci.http.status(400, "Bad Request") + return + end + + local result + local entryfile = "/usr/libexec/istoree/" .. package .. ".sh" + if nixio.fs.access(entryfile) then + local o = luci.util.exec(entryfile .. " status " .. luci.util.shellquote(hostname)) + if o == nil or o == "" then + result = {code=500, msg="entrysh execute failed"} + else + local jsonc = require "luci.jsonc" + local json_parse = jsonc.parse + local status = json_parse(o) + if status == nil then + result = {code=500, msg="json parse failed: " .. o} + else + result = {code=200, status=status} + end + end + else + result = {code=404, msg="entrysh of this package not found"} + end + luci.http.prepare_content("application/json") + luci.http.write_json(result) +end + +function docker_check_dir() + local docker_on_system = luci.sys.call("/usr/libexec/istore/docker check_dir >/dev/null 2>&1") ~= 0 + luci.http.prepare_content("application/json") + luci.http.write_json({code=200, docker_on_system=docker_on_system}) +end + +function docker_check_migrate() + local path = luci.http.formvalue("path") + if path == nil or path == "" then + luci.http.status(400, "Bad Request") + return + end + local r,o,e = is_exec("/usr/libexec/istore/docker migrate_check " .. luci.util.shellquote(path)) + local result = "good" + if r == 1 then + result = "bad" + elseif r == 2 then + result = "existed" + end + luci.http.prepare_content("application/json") + luci.http.write_json({code=200, result=result, error=e}) +end + +function docker_migrate() + local path = luci.http.formvalue("path") + if path == nil or path == "" then + luci.http.status(400, "Bad Request") + return + end + + local action = "migrate" + local overwrite = luci.http.formvalue("overwrite") + if overwrite == "chdir" then + action = "change_dir" + end + local r,o,e = is_exec("/usr/libexec/istore/docker " .. action .. " " .. luci.util.shellquote(path), true) + luci.http.prepare_content("application/json") + luci.http.write_json({code=r, stdout=o, stderr=e}) +end + local function split(str,reps) local resultStrList = {} string.gsub(str,'[^'..reps..']+',function (w) diff --git a/openwrt-packages/luci-app-store/root/bin/is-opkg b/openwrt-packages/luci-app-store/root/bin/is-opkg index 8031e409fc..5fbe847499 100755 --- a/openwrt-packages/luci-app-store/root/bin/is-opkg +++ b/openwrt-packages/luci-app-store/root/bin/is-opkg @@ -247,6 +247,9 @@ case $action in check_space wrapped_in_update opkg_wrap_mirrors install "$@" && try_autoconf ;; + "autoconf") + try_autoconf + ;; "upgrade") new_upgrade "$@" ;; diff --git a/openwrt-packages/luci-app-store/root/usr/libexec/istore/docker b/openwrt-packages/luci-app-store/root/usr/libexec/istore/docker new file mode 100755 index 0000000000..69b51246dc --- /dev/null +++ b/openwrt-packages/luci-app-store/root/usr/libexec/istore/docker @@ -0,0 +1,114 @@ +#!/bin/sh + +handle_part() { + case "$MOUNT" in + "/overlay") + return 1 + ;; + esac + return 0 +} + +check_dir() { + local data_root=$(uci -q get dockerd.globals.data_root) + [ -n "$data_root" ] || return 0 + local block_dev=$(findmnt -T "$data_root" -v -o SOURCE | sed -n 2p) + [ -n "$block_dev" ] || return 0 + [ "overlayfs:/overlay" = "$block_dev" ] && return 1 + local line=$(block info "$block_dev" 2>/dev/null) + [ -n "$line" ] || return 0 + eval "${line##*: } handle_part ${line%%: *}" +} + +migrate_check(){ + local dest="$1" + [ -n "$dest" ] || { + echo "dest dir not specified!" >&2 + return 1 + } + local data_root="$2" + [ -n "$data_root" ] || data_root=$(uci -q get dockerd.globals.data_root) + [ -n "$data_root" ] || { + echo "get docker data_root failed!" >&2 + return 1 + } + + [ "$data_root" = "/" ] || data_root="${data_root%%/}" + [ "$dest" = "/" ] || dest="${dest%%/}" + + [ "$data_root" = "$dest" ] && { + echo "dest dir is the same as data_root!" >&2 + return 1 + } + + [ 1 = "$FORCE" ] && return 0 + [ -e "$dest" ] || return 0 + [ -d "$dest" ] || { + echo "$dest is existed and it's not a dir, use FORCE=1 to overwrite it" >&2 + return 2 + } + [ 0 = "$(ls -A "$dest" | head -1 | wc -l)" ] || { + echo "$dest is existed and it's not empty, use FORCE=1 to overwrite it" >&2 + return 2 + } + return 0 +} + +migrate() { + local dest="$1" + local data_root=$(uci -q get dockerd.globals.data_root) + [ -n "$data_root" ] || { + echo "get docker data_root failed!" >&2 + return 1 + } + [ "$data_root" = "/" ] || data_root="${data_root%%/}" + [ "$dest" = "/" ] || dest="${dest%%/}" + + FORCE=1 migrate_check "$dest" "$data_root" + local check_result=$? + [ 0 = $check_result ] || return $check_result + + if [ "$UCI_ONLY" != 1 ]; then + rm -rf "$dest" + mkdir -p "$dest" + echo "Copy $data_root to $dest ..." + cp -a "$data_root/." "$dest/" || return 1 + fi + + echo "Change dockerd data_root to $dest and restart" + uci set dockerd.globals.data_root="$dest" + uci commit dockerd + /etc/init.d/dockerd restart + + echo "Done" +} + +action=${1} +shift + +usage() { + echo "usage: $1 sub-command [arguments...]" + echo "where sub-command is one of:" + echo " check_dir Check docker data_root is on extrnal disk" + echo " migrate_check {target_dir} Check target_dir is valid for migration, return 2 if target_dir existed and not empty" + echo " migrate {target_dir} Migrate docker data_root to target_dir" + echo " change_dir {target_dir} Migrate docker data_root to target_dir but change dir only (no data copy)" +} + +case $action in + "check_dir") + check_dir + ;; + "migrate") + migrate "$@" + ;; + "migrate_check") + migrate_check "$@" + ;; + "change_dir") + UCI_ONLY=1 migrate "$@" + ;; + *) + usage "$0" + ;; +esac diff --git a/openwrt-packages/luci-app-store/swagger.yaml b/openwrt-packages/luci-app-store/swagger.yaml index ac3c48099d..ac1f89d525 100644 --- a/openwrt-packages/luci-app-store/swagger.yaml +++ b/openwrt-packages/luci-app-store/swagger.yaml @@ -28,7 +28,7 @@ paths: post: tags: - install - summary: 安装插件 + summary: 安装插件。安装过程中使用taskd接口获取日志 parameters: - in: "query" name: "token" @@ -55,6 +55,33 @@ paths: description: OK schema: $ref: "#/definitions/ResponseStore" + /cgi-bin/luci/admin/store/autoconf: + post: + tags: + - install + summary: 自动配置插件 + parameters: + - in: "query" + name: "token" + type: string + required: true + - in: "query" + name: "package" + type: string + required: true + - in: "query" + name: "path" + type: string + description: "可选参数" + - in: "query" + name: "enable" + type: string + description: "可选参数" + responses: + "200": + description: OK + schema: + $ref: "#/definitions/ResponseStore" /cgi-bin/luci/admin/store/remove: post: tags: @@ -148,7 +175,7 @@ paths: get: tags: - log - summary: 任务日志 + summary: 任务日志,已废弃 responses: "200": description: OK @@ -194,11 +221,94 @@ paths: tags: - configured summary: 检查插件是否已经配置过 + parameters: + - in: "query" + name: "uci" + type: string + required: true + description: "要检查的uci配置文件名称" responses: "200": description: OK schema: $ref: "#/definitions/ResponseStoreConfigured" + /cgi-bin/luci/admin/store/entrysh: + post: + tags: + - entrysh + summary: 查询插件运行状态,主要为了获取入口信息。 + description: 调用前应该检查meta数据中autoconf数组包含entrysh,注意如果是安装插件则检查服务器端的autoconf,如果是调用已安装插件则检查路由器端的autoconf。 + parameters: + - in: "query" + name: "token" + type: string + required: true + - in: "query" + name: "package" + type: string + required: true + description: "包名,例如aria2" + - in: "query" + name: "hostname" + type: string + required: true + description: "主机名,不包含端口。前端应该使用location.hostname获取" + responses: + "200": + description: OK + schema: + $ref: "#/definitions/ResponseStoreEntrysh" + /cgi-bin/luci/admin/store/docker_check_dir: + get: + tags: + - docker_check_dir + summary: 检查docker目录是否在系统盘 + responses: + "200": + description: OK + schema: + $ref: "#/definitions/ResponseDockerCheckDir" + /cgi-bin/luci/admin/store/docker_check_migrate: + get: + tags: + - docker_check_migrate + summary: 检查docker迁移目标目录是否有效 + parameters: + - in: "query" + name: "path" + type: string + required: true + description: "完整目标路径" + responses: + "200": + description: OK + schema: + $ref: "#/definitions/ResponseDockerCheckMigrate" + /cgi-bin/luci/admin/store/docker_migrate: + post: + tags: + - docker_migrate + summary: docker迁移到目标目录,异步 + description: 当返回code为0的时候,可以使用taskd接口展示日志,跟安装插件时一样 + parameters: + - in: "query" + name: "token" + type: string + required: true + - in: "query" + name: "path" + type: string + required: true + description: "完整目标路径" + - in: "query" + name: "overwrite" + type: string + description: "如果docker_check_migrate返回的result是existed,使用此参数指定解决方案:‘true’表示覆盖目标目录;‘chdir’表示只修改路径不复制文件" + responses: + "200": + description: OK + schema: + $ref: "#/definitions/ResponseStore" definitions: ResponseStoreToken: @@ -324,4 +434,54 @@ definitions: description: "为200时" configured: type: boolean + ResponseDockerCheckDir: + type: object + properties: + code: + type: integer + description: "为200时" + docker_on_system: + type: boolean + description: "docker数据在系统盘" + ResponseDockerCheckMigrate: + type: object + properties: + code: + type: integer + description: "为200时" + result: + type: string + description: "检查结果。可能值‘good’,‘bad’,‘existed’" + error: + type: string + description: "当result为bad时,此处返回错误日志" + ResponseStoreEntrysh: + type: object + properties: + code: + type: integer + description: "为200时" + msg: + type: string + description: "code不为200时显示错误信息" + status: + type: object + description: "状态和入口信息,不同插件可能有些不一样,仅列出常用公共参数" + properties: + app: + type: string + description: "插件名称,跟请求的包名一致" + docker: + type: boolean + description: "如果是docker插件" + running: + type: boolean + description: "是否运行中" + deployed: + type: boolean + description: "如果是docker插件且未运行,则是否已经部署" + web: + type: string + description: "web端跳转url" + diff --git a/shadowsocks-rust/Cargo.lock b/shadowsocks-rust/Cargo.lock index 42aa060373..a16518ed9e 100644 --- a/shadowsocks-rust/Cargo.lock +++ b/shadowsocks-rust/Cargo.lock @@ -532,18 +532,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.7" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.7" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" dependencies = [ "anstream", "anstyle", @@ -1903,9 +1903,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" dependencies = [ "serde", ] @@ -3100,9 +3100,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "indexmap", "itoa", diff --git a/xray-core/transport/internet/httpupgrade/httpupgrade_test.go b/xray-core/transport/internet/httpupgrade/httpupgrade_test.go index 991c37cb99..f94298ca8a 100644 --- a/xray-core/transport/internet/httpupgrade/httpupgrade_test.go +++ b/xray-core/transport/internet/httpupgrade/httpupgrade_test.go @@ -28,6 +28,7 @@ func Test_listenHTTPUpgradeAndDial(t *testing.T) { defer c.Close() var b [1024]byte + c.SetReadDeadline(time.Now().Add(2 * time.Second)) _, err := c.Read(b[:]) if err != nil { return @@ -87,6 +88,7 @@ func Test_listenHTTPUpgradeAndDialWithHeaders(t *testing.T) { defer c.Close() var b [1024]byte + c.SetReadDeadline(time.Now().Add(2 * time.Second)) _, err := c.Read(b[:]) if err != nil { return diff --git a/xray-core/transport/internet/splithttp/splithttp_test.go b/xray-core/transport/internet/splithttp/splithttp_test.go index 52ced9a0a7..7e22c9adba 100644 --- a/xray-core/transport/internet/splithttp/splithttp_test.go +++ b/xray-core/transport/internet/splithttp/splithttp_test.go @@ -33,6 +33,7 @@ func Test_listenSHAndDial(t *testing.T) { defer c.Close() var b [1024]byte + c.SetReadDeadline(time.Now().Add(2 * time.Second)) _, err := c.Read(b[:]) if err != nil { return diff --git a/xray-core/transport/internet/websocket/ws_test.go b/xray-core/transport/internet/websocket/ws_test.go index 48892ead97..637b7f724a 100644 --- a/xray-core/transport/internet/websocket/ws_test.go +++ b/xray-core/transport/internet/websocket/ws_test.go @@ -28,6 +28,7 @@ func Test_listenWSAndDial(t *testing.T) { defer c.Close() var b [1024]byte + c.SetReadDeadline(time.Now().Add(2 * time.Second)) _, err := c.Read(b[:]) if err != nil { return diff --git a/yass/.github/workflows/compiler.yml b/yass/.github/workflows/compiler.yml index 7549308176..5bf8f5cad1 100644 --- a/yass/.github/workflows/compiler.yml +++ b/yass/.github/workflows/compiler.yml @@ -125,15 +125,15 @@ jobs: - name: Run tests run: | cd build-msvc-${{ matrix.arch }}-${{ matrix.crt-linkage }} - yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks4 - yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks4a - yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks5 - yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks5h - yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type http - yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks4a --ipv6_mode - yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks5 --ipv6_mode - yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks5h --ipv6_mode - yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type http --ipv6_mode + yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks4 || exit /b + yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks4a || exit /b + yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks5 || exit /b + yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks5h || exit /b + yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type http || exit /b + yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks4a --ipv6_mode || exit /b + yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks5 --ipv6_mode || exit /b + yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks5h --ipv6_mode || exit /b + yass_test --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type http --ipv6_mode || exit /b mingw64-compiler-compatible-crosscompiling: strategy: fail-fast: false @@ -252,9 +252,6 @@ jobs: if: ${{ matrix.arch == 'i686' || matrix.arch == 'x86_64' }} run: | cd build-mingw-${{ matrix.arch }} - wine yass_test.exe --gtest_shuffle --gtest_repeat=25 --gtest_throw_on_failure - wine yass_test.exe --gtest_shuffle --gtest_repeat=25 --gtest_throw_on_failure --ipv6_mode - wine yass_test.exe --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks4 wine yass_test.exe --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks4a wine yass_test.exe --gtest_shuffle --gtest_repeat=10 --gtest_throw_on_failure --proxy_type socks5 diff --git a/yass/src/net/content_server.hpp b/yass/src/net/content_server.hpp index 07a16557af..b51aa7faa2 100644 --- a/yass/src/net/content_server.hpp +++ b/yass/src/net/content_server.hpp @@ -254,7 +254,6 @@ class ContentServer { ListenCtx& ctx = listen_ctxs_[listen_ctx_num]; int connection_id = next_connection_id_++; - socket.native_non_blocking(true, ec); socket.non_blocking(true, ec); SetTCPCongestion(socket.native_handle(), ec); SetTCPKeepAlive(socket.native_handle(), ec); diff --git a/yass/src/net/doh_request.cpp b/yass/src/net/doh_request.cpp index 6a404e4860..b22b2418e1 100644 --- a/yass/src/net/doh_request.cpp +++ b/yass/src/net/doh_request.cpp @@ -81,7 +81,6 @@ void DoHRequest::DoRequest(dns_message::DNStype dns_type, const std::string& hos OnDoneRequest(ec, nullptr); return; } - socket_.native_non_blocking(true, ec); socket_.non_blocking(true, ec); scoped_refptr self(this); socket_.async_connect(endpoint_, [this, self](asio::error_code ec) { diff --git a/yass/src/net/dot_request.cpp b/yass/src/net/dot_request.cpp index e697c3812f..41495492db 100644 --- a/yass/src/net/dot_request.cpp +++ b/yass/src/net/dot_request.cpp @@ -73,7 +73,6 @@ void DoTRequest::DoRequest(dns_message::DNStype dns_type, const std::string& hos OnDoneRequest(ec, nullptr); return; } - socket_.native_non_blocking(true, ec); socket_.non_blocking(true, ec); scoped_refptr self(this); socket_.async_connect(endpoint_, [this, self](asio::error_code ec) { diff --git a/yass/src/net/ssl_server_socket.cpp b/yass/src/net/ssl_server_socket.cpp index 75dd6072e0..2214201d5f 100644 --- a/yass/src/net/ssl_server_socket.cpp +++ b/yass/src/net/ssl_server_socket.cpp @@ -41,7 +41,6 @@ SSLServerSocket::~SSLServerSocket() { int SSLServerSocket::Handshake(CompletionOnceCallback callback) { CHECK(!disconnected_); - DCHECK(stream_socket_->native_non_blocking()); DCHECK(stream_socket_->non_blocking()); SSL_set_fd(ssl_.get(), stream_socket_->native_handle()); diff --git a/yass/src/net/ssl_socket.cpp b/yass/src/net/ssl_socket.cpp index 2692a6262e..39ad0fdf38 100644 --- a/yass/src/net/ssl_socket.cpp +++ b/yass/src/net/ssl_socket.cpp @@ -149,7 +149,6 @@ int SSLSocket::Connect(CompletionOnceCallback callback) { // https://crbug.com/499289. CHECK(!disconnected_); - DCHECK(stream_socket_->native_non_blocking()); DCHECK(stream_socket_->non_blocking()); SSL_set_fd(ssl_.get(), stream_socket_->native_handle()); diff --git a/yass/src/net/stream.hpp b/yass/src/net/stream.hpp index 041fe046ce..622e25327b 100644 --- a/yass/src/net/stream.hpp +++ b/yass/src/net/stream.hpp @@ -369,7 +369,6 @@ class stream : public RefCountedThreadSafe { setProtectFd(socket_.native_handle()); #endif SetTCPFastOpenConnect(socket_.native_handle(), ec); - socket_.native_non_blocking(true, ec); socket_.non_blocking(true, ec); scoped_refptr self(this); if (auto connect_timeout = absl::GetFlag(FLAGS_connect_timeout)) { diff --git a/yass/src/ss_test.cpp b/yass/src/ss_test.cpp index fbc9d5f3f4..f4af30d072 100644 --- a/yass/src/ss_test.cpp +++ b/yass/src/ss_test.cpp @@ -271,10 +271,10 @@ class ContentProviderConnection : public RefCountedThreadSafesocket_.shutdown(asio::ip::tcp::socket::shutdown_send, ec); - LOG(WARNING) << "Connection (content-provider) " << connection_id() << " Shutting down"; if (ec) { LOG(WARNING) << "Connection (content-provider) " << connection_id() << " shutdown failure: " << ec; } @@ -391,6 +391,7 @@ class EndToEndTest : public ::testing::TestWithParam { CURLcode ret; const uint8_t* data = g_send_buffer.data(); IOBuf resp_buffer; + resp_buffer.reserve(0, g_send_buffer.length()); curl = curl_easy_init(); ASSERT_TRUE(curl) << "curl initial failure"; @@ -427,6 +428,11 @@ class EndToEndTest : public ::testing::TestWithParam { LOG(FATAL) << "Invalid proxy type: " << absl::GetFlag(FLAGS_proxy_type); } curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); +#if LIBCURL_VERSION_NUM >= 0x076200 + /* Added in 7.62.0. */ + /* The maximum buffer size allowed to be set is 2 megabytes. */ + curl_easy_setopt(curl, CURLOPT_UPLOAD_BUFFERSIZE, 2*1024*1024); +#endif /* we want to use our own read function */ curl_read_callback r_callback = [](char* buffer, size_t size, size_t nmemb, void* clientp) -> size_t { const uint8_t** data = reinterpret_cast(clientp); @@ -439,6 +445,7 @@ class EndToEndTest : public ::testing::TestWithParam { return copied; }; curl_easy_setopt(curl, CURLOPT_READFUNCTION, r_callback); + curl_easy_setopt(curl, CURLOPT_READDATA, &data); /* we want to use our own write function */ curl_write_callback w_callback = [](char* data, size_t size, size_t nmemb, void* clientp) -> size_t { size_t copied = size * nmemb; @@ -450,12 +457,16 @@ class EndToEndTest : public ::testing::TestWithParam { return copied; }; curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, w_callback); - curl_easy_setopt(curl, CURLOPT_READDATA, &data); /* provide the size of the upload, we typecast the value to curl_off_t since we must be sure to use the correct data size */ curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)g_send_buffer.length()); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp_buffer); - curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/7.77.0"); +#if LIBCURL_VERSION_NUM >= 0x075300 + /* Added in 7.10. Growing the buffer was added in 7.53.0. */ + curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, CURL_MAX_READ_SIZE); +#endif + curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1L); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/" LIBCURL_VERSION); ret = curl_easy_perform(curl); curl_easy_cleanup(curl); /* if the request did not complete correctly, show the error diff --git a/yass/third_party/asio/asio/include/asio/detail/impl/win_mutex.ipp b/yass/third_party/asio/asio/include/asio/detail/impl/win_mutex.ipp index 339d1f7b14..bb9d8975b2 100644 --- a/yass/third_party/asio/asio/include/asio/detail/impl/win_mutex.ipp +++ b/yass/third_party/asio/asio/include/asio/detail/impl/win_mutex.ipp @@ -36,13 +36,13 @@ win_mutex::win_mutex() asio::detail::throw_error(ec, "mutex"); } -#if _WIN32_WINNT >= 0x0601 +#if _WIN32_WINNT >= 0x0600 int win_mutex::do_init() { ::InitializeSRWLock(&srwlock_); return 0; } -#else // _WIN32_WINNT >= 0x0601 +#else // _WIN32_WINNT >= 0x0600 int win_mutex::do_init() { #if defined(__MINGW32__) @@ -80,7 +80,7 @@ int win_mutex::do_init() return 0; #endif } -#endif // _WIN32_WINNT >= 0x0601 +#endif // _WIN32_WINNT >= 0x0600 } // namespace detail } // namespace asio diff --git a/yass/third_party/asio/asio/include/asio/detail/impl/win_static_mutex.ipp b/yass/third_party/asio/asio/include/asio/detail/impl/win_static_mutex.ipp index 7aa11f6d48..abe3af125a 100644 --- a/yass/third_party/asio/asio/include/asio/detail/impl/win_static_mutex.ipp +++ b/yass/third_party/asio/asio/include/asio/detail/impl/win_static_mutex.ipp @@ -29,6 +29,7 @@ namespace asio { namespace detail { +#if _WIN32_WINNT < 0x0600 void win_static_mutex::init() { int error = do_init(); @@ -37,12 +38,6 @@ void win_static_mutex::init() asio::detail::throw_error(ec, "static_mutex"); } -#if _WIN32_WINNT >= 0x0601 -int win_static_mutex::do_init() -{ - return 0; -} -#else // _WIN32_WINNT >= 0x0601 int win_static_mutex::do_init() { using namespace std; // For sprintf. @@ -131,7 +126,7 @@ int win_static_mutex::do_init() ::CloseHandle(mutex); return 0; } -#endif // _WIN32_WINNT >= 0x0601 +#endif // _WIN32_WINNT < 0x0600 } // namespace detail } // namespace asio diff --git a/yass/third_party/asio/asio/include/asio/detail/win_mutex.hpp b/yass/third_party/asio/asio/include/asio/detail/win_mutex.hpp index 3be2260344..a99b4128ae 100644 --- a/yass/third_party/asio/asio/include/asio/detail/win_mutex.hpp +++ b/yass/third_party/asio/asio/include/asio/detail/win_mutex.hpp @@ -38,33 +38,33 @@ public: ASIO_DECL win_mutex(); // Destructor. -#if _WIN32_WINNT >= 0x0601 +#if _WIN32_WINNT >= 0x0600 ~win_mutex() = default; -#else +#else // _WIN32_WINNT >= 0x0600 ~win_mutex() { ::DeleteCriticalSection(&crit_section_); } -#endif +#endif // _WIN32_WINNT >= 0x0600 // Lock the mutex. void lock() { -#if _WIN32_WINNT >= 0x0601 +#if _WIN32_WINNT >= 0x0600 ::AcquireSRWLockExclusive(&srwlock_); -#else +#else // _WIN32_WINNT >= 0x0600 ::EnterCriticalSection(&crit_section_); -#endif +#endif // _WIN32_WINNT >= 0x0600 } // Unlock the mutex. void unlock() { -#if _WIN32_WINNT >= 0x0601 +#if _WIN32_WINNT >= 0x0600 ::ReleaseSRWLockExclusive(&srwlock_); -#else +#else // _WIN32_WINNT >= 0x0600 ::LeaveCriticalSection(&crit_section_); -#endif +#endif // _WIN32_WINNT >= 0x0600 } private: @@ -73,11 +73,11 @@ private: // C++ exceptions in the same function. ASIO_DECL int do_init(); -#if _WIN32_WINNT >= 0x0601 +#if _WIN32_WINNT >= 0x0600 ::SRWLOCK srwlock_; -#else +#else // _WIN32_WINNT >= 0x0600 ::CRITICAL_SECTION crit_section_; -#endif +#endif // _WIN32_WINNT >= 0x0600 }; } // namespace detail diff --git a/yass/third_party/asio/asio/include/asio/detail/win_static_mutex.hpp b/yass/third_party/asio/asio/include/asio/detail/win_static_mutex.hpp index d679986667..9b7918af74 100644 --- a/yass/third_party/asio/asio/include/asio/detail/win_static_mutex.hpp +++ b/yass/third_party/asio/asio/include/asio/detail/win_static_mutex.hpp @@ -30,6 +30,10 @@ struct win_static_mutex { typedef asio::detail::scoped_lock scoped_lock; +#if _WIN32_WINNT >= 0x0600 + // Initialise the mutex. + ASIO_DECL void init() {} +#else // _WIN32_WINNT >= 0x0600 // Initialise the mutex. ASIO_DECL void init(); @@ -37,44 +41,45 @@ struct win_static_mutex // init() function since the compiler does not support the use of structured // exceptions and C++ exceptions in the same function. ASIO_DECL int do_init(); +#endif // _WIN32_WINNT >= 0x0600 // Lock the mutex. void lock() { -#if _WIN32_WINNT >= 0x0601 +#if _WIN32_WINNT >= 0x0600 ::AcquireSRWLockExclusive(&srwlock_); -#else +#else // _WIN32_WINNT >= 0x0600 ::EnterCriticalSection(&crit_section_); -#endif +#endif // _WIN32_WINNT >= 0x0600 } // Unlock the mutex. void unlock() { -#if _WIN32_WINNT >= 0x0601 +#if _WIN32_WINNT >= 0x0600 ::ReleaseSRWLockExclusive(&srwlock_); -#else +#else // _WIN32_WINNT >= 0x0600 ::LeaveCriticalSection(&crit_section_); -#endif +#endif // _WIN32_WINNT >= 0x0600 } -#if _WIN32_WINNT >= 0x0601 +#if _WIN32_WINNT >= 0x0600 ::SRWLOCK srwlock_; -#else +#else // _WIN32_WINNT >= 0x0600 bool initialised_; ::CRITICAL_SECTION crit_section_; -#endif +#endif // _WIN32_WINNT >= 0x0600 }; -#if _WIN32_WINNT >= 0x0601 +#if _WIN32_WINNT >= 0x0600 # define ASIO_WIN_STATIC_MUTEX_INIT { SRWLOCK_INIT } -#else +#else // _WIN32_WINNT >= 0x0600 #if defined(UNDER_CE) # define ASIO_WIN_STATIC_MUTEX_INIT { false, { 0, 0, 0, 0, 0 } } #else // defined(UNDER_CE) # define ASIO_WIN_STATIC_MUTEX_INIT { false, { 0, 0, 0, 0, 0, 0 } } #endif // defined(UNDER_CE) -#endif +#endif // _WIN32_WINNT >= 0x0600 } // namespace detail } // namespace asio diff --git a/yass/third_party/gperftools/cmake/config.h.in b/yass/third_party/gperftools/cmake/config.h.in index 9920af1068..2a783af936 100644 --- a/yass/third_party/gperftools/cmake/config.h.in +++ b/yass/third_party/gperftools/cmake/config.h.in @@ -2,11 +2,6 @@ in .. -- this is particularly true for msys/mingw, which uses the unix config.h but also runs code in the windows directory. */ -#ifdef __MINGW32__ -#include "@CMAKE_CURRENT_SOURCE_DIR@/src/windows/config.h" -#define GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_ -#endif - #ifndef GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_ #define GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_ /* used by tcmalloc.h */ diff --git a/yass/third_party/gperftools/src/windows/config.h b/yass/third_party/gperftools/src/windows/config.h deleted file mode 100644 index fd1b61f516..0000000000 --- a/yass/third_party/gperftools/src/windows/config.h +++ /dev/null @@ -1,265 +0,0 @@ -/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ -/* A manual version of config.h fit for windows machines. - * - * Use of this source code is governed by a BSD-style license that can - * be found in the LICENSE file. - */ - -// windows.h whatevevs defines min and max preprocessor macros and -// that breaks ::max() in various places (like numeric_limits) -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#ifndef GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_ -#define GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_ -/* used by tcmalloc.h */ -#define GPERFTOOLS_CONFIG_H_ - -/* Enable aggressive decommit by default */ -/* #undef ENABLE_AGGRESSIVE_DECOMMIT_BY_DEFAULT */ - -/* Build new/delete operators for overaligned types */ -/* #undef ENABLE_ALIGNED_NEW_DELETE */ - -/* Build runtime detection for sized delete */ -/* #undef ENABLE_DYNAMIC_SIZED_DELETE */ - -/* Report large allocation */ -/* #undef ENABLE_LARGE_ALLOC_REPORT */ - -/* Build sized deletion operators */ -/* #undef ENABLE_SIZED_DELETE */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ASM_PTRACE_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_CYGWIN_SIGNAL_H */ - -/* Define to 1 if you have the declaration of `backtrace', and to 0 if you - don't. */ -/* #undef HAVE_DECL_BACKTRACE */ - -/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't. - */ -#define HAVE_DECL_CFREE 0 - -/* Define to 1 if you have the declaration of `memalign', and to 0 if you - don't. */ -#define HAVE_DECL_MEMALIGN 0 - -/* Define to 1 if you have the declaration of `nanosleep', and to 0 if you - don't. */ -#define HAVE_DECL_NANOSLEEP 0 - -/* Define to 1 if you have the declaration of `posix_memalign', and to 0 if - you don't. */ -#define HAVE_DECL_POSIX_MEMALIGN 0 - -/* Define to 1 if you have the declaration of `pvalloc', and to 0 if you - don't. */ -#define HAVE_DECL_PVALLOC 0 - -/* Define to 1 if you have the declaration of `sleep', and to 0 if you don't. - */ -#define HAVE_DECL_SLEEP 0 - -/* Define to 1 if you have the declaration of `valloc', and to 0 if you don't. - */ -#define HAVE_DECL_VALLOC 0 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DLFCN_H */ - -/* Define to 1 if the system has the type `Elf32_Versym'. */ -/* #undef HAVE_ELF32_VERSYM */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_EXECINFO_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_FEATURES_H */ - -/* Define to 1 if you have the `fork' function. */ -/* #undef HAVE_FORK */ - -/* Define to 1 if you have the `geteuid' function. */ -/* #undef HAVE_GETEUID */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_GLOB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_GRP_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LIBUNWIND_H */ - -/* Define if this is Linux that has SIGEV_THREAD_ID */ -/* #undef HAVE_LINUX_SIGEV_THREAD_ID */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MALLOC_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have a working `mmap' system call. */ -/* #undef HAVE_MMAP */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_POLL_H */ - -/* define if libc has program_invocation_name */ -/* #undef HAVE_PROGRAM_INVOCATION_NAME */ - -/* Define if you have POSIX threads libraries and header files. */ -/* #undef HAVE_PTHREAD */ - -/* defined to 1 if pthread symbols are exposed even without include pthread.h - */ -/* #undef HAVE_PTHREAD_DESPITE_ASKING_FOR */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_PWD_H */ - -/* Define to 1 if you have the `sbrk' function. */ -/* #undef HAVE_SBRK */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SCHED_H */ - -/* Define to 1 if the system has the type `struct mallinfo'. */ -/* #undef HAVE_STRUCT_MALLINFO */ - -/* Define to 1 if the system has the type `struct mallinfo2'. */ -/* #undef HAVE_STRUCT_MALLINFO2 */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_CDEFS_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_RESOURCE_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SOCKET_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SYSCALL_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_UCONTEXT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_WAIT_H */ - -/* Define to 1 if compiler supports __thread */ -#define HAVE_TLS 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_UCONTEXT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_UNISTD_H */ - -/* Whether contains _Unwind_Backtrace */ -/* #undef HAVE_UNWIND_BACKTRACE */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_UNWIND_H */ - -/* define if your compiler has __attribute__ */ -/* #undef HAVE___ATTRIBUTE__ */ - -/* define if your compiler supports alignment of functions */ -/* #undef HAVE___ATTRIBUTE__ALIGNED_FN */ - -/* Define to 1 if compiler supports __environ */ -/* #undef HAVE___ENVIRON */ - -/* Define to 1 if you have the `__sbrk' function. */ -/* #undef HAVE___SBRK */ - -/* prefix where we look for installed files */ -/* #undef INSTALL_PREFIX */ - -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -/* #undef LT_OBJDIR */ - -/* Name of package */ -#define PACKAGE "gperftools" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "gperftools@googlegroups.com" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "gperftools" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "gperftools 2.15" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "gperftools" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "2.15" - -/* Always the empty-string on non-windows systems. On windows, should be - "__declspec(dllexport)". This way, when we compile the dll, we export our - functions/classes. It's safe to define this here because config.h is only - used internally, to compile the DLL, and every DLL source file #includes - "config.h" before anything else. */ -#ifndef PERFTOOLS_DLL_DECL -# define PERFTOOLS_IS_A_DLL 1 /* not set if you're statically linking */ -# define PERFTOOLS_DLL_DECL __declspec(dllexport) -# define PERFTOOLS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport) -#endif - -/* Mark the systems where we know it's bad if pthreads runs too - early before main (before threads are initialized, presumably). */ -#ifdef __FreeBSD__ -#define PTHREADS_CRASHES_IF_RUN_TOO_EARLY 1 -#endif - -/* Define 8 bytes of allocation alignment for tcmalloc */ -/* #undef TCMALLOC_ALIGN_8BYTES */ - -/* Define internal page size for tcmalloc as number of left bitshift */ -/* #undef TCMALLOC_PAGE_SIZE_SHIFT */ - -/* C99 says: define this to get the PRI... macros from stdint.h */ -#ifndef __STDC_FORMAT_MACROS -# define __STDC_FORMAT_MACROS 1 -#endif - -// --------------------------------------------------------------------- -// Extra stuff not found in config.h.in - -// This must be defined before the windows.h is included. We need at -// least 0x0400 for mutex.h to have access to TryLock, and at least -// 0x0501 for patch_functions.cc to have access to GetModuleHandleEx. -// (This latter is an optimization we could take out if need be.) -#ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 -#endif - -// We want to make sure not to ever try to #include heap-checker.h -#define NO_HEAP_CHECK 1 - -// TODO(csilvers): include windows/port.h in every relevant source file instead? -#include "windows/port.h" - -#endif /* GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_ */ diff --git a/yass/third_party/nghttp2/cmake/PickyWarningsC.cmake b/yass/third_party/nghttp2/cmake/PickyWarningsC.cmake index 6a5ee27d04..83ca848caa 100644 --- a/yass/third_party/nghttp2/cmake/PickyWarningsC.cmake +++ b/yass/third_party/nghttp2/cmake/PickyWarningsC.cmake @@ -40,9 +40,15 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER_ID MA set(WPICKY_ENABLE "-W") endif() - list(APPEND WPICKY_ENABLE - -Wall - ) + if (MSVC) + list(APPEND WPICKY_ENABLE + -W3 + ) + else() + list(APPEND WPICKY_ENABLE + -Wall + ) + endif() # ---------------------------------- # Add new options here, if in doubt: diff --git a/yass/third_party/nghttp2/cmake/PickyWarningsCXX.cmake b/yass/third_party/nghttp2/cmake/PickyWarningsCXX.cmake index 4699733d25..96fd1ddb13 100644 --- a/yass/third_party/nghttp2/cmake/PickyWarningsCXX.cmake +++ b/yass/third_party/nghttp2/cmake/PickyWarningsCXX.cmake @@ -33,7 +33,11 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID # WPICKY_ENABLE = Options we want to enable as-is. # WPICKY_DETECT = Options we want to test first and enable if available. - set(WPICKY_ENABLE "-Wall") + if (MSVC) + set(WPICKY_ENABLE "-W3") + else() + set(WPICKY_ENABLE "-Wall") + endif() # ---------------------------------- # Add new options here, if in doubt: diff --git a/youtube-dl/test/test_utils.py b/youtube-dl/test/test_utils.py index de7fe80b8b..2947cce7eb 100644 --- a/youtube-dl/test/test_utils.py +++ b/youtube-dl/test/test_utils.py @@ -14,9 +14,11 @@ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import io import itertools import json +import types import xml.etree.ElementTree from youtube_dl.utils import ( + _UnsafeExtensionError, age_restricted, args_to_str, base_url, @@ -270,6 +272,27 @@ class TestUtil(unittest.TestCase): expand_path('~/%s' % env('YOUTUBE_DL_EXPATH_PATH')), '%s/expanded' % compat_getenv('HOME')) + _uncommon_extensions = [ + ('exe', 'abc.exe.ext'), + ('de', 'abc.de.ext'), + ('../.mp4', None), + ('..\\.mp4', None), + ] + + def assertUnsafeExtension(self, ext=None): + assert_raises = self.assertRaises(_UnsafeExtensionError) + assert_raises.ext = ext + orig_exit = assert_raises.__exit__ + + def my_exit(self_, exc_type, exc_val, exc_tb): + did_raise = orig_exit(exc_type, exc_val, exc_tb) + if did_raise and assert_raises.ext is not None: + self.assertEqual(assert_raises.ext, assert_raises.exception.extension, 'Unsafe extension not as unexpected') + return did_raise + + assert_raises.__exit__ = types.MethodType(my_exit, assert_raises) + return assert_raises + def test_prepend_extension(self): self.assertEqual(prepend_extension('abc.ext', 'temp'), 'abc.temp.ext') self.assertEqual(prepend_extension('abc.ext', 'temp', 'ext'), 'abc.temp.ext') @@ -278,6 +301,19 @@ class TestUtil(unittest.TestCase): self.assertEqual(prepend_extension('.abc', 'temp'), '.abc.temp') self.assertEqual(prepend_extension('.abc.ext', 'temp'), '.abc.temp.ext') + # Test uncommon extensions + self.assertEqual(prepend_extension('abc.ext', 'bin'), 'abc.bin.ext') + for ext, result in self._uncommon_extensions: + with self.assertUnsafeExtension(ext): + prepend_extension('abc', ext) + if result: + self.assertEqual(prepend_extension('abc.ext', ext, 'ext'), result) + else: + with self.assertUnsafeExtension(ext): + prepend_extension('abc.ext', ext, 'ext') + with self.assertUnsafeExtension(ext): + prepend_extension('abc.unexpected_ext', ext, 'ext') + def test_replace_extension(self): self.assertEqual(replace_extension('abc.ext', 'temp'), 'abc.temp') self.assertEqual(replace_extension('abc.ext', 'temp', 'ext'), 'abc.temp') @@ -286,6 +322,16 @@ class TestUtil(unittest.TestCase): self.assertEqual(replace_extension('.abc', 'temp'), '.abc.temp') self.assertEqual(replace_extension('.abc.ext', 'temp'), '.abc.temp') + # Test uncommon extensions + self.assertEqual(replace_extension('abc.ext', 'bin'), 'abc.unknown_video') + for ext, _ in self._uncommon_extensions: + with self.assertUnsafeExtension(ext): + replace_extension('abc', ext) + with self.assertUnsafeExtension(ext): + replace_extension('abc.ext', ext, 'ext') + with self.assertUnsafeExtension(ext): + replace_extension('abc.unexpected_ext', ext, 'ext') + def test_subtitles_filename(self): self.assertEqual(subtitles_filename('abc.ext', 'en', 'vtt'), 'abc.en.vtt') self.assertEqual(subtitles_filename('abc.ext', 'en', 'vtt', 'ext'), 'abc.en.vtt') diff --git a/youtube-dl/youtube_dl/YoutubeDL.py b/youtube-dl/youtube_dl/YoutubeDL.py index dad44435f0..c19501915e 100755 --- a/youtube-dl/youtube_dl/YoutubeDL.py +++ b/youtube-dl/youtube_dl/YoutubeDL.py @@ -7,6 +7,7 @@ import collections import copy import datetime import errno +import functools import io import itertools import json @@ -53,6 +54,7 @@ from .compat import ( compat_urllib_request_DataHandler, ) from .utils import ( + _UnsafeExtensionError, age_restricted, args_to_str, bug_reports_message, @@ -129,6 +131,20 @@ if compat_os_name == 'nt': import ctypes +def _catch_unsafe_file_extension(func): + @functools.wraps(func) + def wrapper(self, *args, **kwargs): + try: + return func(self, *args, **kwargs) + except _UnsafeExtensionError as error: + self.report_error( + '{0} found; to avoid damaging your system, this value is disallowed.' + ' If you believe this is an error{1}').format( + error.message, bug_reports_message(',')) + + return wrapper + + class YoutubeDL(object): """YoutubeDL class. @@ -1925,6 +1941,7 @@ class YoutubeDL(object): if self.params.get('forcejson', False): self.to_stdout(json.dumps(self.sanitize_info(info_dict))) + @_catch_unsafe_file_extension def process_info(self, info_dict): """Process a single resolved IE result.""" diff --git a/youtube-dl/youtube_dl/__init__.py b/youtube-dl/youtube_dl/__init__.py index cc8285eba1..06bdfb6890 100644 --- a/youtube-dl/youtube_dl/__init__.py +++ b/youtube-dl/youtube_dl/__init__.py @@ -21,6 +21,7 @@ from .compat import ( workaround_optparse_bug9161, ) from .utils import ( + _UnsafeExtensionError, DateRange, decodeOption, DEFAULT_OUTTMPL, @@ -173,6 +174,9 @@ def _real_main(argv=None): if opts.ap_mso and opts.ap_mso not in MSO_INFO: parser.error('Unsupported TV Provider, use --ap-list-mso to get a list of supported TV Providers') + if opts.no_check_extensions: + _UnsafeExtensionError.lenient = True + def parse_retries(retries): if retries in ('inf', 'infinite'): parsed_retries = float('inf') diff --git a/youtube-dl/youtube_dl/options.py b/youtube-dl/youtube_dl/options.py index 434f520d39..61705d1f02 100644 --- a/youtube-dl/youtube_dl/options.py +++ b/youtube-dl/youtube_dl/options.py @@ -533,6 +533,10 @@ def parseOpts(overrideArguments=None): '--no-check-certificate', action='store_true', dest='no_check_certificate', default=False, help='Suppress HTTPS certificate validation') + workarounds.add_option( + '--no-check-extensions', + action='store_true', dest='no_check_extensions', default=False, + help='Suppress file extension validation') workarounds.add_option( '--prefer-insecure', '--prefer-unsecure', action='store_true', dest='prefer_insecure', diff --git a/youtube-dl/youtube_dl/utils.py b/youtube-dl/youtube_dl/utils.py index 113c913df5..3ec9d38119 100644 --- a/youtube-dl/youtube_dl/utils.py +++ b/youtube-dl/youtube_dl/utils.py @@ -1717,21 +1717,6 @@ TIMEZONE_NAMES = { 'PST': -8, 'PDT': -7 # Pacific } -KNOWN_EXTENSIONS = ( - 'mp4', 'm4a', 'm4p', 'm4b', 'm4r', 'm4v', 'aac', - 'flv', 'f4v', 'f4a', 'f4b', - 'webm', 'ogg', 'ogv', 'oga', 'ogx', 'spx', 'opus', - 'mkv', 'mka', 'mk3d', - 'avi', 'divx', - 'mov', - 'asf', 'wmv', 'wma', - '3gp', '3g2', - 'mp3', - 'flac', - 'ape', - 'wav', - 'f4f', 'f4m', 'm3u8', 'smil') - # needed for sanitizing filenames in restricted mode ACCENT_CHARS = dict(zip('ÂÃÄÀÁÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖŐØŒÙÚÛÜŰÝÞßàáâãäåæçèéêëìíîïðñòóôõöőøœùúûüűýþÿ', itertools.chain('AAAAAA', ['AE'], 'CEEEEIIIIDNOOOOOOO', ['OE'], 'UUUUUY', ['TH', 'ss'], @@ -3959,19 +3944,22 @@ def parse_duration(s): return duration -def prepend_extension(filename, ext, expected_real_ext=None): +def _change_extension(prepend, filename, ext, expected_real_ext=None): name, real_ext = os.path.splitext(filename) - return ( - '{0}.{1}{2}'.format(name, ext, real_ext) - if not expected_real_ext or real_ext[1:] == expected_real_ext - else '{0}.{1}'.format(filename, ext)) + sanitize_extension = _UnsafeExtensionError.sanitize_extension + + if not expected_real_ext or real_ext.partition('.')[0::2] == ('', expected_real_ext): + filename = name + if prepend and real_ext: + sanitize_extension(ext, prepend=prepend) + return ''.join((filename, '.', ext, real_ext)) + + # Mitigate path traversal and file impersonation attacks + return '.'.join((filename, sanitize_extension(ext))) -def replace_extension(filename, ext, expected_real_ext=None): - name, real_ext = os.path.splitext(filename) - return '{0}.{1}'.format( - name if not expected_real_ext or real_ext[1:] == expected_real_ext else filename, - ext) +prepend_extension = functools.partial(_change_extension, True) +replace_extension = functools.partial(_change_extension, False) def check_executable(exe, args=[]): @@ -6561,3 +6549,138 @@ def join_nonempty(*values, **kwargs): if from_dict is not None: values = (traverse_obj(from_dict, variadic(v)) for v in values) return delim.join(map(compat_str, filter(None, values))) + + +class Namespace(object): + """Immutable namespace""" + + def __init__(self, **kw_attr): + self.__dict__.update(kw_attr) + + def __iter__(self): + return iter(self.__dict__.values()) + + @property + def items_(self): + return self.__dict__.items() + + +MEDIA_EXTENSIONS = Namespace( + common_video=('avi', 'flv', 'mkv', 'mov', 'mp4', 'webm'), + video=('3g2', '3gp', 'f4v', 'mk3d', 'divx', 'mpg', 'ogv', 'm4v', 'wmv'), + common_audio=('aiff', 'alac', 'flac', 'm4a', 'mka', 'mp3', 'ogg', 'opus', 'wav'), + audio=('aac', 'ape', 'asf', 'f4a', 'f4b', 'm4b', 'm4p', 'm4r', 'oga', 'ogx', 'spx', 'vorbis', 'wma', 'weba'), + thumbnails=('jpg', 'png', 'webp'), + # storyboards=('mhtml', ), + subtitles=('srt', 'vtt', 'ass', 'lrc', 'ttml'), + manifests=('f4f', 'f4m', 'm3u8', 'smil', 'mpd'), +) +MEDIA_EXTENSIONS.video = MEDIA_EXTENSIONS.common_video + MEDIA_EXTENSIONS.video +MEDIA_EXTENSIONS.audio = MEDIA_EXTENSIONS.common_audio + MEDIA_EXTENSIONS.audio + +KNOWN_EXTENSIONS = ( + MEDIA_EXTENSIONS.video + MEDIA_EXTENSIONS.audio + + MEDIA_EXTENSIONS.manifests +) + + +class _UnsafeExtensionError(Exception): + """ + Mitigation exception for unwanted file overwrite/path traversal + + Ref: https://github.com/yt-dlp/yt-dlp/security/advisories/GHSA-79w7-vh3h-8g4j + """ + _ALLOWED_EXTENSIONS = frozenset(itertools.chain( + ( # internal + 'description', + 'json', + 'meta', + 'orig', + 'part', + 'temp', + 'uncut', + 'unknown_video', + 'ytdl', + ), + # video + MEDIA_EXTENSIONS.video, ( + 'avif', + 'ismv', + 'm2ts', + 'm4s', + 'mng', + 'mpeg', + 'qt', + 'swf', + 'ts', + 'vp9', + 'wvm', + ), + # audio + MEDIA_EXTENSIONS.audio, ( + 'isma', + 'mid', + 'mpga', + 'ra', + ), + # image + MEDIA_EXTENSIONS.thumbnails, ( + 'bmp', + 'gif', + 'ico', + 'heic', + 'jng', + 'jpeg', + 'jxl', + 'svg', + 'tif', + 'wbmp', + ), + # subtitle + MEDIA_EXTENSIONS.subtitles, ( + 'dfxp', + 'fs', + 'ismt', + 'sami', + 'scc', + 'ssa', + 'tt', + ), + # others + MEDIA_EXTENSIONS.manifests, + ( + # not used in yt-dl + # *MEDIA_EXTENSIONS.storyboards, + # 'desktop', + # 'ism', + # 'm3u', + # 'sbv', + # 'swp', + # 'url', + # 'webloc', + # 'xml', + ))) + + def __init__(self, extension): + super(_UnsafeExtensionError, self).__init__('unsafe file extension: {0!r}'.format(extension)) + self.extension = extension + + # support --no-check-extensions + lenient = False + + @classmethod + def sanitize_extension(cls, extension, **kwargs): + # ... /, *, prepend=False + prepend = kwargs.get('prepend', False) + + if '/' in extension or '\\' in extension: + raise cls(extension) + + if not prepend: + last = extension.rpartition('.')[-1] + if last == 'bin': + extension = last = 'unknown_video' + if not (cls.lenient or last.lower() in cls._ALLOWED_EXTENSIONS): + raise cls(extension) + + return extension diff --git a/yt-dlp/.github/workflows/build.yml b/yt-dlp/.github/workflows/build.yml index 1adb62dfb1..12ec5b0d8c 100644 --- a/yt-dlp/.github/workflows/build.yml +++ b/yt-dlp/.github/workflows/build.yml @@ -525,6 +525,10 @@ jobs: # make sure SHA sums are also printed to stdout sha256sum -- * | tee ../SHA2-256SUMS sha512sum -- * | tee ../SHA2-512SUMS + # also print as permanent annotations to the summary page + while read -r shasum; do + echo "::notice title=${shasum##* }::sha256: ${shasum% *}" + done < ../SHA2-256SUMS - name: Make Update spec run: | diff --git a/yt-dlp/CONTRIBUTING.md b/yt-dlp/CONTRIBUTING.md index aeba3c44d1..dbae6476f6 100644 --- a/yt-dlp/CONTRIBUTING.md +++ b/yt-dlp/CONTRIBUTING.md @@ -127,7 +127,7 @@ While these steps won't necessarily ensure that no misuse of the account takes p ### Is the website primarily used for piracy? -We follow [youtube-dl's policy](https://github.com/ytdl-org/youtube-dl#can-you-add-support-for-this-anime-video-site-or-site-which-shows-current-movies-for-free) to not support services that is primarily used for infringing copyright. Additionally, it has been decided to not to support porn sites that specialize in fakes. We also cannot support any service that serves only [DRM protected content](https://en.wikipedia.org/wiki/Digital_rights_management). +We follow [youtube-dl's policy](https://github.com/ytdl-org/youtube-dl#can-you-add-support-for-this-anime-video-site-or-site-which-shows-current-movies-for-free) to not support services that is primarily used for infringing copyright. Additionally, it has been decided to not to support porn sites that specialize in fakes. We also cannot support any service that serves only [DRM protected content](https://en.wikipedia.org/wiki/Digital_rights_management). @@ -215,8 +215,8 @@ After you have ensured this site is distributing its content legally, you can fo ```python from .common import InfoExtractor - - + + class YourExtractorIE(InfoExtractor): _VALID_URL = r'https?://(?:www\.)?yourextractor\.com/watch/(?P[0-9]+)' _TESTS = [{ @@ -244,7 +244,7 @@ After you have ensured this site is distributing its content legally, you can fo def _real_extract(self, url): video_id = self._match_id(url) webpage = self._download_webpage(url, video_id) - + # TODO more code goes here, for example ... title = self._html_search_regex(r'

    (.+?)

    ', webpage, 'title') @@ -320,7 +320,7 @@ Say you have some source dictionary `meta` that you've fetched as JSON with HTTP ```python meta = self._download_json(url, video_id) ``` - + Assume at this point `meta`'s layout is: ```python @@ -750,7 +750,7 @@ Use `url_or_none` for safe URL processing. Use `traverse_obj` and `try_call` (superseeds `dict_get` and `try_get`) for safe metadata extraction from parsed JSON. -Use `unified_strdate` for uniform `upload_date` or any `YYYYMMDD` meta field extraction, `unified_timestamp` for uniform `timestamp` extraction, `parse_filesize` for `filesize` extraction, `parse_count` for count meta fields extraction, `parse_resolution`, `parse_duration` for `duration` extraction, `parse_age_limit` for `age_limit` extraction. +Use `unified_strdate` for uniform `upload_date` or any `YYYYMMDD` meta field extraction, `unified_timestamp` for uniform `timestamp` extraction, `parse_filesize` for `filesize` extraction, `parse_count` for count meta fields extraction, `parse_resolution`, `parse_duration` for `duration` extraction, `parse_age_limit` for `age_limit` extraction. Explore [`yt_dlp/utils/`](yt_dlp/utils/) for more useful convenience functions. diff --git a/yt-dlp/CONTRIBUTORS b/yt-dlp/CONTRIBUTORS index e0d1668ee2..a893572756 100644 --- a/yt-dlp/CONTRIBUTORS +++ b/yt-dlp/CONTRIBUTORS @@ -631,3 +631,16 @@ voidful vtexier WyohKnott trueauracoral +ASertacAkkaya +axpauls +chilinux +hafeoz +JSubelj +jucor +megumintyan +mgedmin +Niluge-KiWi +peisenwang +TheZ3ro +tippfehlr +varunchopra diff --git a/yt-dlp/Changelog.md b/yt-dlp/Changelog.md index 267330208e..3dbbc210c9 100644 --- a/yt-dlp/Changelog.md +++ b/yt-dlp/Changelog.md @@ -4,6 +4,87 @@ # To create a release, dispatch the https://github.com/yt-dlp/yt-dlp/actions/workflows/release.yml workflow on master --> +### 2024.07.01 + +#### Important changes +- Security: [[CVE-2024-10123](https://nvd.nist.gov/vuln/detail/CVE-2024-10123)] [Properly sanitize file-extension to prevent file system modification and RCE](https://github.com/yt-dlp/yt-dlp/security/advisories/GHSA-79w7-vh3h-8g4j) + - Unsafe extensions are now blocked from being downloaded + +#### Core changes +- [Add `playlist_channel` and `playlist_channel_id` fields](https://github.com/yt-dlp/yt-dlp/commit/55e3e6fd21e741ec5ae3d8624de5e5ea345810eb) ([#10266](https://github.com/yt-dlp/yt-dlp/issues/10266)) by [bashonly](https://github.com/bashonly) +- [Disallow unsafe extensions (CVE-2024-38519)](https://github.com/yt-dlp/yt-dlp/commit/5ce582448ececb8d9c30c8c31f58330090ced03a) by [Grub4K](https://github.com/Grub4K) +- **cookies**: [Fix `--cookies-from-browser` DE detection on Linux](https://github.com/yt-dlp/yt-dlp/commit/a8520244b8642880e4d35925e9e49eff94d548de) ([#10237](https://github.com/yt-dlp/yt-dlp/issues/10237)) by [peisenwang](https://github.com/peisenwang) + +#### Extractor changes +- **afreecatv** + - [Support browser impersonation](https://github.com/yt-dlp/yt-dlp/commit/e8352ad6599de7b5371dc39a1a1edc7890aaedb4) ([#10174](https://github.com/yt-dlp/yt-dlp/issues/10174)) by [hui1601](https://github.com/hui1601) + - catchstory: [Add extractor](https://github.com/yt-dlp/yt-dlp/commit/054a3ba7d1293f9fbe21800d62d1e5ddcbded238) ([#10235](https://github.com/yt-dlp/yt-dlp/issues/10235)) by [hui1601](https://github.com/hui1601) +- **bilibili**: [Support legacy formats](https://github.com/yt-dlp/yt-dlp/commit/1d6ab17d0752ee9cf19e3e63c7dec7b600d3f228) ([#9117](https://github.com/yt-dlp/yt-dlp/issues/9117)) by [c-basalt](https://github.com/c-basalt), [GD-Slime](https://github.com/GD-Slime) +- **bitchute**: [Fix extractors](https://github.com/yt-dlp/yt-dlp/commit/5b1a2aa978d0074cee278e7659f32f52ecc4ab53) ([#10301](https://github.com/yt-dlp/yt-dlp/issues/10301)) by [seproDev](https://github.com/seproDev) +- **brightcove**: [Upgrade requests to HTTPS](https://github.com/yt-dlp/yt-dlp/commit/90c3721a322756bb7f4ca10ceb73744500bee37e) ([#10202](https://github.com/yt-dlp/yt-dlp/issues/10202)) by [bashonly](https://github.com/bashonly) +- **cloudflarestream**: [Fix `_VALID_URL` and embed extraction](https://github.com/yt-dlp/yt-dlp/commit/7aa322c02cec54eb77154a89da7e400194f0bd03) ([#10215](https://github.com/yt-dlp/yt-dlp/issues/10215)) by [bashonly](https://github.com/bashonly) +- **cloudycdn**: [Fix formats extraction](https://github.com/yt-dlp/yt-dlp/commit/b758877afa225747fba81c8a580e27583a231734) ([#10271](https://github.com/yt-dlp/yt-dlp/issues/10271)) by [Caesim404](https://github.com/Caesim404) +- **digitalconcerthall**: [Rework extractor](https://github.com/yt-dlp/yt-dlp/commit/2a4f2e82dbeeb0c9130883c83dac689d5260c871) ([#10152](https://github.com/yt-dlp/yt-dlp/issues/10152)) by [seproDev](https://github.com/seproDev), [tippfehlr](https://github.com/tippfehlr) +- **facebook**: reel: [Fix extraction](https://github.com/yt-dlp/yt-dlp/commit/8ca1d57ed08d00efa117820a5a82f763b20e2d1d) ([#10232](https://github.com/yt-dlp/yt-dlp/issues/10232)) by [bashonly](https://github.com/bashonly) +- **francetv** + - [Detect and raise errors for DRM](https://github.com/yt-dlp/yt-dlp/commit/3690c2f59827c79a1bbe388a7c1ae75db7477db2) ([#10165](https://github.com/yt-dlp/yt-dlp/issues/10165)) by [bashonly](https://github.com/bashonly) + - [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/081708d6074dfbb907e25af61ba530bba0d4b31d) ([#10177](https://github.com/yt-dlp/yt-dlp/issues/10177)) by [bashonly](https://github.com/bashonly) +- **generic**: [Add `key_query` extractor-arg](https://github.com/yt-dlp/yt-dlp/commit/5dbac313ae4e3e8521dfe2e1a6a048a98ff4b4fe) by [bashonly](https://github.com/bashonly) +- **graspop**: [Add extractor](https://github.com/yt-dlp/yt-dlp/commit/1d369b4096d79233e0ac2c93762746a64d7a69c8) ([#10268](https://github.com/yt-dlp/yt-dlp/issues/10268)) by [Niluge-KiWi](https://github.com/Niluge-KiWi) +- **jiocinema**: series: [Fix extraction](https://github.com/yt-dlp/yt-dlp/commit/61714f46956f61612032bba857aed7ad1387eccd) ([#10139](https://github.com/yt-dlp/yt-dlp/issues/10139)) by [varunchopra](https://github.com/varunchopra) +- **khanacademy**: [Fix extractors](https://github.com/yt-dlp/yt-dlp/commit/4093eb1fcc29a0e2aea9adfcba479787d9ae0c0c) ([#9136](https://github.com/yt-dlp/yt-dlp/issues/9136)) by [c-basalt](https://github.com/c-basalt) +- **laracasts**: [Add extractors](https://github.com/yt-dlp/yt-dlp/commit/b8da8a98f897599095d4ef1644b8c5fd39921118) ([#10055](https://github.com/yt-dlp/yt-dlp/issues/10055)) by [ASertacAkkaya](https://github.com/ASertacAkkaya), [seproDev](https://github.com/seproDev) +- **matchtv**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/f3411af12e209bc5624e1ac31271b8aabe2d3c90) ([#10190](https://github.com/yt-dlp/yt-dlp/issues/10190)) by [megumintyan](https://github.com/megumintyan) +- **mediasite**: [Fix extraction](https://github.com/yt-dlp/yt-dlp/commit/0953209a857c51648aee89d205c086b0e1dd3864) ([#10273](https://github.com/yt-dlp/yt-dlp/issues/10273)) by [bashonly](https://github.com/bashonly) +- **microsoftembed**: [Add extractors for dev materials](https://github.com/yt-dlp/yt-dlp/commit/9200bc70c94546b2191bb6fbfc9cea98a919cc56) ([#9177](https://github.com/yt-dlp/yt-dlp/issues/9177)) by [c-basalt](https://github.com/c-basalt) +- **mlbtv**: [Fix extraction](https://github.com/yt-dlp/yt-dlp/commit/61edf57f8f13f6dfd81154174e647eb5fdd26089) ([#10296](https://github.com/yt-dlp/yt-dlp/issues/10296)) by [bashonly](https://github.com/bashonly) +- **neteasemusic**: [Extract more formats from new API](https://github.com/yt-dlp/yt-dlp/commit/7a03f88c40b80d3cf54f68edd9d4bdd6aa527570) ([#10258](https://github.com/yt-dlp/yt-dlp/issues/10258)) by [hafeoz](https://github.com/hafeoz) +- **nhkradiru**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/b8e2a5e0e1030076f833917906e19bb6c7b318f6) ([#10106](https://github.com/yt-dlp/yt-dlp/issues/10106)) by [garret1317](https://github.com/garret1317) +- **nuum**: [Fix formats extraction](https://github.com/yt-dlp/yt-dlp/commit/aefede25561a06cba398d4f593eee2fbe942693b) ([#10316](https://github.com/yt-dlp/yt-dlp/issues/10316)) by [DmitryScaletta](https://github.com/DmitryScaletta) +- **orf** + - on + - [Add `prefer_segments_playlist` extractor-arg](https://github.com/yt-dlp/yt-dlp/commit/e6a22834df1776ec4e486526f6df2bf53cb7e06f) ([#10314](https://github.com/yt-dlp/yt-dlp/issues/10314)) by [seproDev](https://github.com/seproDev) + - [Support segmented episodes](https://github.com/yt-dlp/yt-dlp/commit/8b46ad4d8b8ee8c5472af0cde863baa89ca3f425) ([#10053](https://github.com/yt-dlp/yt-dlp/issues/10053)) by [seproDev](https://github.com/seproDev) +- **patreoncampaign**: [Fix `campaign_id` extraction](https://github.com/yt-dlp/yt-dlp/commit/2e5a47da400b645aadbda6afd1156bd89c744f48) ([#10070](https://github.com/yt-dlp/yt-dlp/issues/10070)) by [bashonly](https://github.com/bashonly) +- **podbayfm**: [Fix extraction](https://github.com/yt-dlp/yt-dlp/commit/d4b52ce3fcb8d9578ed12365648eaba8718c603e) ([#10195](https://github.com/yt-dlp/yt-dlp/issues/10195)) by [bashonly](https://github.com/bashonly), [seproDev](https://github.com/seproDev) +- **pokergo**: [Make metadata extraction non-fatal](https://github.com/yt-dlp/yt-dlp/commit/36e8dd832579b5375a0f6626af4268b86b4eb21a) ([#10319](https://github.com/yt-dlp/yt-dlp/issues/10319)) by [axpauls](https://github.com/axpauls) +- **qqmusic**: [Fix extractors](https://github.com/yt-dlp/yt-dlp/commit/4f5d7be3c5590bb257d8ff521572aee9839ab754) ([#9768](https://github.com/yt-dlp/yt-dlp/issues/9768)) by [c-basalt](https://github.com/c-basalt) +- **rtvslo.si**: show: [Add extractor](https://github.com/yt-dlp/yt-dlp/commit/92a1c4abaeeba9a69d611c57b73555cb1a1f00ad) ([#8418](https://github.com/yt-dlp/yt-dlp/issues/8418)) by [JSubelj](https://github.com/JSubelj), [seproDev](https://github.com/seproDev) +- **soundcloud**: [Fix `download` format extraction](https://github.com/yt-dlp/yt-dlp/commit/e53e56b73543799638fa6abb0c78f8b091aa84e1) ([#10125](https://github.com/yt-dlp/yt-dlp/issues/10125)) by [bashonly](https://github.com/bashonly) +- **sproutvideo**: [Add extractors](https://github.com/yt-dlp/yt-dlp/commit/d6c2c2bc84f1434255be5c73baeb17d893d2c0d4) ([#10098](https://github.com/yt-dlp/yt-dlp/issues/10098)) by [bashonly](https://github.com/bashonly), [TheZ3ro](https://github.com/TheZ3ro) +- **tiktok** + - [Detect and raise when login is required](https://github.com/yt-dlp/yt-dlp/commit/ea88129784fcbb6987161df9ba05909325d8e2e9) ([#10124](https://github.com/yt-dlp/yt-dlp/issues/10124)) by [bashonly](https://github.com/bashonly) + - [Fix API extraction](https://github.com/yt-dlp/yt-dlp/commit/96472d72f29550c25c5dcedcde02c38c192b0011) ([#10216](https://github.com/yt-dlp/yt-dlp/issues/10216)) by [bashonly](https://github.com/bashonly) +- **tubitv** + - [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/bef9a9e5361fd7a72e21d0f1a8c8afb70d89e8c5) ([#9975](https://github.com/yt-dlp/yt-dlp/issues/9975)) by [chilinux](https://github.com/chilinux) + - series: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/d7d861811c15585a4f7ec9d5ae68d2ac28de28a0) ([#10116](https://github.com/yt-dlp/yt-dlp/issues/10116)) by [bashonly](https://github.com/bashonly) +- **vimeo**: [Support browser impersonation](https://github.com/yt-dlp/yt-dlp/commit/d4b99a233314bf31f9c842035ea9884673d5313a) ([#10327](https://github.com/yt-dlp/yt-dlp/issues/10327)) by [bashonly](https://github.com/bashonly) +- **youtube** + - [Extract all formats from multi-language m3u8s](https://github.com/yt-dlp/yt-dlp/commit/9bd85019931927a99b0fe0dc58ac51acca9fbe72) ([#9875](https://github.com/yt-dlp/yt-dlp/issues/9875)) by [bashonly](https://github.com/bashonly), [clienthax](https://github.com/clienthax) + - [Skip formats if nsig decoding fails](https://github.com/yt-dlp/yt-dlp/commit/800ec085ccf98420584d8bb38c20a2c079669b09) ([#10223](https://github.com/yt-dlp/yt-dlp/issues/10223)) by [bashonly](https://github.com/bashonly) + - [Suppress "Unavailable videos are hidden" warning](https://github.com/yt-dlp/yt-dlp/commit/24f3097ea9a470a984d0454dc013cafa2325f5f8) ([#10159](https://github.com/yt-dlp/yt-dlp/issues/10159)) by [mgedmin](https://github.com/mgedmin) + - tab: [Fix channel metadata extraction](https://github.com/yt-dlp/yt-dlp/commit/a0d9967f6822fc279e86bce33464194985148727) ([#10071](https://github.com/yt-dlp/yt-dlp/issues/10071)) by [bashonly](https://github.com/bashonly), [shoxie007](https://github.com/shoxie007) + +#### Downloader changes +- **hls**: [Apply `extra_param_to_key_url` from info dict](https://github.com/yt-dlp/yt-dlp/commit/ca8885edd93bdf8912af6c22ee335b6222cb9ba9) by [bashonly](https://github.com/bashonly) + +#### Postprocessor changes +- **embedthumbnail**: [Fix postprocessor](https://github.com/yt-dlp/yt-dlp/commit/f2a4ea1794718e4dc0148bc172cb877f1080903b) ([#10248](https://github.com/yt-dlp/yt-dlp/issues/10248)) by [Grub4K](https://github.com/Grub4K) + +#### Networking changes +- **Request Handler**: requests: [Bump minimum `requests` version to 2.32.2](https://github.com/yt-dlp/yt-dlp/commit/db50f19d76c6870a5a13d0cab9287d684fd7449a) ([#10079](https://github.com/yt-dlp/yt-dlp/issues/10079)) by [bashonly](https://github.com/bashonly) + +#### Misc. changes +- **build** + - [Bump Pyinstaller to `>=6.7.0` for all builds](https://github.com/yt-dlp/yt-dlp/commit/5fdd13006a1c5d78642c8d3c4c7df0448273c2ae) ([#10069](https://github.com/yt-dlp/yt-dlp/issues/10069)) by [bashonly](https://github.com/bashonly), [seproDev](https://github.com/seproDev) + - [Cache dependencies for `macos` job](https://github.com/yt-dlp/yt-dlp/commit/46c1b7cfec1d0e6155083ca7e6948674c64ecb97) ([#10088](https://github.com/yt-dlp/yt-dlp/issues/10088)) by [bashonly](https://github.com/bashonly) + - [Use `macos-12` image for `yt-dlp_macos`](https://github.com/yt-dlp/yt-dlp/commit/03334d639d5282cd4107edb32c623ba400262fc4) ([#10063](https://github.com/yt-dlp/yt-dlp/issues/10063)) by [bashonly](https://github.com/bashonly) +- **cleanup** + - [Add more ruff rules](https://github.com/yt-dlp/yt-dlp/commit/add96eb9f84cfffe85682bf2fb85135746994ee8) ([#10149](https://github.com/yt-dlp/yt-dlp/issues/10149)) by [seproDev](https://github.com/seproDev) + - [Bump ruff to 0.5.x](https://github.com/yt-dlp/yt-dlp/commit/7814c50948a2b9a4c746441ecbc509ae563d5d1f) ([#10282](https://github.com/yt-dlp/yt-dlp/issues/10282)) by [seproDev](https://github.com/seproDev) + - Miscellaneous: [6aaf96a](https://github.com/yt-dlp/yt-dlp/commit/6aaf96a3d6e7d0d426e97e11a2fcf52fda00e733) by [bashonly](https://github.com/bashonly), [c-basalt](https://github.com/c-basalt), [jucor](https://github.com/jucor), [seproDev](https://github.com/seproDev) +- **test**: download: [Raise on network errors](https://github.com/yt-dlp/yt-dlp/commit/54a63e80af82791d2f0985bd0176bb182963fd5f) ([#10283](https://github.com/yt-dlp/yt-dlp/issues/10283)) by [bashonly](https://github.com/bashonly), [seproDev](https://github.com/seproDev) + ### 2024.05.27 #### Extractor changes diff --git a/yt-dlp/Collaborators.md b/yt-dlp/Collaborators.md index 894a853c9b..ee748eb7fd 100644 --- a/yt-dlp/Collaborators.md +++ b/yt-dlp/Collaborators.md @@ -61,3 +61,10 @@ You can also find lists of all [contributors of yt-dlp](CONTRIBUTORS) and [autho * Reworked internals like `traverse_obj`, various core refactors and bugs fixes * Implemented proper progress reporting for parallel downloads * Improved/fixed/added Bundestag, crunchyroll, pr0gramm, Twitter, WrestleUniverse etc + + +## [sepro](https://github.com/seproDev) + +* UX improvements: Warn when ffmpeg is missing, warn when double-clicking exe +* Code cleanup: Remove dead extractors, mark extractors as broken, enable/apply ruff rules +* Improved/fixed/added ArdMediathek, DRTV, Floatplane, MagentaMusik, Naver, Nebula, OnDemandKorea, Vbox7 etc diff --git a/yt-dlp/README.md b/yt-dlp/README.md index ed022c0b9d..e8aeb93f76 100644 --- a/yt-dlp/README.md +++ b/yt-dlp/README.md @@ -141,7 +141,7 @@ You can use `yt-dlp -U` to update if you are using the [release binaries](#relea If you [installed with pip](https://github.com/yt-dlp/yt-dlp/wiki/Installation#with-pip), simply re-run the same command that was used to install the program -For other third-party package managers, see [the wiki](https://github.com/yt-dlp/yt-dlp/wiki/Installation#third-party-package-managers) or refer their documentation +For other third-party package managers, see [the wiki](https://github.com/yt-dlp/yt-dlp/wiki/Installation#third-party-package-managers) or refer to their documentation
    @@ -184,10 +184,10 @@ While all the other dependencies are optional, `ffmpeg` and `ffprobe` are highly ### Strongly recommended -* [**ffmpeg** and **ffprobe**](https://www.ffmpeg.org) - Required for [merging separate video and audio files](#format-selection) as well as for various [post-processing](#post-processing-options) tasks. License [depends on the build](https://www.ffmpeg.org/legal.html) +* [**ffmpeg** and **ffprobe**](https://www.ffmpeg.org) - Required for [merging separate video and audio files](#format-selection), as well as for various [post-processing](#post-processing-options) tasks. License [depends on the build](https://www.ffmpeg.org/legal.html) There are bugs in ffmpeg that cause various issues when used alongside yt-dlp. Since ffmpeg is such an important dependency, we provide [custom builds](https://github.com/yt-dlp/FFmpeg-Builds#ffmpeg-static-auto-builds) with patches for some of these issues at [yt-dlp/FFmpeg-Builds](https://github.com/yt-dlp/FFmpeg-Builds). See [the readme](https://github.com/yt-dlp/FFmpeg-Builds#patches-applied) for details on the specific issues solved by these builds - + **Important**: What you need is ffmpeg *binary*, **NOT** [the Python package of the same name](https://pypi.org/project/ffmpeg) ### Networking @@ -198,7 +198,7 @@ While all the other dependencies are optional, `ffmpeg` and `ffprobe` are highly #### Impersonation -The following provide support for impersonating browser requests. This may be required for some sites that employ TLS fingerprinting. +The following provide support for impersonating browser requests. This may be required for some sites that employ TLS fingerprinting. * [**curl_cffi**](https://github.com/yifeikong/curl_cffi) (recommended) - Python binding for [curl-impersonate](https://github.com/lwthiker/curl-impersonate). Provides impersonation targets for Chrome, Edge and Safari. Licensed under [MIT](https://github.com/yifeikong/curl_cffi/blob/main/LICENSE) * Can be installed with the `curl-cffi` group, e.g. `pip install "yt-dlp[default,curl-cffi]"` @@ -275,7 +275,7 @@ py -m bundle.py2exe ### Related scripts * **`devscripts/install_deps.py`** - Install dependencies for yt-dlp. -* **`devscripts/update-version.py`** - Update the version number based on current date. +* **`devscripts/update-version.py`** - Update the version number based on the current date. * **`devscripts/set-variant.py`** - Set the build variant of the executable. * **`devscripts/make_changelog.py`** - Create a markdown changelog using short commit messages and update `CONTRIBUTORS` file. * **`devscripts/make_lazy_extractors.py`** - Create lazy extractors. Running this before building the binaries (any variant) will improve their startup performance. Set the environment variable `YTDLP_NO_LAZY_EXTRACTORS=1` if you wish to forcefully disable lazy extractor loading. @@ -456,8 +456,8 @@ If you fork the project on GitHub, you can run your fork's [build workflow](.git is not present, and "&" to check multiple conditions. Use a "\" to escape "&" or quotes if needed. If used multiple times, - the filter matches if atleast one of the - conditions are met. E.g. --match-filter + the filter matches if at least one of the + conditions is met. E.g. --match-filter !is_live --match-filter "like_count>?100 & description~='(?i)\bcats \& dogs\b'" matches only videos that are not live OR those that @@ -674,7 +674,7 @@ If you fork the project on GitHub, you can run your fork's [build workflow](.git PROFILE to load cookies from, and the CONTAINER name (if Firefox) ("none" for no container) can be given with their - respective seperators. By default, all + respective separators. By default, all containers of the most recently accessed profile are used. Currently supported keyrings are: basictext, gnomekeyring, @@ -1036,7 +1036,7 @@ If you fork the project on GitHub, you can run your fork's [build workflow](.git --print/--output), "before_dl" (before each video download), "post_process" (after each video download; default), "after_move" - (after moving video file to it's final + (after moving video file to its final locations), "after_video" (after downloading and processing all formats of a video), or "playlist" (at end of playlist). This option @@ -1125,7 +1125,7 @@ You can configure yt-dlp by placing any supported command line option to a confi * `/etc/yt-dlp/config` * `/etc/yt-dlp/config.txt` -E.g. with the following configuration file yt-dlp will always extract the audio, not copy the mtime, use a proxy and save all videos under `YouTube` directory in your home directory: +E.g. with the following configuration file, yt-dlp will always extract the audio, not copy the mtime, use a proxy and save all videos under `YouTube` directory in your home directory: ``` # Lines starting with # are comments @@ -1142,7 +1142,7 @@ E.g. with the following configuration file yt-dlp will always extract the audio, -o ~/YouTube/%(title)s.%(ext)s ``` -**Note**: Options in configuration file are just the same options aka switches used in regular command line calls; thus there **must be no whitespace** after `-` or `--`, e.g. `-o` or `--proxy` but not `- o` or `-- proxy`. They must also be quoted when necessary as-if it were a UNIX shell. +**Note**: Options in configuration file are just the same options aka switches used in regular command line calls; thus there **must be no whitespace** after `-` or `--`, e.g. `-o` or `--proxy` but not `- o` or `-- proxy`. They must also be quoted when necessary, as if it were a UNIX shell. You can use `--ignore-config` if you want to disable all configuration files for a particular yt-dlp run. If `--ignore-config` is found inside any configuration file, no further configuration will be loaded. For example, having the option in the portable configuration file prevents loading of home, user, and system configurations. Additionally, (for backward compatibility) if `--ignore-config` is found inside the system configuration file, the user configuration is not loaded. @@ -1154,12 +1154,12 @@ If you want your file to be decoded differently, add `# coding: ENCODING` to the ### Authentication with netrc -You may also want to configure automatic credentials storage for extractors that support authentication (by providing login and password with `--username` and `--password`) in order not to pass credentials as command line arguments on every yt-dlp execution and prevent tracking plain text passwords in the shell command history. You can achieve this using a [`.netrc` file](https://stackoverflow.com/tags/.netrc/info) on a per-extractor basis. For that you will need to create a `.netrc` file in `--netrc-location` and restrict permissions to read/write by only you: +You may also want to configure automatic credentials storage for extractors that support authentication (by providing login and password with `--username` and `--password`) in order not to pass credentials as command line arguments on every yt-dlp execution and prevent tracking plain text passwords in the shell command history. You can achieve this using a [`.netrc` file](https://stackoverflow.com/tags/.netrc/info) on a per-extractor basis. For that, you will need to create a `.netrc` file in `--netrc-location` and restrict permissions to read/write by only you: ``` touch ${HOME}/.netrc chmod a-rwx,u+rw ${HOME}/.netrc ``` -After that you can add credentials for an extractor in the following format, where *extractor* is the name of the extractor in lowercase: +After that, you can add credentials for an extractor in the following format, where *extractor* is the name of the extractor in lowercase: ``` machine login password ``` @@ -1201,7 +1201,7 @@ It may however also contain special sequences that will be replaced when downloa The field names themselves (the part inside the parenthesis) can also have some special formatting: -1. **Object traversal**: The dictionaries and lists available in metadata can be traversed by using a dot `.` separator; e.g. `%(tags.0)s`, `%(subtitles.en.-1.ext)s`. You can do Python slicing with colon `:`; E.g. `%(id.3:7:-1)s`, `%(formats.:.format_id)s`. Curly braces `{}` can be used to build dictionaries with only specific keys; e.g. `%(formats.:.{format_id,height})#j`. An empty field name `%()s` refers to the entire infodict; e.g. `%(.{id,title})s`. Note that all the fields that become available using this method are not listed below. Use `-j` to see such fields +1. **Object traversal**: The dictionaries and lists available in metadata can be traversed by using a dot `.` separator; e.g. `%(tags.0)s`, `%(subtitles.en.-1.ext)s`. You can do Python slicing with colon `:`; E.g. `%(id.3:7)s`, `%(id.6:2:-1)s`, `%(formats.:.format_id)s`. Curly braces `{}` can be used to build dictionaries with only specific keys; e.g. `%(formats.:.{format_id,height})#j`. An empty field name `%()s` refers to the entire infodict; e.g. `%(.{id,title})s`. Note that all the fields that become available using this method are not listed below. Use `-j` to see such fields 1. **Arithmetic**: Simple arithmetic can be done on numeric fields using `+`, `-` and `*`. E.g. `%(playlist_index+10)03d`, `%(n_entries+1-playlist_index)d` @@ -1222,7 +1222,7 @@ To summarize, the general syntax for a field is: %(name[.keys][addition][>strf][,alternate][&replacement][|default])[flags][width][.precision][length]type ``` -Additionally, you can set different output templates for the various metadata files separately from the general output template by specifying the type of file followed by the template separated by a colon `:`. The different file types supported are `subtitle`, `thumbnail`, `description`, `annotation` (deprecated), `infojson`, `link`, `pl_thumbnail`, `pl_description`, `pl_infojson`, `chapter`, `pl_video`. E.g. `-o "%(title)s.%(ext)s" -o "thumbnail:%(title)s\%(title)s.%(ext)s"` will put the thumbnails in a folder with the same name as the video. If any of the templates is empty, that type of file will not be written. E.g. `--write-thumbnail -o "thumbnail:"` will write thumbnails only for playlists and not for video. +Additionally, you can set different output templates for the various metadata files separately from the general output template by specifying the type of file followed by the template separated by a colon `:`. The different file types supported are `subtitle`, `thumbnail`, `description`, `annotation` (deprecated), `infojson`, `link`, `pl_thumbnail`, `pl_description`, `pl_infojson`, `chapter`, `pl_video`. E.g. `-o "%(title)s.%(ext)s" -o "thumbnail:%(title)s\%(title)s.%(ext)s"` will put the thumbnails in a folder with the same name as the video. If any of the templates is empty, that type of file will not be written. E.g. `--write-thumbnail -o "thumbnail:"` will write thumbnails only for playlists and not for video. @@ -1282,7 +1282,7 @@ The available fields are: - `n_entries` (numeric): Total number of extracted items in the playlist - `playlist_id` (string): Identifier of the playlist that contains the video - `playlist_title` (string): Name of the playlist that contains the video - - `playlist` (string): `playlist_id` or `playlist_title` + - `playlist` (string): `playlist_title` if available or else `playlist_id` - `playlist_count` (numeric): Total number of items in the playlist. May not be known if entire playlist is not extracted - `playlist_index` (numeric): Index of the video in the playlist padded with leading zeros according the final index - `playlist_autonumber` (numeric): Position of the video in the playlist download queue padded with leading zeros according to the total length of the playlist @@ -1290,7 +1290,7 @@ The available fields are: - `playlist_uploader_id` (string): Nickname or id of the playlist uploader - `playlist_channel` (string): Display name of the channel that uploaded the playlist - `playlist_channel_id` (string): Identifier of the channel that uploaded the playlist - - `webpage_url` (string): A URL to the video webpage which if given to yt-dlp should allow to get the same result again + - `webpage_url` (string): A URL to the video webpage which, if given to yt-dlp, should yield the same result again - `webpage_url_basename` (string): The basename of the webpage URL - `webpage_url_domain` (string): The domain of the webpage URL - `original_url` (string): The URL given by the user (or same as `webpage_url` for playlist entries) @@ -1306,10 +1306,10 @@ Available for the video that belongs to some logical chapter or section: - `chapter_number` (numeric): Number of the chapter the video belongs to - `chapter_id` (string): Id of the chapter the video belongs to -Available for the video that is an episode of some series or programme: +Available for the video that is an episode of some series or program: - - `series` (string): Title of the series or programme the video episode belongs to - - `series_id` (string): Id of the series or programme the video episode belongs to + - `series` (string): Title of the series or program the video episode belongs to + - `series_id` (string): Id of the series or program the video episode belongs to - `season` (string): Title of the season the video episode belongs to - `season_number` (numeric): Number of the season the video episode belongs to - `season_id` (string): Id of the season the video episode belongs to @@ -1349,9 +1349,9 @@ Available only when used in `--print`: - `thumbnails_table` (table): The thumbnail format table as printed by `--list-thumbnails` - `subtitles_table` (table): The subtitle format table as printed by `--list-subs` - `automatic_captions_table` (table): The automatic subtitle format table as printed by `--list-subs` - + Available only after the video is downloaded (`post_process`/`after_move`): - + - `filepath`: Actual path of downloaded video file Available only in `--sponsorblock-chapter-title`: @@ -1366,7 +1366,7 @@ Available only in `--sponsorblock-chapter-title`: Each aforementioned sequence when referenced in an output template will be replaced by the actual value corresponding to the sequence name. E.g. for `-o %(title)s-%(id)s.%(ext)s` and an mp4 video with title `yt-dlp test video` and id `BaW_jenozKc`, this will result in a `yt-dlp test video-BaW_jenozKc.mp4` file created in the current directory. -**Note**: Some of the sequences are not guaranteed to be present since they depend on the metadata obtained by a particular extractor. Such sequences will be replaced with placeholder value provided with `--output-na-placeholder` (`NA` by default). +**Note**: Some of the sequences are not guaranteed to be present, since they depend on the metadata obtained by a particular extractor. Such sequences will be replaced with placeholder value provided with `--output-na-placeholder` (`NA` by default). **Tip**: Look at the `-j` output to identify which fields are available for the particular URL @@ -1444,7 +1444,7 @@ You can also use special names to select particular edge case formats: - `all`: Select **all formats** separately - `mergeall`: Select and **merge all formats** (Must be used with `--audio-multistreams`, `--video-multistreams` or both) - - `b*`, `best*`: Select the best quality format that **contains either** a video or an audio or both (ie; `vcodec!=none or acodec!=none`) + - `b*`, `best*`: Select the best quality format that **contains either** a video or an audio or both (i.e.; `vcodec!=none or acodec!=none`) - `b`, `best`: Select the best quality format that **contains both** video and audio. Equivalent to `best*[vcodec!=none][acodec!=none]` - `bv`, `bestvideo`: Select the best quality **video-only** format. Equivalent to `best*[acodec=none]` - `bv*`, `bestvideo*`: Select the best quality format that **contains video**. It may also contain audio. Equivalent to `best*[vcodec!=none]` @@ -1457,7 +1457,7 @@ You can also use special names to select particular edge case formats: - `wa`, `worstaudio`: Select the worst quality audio-only format. Equivalent to `worst*[vcodec=none]` - `wa*`, `worstaudio*`: Select the worst quality format that contains audio. It may also contain video. Equivalent to `worst*[acodec!=none]` -For example, to download the worst quality video-only format you can use `-f worstvideo`. It is however recommended not to use `worst` and related options. When your format selector is `worst`, the format which is worst in all respects is selected. Most of the time, what you actually want is the video with the smallest filesize instead. So it is generally better to use `-S +size` or more rigorously, `-S +size,+br,+res,+fps` instead of `-f worst`. See [Sorting Formats](#sorting-formats) for more details. +For example, to download the worst quality video-only format you can use `-f worstvideo`. It is, however, recommended not to use `worst` and related options. When your format selector is `worst`, the format which is worst in all respects is selected. Most of the time, what you actually want is the video with the smallest filesize instead. So it is generally better to use `-S +size` or more rigorously, `-S +size,+br,+res,+fps` instead of `-f worst`. See [Sorting Formats](#sorting-formats) for more details. You can select the n'th best format of a type by using `best.`. For example, `best.2` will select the 2nd best combined format. Similarly, `bv*.3` will select the 3rd best format that contains a video stream. @@ -1507,7 +1507,7 @@ Also filtering work for comparisons `=` (equals), `^=` (starts with), `$=` (ends Any string comparison may be prefixed with negation `!` in order to produce an opposite comparison, e.g. `!*=` (does not contain). The comparand of a string comparison needs to be quoted with either double or single quotes if it contains spaces or special characters other than `._-`. -**Note**: None of the aforementioned meta fields are guaranteed to be present since this solely depends on the metadata obtained by particular extractor, i.e. the metadata offered by the website. Any other field made available by the extractor can also be used for filtering. +**Note**: None of the aforementioned meta fields are guaranteed to be present since this solely depends on the metadata obtained by the particular extractor, i.e. the metadata offered by the website. Any other field made available by the extractor can also be used for filtering. Formats for which the value is not known are excluded unless you put a question mark (`?`) after the operator. You can combine format filters, so `-f "bv[height<=?720][tbr>500]"` selects up to 720p videos (or videos where the height is not known) with a bitrate of at least 500 kbps. You can also use the filters with `all` to download all formats that satisfy the filter, e.g. `-f "all[vcodec=none]"` selects all audio-only formats. @@ -1546,14 +1546,14 @@ The available fields are: - `abr`: Average audio bitrate in [kbps](## "1000 bits/sec") - `br`: Average bitrate in [kbps](## "1000 bits/sec"), `tbr`/`vbr`/`abr` - `asr`: Audio sample rate in Hz - + **Deprecation warning**: Many of these fields have (currently undocumented) aliases, that may be removed in a future version. It is recommended to use only the documented field names. All fields, unless specified otherwise, are sorted in descending order. To reverse this, prefix the field with a `+`. E.g. `+res` prefers format with the smallest resolution. Additionally, you can suffix a preferred value for the fields, separated by a `:`. E.g. `res:720` prefers larger videos, but no larger than 720p and the smallest video if there are no videos less than 720p. For `codec` and `ext`, you can provide two preferred values, the first for video and the second for audio. E.g. `+codec:avc:m4a` (equivalent to `+vcodec:avc,+acodec:m4a`) sets the video codec preference to `h264` > `h265` > `vp9` > `vp9.2` > `av01` > `vp8` > `h263` > `theora` and audio codec preference to `mp4a` > `aac` > `vorbis` > `opus` > `mp3` > `ac3` > `dts`. You can also make the sorting prefer the nearest values to the provided by using `~` as the delimiter. E.g. `filesize~1G` prefers the format with filesize closest to 1 GiB. -The fields `hasvid` and `ie_pref` are always given highest priority in sorting, irrespective of the user-defined order. This behaviour can be changed by using `--format-sort-force`. Apart from these, the default order used is: `lang,quality,res,fps,hdr:12,vcodec:vp9.2,channels,acodec,size,br,asr,proto,ext,hasaud,source,id`. The extractors may override this default order, but they cannot override the user-provided order. +The fields `hasvid` and `ie_pref` are always given highest priority in sorting, irrespective of the user-defined order. This behavior can be changed by using `--format-sort-force`. Apart from these, the default order used is: `lang,quality,res,fps,hdr:12,vcodec:vp9.2,channels,acodec,size,br,asr,proto,ext,hasaud,source,id`. The extractors may override this default order, but they cannot override the user-provided order. -Note that the default has `vcodec:vp9.2`; i.e. `av1` is not preferred. Similarly, the default for hdr is `hdr:12`; i.e. dolby vision is not preferred. These choices are made since DV and AV1 formats are not yet fully compatible with most devices. This may be changed in the future as more devices become capable of smoothly playing back these formats. +Note that the default has `vcodec:vp9.2`; i.e. `av1` is not preferred. Similarly, the default for hdr is `hdr:12`; i.e. Dolby Vision is not preferred. These choices are made since DV and AV1 formats are not yet fully compatible with most devices. This may be changed in the future as more devices become capable of smoothly playing back these formats. If your format selector is `worst`, the last item is selected after sorting. This means it will select the format that is worst in all respects. Most of the time, what you actually want is the video with the smallest filesize instead. So it is generally better to use `-f best -S +size,+br,+res,+fps`. @@ -1765,7 +1765,7 @@ The following extractors use this feature: #### youtube * `lang`: Prefer translated metadata (`title`, `description` etc) of this language code (case-sensitive). By default, the video primary language metadata is preferred, with a fallback to `en` translated. See [youtube.py](https://github.com/yt-dlp/yt-dlp/blob/c26f9b991a0681fd3ea548d535919cec1fbbd430/yt_dlp/extractor/youtube.py#L381-L390) for list of supported content language codes * `skip`: One or more of `hls`, `dash` or `translated_subs` to skip extraction of the m3u8 manifests, dash manifests and [auto-translated subtitles](https://github.com/yt-dlp/yt-dlp/issues/4090#issuecomment-1158102032) respectively -* `player_client`: Clients to extract video data from. The main clients are `web`, `ios` and `android`, with variants `_music`, `_embedded`, `_embedscreen`, `_creator` (e.g. `web_embedded`); and `mweb`, `mweb_embedscreen` and `tv_embedded` (agegate bypass) with no variants. By default, `ios,web` is used, but `tv_embedded` and `creator` variants are added as required for age-gated videos. Similarly, the music variants are added for `music.youtube.com` urls. The `android` clients will always be given lowest priority since their formats are broken. You can use `all` to use all the clients, and `default` for the default clients. +* `player_client`: Clients to extract video data from. The main clients are `web`, `ios` and `android`, with variants `_music`, `_embedded`, `_embedscreen`, `_creator` (e.g. `web_embedded`); and `mediaconnect`, `mweb`, `mweb_embedscreen` and `tv_embedded` (agegate bypass) with no variants. By default, `ios,web` is used, but `tv_embedded` and `creator` variants are added as required for age-gated videos. Similarly, the music variants are added for `music.youtube.com` urls. The `android` clients will always be given lowest priority since their formats are broken. You can use `all` to use all the clients, and `default` for the default clients. * `player_skip`: Skip some network requests that are generally needed for robust extraction. One or more of `configs` (skip client configs), `webpage` (skip initial webpage), `js` (skip js player). While these options can help reduce the number of requests needed or avoid some rate-limiting, they could cause some issues. See [#860](https://github.com/yt-dlp/yt-dlp/pull/860) for more details * `player_params`: YouTube player parameters to use for player requests. Will overwrite any default ones set by yt-dlp. * `comment_sort`: `top` or `new` (default) - choose comment sorting mode (on YouTube's side) @@ -1851,11 +1851,14 @@ The following extractors use this feature: * `cdn`: One or more CDN IDs to use with the API call for stream URLs, e.g. `gcp_cdn`, `gs_cdn_pc_app`, `gs_cdn_mobile_web`, `gs_cdn_pc_web` #### soundcloud -* `formats`: Formats to request from the API. Requested values should be in the format of `{protocol}_{extension}` (omitting the bitrate), e.g. `hls_opus,http_aac`. The `*` character functions as a wildcard, e.g. `*_mp3`, and can passed by itself to request all formats. Known protocols include `http`, `hls` and `hls-aes`; known extensions include `aac`, `opus` and `mp3`. Original `download` formats are always extracted. Default is `http_aac,hls_aac,http_opus,hls_opus,http_mp3,hls_mp3` +* `formats`: Formats to request from the API. Requested values should be in the format of `{protocol}_{extension}` (omitting the bitrate), e.g. `hls_opus,http_aac`. The `*` character functions as a wildcard, e.g. `*_mp3`, and can be passed by itself to request all formats. Known protocols include `http`, `hls` and `hls-aes`; known extensions include `aac`, `opus` and `mp3`. Original `download` formats are always extracted. Default is `http_aac,hls_aac,http_opus,hls_opus,http_mp3,hls_mp3` #### orfon (orf:on) * `prefer_segments_playlist`: Prefer a playlist of program segments instead of a single complete video when available. If individual segments are desired, use `--concat-playlist never --extractor-args "orfon:prefer_segments_playlist"` +#### bilibili +* `prefer_multi_flv`: Prefer extracting flv formats over mp4 for older videos that still provide legacy formats + **Note**: These options may be changed/removed in the future without concern for backward compatibility @@ -1865,16 +1868,16 @@ The following extractors use this feature: Note that **all** plugins are imported even if not invoked, and that **there are no checks** performed on plugin code. **Use plugins at your own risk and only if you trust the code!** -Plugins can be of ``s `extractor` or `postprocessor`. -- Extractor plugins do not need to be enabled from the CLI and are automatically invoked when the input URL is suitable for it. -- Extractor plugins take priority over builtin extractors. +Plugins can be of ``s `extractor` or `postprocessor`. +- Extractor plugins do not need to be enabled from the CLI and are automatically invoked when the input URL is suitable for it. +- Extractor plugins take priority over built-in extractors. - Postprocessor plugins can be invoked using `--use-postprocessor NAME`. Plugins are loaded from the namespace packages `yt_dlp_plugins.extractor` and `yt_dlp_plugins.postprocessor`. In other words, the file structure on the disk looks something like: - + yt_dlp_plugins/ extractor/ myplugin.py @@ -1922,7 +1925,7 @@ Run yt-dlp with `--verbose` to check if the plugin has been loaded. See the [yt-dlp-sample-plugins](https://github.com/yt-dlp/yt-dlp-sample-plugins) repo for a template plugin package and the [Plugin Development](https://github.com/yt-dlp/yt-dlp/wiki/Plugin-Development) section of the wiki for a plugin development guide. -All public classes with a name ending in `IE`/`PP` are imported from each file for extractors and postprocessors repectively. This respects underscore prefix (e.g. `_MyBasePluginIE` is private) and `__all__`. Modules can similarly be excluded by prefixing the module name with an underscore (e.g. `_myplugin.py`). +All public classes with a name ending in `IE`/`PP` are imported from each file for extractors and postprocessors respectively. This respects underscore prefix (e.g. `_MyBasePluginIE` is private) and `__all__`. Modules can similarly be excluded by prefixing the module name with an underscore (e.g. `_myplugin.py`). To replace an existing extractor with a subclass of one, set the `plugin_name` class keyword argument (e.g. `class MyPluginIE(ABuiltInIE, plugin_name='myplugin')` will replace `ABuiltInIE` with `MyPluginIE`). Since the extractor replaces the parent, you should exclude the subclass extractor from being imported separately by making it private using one of the methods described above. @@ -1934,7 +1937,7 @@ See the [Developer Instructions](https://github.com/yt-dlp/yt-dlp/blob/master/CO yt-dlp makes the best effort to be a good command-line program, and thus should be callable from any programming language. -Your program should avoid parsing the normal stdout since they may change in future versions. Instead they should use options such as `-J`, `--print`, `--progress-template`, `--exec` etc to create console output that you can reliably reproduce and parse. +Your program should avoid parsing the normal stdout since they may change in future versions. Instead, they should use options such as `-J`, `--print`, `--progress-template`, `--exec` etc to create console output that you can reliably reproduce and parse. From a Python program, you can embed yt-dlp in a more powerful fashion, like this: @@ -2226,6 +2229,14 @@ For ease of use, a few more compat options are available: * `--compat-options 2022`: Same as `--compat-options 2023,playlist-match-filter,no-external-downloader-progress,prefer-legacy-http-handler,manifest-filesize-approx` * `--compat-options 2023`: Currently does nothing. Use this to enable all future compat options +The following compat options restore vulnerable behavior from before security patches: + +* `--compat-options allow-unsafe-ext`: Allow files with any extension (including unsafe ones) to be downloaded ([GHSA-79w7-vh3h-8g4j]()) + + > :warning: Only use if a valid file download is rejected because its extension is detected as uncommon + > + > **This option can enable remote code execution! Consider [opening an issue]() instead!** + ### Deprecated options These are all the deprecated options and the current alternative to achieve the same effect diff --git a/yt-dlp/devscripts/changelog_override.json b/yt-dlp/devscripts/changelog_override.json index 86e8ec2f99..ced38a0ddf 100644 --- a/yt-dlp/devscripts/changelog_override.json +++ b/yt-dlp/devscripts/changelog_override.json @@ -169,5 +169,16 @@ "when": "5c019f6328ad40d66561eac3c4de0b3cd070d0f6", "short": "[cleanup] Misc (#9765)", "authors": ["bashonly", "Grub4K", "seproDev"] + }, + { + "action": "change", + "when": "e6a22834df1776ec4e486526f6df2bf53cb7e06f", + "short": "[ie/orf:on] Add `prefer_segments_playlist` extractor-arg (#10314)", + "authors": ["seproDev"] + }, + { + "action": "add", + "when": "6aaf96a3d6e7d0d426e97e11a2fcf52fda00e733", + "short": "[priority] Security: [[CVE-2024-10123](https://nvd.nist.gov/vuln/detail/CVE-2024-10123)] [Properly sanitize file-extension to prevent file system modification and RCE](https://github.com/yt-dlp/yt-dlp/security/advisories/GHSA-79w7-vh3h-8g4j)\n - Unsafe extensions are now blocked from being downloaded" } ] diff --git a/yt-dlp/devscripts/cli_to_api.py b/yt-dlp/devscripts/cli_to_api.py old mode 100644 new mode 100755 index 2aa51eb6e9..9c2710e09f --- a/yt-dlp/devscripts/cli_to_api.py +++ b/yt-dlp/devscripts/cli_to_api.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + # Allow direct execution import os import sys diff --git a/yt-dlp/pyproject.toml b/yt-dlp/pyproject.toml index a2442a14d5..39986a355c 100644 --- a/yt-dlp/pyproject.toml +++ b/yt-dlp/pyproject.toml @@ -299,7 +299,7 @@ banned-from = [ "string", "sys", "time", - "urllib", + "urllib.parse", "uuid", "xml", ] diff --git a/yt-dlp/supportedsites.md b/yt-dlp/supportedsites.md index 3873956133..656366b4a9 100644 --- a/yt-dlp/supportedsites.md +++ b/yt-dlp/supportedsites.md @@ -46,6 +46,7 @@ - **aenetworks:show** - **AeonCo** - **afreecatv**: [*afreecatv*](## "netrc machine") afreecatv.com + - **afreecatv:catchstory**: [*afreecatv*](## "netrc machine") afreecatv.com catch story - **afreecatv:live**: [*afreecatv*](## "netrc machine") afreecatv.com livestreams - **afreecatv:user** - **AirTV** @@ -542,6 +543,7 @@ - **Goshgay** - **GoToStage** - **GPUTechConf** + - **Graspop** - **Gronkh** - **gronkh:feed** - **gronkh:vods** @@ -678,6 +680,8 @@ - **la7.it** - **la7.it:​pod:episode** - **la7.it:podcast** + - **laracasts** + - **laracasts:series** - **LastFM** - **LastFMPlaylist** - **LastFMUser** @@ -775,7 +779,12 @@ - **MelonVOD** - **Metacritic** - **mewatch** + - **MicrosoftBuild** - **MicrosoftEmbed** + - **MicrosoftLearnEpisode** + - **MicrosoftLearnPlaylist** + - **MicrosoftLearnSession** + - **MicrosoftMedius** - **microsoftstream**: Microsoft Stream - **mildom**: Record ongoing live by specific user in Mildom - **mildom:clip**: Clip in Mildom @@ -838,8 +847,6 @@ - **MusicdexArtist** - **MusicdexPlaylist** - **MusicdexSong** - - **mva**: Microsoft Virtual Academy videos - - **mva:course**: Microsoft Virtual Academy courses - **Mx3** - **Mx3Neo** - **Mx3Volksmusik** @@ -1131,6 +1138,7 @@ - **QingTing** - **qqmusic**: QQ音乐 - **qqmusic:album**: QQ音乐 - 专辑 + - **qqmusic:mv**: QQ音乐 - MV - **qqmusic:playlist**: QQ音乐 - 歌单 - **qqmusic:singer**: QQ音乐 - 歌手 - **qqmusic:toplist**: QQ音乐 - 排行榜 @@ -1237,6 +1245,7 @@ - **rtve.es:television** - **RTVS** - **rtvslo.si** + - **rtvslo.si:show** - **RudoVideo** - **Rule34Video** - **Rumble** @@ -1360,6 +1369,7 @@ - **SpreakerShowPage** - **SpringboardPlatform** - **Sprout** + - **SproutVideo** - **sr:mediathek**: Saarländischer Rundfunk (**Currently broken**) - **SRGSSR** - **SRGSSRPlay**: srf.ch, rts.ch, rsi.ch, rtr.ch and swissinfo.ch play sites @@ -1494,8 +1504,8 @@ - **Tube8**: (**Currently broken**) - **TubeTuGraz**: [*tubetugraz*](## "netrc machine") tube.tugraz.at - **TubeTuGrazSeries**: [*tubetugraz*](## "netrc machine") - - **TubiTv**: [*tubitv*](## "netrc machine") - - **TubiTvShow** + - **tubitv**: [*tubitv*](## "netrc machine") + - **tubitv:series** - **Tumblr**: [*tumblr*](## "netrc machine") - **TuneInPodcast** - **TuneInPodcastEpisode** @@ -1607,6 +1617,7 @@ - **VidioPremier**: [*vidio*](## "netrc machine") - **VidLii** - **Vidly** + - **vids.io** - **viewlift** - **viewlift:embed** - **Viidea** diff --git a/yt-dlp/test/test_jsinterp.py b/yt-dlp/test/test_jsinterp.py index 86928a6a02..7c556e4611 100644 --- a/yt-dlp/test/test_jsinterp.py +++ b/yt-dlp/test/test_jsinterp.py @@ -92,6 +92,7 @@ class TestJSInterpreter(unittest.TestCase): self._test('function f(){return 0 && 1 || 2;}', 2) self._test('function f(){return 0 ?? 42;}', 0) self._test('function f(){return "life, the universe and everything" < 42;}', False) + self._test('function f(){return 0 - 7 * - 6;}', 42) def test_array_access(self): self._test('function f(){var x = [1,2,3]; x[0] = 4; x[0] = 5; x[2.0] = 7; return x;}', [5, 2, 7]) diff --git a/yt-dlp/test/test_utils.py b/yt-dlp/test/test_utils.py index 251739686e..3ff1f8b556 100644 --- a/yt-dlp/test/test_utils.py +++ b/yt-dlp/test/test_utils.py @@ -130,6 +130,7 @@ from yt_dlp.utils import ( xpath_text, xpath_with_ns, ) +from yt_dlp.utils._utils import _UnsafeExtensionError from yt_dlp.utils.networking import ( HTTPHeaderDict, escape_rfc3986, @@ -281,6 +282,13 @@ class TestUtil(unittest.TestCase): finally: os.environ['HOME'] = old_home or '' + _uncommon_extensions = [ + ('exe', 'abc.exe.ext'), + ('de', 'abc.de.ext'), + ('../.mp4', None), + ('..\\.mp4', None), + ] + def test_prepend_extension(self): self.assertEqual(prepend_extension('abc.ext', 'temp'), 'abc.temp.ext') self.assertEqual(prepend_extension('abc.ext', 'temp', 'ext'), 'abc.temp.ext') @@ -289,6 +297,19 @@ class TestUtil(unittest.TestCase): self.assertEqual(prepend_extension('.abc', 'temp'), '.abc.temp') self.assertEqual(prepend_extension('.abc.ext', 'temp'), '.abc.temp.ext') + # Test uncommon extensions + self.assertEqual(prepend_extension('abc.ext', 'bin'), 'abc.bin.ext') + for ext, result in self._uncommon_extensions: + with self.assertRaises(_UnsafeExtensionError): + prepend_extension('abc', ext) + if result: + self.assertEqual(prepend_extension('abc.ext', ext, 'ext'), result) + else: + with self.assertRaises(_UnsafeExtensionError): + prepend_extension('abc.ext', ext, 'ext') + with self.assertRaises(_UnsafeExtensionError): + prepend_extension('abc.unexpected_ext', ext, 'ext') + def test_replace_extension(self): self.assertEqual(replace_extension('abc.ext', 'temp'), 'abc.temp') self.assertEqual(replace_extension('abc.ext', 'temp', 'ext'), 'abc.temp') @@ -297,6 +318,16 @@ class TestUtil(unittest.TestCase): self.assertEqual(replace_extension('.abc', 'temp'), '.abc.temp') self.assertEqual(replace_extension('.abc.ext', 'temp'), '.abc.temp') + # Test uncommon extensions + self.assertEqual(replace_extension('abc.ext', 'bin'), 'abc.unknown_video') + for ext, _ in self._uncommon_extensions: + with self.assertRaises(_UnsafeExtensionError): + replace_extension('abc', ext) + with self.assertRaises(_UnsafeExtensionError): + replace_extension('abc.ext', ext, 'ext') + with self.assertRaises(_UnsafeExtensionError): + replace_extension('abc.unexpected_ext', ext, 'ext') + def test_subtitles_filename(self): self.assertEqual(subtitles_filename('abc.ext', 'en', 'vtt'), 'abc.en.vtt') self.assertEqual(subtitles_filename('abc.ext', 'en', 'vtt', 'ext'), 'abc.en.vtt') diff --git a/yt-dlp/test/test_youtube_signature.py b/yt-dlp/test/test_youtube_signature.py index bfaff83a0a..b0f3269e1c 100644 --- a/yt-dlp/test/test_youtube_signature.py +++ b/yt-dlp/test/test_youtube_signature.py @@ -163,6 +163,10 @@ _NSIG_TESTS = [ 'https://www.youtube.com/s/player/b7910ca8/player_ias.vflset/en_US/base.js', '_hXMCwMt9qE310D', 'LoZMgkkofRMCZQ', ), + ( + 'https://www.youtube.com/s/player/590f65a6/player_ias.vflset/en_US/base.js', + '1tm7-g_A9zsI8_Lay_', 'xI4Vem4Put_rOg', + ), ] diff --git a/yt-dlp/yt_dlp/YoutubeDL.py b/yt-dlp/yt_dlp/YoutubeDL.py index ba29b29dcb..e56c3ed3c9 100644 --- a/yt-dlp/yt_dlp/YoutubeDL.py +++ b/yt-dlp/yt_dlp/YoutubeDL.py @@ -4,6 +4,7 @@ import copy import datetime as dt import errno import fileinput +import functools import http.cookiejar import io import itertools @@ -24,7 +25,7 @@ import traceback import unicodedata from .cache import Cache -from .compat import functools, urllib # isort: split +from .compat import urllib # isort: split from .compat import compat_os_name, urllib_req_to_req from .cookies import LenientSimpleCookie, load_cookies from .downloader import FFmpegFD, get_suitable_downloader, shorten_protocol_name @@ -158,7 +159,7 @@ from .utils import ( write_json_file, write_string, ) -from .utils._utils import _YDLLogger +from .utils._utils import _UnsafeExtensionError, _YDLLogger from .utils.networking import ( HTTPHeaderDict, clean_headers, @@ -171,6 +172,20 @@ if compat_os_name == 'nt': import ctypes +def _catch_unsafe_extension_error(func): + @functools.wraps(func) + def wrapper(self, *args, **kwargs): + try: + return func(self, *args, **kwargs) + except _UnsafeExtensionError as error: + self.report_error( + f'The extracted extension ({error.extension!r}) is unusual ' + 'and will be skipped for safety reasons. ' + f'If you believe this is an error{bug_reports_message(",")}') + + return wrapper + + class YoutubeDL: """YoutubeDL class. @@ -453,8 +468,9 @@ class YoutubeDL: Set the value to 'native' to use the native downloader compat_opts: Compatibility options. See "Differences in default behavior". The following options do not work when used through the API: - filename, abort-on-error, multistreams, no-live-chat, format-sort - no-clean-infojson, no-playlist-metafiles, no-keep-subs, no-attach-info-json. + filename, abort-on-error, multistreams, no-live-chat, + format-sort, no-clean-infojson, no-playlist-metafiles, + no-keep-subs, no-attach-info-json, allow-unsafe-ext. Refer __init__.py for their implementation progress_template: Dictionary of templates for progress outputs. Allowed keys are 'download', 'postprocess', @@ -1399,6 +1415,7 @@ class YoutubeDL: outtmpl, info_dict = self.prepare_outtmpl(outtmpl, info_dict, *args, **kwargs) return self.escape_outtmpl(outtmpl) % info_dict + @_catch_unsafe_extension_error def _prepare_filename(self, info_dict, *, outtmpl=None, tmpl_type=None): assert None in (outtmpl, tmpl_type), 'outtmpl and tmpl_type are mutually exclusive' if outtmpl is None: @@ -3191,6 +3208,7 @@ class YoutubeDL: os.remove(file) return None + @_catch_unsafe_extension_error def process_info(self, info_dict): """Process a single resolved IE result. (Modifies it in-place)""" diff --git a/yt-dlp/yt_dlp/__init__.py b/yt-dlp/yt_dlp/__init__.py index c18af75891..f88f15d70c 100644 --- a/yt-dlp/yt_dlp/__init__.py +++ b/yt-dlp/yt_dlp/__init__.py @@ -64,6 +64,7 @@ from .utils import ( write_string, ) from .utils.networking import std_headers +from .utils._utils import _UnsafeExtensionError from .YoutubeDL import YoutubeDL _IN_CLI = False @@ -593,6 +594,13 @@ def validate_options(opts): if opts.ap_username is not None and opts.ap_password is None: opts.ap_password = getpass.getpass('Type TV provider account password and press [Return]: ') + # compat option changes global state destructively; only allow from cli + if 'allow-unsafe-ext' in opts.compat_opts: + warnings.append( + 'Using allow-unsafe-ext opens you up to potential attacks. ' + 'Use with great care!') + _UnsafeExtensionError.sanitize_extension = lambda x: x + return warnings, deprecation_warnings diff --git a/yt-dlp/yt_dlp/cookies.py b/yt-dlp/yt_dlp/cookies.py index d07269a677..070d2fcb98 100644 --- a/yt-dlp/yt_dlp/cookies.py +++ b/yt-dlp/yt_dlp/cookies.py @@ -2,7 +2,9 @@ import base64 import collections import contextlib import datetime as dt +import functools import glob +import hashlib import http.cookiejar import http.cookies import io @@ -17,14 +19,12 @@ import tempfile import time import urllib.request from enum import Enum, auto -from hashlib import pbkdf2_hmac from .aes import ( aes_cbc_decrypt_bytes, aes_gcm_decrypt_and_verify_bytes, unpad_pkcs7, ) -from .compat import functools # isort: split from .compat import compat_os_name from .dependencies import ( _SECRETSTORAGE_UNAVAILABLE_REASON, @@ -999,7 +999,7 @@ def _get_windows_v10_key(browser_root, logger): def pbkdf2_sha1(password, salt, iterations, key_length): - return pbkdf2_hmac('sha1', password, salt, iterations, key_length) + return hashlib.pbkdf2_hmac('sha1', password, salt, iterations, key_length) def _decrypt_aes_cbc_multi(ciphertext, keys, logger, initialization_vector=b' ' * 16): diff --git a/yt-dlp/yt_dlp/downloader/external.py b/yt-dlp/yt_dlp/downloader/external.py index 63c1085699..ae2372915b 100644 --- a/yt-dlp/yt_dlp/downloader/external.py +++ b/yt-dlp/yt_dlp/downloader/external.py @@ -1,4 +1,5 @@ import enum +import functools import json import os import re @@ -9,7 +10,6 @@ import time import uuid from .fragment import FragmentFD -from ..compat import functools from ..networking import Request from ..postprocessor.ffmpeg import EXT_TO_OUT_FORMATS, FFmpegPostProcessor from ..utils import ( diff --git a/yt-dlp/yt_dlp/extractor/arcpublishing.py b/yt-dlp/yt_dlp/extractor/arcpublishing.py index 338bada7c8..8da9bc4ccb 100644 --- a/yt-dlp/yt_dlp/extractor/arcpublishing.py +++ b/yt-dlp/yt_dlp/extractor/arcpublishing.py @@ -4,6 +4,7 @@ from .common import InfoExtractor from ..utils import ( extract_attributes, int_or_none, + join_nonempty, parse_iso8601, try_get, ) @@ -136,7 +137,7 @@ class ArcPublishingIE(InfoExtractor): else: vbr = int_or_none(s.get('bitrate')) formats.append({ - 'format_id': f'{stream_type}-{vbr}' if vbr else stream_type, + 'format_id': join_nonempty(stream_type, vbr), 'vbr': vbr, 'width': int_or_none(s.get('width')), 'height': int_or_none(s.get('height')), diff --git a/yt-dlp/yt_dlp/extractor/arkena.py b/yt-dlp/yt_dlp/extractor/arkena.py index b0e853d57a..aa6c5ca4d6 100644 --- a/yt-dlp/yt_dlp/extractor/arkena.py +++ b/yt-dlp/yt_dlp/extractor/arkena.py @@ -131,8 +131,8 @@ class ArkenaIE(InfoExtractor): formats.extend(self._extract_f4m_formats( href, video_id, f4m_id='hds', fatal=False)) elif mime_type == 'application/dash+xml': - formats.extend(self._extract_f4m_formats( - href, video_id, f4m_id='hds', fatal=False)) + formats.extend(self._extract_mpd_formats( + href, video_id, mpd_id='dash', fatal=False)) elif mime_type == 'application/vnd.ms-sstr+xml': formats.extend(self._extract_ism_formats( href, video_id, ism_id='mss', fatal=False)) diff --git a/yt-dlp/yt_dlp/extractor/bandcamp.py b/yt-dlp/yt_dlp/extractor/bandcamp.py index 6128de791b..61cbab5a7a 100644 --- a/yt-dlp/yt_dlp/extractor/bandcamp.py +++ b/yt-dlp/yt_dlp/extractor/bandcamp.py @@ -41,7 +41,7 @@ class BandcampIE(InfoExtractor): 'uploader_id': 'youtube-dl', 'thumbnail': 'https://f4.bcbits.com/img/a3216802731_5.jpg', }, - '_skip': 'There is a limit of 200 free downloads / month for the test song', + 'skip': 'There is a limit of 200 free downloads / month for the test song', }, { # free download 'url': 'http://benprunty.bandcamp.com/track/lanius-battle', diff --git a/yt-dlp/yt_dlp/extractor/bilibili.py b/yt-dlp/yt_dlp/extractor/bilibili.py index 411b48c282..a84b7a6f7c 100644 --- a/yt-dlp/yt_dlp/extractor/bilibili.py +++ b/yt-dlp/yt_dlp/extractor/bilibili.py @@ -31,12 +31,12 @@ from ..utils import ( mimetype2ext, parse_count, parse_qs, + parse_resolution, qualities, smuggle_url, srt_subtitles_timecode, str_or_none, traverse_obj, - try_call, unified_timestamp, unsmuggle_url, url_or_none, @@ -47,6 +47,23 @@ from ..utils import ( class BilibiliBaseIE(InfoExtractor): _FORMAT_ID_RE = re.compile(r'-(\d+)\.m4s\?') + _WBI_KEY_CACHE_TIMEOUT = 30 # exact expire timeout is unclear, use 30s for one session + _wbi_key_cache = {} + + @property + def is_logged_in(self): + return bool(self._get_cookies('https://api.bilibili.com').get('SESSDATA')) + + def _check_missing_formats(self, play_info, formats): + parsed_qualities = set(traverse_obj(formats, (..., 'quality'))) + missing_formats = join_nonempty(*[ + traverse_obj(fmt, 'new_description', 'display_desc', 'quality') + for fmt in traverse_obj(play_info, ( + 'support_formats', lambda _, v: v['quality'] not in parsed_qualities))], delim=', ') + if missing_formats: + self.to_screen( + f'Format(s) {missing_formats} are missing; you have to login or ' + f'become a premium member to download them. {self._login_hint()}') def extract_formats(self, play_info): format_names = { @@ -86,18 +103,75 @@ class BilibiliBaseIE(InfoExtractor): 'format': format_names.get(video.get('id')), } for video in traverse_obj(play_info, ('dash', 'video', ...))) - missing_formats = format_names.keys() - set(traverse_obj(formats, (..., 'quality'))) - if missing_formats: - self.to_screen(f'Format(s) {", ".join(format_names[i] for i in missing_formats)} are missing; ' - f'you have to login or become premium member to download them. {self._login_hint()}') + if formats: + self._check_missing_formats(play_info, formats) + fragments = traverse_obj(play_info, ('durl', lambda _, v: url_or_none(v['url']), { + 'url': ('url', {url_or_none}), + 'duration': ('length', {functools.partial(float_or_none, scale=1000)}), + 'filesize': ('size', {int_or_none}), + })) + if fragments: + formats.append({ + 'url': fragments[0]['url'], + 'filesize': sum(traverse_obj(fragments, (..., 'filesize'))), + **({ + 'fragments': fragments, + 'protocol': 'http_dash_segments', + } if len(fragments) > 1 else {}), + **traverse_obj(play_info, { + 'quality': ('quality', {int_or_none}), + 'format_id': ('quality', {str_or_none}), + 'format_note': ('quality', {lambda x: format_names.get(x)}), + 'duration': ('timelength', {functools.partial(float_or_none, scale=1000)}), + }), + **parse_resolution(format_names.get(play_info.get('quality'))), + }) return formats - def _download_playinfo(self, video_id, cid, headers=None): + def _get_wbi_key(self, video_id): + if time.time() < self._wbi_key_cache.get('ts', 0) + self._WBI_KEY_CACHE_TIMEOUT: + return self._wbi_key_cache['key'] + + session_data = self._download_json( + 'https://api.bilibili.com/x/web-interface/nav', video_id, note='Downloading wbi sign') + + lookup = ''.join(traverse_obj(session_data, ( + 'data', 'wbi_img', ('img_url', 'sub_url'), + {lambda x: x.rpartition('/')[2].partition('.')[0]}))) + + # from getMixinKey() in the vendor js + mixin_key_enc_tab = [ + 46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, + 33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40, + 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11, + 36, 20, 34, 44, 52, + ] + + self._wbi_key_cache.update({ + 'key': ''.join(lookup[i] for i in mixin_key_enc_tab)[:32], + 'ts': time.time(), + }) + return self._wbi_key_cache['key'] + + def _sign_wbi(self, params, video_id): + params['wts'] = round(time.time()) + params = { + k: ''.join(filter(lambda char: char not in "!'()*", str(v))) + for k, v in sorted(params.items()) + } + query = urllib.parse.urlencode(params) + params['w_rid'] = hashlib.md5(f'{query}{self._get_wbi_key(video_id)}'.encode()).hexdigest() + return params + + def _download_playinfo(self, bvid, cid, headers=None, qn=None): + params = {'bvid': bvid, 'cid': cid, 'fnval': 4048} + if qn: + params['qn'] = qn return self._download_json( - 'https://api.bilibili.com/x/player/playurl', video_id, - query={'bvid': video_id, 'cid': cid, 'fnval': 4048}, - note=f'Downloading video formats for cid {cid}', headers=headers)['data'] + 'https://api.bilibili.com/x/player/wbi/playurl', bvid, + query=self._sign_wbi(params, bvid), headers=headers, + note=f'Downloading video formats for cid {cid} {qn or ""}')['data'] def json2srt(self, json_data): srt_data = '' @@ -115,15 +189,15 @@ class BilibiliBaseIE(InfoExtractor): }], } - subtitle_info = traverse_obj(self._download_json( + video_info = self._download_json( 'https://api.bilibili.com/x/player/v2', video_id, query={'aid': aid, 'cid': cid} if aid else {'bvid': video_id, 'cid': cid}, - note=f'Extracting subtitle info {cid}'), ('data', 'subtitle')) - subs_list = traverse_obj(subtitle_info, ('subtitles', lambda _, v: v['subtitle_url'] and v['lan'])) - if not subs_list and traverse_obj(subtitle_info, 'allow_submit'): - if not self._get_cookies('https://api.bilibili.com').get('SESSDATA'): # no login session cookie - self.report_warning(f'CC subtitles (if any) are only visible when logged in. {self._login_hint()}', only_once=True) - for s in subs_list: + note=f'Extracting subtitle info {cid}') + if traverse_obj(video_info, ('data', 'need_login_subtitle')): + self.report_warning( + f'Subtitles are only available when logged in. {self._login_hint()}', only_once=True) + for s in traverse_obj(video_info, ( + 'data', 'subtitle', 'subtitles', lambda _, v: v['subtitle_url'] and v['lan'])): subtitles.setdefault(s['lan'], []).append({ 'ext': 'srt', 'data': self.json2srt(self._download_json(s['subtitle_url'], video_id)), @@ -203,15 +277,15 @@ class BilibiliBaseIE(InfoExtractor): self._get_divisions(video_id, graph_version, edges, choice['edge_id'], cid_edges=cid_edges) return cid_edges - def _get_interactive_entries(self, video_id, cid, metainfo): + def _get_interactive_entries(self, video_id, cid, metainfo, headers=None): graph_version = traverse_obj( self._download_json( 'https://api.bilibili.com/x/player/wbi/v2', video_id, - 'Extracting graph version', query={'bvid': video_id, 'cid': cid}), + 'Extracting graph version', query={'bvid': video_id, 'cid': cid}, headers=headers), ('data', 'interaction', 'graph_version', {int_or_none})) cid_edges = self._get_divisions(video_id, graph_version, {1: {'cid': cid}}, 1) for cid, edges in cid_edges.items(): - play_info = self._download_playinfo(video_id, cid) + play_info = self._download_playinfo(video_id, cid, headers=headers) yield { **metainfo, 'id': f'{video_id}_{cid}', @@ -243,17 +317,17 @@ class BiliBiliIE(BilibiliBaseIE): 'timestamp': 1488353834, 'like_count': int, 'view_count': int, + '_old_archive_ids': ['bilibili 8903802_part1'], }, }, { 'note': 'old av URL version', 'url': 'http://www.bilibili.com/video/av1074402/', 'info_dict': { - 'thumbnail': r're:^https?://.*\.(jpg|jpeg)$', + 'id': 'BV11x411K7CN', 'ext': 'mp4', + 'title': '【金坷垃】金泡沫', 'uploader': '菊子桑', 'uploader_id': '156160', - 'id': 'BV11x411K7CN', - 'title': '【金坷垃】金泡沫', 'duration': 308.36, 'upload_date': '20140420', 'timestamp': 1397983878, @@ -262,6 +336,8 @@ class BiliBiliIE(BilibiliBaseIE): 'comment_count': int, 'view_count': int, 'tags': list, + 'thumbnail': r're:^https?://.*\.(jpg|jpeg)$', + '_old_archive_ids': ['bilibili 1074402_part1'], }, 'params': {'skip_download': True}, }, { @@ -288,6 +364,7 @@ class BiliBiliIE(BilibiliBaseIE): 'view_count': int, 'description': 'md5:e3c401cf7bc363118d1783dd74068a68', 'duration': 90.314, + '_old_archive_ids': ['bilibili 498159642_part1'], }, }], }, { @@ -308,28 +385,8 @@ class BiliBiliIE(BilibiliBaseIE): 'view_count': int, 'description': 'md5:e3c401cf7bc363118d1783dd74068a68', 'duration': 90.314, + '_old_archive_ids': ['bilibili 498159642_part1'], }, - }, { - 'note': 'video has subtitles', - 'url': 'https://www.bilibili.com/video/BV12N4y1M7rh', - 'info_dict': { - 'id': 'BV12N4y1M7rh', - 'ext': 'mp4', - 'title': 'md5:96e8bb42c2b432c0d4ce3434a61479c1', - 'tags': list, - 'description': 'md5:afde2b7ba9025c01d9e3dde10de221e4', - 'duration': 313.557, - 'upload_date': '20220709', - 'uploader': '小夫太渴', - 'timestamp': 1657347907, - 'uploader_id': '1326814124', - 'comment_count': int, - 'view_count': int, - 'like_count': int, - 'thumbnail': r're:^https?://.*\.(jpg|jpeg|png)$', - 'subtitles': 'count:2', - }, - 'params': {'listsubtitles': True}, }, { 'url': 'https://www.bilibili.com/video/av8903802/', 'info_dict': { @@ -347,6 +404,7 @@ class BiliBiliIE(BilibiliBaseIE): 'comment_count': int, 'view_count': int, 'like_count': int, + '_old_archive_ids': ['bilibili 8903802_part1'], }, 'params': { 'skip_download': True, @@ -370,6 +428,7 @@ class BiliBiliIE(BilibiliBaseIE): 'view_count': int, 'like_count': int, 'thumbnail': r're:^https?://.*\.(jpg|jpeg|png)$', + '_old_archive_ids': ['bilibili 463665680_part1'], }, 'params': {'skip_download': True}, }, { @@ -388,8 +447,8 @@ class BiliBiliIE(BilibiliBaseIE): 'view_count': int, 'like_count': int, 'thumbnail': r're:^https?://.*\.(jpg|jpeg|png)$', + '_old_archive_ids': ['bilibili 893839363_part1'], }, - 'params': {'skip_download': True}, }, { 'note': 'newer festival video', 'url': 'https://www.bilibili.com/festival/2023honkaiimpact3gala?bvid=BV1ay4y1d77f', @@ -406,8 +465,57 @@ class BiliBiliIE(BilibiliBaseIE): 'view_count': int, 'like_count': int, 'thumbnail': r're:^https?://.*\.(jpg|jpeg|png)$', + '_old_archive_ids': ['bilibili 778246196_part1'], + }, + }, { + 'note': 'legacy flv/mp4 video', + 'url': 'https://www.bilibili.com/video/BV1ms411Q7vw/?p=4', + 'info_dict': { + 'id': 'BV1ms411Q7vw_p4', + 'title': '[搞笑]【动画】云南方言快乐生产线出品 p04 新烧包谷之漫游桃花岛', + 'timestamp': 1458222815, + 'upload_date': '20160317', + 'description': '云南方言快乐生产线出品', + 'duration': float, + 'uploader': '一笑颠天', + 'uploader_id': '3916081', + 'view_count': int, + 'comment_count': int, + 'like_count': int, + 'tags': list, + 'thumbnail': r're:^https?://.*\.(jpg|jpeg|png)$', + '_old_archive_ids': ['bilibili 4120229_part4'], + }, + 'params': {'extractor_args': {'bilibili': {'prefer_multi_flv': ['32']}}}, + 'playlist_count': 19, + 'playlist': [{ + 'info_dict': { + 'id': 'BV1ms411Q7vw_p4_0', + 'ext': 'flv', + 'title': '[搞笑]【动画】云南方言快乐生产线出品 p04 新烧包谷之漫游桃花岛', + 'duration': 399.102, + }, + }], + }, { + 'note': 'legacy mp4-only video', + 'url': 'https://www.bilibili.com/video/BV1nx411u79K', + 'info_dict': { + 'id': 'BV1nx411u79K', + 'ext': 'mp4', + 'title': '【练习室】201603声乐练习《No Air》with VigoVan', + 'timestamp': 1508893551, + 'upload_date': '20171025', + 'description': '@ZERO-G伯远\n声乐练习 《No Air》with Vigo Van', + 'duration': 80.384, + 'uploader': '伯远', + 'uploader_id': '10584494', + 'comment_count': int, + 'view_count': int, + 'like_count': int, + 'tags': list, + 'thumbnail': r're:^https?://.*\.(jpg|jpeg|png)$', + '_old_archive_ids': ['bilibili 15700301_part1'], }, - 'params': {'skip_download': True}, }, { 'note': 'interactive/split-path video', 'url': 'https://www.bilibili.com/video/BV1af4y1H7ga/', @@ -425,6 +533,7 @@ class BiliBiliIE(BilibiliBaseIE): 'view_count': int, 'like_count': int, 'thumbnail': r're:^https?://.*\.(jpg|jpeg|png)$', + '_old_archive_ids': ['bilibili 292734508_part1'], }, 'playlist_count': 33, 'playlist': [{ @@ -443,6 +552,7 @@ class BiliBiliIE(BilibiliBaseIE): 'view_count': int, 'like_count': int, 'thumbnail': r're:^https?://.*\.(jpg|jpeg|png)$', + '_old_archive_ids': ['bilibili 292734508_part1'], }, }], }, { @@ -465,6 +575,29 @@ class BiliBiliIE(BilibiliBaseIE): 'upload_date': '20191021', 'thumbnail': r're:^https?://.*\.(jpg|jpeg|png)$', }, + }, { + 'note': 'video has subtitles, which requires login', + 'url': 'https://www.bilibili.com/video/BV12N4y1M7rh', + 'info_dict': { + 'id': 'BV12N4y1M7rh', + 'ext': 'mp4', + 'title': 'md5:96e8bb42c2b432c0d4ce3434a61479c1', + 'tags': list, + 'description': 'md5:afde2b7ba9025c01d9e3dde10de221e4', + 'duration': 313.557, + 'upload_date': '20220709', + 'uploader': '小夫太渴', + 'timestamp': 1657347907, + 'uploader_id': '1326814124', + 'comment_count': int, + 'view_count': int, + 'like_count': int, + 'thumbnail': r're:^https?://.*\.(jpg|jpeg|png)$', + 'subtitles': 'count:2', # login required for CC subtitle + '_old_archive_ids': ['bilibili 898179753_part1'], + }, + 'params': {'listsubtitles': True}, + 'skip': 'login required for subtitle', }, { 'url': 'https://www.bilibili.com/video/BV1jL41167ZG/', 'info_dict': { @@ -498,8 +631,9 @@ class BiliBiliIE(BilibiliBaseIE): if not self._match_valid_url(urlh.url): return self.url_result(urlh.url) - initial_state = self._search_json(r'window\.__INITIAL_STATE__\s*=', webpage, 'initial state', video_id) + headers['Referer'] = url + initial_state = self._search_json(r'window\.__INITIAL_STATE__\s*=', webpage, 'initial state', video_id) is_festival = 'videoData' not in initial_state if is_festival: video_data = initial_state['videoInfo'] @@ -548,7 +682,6 @@ class BiliBiliIE(BilibiliBaseIE): aid = video_data.get('aid') old_video_id = format_field(aid, None, f'%s_part{part_id or 1}') - cid = traverse_obj(video_data, ('pages', part_id - 1, 'cid')) if part_id else video_data.get('cid') festival_info = {} @@ -586,18 +719,65 @@ class BiliBiliIE(BilibiliBaseIE): is_interactive = traverse_obj(video_data, ('rights', 'is_stein_gate')) if is_interactive: return self.playlist_result( - self._get_interactive_entries(video_id, cid, metainfo), **metainfo, + self._get_interactive_entries(video_id, cid, metainfo, headers=headers), **metainfo, duration=traverse_obj(initial_state, ('videoData', 'duration', {int_or_none})), __post_extractor=self.extract_comments(aid)) else: - return { - **metainfo, - 'duration': float_or_none(play_info.get('timelength'), scale=1000), - 'chapters': self._get_chapters(aid, cid), - 'subtitles': self.extract_subtitles(video_id, cid), - 'formats': self.extract_formats(play_info), - '__post_extractor': self.extract_comments(aid), - } + formats = self.extract_formats(play_info) + + if not traverse_obj(play_info, ('dash')): + # we only have legacy formats and need additional work + has_qn = lambda x: x in traverse_obj(formats, (..., 'quality')) + for qn in traverse_obj(play_info, ('accept_quality', lambda _, v: not has_qn(v), {int})): + formats.extend(traverse_obj( + self.extract_formats(self._download_playinfo(video_id, cid, headers=headers, qn=qn)), + lambda _, v: not has_qn(v['quality']))) + self._check_missing_formats(play_info, formats) + flv_formats = traverse_obj(formats, lambda _, v: v['fragments']) + if flv_formats and len(flv_formats) < len(formats): + # Flv and mp4 are incompatible due to `multi_video` workaround, so drop one + if not self._configuration_arg('prefer_multi_flv'): + dropped_fmts = ', '.join( + f'{f.get("format_note")} ({f.get("format_id")})' for f in flv_formats) + formats = traverse_obj(formats, lambda _, v: not v.get('fragments')) + if dropped_fmts: + self.to_screen( + f'Dropping incompatible flv format(s) {dropped_fmts} since mp4 is available. ' + 'To extract flv, pass --extractor-args "bilibili:prefer_multi_flv"') + else: + formats = traverse_obj( + # XXX: Filtering by extractor-arg is for testing purposes + formats, lambda _, v: v['quality'] == int(self._configuration_arg('prefer_multi_flv')[0]), + ) or [max(flv_formats, key=lambda x: x['quality'])] + + if traverse_obj(formats, (0, 'fragments')): + # We have flv formats, which are individual short videos with their own timestamps and metainfo + # Binary concatenation corrupts their timestamps, so we need a `multi_video` workaround + return { + **metainfo, + '_type': 'multi_video', + 'entries': [{ + 'id': f'{metainfo["id"]}_{idx}', + 'title': metainfo['title'], + 'http_headers': metainfo['http_headers'], + 'formats': [{ + **fragment, + 'format_id': formats[0].get('format_id'), + }], + 'subtitles': self.extract_subtitles(video_id, cid) if idx == 0 else None, + '__post_extractor': self.extract_comments(aid) if idx == 0 else None, + } for idx, fragment in enumerate(formats[0]['fragments'])], + 'duration': float_or_none(play_info.get('timelength'), scale=1000), + } + else: + return { + **metainfo, + 'formats': formats, + 'duration': float_or_none(play_info.get('timelength'), scale=1000), + 'chapters': self._get_chapters(aid, cid), + 'subtitles': self.extract_subtitles(video_id, cid), + '__post_extractor': self.extract_comments(aid), + } class BiliBiliBangumiIE(BilibiliBaseIE): @@ -968,7 +1148,7 @@ class BilibiliCheeseSeasonIE(BilibiliCheeseBaseIE): })) -class BilibiliSpaceBaseIE(InfoExtractor): +class BilibiliSpaceBaseIE(BilibiliBaseIE): def _extract_playlist(self, fetch_page, get_metadata, get_entries): first_page = fetch_page(0) metadata = get_metadata(first_page) @@ -988,73 +1168,53 @@ class BilibiliSpaceVideoIE(BilibiliSpaceBaseIE): 'id': '3985676', }, 'playlist_mincount': 178, + 'skip': 'login required', }, { 'url': 'https://space.bilibili.com/313580179/video', 'info_dict': { 'id': '313580179', }, 'playlist_mincount': 92, + 'skip': 'login required', }] - def _extract_signature(self, playlist_id): - session_data = self._download_json('https://api.bilibili.com/x/web-interface/nav', playlist_id, fatal=False) - - key_from_url = lambda x: x[x.rfind('/') + 1:].split('.')[0] - img_key = traverse_obj( - session_data, ('data', 'wbi_img', 'img_url', {key_from_url})) or '34478ba821254d9d93542680e3b86100' - sub_key = traverse_obj( - session_data, ('data', 'wbi_img', 'sub_url', {key_from_url})) or '7e16a90d190a4355a78fd00b32a38de6' - - session_key = img_key + sub_key - - signature_values = [] - for position in ( - 46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, 33, 9, 42, 19, 29, 28, 14, 39, - 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40, 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, - 57, 62, 11, 36, 20, 34, 44, 52, - ): - char_at_position = try_call(lambda: session_key[position]) - if char_at_position: - signature_values.append(char_at_position) - - return ''.join(signature_values)[:32] - def _real_extract(self, url): playlist_id, is_video_url = self._match_valid_url(url).group('id', 'video') if not is_video_url: self.to_screen('A channel URL was given. Only the channel\'s videos will be downloaded. ' 'To download audios, add a "/audio" to the URL') - signature = self._extract_signature(playlist_id) - def fetch_page(page_idx): query = { 'keyword': '', 'mid': playlist_id, - 'order': 'pubdate', + 'order': traverse_obj(parse_qs(url), ('order', 0)) or 'pubdate', 'order_avoided': 'true', 'platform': 'web', 'pn': page_idx + 1, 'ps': 30, 'tid': 0, 'web_location': 1550101, - 'wts': int(time.time()), } - query['w_rid'] = hashlib.md5(f'{urllib.parse.urlencode(query)}{signature}'.encode()).hexdigest() try: - response = self._download_json('https://api.bilibili.com/x/space/wbi/arc/search', - playlist_id, note=f'Downloading page {page_idx}', query=query, - headers={'referer': url}) + response = self._download_json( + 'https://api.bilibili.com/x/space/wbi/arc/search', playlist_id, + query=self._sign_wbi(query, playlist_id), + note=f'Downloading space page {page_idx}', headers={'Referer': url}) except ExtractorError as e: if isinstance(e.cause, HTTPError) and e.cause.status == 412: raise ExtractorError( 'Request is blocked by server (412), please add cookies, wait and try later.', expected=True) raise - if response['code'] in (-352, -401): + status_code = response['code'] + if status_code == -401: raise ExtractorError( - f'Request is blocked by server ({-response["code"]}), ' - 'please add cookies, wait and try later.', expected=True) + 'Request is blocked by server (401), please add cookies, wait and try later.', expected=True) + elif status_code == -352 and not self.is_logged_in: + self.raise_login_required('Request is rejected, you need to login to access playlist') + elif status_code != 0: + raise ExtractorError(f'Request failed ({status_code}): {response.get("message") or "Unknown error"}') return response['data'] def get_metadata(page_data): @@ -1280,7 +1440,10 @@ class BilibiliWatchlaterIE(BilibiliSpaceListBaseIE): _VALID_URL = r'https?://(?:www\.)?bilibili\.com/watchlater/?(?:[?#]|$)' _TESTS = [{ 'url': 'https://www.bilibili.com/watchlater/#/list', - 'info_dict': {'id': 'watchlater'}, + 'info_dict': { + 'id': r're:\d+', + 'title': '稍后再看', + }, 'playlist_mincount': 0, 'skip': 'login required', }] @@ -1356,14 +1519,19 @@ class BilibiliPlaylistIE(BilibiliSpaceListBaseIE): 'skip': 'redirect url', }, { 'url': 'https://www.bilibili.com/list/watchlater', - 'info_dict': {'id': 'watchlater'}, + 'info_dict': { + 'id': r're:2_\d+', + 'title': '稍后再看', + 'uploader': str, + 'uploader_id': str, + }, 'playlist_mincount': 0, 'skip': 'login required', }, { 'url': 'https://www.bilibili.com/medialist/play/watchlater', 'info_dict': {'id': 'watchlater'}, 'playlist_mincount': 0, - 'skip': 'login required', + 'skip': 'redirect url & login required', }] def _extract_medialist(self, query, list_id): @@ -1414,7 +1582,7 @@ class BilibiliPlaylistIE(BilibiliSpaceListBaseIE): 'title': ('title', {str}), 'uploader': ('upper', 'name', {str}), 'uploader_id': ('upper', 'mid', {str_or_none}), - 'timestamp': ('ctime', {int_or_none}), + 'timestamp': ('ctime', {int_or_none}, {lambda x: x or None}), 'thumbnail': ('cover', {url_or_none}), })), } @@ -1808,7 +1976,8 @@ class BiliIntlBaseIE(InfoExtractor): public_key = Cryptodome.RSA.importKey(key_data['key']) password_hash = Cryptodome.PKCS1_v1_5.new(public_key).encrypt((key_data['hash'] + password).encode()) login_post = self._download_json( - 'https://passport.bilibili.tv/x/intl/passport-login/web/login/password?lang=en-US', None, data=urlencode_postdata({ + 'https://passport.bilibili.tv/x/intl/passport-login/web/login/password?lang=en-US', None, + data=urlencode_postdata({ 'username': username, 'password': base64.b64encode(password_hash).decode('ascii'), 'keep_me': 'true', @@ -2140,7 +2309,8 @@ class BiliIntlSeriesIE(BiliIntlBaseIE): def _real_extract(self, url): series_id = self._match_id(url) - series_info = self._call_api(f'/web/v2/ogv/play/season_info?season_id={series_id}&platform=web', series_id).get('season') or {} + series_info = self._call_api( + f'/web/v2/ogv/play/season_info?season_id={series_id}&platform=web', series_id).get('season') or {} return self.playlist_result( self._entries(series_id), series_id, series_info.get('title'), series_info.get('description'), categories=traverse_obj(series_info, ('styles', ..., 'title'), expected_type=str_or_none), diff --git a/yt-dlp/yt_dlp/extractor/brightcove.py b/yt-dlp/yt_dlp/extractor/brightcove.py index 56d74764fd..2526f25dac 100644 --- a/yt-dlp/yt_dlp/extractor/brightcove.py +++ b/yt-dlp/yt_dlp/extractor/brightcove.py @@ -18,6 +18,7 @@ from ..utils import ( fix_xml_ampersands, float_or_none, int_or_none, + join_nonempty, js_to_json, mimetype2ext, parse_iso8601, @@ -538,12 +539,7 @@ class BrightcoveNewBaseIE(AdobePassIE): }) def build_format_id(kind): - format_id = kind - if tbr: - format_id += f'-{int(tbr)}k' - if height: - format_id += f'-{height}p' - return format_id + return join_nonempty(kind, tbr and f'{int(tbr)}k', height and f'{height}p') if src or streaming_src: f.update({ diff --git a/yt-dlp/yt_dlp/extractor/cbsnews.py b/yt-dlp/yt_dlp/extractor/cbsnews.py index 5a8ebb8476..972e111190 100644 --- a/yt-dlp/yt_dlp/extractor/cbsnews.py +++ b/yt-dlp/yt_dlp/extractor/cbsnews.py @@ -1,6 +1,5 @@ import base64 import re -import urllib.error import urllib.parse import zlib diff --git a/yt-dlp/yt_dlp/extractor/dailymail.py b/yt-dlp/yt_dlp/extractor/dailymail.py index 516df1b5cf..540676ac0f 100644 --- a/yt-dlp/yt_dlp/extractor/dailymail.py +++ b/yt-dlp/yt_dlp/extractor/dailymail.py @@ -2,6 +2,7 @@ from .common import InfoExtractor from ..utils import ( determine_protocol, int_or_none, + join_nonempty, try_get, unescapeHTML, ) @@ -52,7 +53,7 @@ class DailyMailIE(InfoExtractor): is_hls = container == 'M2TS' protocol = 'm3u8_native' if is_hls else determine_protocol({'url': rendition_url}) formats.append({ - 'format_id': ('hls' if is_hls else protocol) + (f'-{tbr}' if tbr else ''), + 'format_id': join_nonempty('hls' if is_hls else protocol, tbr), 'url': rendition_url, 'width': int_or_none(rendition.get('frameWidth')), 'height': int_or_none(rendition.get('frameHeight')), diff --git a/yt-dlp/yt_dlp/extractor/eitb.py b/yt-dlp/yt_dlp/extractor/eitb.py index 3e27507965..18b802eb15 100644 --- a/yt-dlp/yt_dlp/extractor/eitb.py +++ b/yt-dlp/yt_dlp/extractor/eitb.py @@ -1,6 +1,11 @@ from .common import InfoExtractor from ..networking import Request -from ..utils import float_or_none, int_or_none, parse_iso8601 +from ..utils import ( + float_or_none, + int_or_none, + join_nonempty, + parse_iso8601, +) class EitbIE(InfoExtractor): @@ -37,12 +42,9 @@ class EitbIE(InfoExtractor): if not video_url: continue tbr = float_or_none(rendition.get('ENCODING_RATE'), 1000) - format_id = 'http' - if tbr: - format_id += f'-{int(tbr)}' formats.append({ 'url': rendition['PMD_URL'], - 'format_id': format_id, + 'format_id': join_nonempty('http', int_or_none(tbr)), 'width': int_or_none(rendition.get('FRAME_WIDTH')), 'height': int_or_none(rendition.get('FRAME_HEIGHT')), 'tbr': tbr, diff --git a/yt-dlp/yt_dlp/extractor/eporner.py b/yt-dlp/yt_dlp/extractor/eporner.py index e0b6ca96fb..2d25c6b4df 100644 --- a/yt-dlp/yt_dlp/extractor/eporner.py +++ b/yt-dlp/yt_dlp/extractor/eporner.py @@ -29,9 +29,6 @@ class EpornerIE(InfoExtractor): 'view_count': int, 'age_limit': 18, }, - 'params': { - 'proxy': '127.0.0.1:8118', - }, }, { # New (May 2016) URL layout 'url': 'http://www.eporner.com/hd-porn/3YRUtzMcWn0/Star-Wars-XXX-Parody/', diff --git a/yt-dlp/yt_dlp/extractor/go.py b/yt-dlp/yt_dlp/extractor/go.py index bbb23ffc0a..83c1979db8 100644 --- a/yt-dlp/yt_dlp/extractor/go.py +++ b/yt-dlp/yt_dlp/extractor/go.py @@ -5,6 +5,7 @@ from ..utils import ( ExtractorError, determine_ext, int_or_none, + join_nonempty, parse_age_limit, remove_end, remove_start, @@ -287,7 +288,7 @@ class GoIE(AdobePassIE): if mobj: height = int(mobj.group(2)) f.update({ - 'format_id': (f'{format_id}-' if format_id else '') + f'{height}P', + 'format_id': join_nonempty(format_id, f'{height}P'), 'width': int(mobj.group(1)), 'height': height, }) diff --git a/yt-dlp/yt_dlp/extractor/hbo.py b/yt-dlp/yt_dlp/extractor/hbo.py index 146d8a23d8..34cff458d8 100644 --- a/yt-dlp/yt_dlp/extractor/hbo.py +++ b/yt-dlp/yt_dlp/extractor/hbo.py @@ -3,6 +3,7 @@ import re from .common import InfoExtractor from ..utils import ( int_or_none, + join_nonempty, parse_duration, urljoin, xpath_element, @@ -69,7 +70,7 @@ class HBOBaseIE(InfoExtractor): height = format_info.get('height') fmt = { 'url': path, - 'format_id': 'http{}'.format(f'-{height}p' if height else ''), + 'format_id': join_nonempty('http'. height and f'{height}p'), 'width': format_info.get('width'), 'height': height, } diff --git a/yt-dlp/yt_dlp/extractor/hketv.py b/yt-dlp/yt_dlp/extractor/hketv.py index bffb6afe02..3998abc121 100644 --- a/yt-dlp/yt_dlp/extractor/hketv.py +++ b/yt-dlp/yt_dlp/extractor/hketv.py @@ -44,9 +44,6 @@ class HKETVIE(InfoExtractor): 'duration': 907, 'subtitles': {}, }, - 'params': { - 'geo_verification_proxy': '', - }, 'skip': 'Geo restricted to HK', }] diff --git a/yt-dlp/yt_dlp/extractor/instagram.py b/yt-dlp/yt_dlp/extractor/instagram.py index c8bf7e9c4a..754f710ae2 100644 --- a/yt-dlp/yt_dlp/extractor/instagram.py +++ b/yt-dlp/yt_dlp/extractor/instagram.py @@ -453,7 +453,7 @@ class InstagramIE(InstagramBaseIE): else: self.report_warning('Main webpage is locked behind the login page. Retrying with embed webpage (some metadata might be missing).') webpage = self._download_webpage( - f'{url}/embed/', video_id, note='Downloading embed webpage', fatal=False) + f'{url}/embed/', video_id, note='Downloading embed webpage', fatal=False) or '' additional_data = self._search_json( r'window\.__additionalDataLoaded\s*\(\s*[^,]+,', webpage, 'additional data', video_id, fatal=False) if not additional_data and not media: diff --git a/yt-dlp/yt_dlp/extractor/iwara.py b/yt-dlp/yt_dlp/extractor/iwara.py index df2088f9e7..5b5c367ad8 100644 --- a/yt-dlp/yt_dlp/extractor/iwara.py +++ b/yt-dlp/yt_dlp/extractor/iwara.py @@ -2,7 +2,6 @@ import functools import hashlib import json import time -import urllib.error import urllib.parse from .common import InfoExtractor diff --git a/yt-dlp/yt_dlp/extractor/nbc.py b/yt-dlp/yt_dlp/extractor/nbc.py index 1da2cad3d4..8f6fb22b17 100644 --- a/yt-dlp/yt_dlp/extractor/nbc.py +++ b/yt-dlp/yt_dlp/extractor/nbc.py @@ -16,6 +16,7 @@ from ..utils import ( determine_ext, float_or_none, int_or_none, + join_nonempty, mimetype2ext, parse_age_limit, parse_duration, @@ -498,10 +499,8 @@ class NBCNewsIE(ThePlatformIE): # XXX: Do not subclass from concrete IE m3u8_id=format_id, fatal=False)) continue tbr = int_or_none(va.get('bitrate'), 1000) - if tbr: - format_id += f'-{tbr}' formats.append({ - 'format_id': format_id, + 'format_id': join_nonempty(format_id, tbr), 'url': public_url, 'width': int_or_none(va.get('width')), 'height': int_or_none(va.get('height')), diff --git a/yt-dlp/yt_dlp/extractor/nhl.py b/yt-dlp/yt_dlp/extractor/nhl.py index 83dd480cfa..ca47a81211 100644 --- a/yt-dlp/yt_dlp/extractor/nhl.py +++ b/yt-dlp/yt_dlp/extractor/nhl.py @@ -2,6 +2,7 @@ from .common import InfoExtractor from ..utils import ( determine_ext, int_or_none, + join_nonempty, parse_duration, parse_iso8601, ) @@ -41,7 +42,7 @@ class NHLBaseIE(InfoExtractor): else: height = int_or_none(playback.get('height')) formats.append({ - 'format_id': playback.get('name', 'http' + (f'-{height}p' if height else '')), + 'format_id': playback.get('name') or join_nonempty('http', height and f'{height}p'), 'url': playback_url, 'width': int_or_none(playback.get('width')), 'height': height, diff --git a/yt-dlp/yt_dlp/extractor/patreon.py b/yt-dlp/yt_dlp/extractor/patreon.py index 5dc46e3171..7d6e8439c6 100644 --- a/yt-dlp/yt_dlp/extractor/patreon.py +++ b/yt-dlp/yt_dlp/extractor/patreon.py @@ -316,7 +316,8 @@ class PatreonIE(PatreonBaseIE): r'(https(?:%3A%2F%2F|://)player\.vimeo\.com.+app_id(?:=|%3D)+\d+)', traverse_obj(attributes, ('embed', 'html', {str})), 'vimeo url', fatal=False) or '') if url_or_none(v_url) and self._request_webpage( - v_url, video_id, 'Checking Vimeo embed URL', headers=headers, fatal=False, errnote=False): + v_url, video_id, 'Checking Vimeo embed URL', headers=headers, + fatal=False, errnote=False, expected_status=429): # 429 is TLS fingerprint rejection entries.append(self.url_result( VimeoIE._smuggle_referrer(v_url, 'https://patreon.com/'), VimeoIE, url_transparent=True)) diff --git a/yt-dlp/yt_dlp/extractor/peloton.py b/yt-dlp/yt_dlp/extractor/peloton.py index c0443e9c91..5999d4a6a0 100644 --- a/yt-dlp/yt_dlp/extractor/peloton.py +++ b/yt-dlp/yt_dlp/extractor/peloton.py @@ -41,7 +41,7 @@ class PelotonIE(InfoExtractor): }, 'params': { 'skip_download': 'm3u8', }, - '_skip': 'Account needed', + 'skip': 'Account needed', }, { 'url': 'https://members.onepeloton.com/classes/player/26603d53d6bb4de1b340514864a6a6a8', 'info_dict': { @@ -61,7 +61,7 @@ class PelotonIE(InfoExtractor): }, 'params': { 'skip_download': 'm3u8', }, - '_skip': 'Account needed', + 'skip': 'Account needed', }] _MANIFEST_URL_TEMPLATE = '%s?hdnea=%s' @@ -199,7 +199,7 @@ class PelotonLiveIE(InfoExtractor): 'params': { 'skip_download': 'm3u8', }, - '_skip': 'Account needed', + 'skip': 'Account needed', } def _real_extract(self, url): diff --git a/yt-dlp/yt_dlp/extractor/performgroup.py b/yt-dlp/yt_dlp/extractor/performgroup.py index c0d5575912..df726c975b 100644 --- a/yt-dlp/yt_dlp/extractor/performgroup.py +++ b/yt-dlp/yt_dlp/extractor/performgroup.py @@ -1,5 +1,5 @@ from .common import InfoExtractor -from ..utils import int_or_none +from ..utils import int_or_none, join_nonempty class PerformGroupIE(InfoExtractor): @@ -50,11 +50,8 @@ class PerformGroupIE(InfoExtractor): if not c_url: continue tbr = int_or_none(c.get('bitrate'), 1000) - format_id = 'http' - if tbr: - format_id += f'-{tbr}' formats.append({ - 'format_id': format_id, + 'format_id': join_nonempty('http', tbr), 'url': c_url, 'tbr': tbr, 'width': int_or_none(c.get('width')), diff --git a/yt-dlp/yt_dlp/extractor/pr0gramm.py b/yt-dlp/yt_dlp/extractor/pr0gramm.py index f2c4e12e66..b0d6475fe4 100644 --- a/yt-dlp/yt_dlp/extractor/pr0gramm.py +++ b/yt-dlp/yt_dlp/extractor/pr0gramm.py @@ -1,9 +1,9 @@ import datetime as dt +import functools import json import urllib.parse from .common import InfoExtractor -from ..compat import functools from ..utils import ( ExtractorError, float_or_none, diff --git a/yt-dlp/yt_dlp/extractor/prosiebensat1.py b/yt-dlp/yt_dlp/extractor/prosiebensat1.py index 6a3e0971cd..e8a4712051 100644 --- a/yt-dlp/yt_dlp/extractor/prosiebensat1.py +++ b/yt-dlp/yt_dlp/extractor/prosiebensat1.py @@ -7,6 +7,7 @@ from ..utils import ( determine_ext, float_or_none, int_or_none, + join_nonempty, merge_dicts, unified_strdate, ) @@ -147,13 +148,13 @@ class ProSiebenSat1BaseIE(InfoExtractor): 'page_url': 'http://www.prosieben.de', 'tbr': tbr, 'ext': 'flv', - 'format_id': 'rtmp{}'.format(f'-{tbr}' if tbr else ''), + 'format_id': join_nonempty('rtmp', tbr), }) else: formats.append({ 'url': source_url, 'tbr': tbr, - 'format_id': 'http{}'.format(f'-{tbr}' if tbr else ''), + 'format_id': join_nonempty('http', tbr), }) return { diff --git a/yt-dlp/yt_dlp/extractor/tubetugraz.py b/yt-dlp/yt_dlp/extractor/tubetugraz.py index e13375f0a1..d5dbf007b1 100644 --- a/yt-dlp/yt_dlp/extractor/tubetugraz.py +++ b/yt-dlp/yt_dlp/extractor/tubetugraz.py @@ -21,7 +21,7 @@ class TubeTuGrazBaseIE(InfoExtractor): if not urlh: return - content, urlh = self._download_webpage_handle( + response = self._download_webpage_handle( urlh.url, None, fatal=False, headers={'referer': urlh.url}, note='logging in', errnote='unable to log in', data=urlencode_postdata({ @@ -30,7 +30,11 @@ class TubeTuGrazBaseIE(InfoExtractor): 'j_username': username, 'j_password': password, })) - if not urlh or urlh.url == 'https://tube.tugraz.at/paella/ui/index.html': + if not response: + return + + content, urlh = response + if urlh.url == 'https://tube.tugraz.at/paella/ui/index.html': return if not self._html_search_regex( @@ -39,7 +43,7 @@ class TubeTuGrazBaseIE(InfoExtractor): self.report_warning('unable to login: incorrect password') return - content, urlh = self._download_webpage_handle( + urlh = self._request_webpage( urlh.url, None, fatal=False, headers={'referer': urlh.url}, note='logging in with TFA', errnote='unable to log in with TFA', data=urlencode_postdata({ diff --git a/yt-dlp/yt_dlp/extractor/twitter.py b/yt-dlp/yt_dlp/extractor/twitter.py index 4ed48ec5ac..d056797f3c 100644 --- a/yt-dlp/yt_dlp/extractor/twitter.py +++ b/yt-dlp/yt_dlp/extractor/twitter.py @@ -14,6 +14,7 @@ from ..utils import ( float_or_none, format_field, int_or_none, + join_nonempty, make_archive_id, remove_end, str_or_none, @@ -107,7 +108,7 @@ class TwitterBaseIE(InfoExtractor): tbr = int_or_none(dict_get(variant, ('bitrate', 'bit_rate')), 1000) or None f = { 'url': variant_url, - 'format_id': 'http' + (f'-{tbr}' if tbr else ''), + 'format_id': join_nonempty('http', tbr), 'tbr': tbr, } self._search_dimensions_in_video_url(f, variant_url) diff --git a/yt-dlp/yt_dlp/extractor/viewlift.py b/yt-dlp/yt_dlp/extractor/viewlift.py index 7ac094f2f0..4a7ba9839e 100644 --- a/yt-dlp/yt_dlp/extractor/viewlift.py +++ b/yt-dlp/yt_dlp/extractor/viewlift.py @@ -5,6 +5,7 @@ from ..networking.exceptions import HTTPError from ..utils import ( ExtractorError, int_or_none, + join_nonempty, parse_age_limit, traverse_obj, ) @@ -120,7 +121,7 @@ class ViewLiftEmbedIE(ViewLiftBaseIE): 'height', default=None)) formats.append({ 'url': video_asset_url, - 'format_id': 'http{}'.format(f'-{bitrate}' if bitrate else ''), + 'format_id': join_nonempty('http', bitrate), 'tbr': bitrate, 'height': height, 'vcodec': video_asset.get('codec'), diff --git a/yt-dlp/yt_dlp/extractor/vimeo.py b/yt-dlp/yt_dlp/extractor/vimeo.py index 7e79032f28..a4ab7e24a9 100644 --- a/yt-dlp/yt_dlp/extractor/vimeo.py +++ b/yt-dlp/yt_dlp/extractor/vimeo.py @@ -829,21 +829,33 @@ class VimeoIE(VimeoBaseInfoExtractor): url = 'https://vimeo.com/' + video_id self._try_album_password(url) + is_secure = urllib.parse.urlparse(url).scheme == 'https' try: # Retrieve video webpage to extract further information webpage, urlh = self._download_webpage_handle( - url, video_id, headers=headers) + url, video_id, headers=headers, impersonate=is_secure) redirect_url = urlh.url - except ExtractorError as ee: - if isinstance(ee.cause, HTTPError) and ee.cause.status == 403: - errmsg = ee.cause.response.read() - if b'Because of its privacy settings, this video cannot be played here' in errmsg: - raise ExtractorError( - 'Cannot download embed-only video without embedding ' - 'URL. Please call yt-dlp with the URL of the page ' - 'that embeds this video.', - expected=True) - raise + except ExtractorError as error: + if not isinstance(error.cause, HTTPError) or error.cause.status not in (403, 429): + raise + errmsg = error.cause.response.read() + if b'Because of its privacy settings, this video cannot be played here' in errmsg: + raise ExtractorError( + 'Cannot download embed-only video without embedding URL. Please call yt-dlp ' + 'with the URL of the page that embeds this video.', expected=True) + # 403 == vimeo.com TLS fingerprint or DC IP block; 429 == player.vimeo.com TLS FP block + status = error.cause.status + dcip_msg = 'If you are using a data center IP or VPN/proxy, your IP may be blocked' + if target := error.cause.response.extensions.get('impersonate'): + raise ExtractorError( + f'Got HTTP Error {status} when using impersonate target "{target}". {dcip_msg}') + elif not is_secure: + raise ExtractorError(f'Got HTTP Error {status}. {dcip_msg}', expected=True) + raise ExtractorError( + 'This request has been blocked due to its TLS fingerprint. Install a ' + 'required impersonation dependency if possible, or else if you are okay with ' + f'{self._downloader._format_err("compromising your security/cookies", "light red")}, ' + f'try replacing "https:" with "http:" in the input URL. {dcip_msg}.', expected=True) if '://player.vimeo.com/video/' in url: config = self._search_json( diff --git a/yt-dlp/yt_dlp/extractor/weibo.py b/yt-dlp/yt_dlp/extractor/weibo.py index 3e82909825..b5c0e926f8 100644 --- a/yt-dlp/yt_dlp/extractor/weibo.py +++ b/yt-dlp/yt_dlp/extractor/weibo.py @@ -52,6 +52,7 @@ class WeiboBaseIE(InfoExtractor): }) def _weibo_download_json(self, url, video_id, *args, fatal=True, note='Downloading JSON metadata', **kwargs): + # XXX: Always fatal; _download_webpage_handle only returns False (not a tuple) on error webpage, urlh = self._download_webpage_handle(url, video_id, *args, fatal=fatal, note=note, **kwargs) if urllib.parse.urlparse(urlh.url).netloc == 'passport.weibo.com': self._update_visitor_cookies(urlh.url, video_id) diff --git a/yt-dlp/yt_dlp/extractor/wsj.py b/yt-dlp/yt_dlp/extractor/wsj.py index 7b3f6aa2ae..b6b656f7d3 100644 --- a/yt-dlp/yt_dlp/extractor/wsj.py +++ b/yt-dlp/yt_dlp/extractor/wsj.py @@ -2,6 +2,7 @@ from .common import InfoExtractor from ..utils import ( float_or_none, int_or_none, + join_nonempty, unified_strdate, ) @@ -76,7 +77,7 @@ class WSJIE(InfoExtractor): tbr = int_or_none(v.get('bitrate')) formats.append({ 'url': mp4_url, - 'format_id': 'http' + (f'-{tbr}' if tbr else ''), + 'format_id': join_nonempty('http', tbr), 'tbr': tbr, 'width': int_or_none(v.get('width')), 'height': int_or_none(v.get('height')), diff --git a/yt-dlp/yt_dlp/extractor/yahoo.py b/yt-dlp/yt_dlp/extractor/yahoo.py index f0ba830380..35e71209c5 100644 --- a/yt-dlp/yt_dlp/extractor/yahoo.py +++ b/yt-dlp/yt_dlp/extractor/yahoo.py @@ -8,6 +8,7 @@ from ..utils import ( ExtractorError, clean_html, int_or_none, + join_nonempty, mimetype2ext, parse_iso8601, traverse_obj, @@ -213,7 +214,7 @@ class YahooIE(InfoExtractor): tbr = int_or_none(s.get('bitrate')) formats.append({ 'url': s_url, - 'format_id': fmt + (f'-{tbr}' if tbr else ''), + 'format_id': join_nonempty(fmt, tbr), 'width': int_or_none(s.get('width')), 'height': int_or_none(s.get('height')), 'tbr': tbr, @@ -371,12 +372,13 @@ class YahooJapanNewsIE(InfoExtractor): url, content_id, 'mp4', 'm3u8_native', m3u8_id='hls', fatal=False)) else: + bitrate = int_or_none(vid.get('bitrate')) formats.append({ 'url': url, - 'format_id': f'http-{vid.get("bitrate")}', + 'format_id': join_nonempty('http', bitrate), 'height': int_or_none(vid.get('height')), 'width': int_or_none(vid.get('width')), - 'tbr': int_or_none(vid.get('bitrate')), + 'tbr': bitrate, }) self._remove_duplicate_formats(formats) diff --git a/yt-dlp/yt_dlp/extractor/yandexdisk.py b/yt-dlp/yt_dlp/extractor/yandexdisk.py index 56aa792929..3214816701 100644 --- a/yt-dlp/yt_dlp/extractor/yandexdisk.py +++ b/yt-dlp/yt_dlp/extractor/yandexdisk.py @@ -5,6 +5,7 @@ from ..utils import ( determine_ext, float_or_none, int_or_none, + join_nonempty, mimetype2ext, try_get, urljoin, @@ -116,12 +117,9 @@ class YandexDiskIE(InfoExtractor): else: size = video.get('size') or {} height = int_or_none(size.get('height')) - format_id = 'hls' - if height: - format_id += f'-{height}p' formats.append({ 'ext': 'mp4', - 'format_id': format_id, + 'format_id': join_nonempty('hls', height and f'{height}p'), 'height': height, 'protocol': 'm3u8_native', 'url': format_url, diff --git a/yt-dlp/yt_dlp/extractor/youtube.py b/yt-dlp/yt_dlp/extractor/youtube.py index 094b1e9a36..18e0ee91c7 100644 --- a/yt-dlp/yt_dlp/extractor/youtube.py +++ b/yt-dlp/yt_dlp/extractor/youtube.py @@ -4,6 +4,7 @@ import collections import copy import datetime as dt import enum +import functools import hashlib import itertools import json @@ -20,7 +21,6 @@ import urllib.parse from .common import InfoExtractor, SearchInfoExtractor from .openload import PhantomJSwrapper -from ..compat import functools from ..jsinterp import JSInterpreter from ..networking.exceptions import HTTPError, network_exceptions from ..utils import ( diff --git a/yt-dlp/yt_dlp/networking/_websockets.py b/yt-dlp/yt_dlp/networking/_websockets.py index 2153080a34..15db4fe433 100644 --- a/yt-dlp/yt_dlp/networking/_websockets.py +++ b/yt-dlp/yt_dlp/networking/_websockets.py @@ -1,6 +1,7 @@ from __future__ import annotations import contextlib +import functools import io import logging import ssl @@ -22,7 +23,6 @@ from .exceptions import ( TransportError, ) from .websocket import WebSocketRequestHandler, WebSocketResponse -from ..compat import functools from ..dependencies import websockets from ..socks import ProxyError as SocksProxyError from ..utils import int_or_none diff --git a/yt-dlp/yt_dlp/options.py b/yt-dlp/yt_dlp/options.py index 3d4c076610..1b18575c18 100644 --- a/yt-dlp/yt_dlp/options.py +++ b/yt-dlp/yt_dlp/options.py @@ -474,7 +474,7 @@ def create_parser(): 'no-attach-info-json', 'embed-thumbnail-atomicparsley', 'no-external-downloader-progress', 'embed-metadata', 'seperate-video-versions', 'no-clean-infojson', 'no-keep-subs', 'no-certifi', 'no-youtube-channel-redirect', 'no-youtube-unavailable-videos', 'no-youtube-prefer-utc-upload-date', - 'prefer-legacy-http-handler', 'manifest-filesize-approx', + 'prefer-legacy-http-handler', 'manifest-filesize-approx', 'allow-unsafe-ext', }, 'aliases': { 'youtube-dl': ['all', '-multistreams', '-playlist-match-filter', '-manifest-filesize-approx'], 'youtube-dlc': ['all', '-no-youtube-channel-redirect', '-no-live-chat', '-playlist-match-filter', '-manifest-filesize-approx'], @@ -646,7 +646,7 @@ def create_parser(): 'You can also simply specify a field to match if the field is present, ' 'use "!field" to check if the field is not present, and "&" to check multiple conditions. ' 'Use a "\\" to escape "&" or quotes if needed. If used multiple times, ' - 'the filter matches if atleast one of the conditions are met. E.g. --match-filter ' + 'the filter matches if at least one of the conditions is met. E.g. --match-filter ' '!is_live --match-filter "like_count>?100 & description~=\'(?i)\\bcats \\& dogs\\b\'" ' 'matches only videos that are not live OR those that have a like count more than 100 ' '(or the like field is not available) and also has a description ' @@ -1479,7 +1479,7 @@ def create_parser(): 'Optionally, the KEYRING used for decrypting Chromium cookies on Linux, ' 'the name/path of the PROFILE to load cookies from, ' 'and the CONTAINER name (if Firefox) ("none" for no container) ' - 'can be given with their respective seperators. ' + 'can be given with their respective separators. ' 'By default, all containers of the most recently accessed profile are used. ' f'Currently supported keyrings are: {", ".join(map(str.lower, sorted(SUPPORTED_KEYRINGS)))}')) filesystem.add_option( @@ -1781,7 +1781,7 @@ def create_parser(): 'It can be one of "pre_process" (after video extraction), "after_filter" (after video passes filter), ' '"video" (after --format; before --print/--output), "before_dl" (before each video download), ' '"post_process" (after each video download; default), ' - '"after_move" (after moving video file to it\'s final locations), ' + '"after_move" (after moving video file to its final locations), ' '"after_video" (after downloading and processing all formats of a video), ' 'or "playlist" (at end of playlist). ' 'This option can be used multiple times to add different postprocessors')) diff --git a/yt-dlp/yt_dlp/postprocessor/ffmpeg.py b/yt-dlp/yt_dlp/postprocessor/ffmpeg.py index 1ed37af518..164c46d143 100644 --- a/yt-dlp/yt_dlp/postprocessor/ffmpeg.py +++ b/yt-dlp/yt_dlp/postprocessor/ffmpeg.py @@ -1,5 +1,6 @@ import collections import contextvars +import functools import itertools import json import os @@ -8,7 +9,7 @@ import subprocess import time from .common import PostProcessor -from ..compat import functools, imghdr +from ..compat import imghdr from ..utils import ( MEDIA_EXTENSIONS, ISO639Utils, diff --git a/yt-dlp/yt_dlp/utils/_utils.py b/yt-dlp/yt_dlp/utils/_utils.py index 664675a099..b5e1e2950c 100644 --- a/yt-dlp/yt_dlp/utils/_utils.py +++ b/yt-dlp/yt_dlp/utils/_utils.py @@ -2085,17 +2085,20 @@ def parse_duration(s): (days, 86400), (hours, 3600), (mins, 60), (secs, 1), (ms, 1))) -def prepend_extension(filename, ext, expected_real_ext=None): +def _change_extension(prepend, filename, ext, expected_real_ext=None): name, real_ext = os.path.splitext(filename) - return ( - f'{name}.{ext}{real_ext}' - if not expected_real_ext or real_ext[1:] == expected_real_ext - else f'{filename}.{ext}') + + if not expected_real_ext or real_ext[1:] == expected_real_ext: + filename = name + if prepend and real_ext: + _UnsafeExtensionError.sanitize_extension(ext, prepend=True) + return f'{filename}.{ext}{real_ext}' + + return f'{filename}.{_UnsafeExtensionError.sanitize_extension(ext)}' -def replace_extension(filename, ext, expected_real_ext=None): - name, real_ext = os.path.splitext(filename) - return f'{name if not expected_real_ext or real_ext[1:] == expected_real_ext else filename}.{ext}' +prepend_extension = functools.partial(_change_extension, True) +replace_extension = functools.partial(_change_extension, False) def check_executable(exe, args=[]): @@ -5035,6 +5038,101 @@ MEDIA_EXTENSIONS.audio += MEDIA_EXTENSIONS.common_audio KNOWN_EXTENSIONS = (*MEDIA_EXTENSIONS.video, *MEDIA_EXTENSIONS.audio, *MEDIA_EXTENSIONS.manifests) +class _UnsafeExtensionError(Exception): + """ + Mitigation exception for uncommon/malicious file extensions + This should be caught in YoutubeDL.py alongside a warning + + Ref: https://github.com/yt-dlp/yt-dlp/security/advisories/GHSA-79w7-vh3h-8g4j + """ + ALLOWED_EXTENSIONS = frozenset([ + # internal + 'description', + 'json', + 'meta', + 'orig', + 'part', + 'temp', + 'uncut', + 'unknown_video', + 'ytdl', + + # video + *MEDIA_EXTENSIONS.video, + 'avif', + 'ismv', + 'm2ts', + 'm4s', + 'mng', + 'mpeg', + 'qt', + 'swf', + 'ts', + 'vp9', + 'wvm', + + # audio + *MEDIA_EXTENSIONS.audio, + 'isma', + 'mid', + 'mpga', + 'ra', + + # image + *MEDIA_EXTENSIONS.thumbnails, + 'bmp', + 'gif', + 'heic', + 'ico', + 'jng', + 'jpeg', + 'jxl', + 'svg', + 'tif', + 'wbmp', + + # subtitle + *MEDIA_EXTENSIONS.subtitles, + 'dfxp', + 'fs', + 'ismt', + 'sami', + 'scc', + 'ssa', + 'tt', + 'ttml', + + # others + *MEDIA_EXTENSIONS.manifests, + *MEDIA_EXTENSIONS.storyboards, + 'desktop', + 'ism', + 'm3u', + 'sbv', + 'url', + 'webloc', + 'xml', + ]) + + def __init__(self, extension, /): + super().__init__(f'unsafe file extension: {extension!r}') + self.extension = extension + + @classmethod + def sanitize_extension(cls, extension, /, *, prepend=False): + if '/' in extension or '\\' in extension: + raise cls(extension) + + if not prepend: + _, _, last = extension.rpartition('.') + if last == 'bin': + extension = last = 'unknown_video' + if last.lower() not in cls.ALLOWED_EXTENSIONS: + raise cls(extension) + + return extension + + class RetryManager: """Usage: for retry in RetryManager(...): diff --git a/yt-dlp/yt_dlp/version.py b/yt-dlp/yt_dlp/version.py index a90b288c9a..6e8fd3ae85 100644 --- a/yt-dlp/yt_dlp/version.py +++ b/yt-dlp/yt_dlp/version.py @@ -1,8 +1,8 @@ # Autogenerated by devscripts/update-version.py -__version__ = '2024.05.27' +__version__ = '2024.07.01' -RELEASE_GIT_HEAD = '12b248ce60be1aa1362edd839d915bba70dbee4b' +RELEASE_GIT_HEAD = '5ce582448ececb8d9c30c8c31f58330090ced03a' VARIANT = None @@ -12,4 +12,4 @@ CHANNEL = 'stable' ORIGIN = 'yt-dlp/yt-dlp' -_pkg_version = '2024.05.27' +_pkg_version = '2024.07.01'