From e4ce3e16d9970d46922e4c1dd17879121c5df99f Mon Sep 17 00:00:00 2001 From: "github-action[bot]" Date: Sun, 22 Mar 2026 19:51:04 +0100 Subject: [PATCH] Update On Sun Mar 22 19:51:04 CET 2026 --- .github/update.log | 1 + clash-meta/dns/util.go | 14 +- clash-nyanpasu/backend/Cargo.lock | 38 +- .../frontend/interface/package.json | 2 +- clash-nyanpasu/frontend/nyanpasu/package.json | 4 +- clash-nyanpasu/manifest/version.json | 4 +- clash-nyanpasu/pnpm-lock.yaml | 312 +- lede/include/kernel-5.10 | 4 +- lede/include/kernel-5.15 | 4 +- lede/include/kernel-6.1 | 4 +- lede/include/kernel-6.12 | 4 +- lede/include/kernel-6.6 | 4 +- ...v-Fix-CS-polarity-if-GPIO-descriptor.patch | 2 +- ...ompletely-disable-the-spidev-warning.patch | 2 +- ...o_user-and-__copy_from_user-performa.patch | 2 +- ...ehat-Add-Raspberry-Pi-Sense-HAT-to-s.patch | 6 +- ...-for-all-the-downstream-rpi-sound-ca.patch | 2 +- ...bcm2835-virtgpio-Virtual-GPIO-driver.patch | 2 +- ...fault-mouse-polling-interval-to-60Hz.patch | 4 +- ...Disable-TCP-Segmentation-Offload-TSO.patch | 2 +- ...e-link-events-to-minimize-poll-storm.patch | 2 +- ...8xx-Enable-LEDs-and-auto-negotiation.patch | 6 +- ...180-Default-to-the-first-valid-input.patch | 4 +- ...v7180-Add-YPrPb-support-for-ADV7282M.patch | 2 +- ...m-v3d-Clock-V3D-down-when-not-in-use.patch | 4 +- ...-v3d-Switch-clock-setting-to-new-api.patch | 4 +- ...ce-quirks-for-Freeway-Airmouse-T3-an.patch | 4 +- ...7-Support-for-the-Sony-IMX477-sensor.patch | 2 +- ...9-Support-for-the-Sony-IMX519-sensor.patch | 2 +- ...vicetree-Add-documentation-for-imx37.patch | 2 +- ...s-media-Add-binding-for-the-Raspberr.patch | 2 +- ...vices-ISP-Add-a-more-complex-ISP-pro.patch | 2 +- ...ov5647-Parse-and-register-properties.patch | 8 +- ...2c-ov5647-Correct-pixel-array-offset.patch | 25 - ...-ov5647-Correct-minimum-VBLANK-value.patch | 26 - ...-Add-a-timing-for-the-Raspberry-Pi-7.patch | 16 +- ...-a-driver-that-wraps-the-PWM-API-as-.patch | 2 +- ...-Sensor-should-report-RAW-color-spac.patch | 50 - ...a-i2c-ov5647-Support-HFLIP-and-VFLIP.patch | 2 +- ...dev-Restore-loading-from-Device-Tree.patch | 2 +- ...47-Add-support-for-regulator-control.patch | 2 +- ...2c-Add-configuration-for-RPi-POE-HAT.patch | 8 +- ...-Use-v4l2_async_register_subdev_sens.patch | 2 +- ...a-introduce-a-customisable-threshold.patch | 4 +- ...s-media-i2c-Add-Arducam-Pivariety-Se.patch | 2 +- ...e-jump-labels-before-they-are-initia.patch | 2 +- ...s-media-i2c-Add-Arducam-64MP-CMOS-se.patch | 2 +- ...-Nasty-hack-to-allow-input-selection.patch | 2 +- ...a-i2c-Add-IMX708-CMOS-sensor-binding.patch | 2 +- ...53x-Add-ti-tca9554-compatible-string.patch | 2 +- ...hwmon-aht10-Add-DT-compatible-string.patch | 4 +- ...a-i2c-Replace-IMX708-sensor-binding-.patch | 2 +- .../950-0344-sdhci-Add-SD-Express-hook.patch | 2 +- ...-net-macb-Also-set-DMA-coherent-mask.patch | 12 +- ...wc3-Set-DMA-and-coherent-masks-early.patch | 20 +- .../950-0352-mfd-Add-rp1-driver.patch | 2 +- ...f-dwcmshc-define-sdio-timeout-clocks.patch | 12 +- ...ware-Add-SMBUS-quick-command-support.patch | 8 +- ...ndings-i2c-Add-Rohm-BU64754-bindings.patch | 2 +- ...HM-BU64754-Camera-Autofocus-Actuator.patch | 2 +- ...0-Use-MEDIA_BUS_FMT_UYVY8_1X16-for-C.patch | 4 +- ...0-Add-support-for-V4L2_CID_LINK_FREQ.patch | 10 +- ...-add-FS-LS-bus-instance-parkmode-dis.patch | 8 +- ...ware-Support-non-standard-bus-speeds.patch | 2 +- ...78xx-Read-initial-EEE-status-from-DT.patch | 2 +- ...-bindings-Add-RPI-RP2040-GPIO-Bridge.patch | 2 +- ...river-for-the-RPI-RP2040-GPIO-bridge.patch | 2 +- ...edia-dt-bindings-i2c-Add-Sony-IMX500.patch | 2 +- ...2c-Add-driver-for-Sony-IMX500-sensor.patch | 2 +- ...v5647-Add-control-of-V4L2_CID_HBLANK.patch | 4 +- ...-Add-V4L2_CID_LINK_FREQUENCY-control.patch | 8 +- ...heck-emulated-zones-around-the-CMA-w.patch | 6 +- ...d-support-for-setting-NAK-enhancemen.patch | 8 +- ...pci-Disable-Host-Memory-Buffer-usage.patch | 6 +- ...arn-if-no-host-bridge-NUMA-node-info.patch | 2 +- ...Add-Raspberry-Pi-HEVC-decoder-driver.patch | 2 +- ...e-a-V3D-tech-revision-to-all-support.patch | 4 +- ...SMS-registers-for-power-on-off-and-r.patch | 2 +- ...st-PHY-PLL-setup-to-use-a-54MHz-inpu.patch | 14 +- ...same-constant-table-for-config-space.patch | 10 +- ...-two-changes-in-MDIO-register-fields.patch | 4 +- ...ify-conversion-of-irq_domain_set_inf.patch | 2 +- ...BCM7712-2712-specific-AXI-bridge-han.patch | 4 +- ...le-CRS-software-visibility-after-lin.patch | 4 +- ...brcmstb-add-NO_SSC-quirk-for-BCM2712.patch | 4 +- ...tb-optionally-extend-Tperst_clk-time.patch | 4 +- ...of-dwcmshc-define-sdio-timeout-clock.patch | 2 +- ...-add-more-safeguards-for-clkreq-safe.patch | 2 +- ...-around-VL805-firmware-ASPM-meddling.patch | 2 +- ...hwmon-aht10-Fix-AHT20-initialization.patch | 27 +- ...b-Add-link-statistics-debug-features.patch | 14 +- ...m-v3d-Don-t-retrieve-the-clock-twice.patch | 2 +- ...t-env-add-optional-env-size-property.patch | 62 + ...g-annotation-to-fix-build-with-GCC15.patch | 63 + ...6.13-jiffies-Define-secs_to_jiffies.patch} | 0 ...nsigned-long-in-secs_to_jiffies-con.patch} | 0 .../200-v6.14-compiler.h-add-const_true.patch | 117 - ...-property-add-of_graph_get_next_port.patch | 199 + ....16-bitfield-Add-FIELD_MODIFY-helper.patch | 70 - ...ework-bus-matching-to-avoid-warnings.patch | 61 + ...ARN-when-attempting-translating-non-.patch | 85 + ...nent-add-function-to-query-the-bound.patch | 69 - ...Add-functions-to-parse-memory-region.patch | 163 + ...copy-size-from-value-range-tracking.patch} | 0 ...Add-missing-IORESOURCE_MEM-flag-on-r.patch | 32 + ...-add-support-for-FORESEE-F35SQA001G.patch} | 0 ...-add-support-for-FudanMicro-FM25S01A.patch | 124 + ...02-v6.18-mtd-nand-move-chunk-to-core.patch | 329 ++ ...msh-remove-QE-bit-for-FM25S01A-flash.patch | 28 + ...nand-qcom-cleanup-qcom_nandc-driver.patch} | 19 +- ...-qcom-Add-qcom-prefix-to-common-api.patch} | 0 ...4-mtd-nand-Add-qpic_common-API-file.patch} | 0 ...and-qcom-use-FIELD_PREP-and-GENMASK.patch} | 0 ...fix-broken-config-in-qcom_param_pag.patch} | 0 ...Fix-build-issue-on-x86-architecture.patch} | 0 ...driver-for-QCOM-SPI-NAND-flash-Inte.patch} | 0 ...d-Fix-ECC_CFG_ECC_DISABLE-shift-in-.patch} | 0 ...d-avoid-memleak-in-qcom_spi_ecc_ini.patch} | 0 ...D-should-be-tristate-and-depend-on-.patch} | 0 ...te-errors-from-qcom_spi_block_erase.patch} | 0 ...D_READ_LOCATION_2-register-handling.patch} | 0 ...d-use-kmalloc-for-OOB-buffer-alloca.patch} | 0 ...wlen-member-of-struct-qpic_spi_nand.patch} | 0 ...plicit-test-for-built-in-CONFIG_SPI_.patch | 37 + ...e-user-chip-specific-ECC-properties.patch} | 20 +- ....14-mtd-nand-change-to-qpic_version2.patch | 20 - ...c-snand-use-CW_PER_PAGE_MASK-bitmask.patch | 113 + ...ic-snand-reallocate-BAM-transactions.patch | 81 + ...-qpic-snand-don-t-hardcode-ECC-steps.patch | 31 + ...mon-add-defines-for-ECC_MODE-values.patch} | 12 +- ...-add-support-for-8-bits-ECC-strength.patch | 66 + ...nd-use-correct-CW_PER_PAGE-value-for.patch | 56 + ...nd-fix-calculating-of-ECC-OOB-region.patch | 69 + ...nd-brcmnand-remove-unused-parameters.patch | 88 + ...d-fix-NAND-timeout-when-accessing-eM.patch | 30 + ...cmnand-legacy-exec_op-implementation.patch | 299 ++ ...nd-unregister-ECC-engine-on-probe-er.patch | 48 + ...nd-fix-direct-mapping-creation-sizes.patch | 63 + ...ry-a-regular-dirmap-if-creating-a-di.patch | 98 + ...epeat-reading-in-regular-mode-if-con.patch | 64 + ...and-esmt-add-support-for-F50L1G41LC.patch} | 2 +- ...dd-support-for-FudanMicro-FM25S01BI3.patch | 115 + ...t-for-defining-read-only-partitions.patch} | 2 +- ....13-block-introduce-add_disk_fwnode.patch} | 0 ...partitions-fwnode-if-found-in-mmc-c.patch} | 0 ...t-for-partition-table-defined-in-OF.patch} | 0 ...ink-move-manual-flow-control-setting.patch | 41 + ...-MLO_AN_FIXED-resolve-handling-to-if.patch | 42 + ...-MLO_AN_PHY-resolve-handling-to-if-s.patch | 37 + ...ve-switch-statement-in-resolve-handl.patch | 127 + ...net-phylink-clean-up-phylink_resolve.patch | 85 + ...-phylink-and-pcs-into-phylink_pcs_ne.patch | 95 + ...t-cur_link_an_mode-into-requested-an.patch | 290 ++ ...k-add-debug-for-phylink_major_config.patch | 66 + ...04-v6.14-net-phy-add-phy_inband_caps.patch | 118 + ...881-implement-phy_inband_caps-method.patch | 41 + ...ell-implement-phy_inband_caps-method.patch | 63 + ...-v6.14-net-phy-add-phy_config_inband.patch | 79 + ...rvell-implement-config_inband-method.patch | 77 + ...t-phylink-add-pcs_inband_caps-method.patch | 159 + ...eta-implement-pcs_inband_caps-method.patch | 64 + ...pp2-implement-pcs_inband_caps-method.patch | 62 + ...-negotiation-of-in-band-capabilities.patch | 228 ++ ...phylink-remove-phylink_phy_no_inband.patch | 110 + ...ynx-implement-pcs_inband_caps-method.patch | 53 + ...lynxi-implement-pcs_inband_caps-meth.patch | 47 + ...pcs-implement-pcs_inband_caps-method.patch | 58 + ...link-provide-phylink_get_inband_type.patch | 117 + ...ble-autoneg-for-interfaces-that-have.patch | 68 + ...3-net-dsa-use-ethtool-string-helpers.patch | 30 + ...sa-b53-mdio-add-support-for-BCM53101.patch | 76 + ...sa-b53-implement-setting-ageing-time.patch | 105 + ...ot-configure-bcm63xx-s-IMP-port-inte.patch | 70 + ...brcm-add-support-for-legacy-FCS-tags.patch | 188 + ...-net-dsa-b53-support-legacy-FCS-tags.patch | 48 + ...-net-dsa-b53-detect-BCM5325-variants.patch | 112 + ...port-for-FDB-operations-on-5325-5365.patch | 250 ++ ...3-prevent-FAST_AGE-access-on-BCM5325.patch | 51 + ...ent-BRCM_HDR-access-on-older-devices.patch | 33 + ...nicast-multicast-flooding-on-BCM5325.patch | 128 + ...3-Add-phy_enable-phy_disable-methods.patch | 50 + ...efine-chip-IDs-for-more-bcm63xx-SoCs.patch | 124 + ...nce-and-register-layout-for-bcm63268.patch | 69 + ...mmap-Add-register-layout-for-bcm6318.patch | 47 + ...mmap-Add-register-layout-for-bcm6368.patch | 42 + ...Implement-bcm63xx-ephy-power-control.patch | 100 + ...d-gphy-port-to-phy-info-for-bcm63268.patch | 33 + ...mplement-bcm63268-gphy-power-control.patch | 77 + ...rved-register-access-in-b53_fdb_dump.patch | 72 + ...dsa-b53-fix-ageing-time-for-BCM53101.patch | 77 + ...und-ARL-searches-for-4-ARL-bin-chips.patch | 61 + ...mark-link-local-traffic-as-offloaded.patch | 59 + ...ead-25-use-the-entry-for-comparision.patch | 85 + ...-ARL-entries-into-their-own-function.patch | 117 + ...ARL-entries-into-their-own-functions.patch | 93 + ...accessors-for-accessing-ARL_SRCH_CTL.patch | 85 + ...earch-entry-into-their-own-functions.patch | 86 + ...-ARL-entry-functions-into-ops-struct.patch | 348 ++ ...-for-5389-5397-5398-ARL-entry-format.patch | 221 + ...support-for-bcm63xx-ARL-entry-format.patch | 177 + ...LAN_ID_IDX-write-size-for-BCM5325-65.patch | 38 + ...acting-VID-from-entry-for-BCM5325-65.patch | 35 + ...-search-result-offset-for-BCM5325-65.patch | 78 + ...t-unicast-ARL-entries-for-BCM5325-65.patch | 51 + ...25-65-ARL-entry-multicast-port-masks.patch | 120 + ...sa-b53-fix-BCM5325-65-ARL-entry-VIDs.patch | 140 + ...t-dsa-b53-allow-VID-0-for-BCM5325-65.patch | 44 + ...ly-receive-all-multicast-packets-if-.patch | 41 + ...-net-usb-qmi_wwan-add-Quectel-RG255C.patch | 47 + ...-Introduce-device-managed-variant-of.patch | 74 + ...-sched-Export-mq-functions-for-reuse.patch | 255 ++ ...ke-Factor-out-config-variables-into-.patch | 636 +++ ...ke-Add-cake_mq-qdisc-for-using-cake-.patch | 130 + ...ke-Share-config-across-cake_mq-sub-q.patch | 318 ++ ...ke-share-shaper-state-across-sub-ins.patch | 175 + ...ting-add-selftests-for-cake_mq-qdisc.patch | 606 +++ ...void-separate-allocation-of-struct-c.patch | 112 + ...ke-avoid-sync-overhead-when-unlimite.patch | 32 + ...ke-fixup-cake_mq-rate-adjustment-for.patch | 187 + ...n-tag-insertion-stripping-by-defaul.patch} | 0 ...hy-mediatek-ge-soc-Fix-coding-style.patch} | 0 ...ge-soc-Shrink-line-wrapping-to-80-c.patch} | 0 ...ge-soc-Propagate-error-code-correct.patch} | 0 ...Re-organize-MediaTek-ethernet-phy-d.patch} | 0 ...Move-LED-helper-functions-into-mtk-.patch} | 0 ...Improve-readability-of-mtk-phy-lib..patch} | 0 ...Integrate-read-write-page-helper-fu.patch} | 0 ...k-add-MT7530-MT7531-s-PHY-ID-macros.patch} | 0 ...-phy-Constify-struct-mdio_device_id.patch} | 6 +- ...ek-Change-to-more-meaningful-macros.patch} | 0 ...Add-token-ring-access-helper-functi.patch} | 0 ...Add-token-ring-set-bit-operation-su.patch} | 0 ...Add-token-ring-clear-bit-operation-.patch} | 0 ...Move-some-macros-to-phy-lib-for-lat.patch} | 0 ...permit-to-compile-test-GE-SOC-PHY-d.patch} | 0 ...tek-add-Airoha-PHY-ID-to-SoC-driver.patch} | 0 ...init-val-in-.phy_led_polarity_set-f.patch} | 0 ...t-ethernet-mediatek-add-EEE-support.patch} | 6 +- ...ia-allow-forcing-order-of-MDI-pairs.patch} | 0 ...fix-return-value-check-in-aqr107_co.patch} | 0 ...t-active-high-property-for-PHY-LEDs.patch} | 2 +- ...correctly-describe-LED-polarity-ove.patch} | 0 ...t-phy-mxl-gpy-add-basic-LED-support.patch} | 0 ...dd-missing-support-for-TRIGGER_NETD.patch} | 0 ...gpy-correctly-describe-LED-polarity.patch} | 0 ...intel-xway-add-support-for-PHY-LEDs.patch} | 0 ...defined-behavior-in-_led_polarity_se.patch | 64 + ...t-dsa-mv88e6xxx-Support-LED-control.patch} | 0 ...x-fix-unreleased-fwnode_handle-in-se.patch | 31 + ...x-Fix-fwnode-reference-leaks-in-mv88.patch | 68 + ...ginal-workaround-for-RTL8125-broken-.patch | 2 +- ...TSO-on-selected-chip-versions-per-de.patch | 4 +- ...plement-additional-ethtool-stats-ops.patch | 2 +- ...169-don-t-take-RTNL-lock-in-rtl_task.patch | 6 +- ...-custom-flag-with-disable_work-et-al.patch | 12 +- ...itialization-of-RSS-registers-on-RTL.patch | 2 +- ...leftover-locks-after-reverted-change.patch | 2 +- ...r-driver-2.5G-5G-EEE-advertisement-c.patch | 2 +- ...sed-flag-RTL_FLAG_TASK_RESET_NO_QUEU.patch | 2 +- ...9-remove-support-for-chip-version-11.patch | 8 +- ...adjust-version-numbering-for-RTL8126.patch | 26 +- ...r8169-add-support-for-RTL8125D-rev.b.patch | 4 +- ...8169-add-support-for-RTL8125BP-rev.b.patch | 4 +- ...5-ops-for-MDIO_MMD_VENDOR2-registers.patch | 4 +- ...ax-jumbo-packet-size-on-RTL8125-RTL8.patch | 2 +- ...way-from-deprecated-pcim_iomap_table.patch | 2 +- ...8168H-RTL8168EP-RTL8168FP-ASPM-suppo.patch | 2 +- ...r-rtl_csi_mod-for-accessing-extended.patch | 6 +- ...8169-refactor-chip-version-detection.patch | 8 +- ...GA_MAC_VER_LAST-to-facilitate-adding.patch | 16 +- ...pci_prepare_to_sleep-in-rtl_shutdown.patch | 2 +- ...rge-chip-versions-70-and-71-RTL8126A.patch | 12 +- ...rge-chip-versions-64-and-65-RTL8125D.patch | 4 +- ...erge-chip-versions-52-and-53-RTL8117.patch | 4 +- ...v6.16-r8169-add-support-for-RTL8127A.patch | 14 +- ...altek-convert-RTL8226-CG-to-c45-only.patch | 169 + ...le-serdes-option-mode-for-RTL8226-CG.patch | 92 + ...s-PHY-driver-to-.match_phy_device-OP.patch | 2 +- ...hy-introduce-genphy_match_phy_device.patch | 2 +- ...dd-support-for-Aeonsemi-AS21xxx-PHYs.patch | 17 +- ...dsa-Move-KS8995-to-the-DSA-subsystem.patch | 1092 +++++ ...et-dsa-ks8995-Add-proper-RESET-delay.patch | 40 + ...-ks8995-Delete-sysfs-register-access.patch | 109 + ...t-dsa-ks8995-Add-basic-switch-set-up.patch | 546 +++ ...add-error-handling-to-rtl8211f_get_w.patch | 39 + ...Avoid-PHYCR2-access-if-PHYCR2-not-pr.patch | 61 + ...tek-fix-RTL8211F-wake-on-lan-support.patch | 352 ++ ...-phy-realtek-fix-rtl8221b-vm-cg-name.patch | 70 + ...support-for-TRIGGER_NETDEV_LINK-on-R.patch | 105 + ...ek-Add-RTL8224-cable-testing-support.patch | 272 ++ ...k-add-interrupt-support-for-RTL8221B.patch | 105 + ...k-create-rtl8211f_config_rgmii_delay.patch | 128 + ...altek-eliminate-priv-phycr2-variable.patch | 101 + ...ealtek-eliminate-has_phycr2-variable.patch | 55 + ...allow-CLKOUT-to-be-disabled-on-RTL82.patch | 101 + ...altek-eliminate-priv-phycr1-variable.patch | 107 + ...create-rtl8211f_config_phy_eee-helpe.patch | 58 + ...e-phy_id_compare_vendor-PHY-ID-helpe.patch | 58 + ...better-handle-PHY-HW-reset-on-soft-r.patch | 45 + ...VD-Restore-disabling-of-PHY-mode-EEE.patch | 61 + ...ks-add-binding-for-gated-fixed-clock.patch | 82 + ...regmap-Use-generic-request-free-ops.patch} | 2 +- ...-termination-to-fix-build-with-GCC15.patch | 39 + ...ngs-leds-Add-LED1202-LED-Controller.patch} | 31 +- ...2-v6.14-leds-Add-LED1202-I2C-driver.patch} | 54 +- ...t1202-Fix-NULL-pointer-access-error.patch} | 17 +- ...a-faux-bus-for-use-when-a-simple-dev.patch | 2 +- .../files/drivers/bcma/fallback-sprom.c | 7 +- .../files/drivers/bcma/fallback-sprom.h | 7 + .../files/drivers/net/phy/rtl8261n/Kconfig | 5 + .../files/drivers/net/phy/rtl8261n/Makefile | 11 + .../phy/rtl8261n/construct/conf_rtl8261n_c.c | 1465 +++++++ .../phy/rtl8261n/construct/conf_rtl8264b.c | 2177 ++++++++++ .../files/drivers/net/phy/rtl8261n/error.h | 165 + .../drivers/net/phy/rtl8261n/phy_patch.c | 190 + .../drivers/net/phy/rtl8261n/phy_patch.h | 174 + .../net/phy/rtl8261n/phy_rtl826xb_patch.c | 1031 +++++ .../net/phy/rtl8261n/phy_rtl826xb_patch.h | 63 + .../files/drivers/net/phy/rtl8261n/rtk_osal.c | 57 + .../files/drivers/net/phy/rtl8261n/rtk_osal.h | 99 + .../files/drivers/net/phy/rtl8261n/rtk_phy.c | 324 ++ .../drivers/net/phy/rtl8261n/rtk_phylib.c | 108 + .../drivers/net/phy/rtl8261n/rtk_phylib.h | 106 + .../drivers/net/phy/rtl8261n/rtk_phylib_def.h | 166 + .../net/phy/rtl8261n/rtk_phylib_rtl826xb.c | 57 + .../net/phy/rtl8261n/rtk_phylib_rtl826xb.h | 19 + .../files/drivers/net/phy/rtl8261n/type.h | 117 + .../files/drivers/ssb/fallback-sprom.c | 7 +- .../files/drivers/ssb/fallback-sprom.h | 7 + .../hack-6.12/249-udp-tunnel-selection.patch | 36 + .../generic/hack-6.12/253-ksmbd-config.patch | 2 +- .../hack-6.12/259-regmap_dynamic.patch | 2 +- ...rans-call-add-disks-after-mtd-device.patch | 2 +- ...upport-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch | 2 +- .../hack-6.12/430-mtk-bmt-support.patch | 4 +- ...y-to-free-deferred-skbs-while-waitin.patch | 12 +- .../700-swconfig_switch_drivers.patch | 2 +- ...-dsa-mv88e6xxx-disable-ATU-violation.patch | 2 +- .../721-net-add-packet-mangeling.patch | 2 +- ..._eth_soc-add-hw-dump-for-forced-rese.patch | 12 +- .../735-net-phy-realtek-rtl8261n.patch | 21 + ...mtk-lynxi-workaround-2500BaseX-no-an.patch | 6 +- ...comm-yt8821-bus-collision-workaround.patch | 85 + .../780-usb-net-MeigLink_modem_support.patch | 8 +- .../800-GPIO-add-named-gpio-exports.patch | 2 +- .../810-bcma-ssb-fallback-sprom.patch | 41 +- .../generic/hack-6.12/902-debloat_proc.patch | 12 +- .../hack-6.12/904-debloat_dma_buf.patch | 2 +- ...ge_allow_receiption_on_disabled_port.patch | 4 +- .../203-kallsyms_uncompressed.patch | 4 +- ...-simple-bus-compatible-from-ifc-node.patch | 125 + ...malloc-tlb_vpn-array-to-avoid-stack-.patch | 60 + ...revent-a-TLB-shutdown-on-initial-uni.patch | 146 + .../400-mtd-mtdsplit-support.patch | 8 +- ...er-NVMEM-devices-for-partitions-with.patch | 48 - ...-add-support-for-8-bits-ECC-strength.patch | 388 -- ...ronix-disable-continuous-read-for-MX.patch | 39 + ...nd-Add-support-for-Etron-EM73D044VCx.patch | 10 +- ...add-uImage.FIT-subimage-block-driver.patch | 2 +- ...net-sfp-improve-Huawei-MA5671a-fixup.patch | 149 + ...ly-receive-all-multicast-packets-if-.patch | 24 - .../650-net-pppoe-implement-GRO-support.patch | 8 +- ...Add-support-for-MAP-E-FMRs-mesh-mode.patch | 22 +- ...ng-with-source-address-failed-policy.patch | 20 +- ..._F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch | 4 +- ...d-missing-check-for-TCP-fraglist-GRO.patch | 2 +- ...les-ignore-EOPNOTSUPP-on-flowtable-d.patch | 2 +- ...detach-callback-to-struct-phy_driver.patch | 2 +- ...-phy-led_triggers-during-probe-to-av.patch | 116 + ...e-host_interfaces-when-attaching-PHY.patch | 4 +- ...d-knob-for-filtering-rx-tx-BPDU-pack.patch | 8 +- ...-use-genphy_soft_reset-for-2.5G-PHYs.patch | 38 +- ...sable-SGMII-in-band-AN-for-2-5G-PHYs.patch | 51 +- ...make-sure-paged-read-is-protected-by.patch | 2 +- .../720-04-net-phy-realtek-setup-aldps.patch | 81 +- ...tek-detect-early-version-of-RTL8221B.patch | 2 +- ...ealtek-support-interrupt-of-RTL8221B.patch | 102 - ...ealtek-mark-existing-MMDs-as-present.patch | 2 +- ...hy-realtek-work-around-broken-serdes.patch | 58 + ...t-phy-realtek-disable-MDIO-broadcast.patch | 28 +- ...rnet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch | 21 - ..._eth_soc-optimize-dma-ring-address-i.patch | 486 +++ ...mtk_eth_soc-shrink-struct-mtk_tx_buf.patch | 124 + ..._eth_soc-add-support-for-sending-fra.patch | 519 +++ ...ernet-mtk_eth_soc-use-napi_build_skb.patch | 4 +- ...-mediatek-enlarge-DMA-reserve-buffer.patch | 4 +- ..._eth_soc-zero-initialize-PPE-flow-ta.patch | 27 + ..._eth_soc-add-paths-and-SerDes-modes-.patch | 72 +- ...th_soc-reduce-rx-ring-size-for-older.patch | 26 +- ..._eth_soc-do-not-enable-page-pool-sta.patch | 4 +- ...lynxi-add-platform-driver-for-MT7988.patch | 14 +- ...-add-driver-for-MediaTek-USXGMII-PCS.patch | 2 +- ...dd-quirk-for-FlyPro-10Gbase-T-module.patch | 28 - ...Fix-DMA-allocations-on-57766-devices.patch | 2 +- ...pio-cascade-add-generic-GPIO-cascade.patch | 2 +- ...e-old-opp-to-config_clks-on-_set_opp.patch | 26 + .../810-pci_disable_common_quirks.patch | 6 +- ...e-single-creation-of-sysfs-entry-for.patch | 142 + .../pending-6.12/834-ledtrig-libata.patch | 8 +- .../pending-6.12/920-mangle_bootargs.patch | 6 +- ...ruct-device-pointer-to-device-contex.patch | 60 + ...ek-mt7986-bpi-r3-Change-fan-PWM-valu.patch | 72 + ...k-enable-ies_present-flag-for-MT798x.patch | 59 + ...iatek-MT7981-some-register-map-fixes.patch | 76 + ...k-mt7988-Add-xsphy-for-ssusb0-pcie2.patch} | 7 +- ...ediatek-mt7988a-bpi-r4-enable-xsphy.patch} | 4 +- ...-mediatek-mt7988-add-spi-controllers.patch | 112 - ...-mediatek-mt7988-add-spi-controllers.patch | 69 + ...move-uart0-and-spi1-pins-to-soc-dtsi.patch | 133 - ...ek-mt7988-move-uart0-and-spi1-pins-t.patch | 90 + ...m64-dts-mediatek-mt7988-add-cci-node.patch | 128 - ...m64-dts-mediatek-mt7988-add-cci-node.patch | 86 + ...8-add-phy-calibration-efuse-subnodes.patch | 85 - ...ek-mt7988-add-phy-calibration-efuse-.patch | 42 + ...7988a-bpi-r4-Add-fan-and-coolingmaps.patch | 98 - ...ek-mt7988a-bpi-r4-Add-fan-and-coolin.patch | 59 + ...k-mt7988a-bpi-r4-configure-spi-nodes.patch | 99 - ...tek-mt7988a-bpi-r4-configure-spi-node.patc | 55 + ...7988a-bpi-r4-add-proc-supply-for-cci.patch | 68 - ...ek-mt7988a-bpi-r4-add-proc-supply-fo.patch | 28 + ...4-dts-mediatek-fix-mt7981-spim-clock.patch | 53 + ...ek-add-MT7988A-reference-board-devic.patch | 21 +- ...dts-mediatek-mt7988a-complete-bpi-r4.patch | 26 +- ...-dts-mt7986a-bpi-r3-mini-wifi-eeprom.patch | 136 - .../198-dts-mt7988a-enable-wed.patch | 167 + ...ek-mt7986-increase-ATF-reserved-memo.patch | 29 + ...-phy-phy-mtk-tphy-Add-hifsys-support.patch | 2 +- ...rng-add-driver-for-MediaTek-TRNG-SMC.patch | 133 - ...k-add-support-for-hw-access-via-SMCC.patch | 212 + .../330-snand-mtk-bmt-support.patch | 6 +- ...Add-support-for-the-Fidelix-FM35X1GA.patch | 14 +- ...-mediatek-add-mt7987-pinctrl-support.patch | 2 +- ...-mtd-spinand-fix-support-for-FORESEE.patch | 19 + ...ers-spi-mem-Add-spi-calibration-hook.patch | 4 +- ...and-Add-calibration-support-for-spin.patch | 4 +- ...nor-Add-calibration-support-for-spi-.patch | 2 +- .../500-gsw-rtl8367s-mt7622-support.patch | 2 +- ...ert-PERST-for-100ms-for-power-and-cl.patch | 34 - ...-Add-2.5Gphy-firmware-dt-bindings-an.patch | 2 +- ...-add-driver-for-built-in-2.5G-ethern.patch | 6 +- ...ediatek-add-support-for-coherent-DMA.patch | 2 +- ...-don-t-use-SGMII-AN-if-using-phylink.patch | 63 - .../737-net-dsa-add-Airoha-AN8855.patch | 4 +- ...-negotiation-of-in-band-capabilities.patch | 1242 ------ ...ernet-mtk_eth_soc-add-mt7987-support.patch | 10 +- ...se-hardware-configuration-for-mt7987.patch | 2 +- ...63-arm64-dts-mt7986-add-sound-wm8960.patch | 2 +- .../901-arm-add-cmdline-override.patch | 2 +- ...tk_wed-move-dlm-a-dedicated-dts-node.patch | 4 +- .../950-smartrg-i2c-led-driver.patch | 2 +- ...i-r3-add-label-to-gmac-for-sfp1-port.patch | 10 + ...960-asus-hack-u-boot-ignore-mtdparts.patch | 47 + ...mediatek-gen3-Add-WIFI-HW-reset-flow.patch | 88 + mieru/.github/workflows/mihomo.yaml | 16 +- mihomo/dns/util.go | 14 +- openwrt-packages/adguardhome/Makefile | 42 +- .../adguardhome/files/adguardhome.conf | 30 + .../adguardhome/files/adguardhome.config | 4 - .../adguardhome/files/adguardhome.defaults | 109 + .../adguardhome/files/adguardhome.init | 122 +- .../adguardhome/files/adguardhome.json | 22 + .../adguardhome/files/adguardhome.sysctl | 3 + .../luci-app-adguardhome/Makefile | 30 +- .../luci-app-adguardhome/README.md | 145 + .../luasrc/controller/AdGuardHome.lua | 235 +- .../luasrc/model/cbi/AdGuardHome/base.lua | 406 +- .../luasrc/model/cbi/AdGuardHome/manual.lua | 150 +- .../po/zh_Hans/adguardhome.po | 598 ++- .../root/etc/init.d/AdGuardHome | 645 +-- .../root/usr/share/AdGuardHome/addhost.sh | 75 +- .../root/usr/share/AdGuardHome/gfw2adg.sh | 198 +- .../root/usr/share/AdGuardHome/update_core.sh | 449 +- .../root/usr/share/AdGuardHome/waitnet.sh | 40 +- openwrt-packages/luci-app-aliddns/Makefile | 2 +- .../luci-app-fileassistant/README.md | 155 + .../resources/fileassistant/fb.css | 79 +- .../luci-static/resources/fileassistant/fb.js | 354 +- .../luasrc/controller/fileassistant.lua | 486 ++- .../rpcd/acl.d/luci-app-fileassistant.json | 11 +- openwrt-packages/luci-app-guest-wifi/Makefile | 10 +- .../luci-app-guest-wifi/README.md | 78 +- .../luci-static/resources/view/guest-wifi.js | 46 - .../resources/view/guest-wifi/wifi.js | 94 +- .../luasrc/controller/guest-wifi.lua | 14 +- .../luasrc/model/cbi/guest-wifi/wifi.lua | 25 +- .../po/templates/guest-wifi.pot | 13 +- openwrt-packages/luci-app-guest-wifi/po/zh-cn | 1 + .../luci-app-guest-wifi/po/zh_Hans | 1 - .../po/{zh-cn => zh_Hans}/guest-wifi.po | 14 +- .../root/etc/config/guest-wifi | 3 - .../root/etc/init.d/guest-wifi | 8 +- .../root/etc/uci-defaults/40_luci-guest-wifi | 11 +- .../uci-defaults/luci-i18n-guest-wifi-zh-cn | 8 - .../lib/lua/luci/controller/guest-wifi.lua | 9 - .../root/usr/sbin/guest-wifi | 19 - .../share/rpcd/acl.d/luci-app-guest-wifi.json | 26 +- openwrt-packages/luci-theme-alpha/Makefile | 2 +- .../luci-theme-alpha/js/menu-alpha.js | 74 +- .../luci-theme-alpha/luasrc/gaya/gaya.css | 73 +- .../luci-theme-alpha/luasrc/gaya/gaya.css.bak | 3625 ----------------- .../luci-theme-alpha/luasrc/style/catatan.txt | 1 - .../luasrc/style/openwrt20thanniversary.png | Bin 183284 -> 126625 bytes .../luci-theme-alpha/luasrc/style/style.css | 3 +- .../luci-theme-alpha/template/footer.htm | 209 +- .../luci-theme-alpha/template/footer.ut | 2 +- .../luci-theme-alpha/template/header.htm | 184 +- .../luci-theme-alpha/template/header.ut | 1 + .../luci-theme-alpha/template/sysauth.htm | 2 +- .../luci-theme-alpha/template/sysauth.ut | 2 +- openwrt-packages/luci-theme-ifit/Makefile | 56 - .../luci-theme-ifit/files/10_luci-theme-ifit | 7 - .../files/htdocs/css/style.css | 2721 ------------- .../luci-theme-ifit/files/htdocs/favicon.ico | Bin 67646 -> 0 bytes .../htdocs/fonts/Roboto-Medium-webfont.woff | Bin 70200 -> 0 bytes .../htdocs/fonts/Roboto-Regular-webfont.woff | Bin 68776 -> 0 bytes .../files/htdocs/fonts/font.eot | Bin 1912 -> 0 bytes .../files/htdocs/fonts/font.svg | 16 - .../files/htdocs/fonts/font.ttf | Bin 1748 -> 0 bytes .../files/htdocs/fonts/font.woff | Bin 1824 -> 0 bytes .../files/htdocs/fonts/icomoon.eot | Bin 24952 -> 0 bytes .../files/htdocs/fonts/icomoon.svg | 130 - .../files/htdocs/fonts/icomoon.ttf | Bin 24788 -> 0 bytes .../files/htdocs/fonts/icomoon.woff | Bin 24864 -> 0 bytes .../files/htdocs/images/main_bg.jpg | Bin 535588 -> 0 bytes .../files/htdocs/images/main_bg_5k.jpg | Bin 1267748 -> 0 bytes .../files/htdocs/js/jquery.min.js | 6 - .../luci-theme-ifit/files/htdocs/js/script.js | 238 -- .../luci-theme-ifit/files/htdocs/logo.png | Bin 222458 -> 0 bytes .../files/templates/footer.htm | 53 - .../files/templates/header.htm | 278 -- .../model/cbi/passwall/client/acl_config.lua | 5 + .../model/cbi/passwall/client/global.lua | 3 +- .../model/cbi/passwall/client/type/ray.lua | 2 +- .../cbi/passwall/client/type/sing-box.lua | 31 +- .../luasrc/passwall/util_sing-box.lua | 19 +- .../luasrc/passwall/util_xray.lua | 2 +- .../passwall/node_config/link_share_man.htm | 74 + .../luci-app-passwall/po/zh-cn/passwall.po | 3 + .../root/usr/share/passwall/app.sh | 12 +- .../share/passwall/helper_chinadns_add.lua | 5 +- .../share/passwall/helper_smartdns_add.lua | 2 +- .../root/usr/share/passwall/subscribe.lua | 62 + .../rules/shadowsocks-rust-orientation.mdc | 74 + .../.github/workflows/build-msrv.yml | 18 +- shadowsocks-rust/Cargo.lock | 58 +- shadowsocks-rust/Cargo.toml | 6 +- shadowsocks-rust/Dockerfile | 2 +- shadowsocks-rust/clippy.toml | 2 +- .../crates/shadowsocks-service/Cargo.toml | 8 +- .../crates/shadowsocks/Cargo.toml | 4 +- shadowsocks-rust/debian/changelog | 8 + small/gn/Makefile | 7 +- small/gn/src/out/last_commit_position.h | 4 +- .../model/cbi/passwall/client/acl_config.lua | 5 + .../model/cbi/passwall/client/global.lua | 3 +- .../model/cbi/passwall/client/type/ray.lua | 2 +- .../cbi/passwall/client/type/sing-box.lua | 31 +- .../luasrc/passwall/util_sing-box.lua | 19 +- .../luasrc/passwall/util_xray.lua | 2 +- .../passwall/node_config/link_share_man.htm | 74 + small/luci-app-passwall/po/zh-cn/passwall.po | 3 + .../root/usr/share/passwall/app.sh | 12 +- .../share/passwall/helper_chinadns_add.lua | 5 +- .../share/passwall/helper_smartdns_add.lua | 2 +- .../root/usr/share/passwall/subscribe.lua | 62 + .../view/shadowsocksr/Sortable.min.js | 2 + .../luasrc/controller/shadowsocksr.lua | 335 +- .../model/cbi/shadowsocksr/advanced.lua | 68 +- .../model/cbi/shadowsocksr/client-config.lua | 262 +- .../luasrc/model/cbi/shadowsocksr/servers.lua | 159 +- .../luasrc/view/shadowsocksr/server_list.htm | 952 +++-- .../luasrc/view/shadowsocksr/socket.htm | 3 + .../luasrc/view/shadowsocksr/ssrurl.htm | 67 +- .../po/templates/ssr-plus.pot | 1128 ++--- .../luci-app-ssr-plus/po/zh_Hans/ssr-plus.po | 1154 +++--- .../root/etc/init.d/shadowsocksr | 15 +- .../usr/share/shadowsocksr/gen_config.lua | 176 +- .../root/usr/share/shadowsocksr/hy2_test.sh | 175 + .../share/shadowsocksr/shadowsocksr.config | 1 + .../root/usr/share/shadowsocksr/subscribe.lua | 226 +- small/v2ray-geodata/Makefile | 4 +- .../v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx | 12 +- xray-core/README.md | 3 + xray-core/common/xudp/xudp.go | 2 +- xray-core/go.mod | 4 +- xray-core/go.sum | 6 +- xray-core/infra/conf/wireguard.go | 2 +- xray-core/proxy/proxy.go | 66 +- xray-core/proxy/wireguard/client.go | 36 + xray-core/proxy/wireguard/gvisortun/tun.go | 39 +- xray-core/proxy/wireguard/server.go | 52 +- xray-core/proxy/wireguard/tun.go | 254 +- xray-core/transport/internet/hysteria/hub.go | 47 +- yt-dlp/yt_dlp/extractor/rtp.py | 202 +- 594 files changed, 32815 insertions(+), 15519 deletions(-) delete mode 100644 lede/target/linux/bcm27xx/patches-6.12/950-0225-media-i2c-ov5647-Correct-pixel-array-offset.patch delete mode 100644 lede/target/linux/bcm27xx/patches-6.12/950-0226-media-i2c-ov5647-Correct-minimum-VBLANK-value.patch delete mode 100644 lede/target/linux/bcm27xx/patches-6.12/950-0248-media-i2c-ov5647-Sensor-should-report-RAW-color-spac.patch create mode 100644 lede/target/linux/generic/backport-6.12/010-v6.19-nvmem-layouts-u-boot-env-add-optional-env-size-property.patch create mode 100644 lede/target/linux/generic/backport-6.12/152-v6.16-net-wireguard-add-nonstring-annotation-to-fix-build-with-GCC15.patch rename lede/target/linux/generic/backport-6.12/{330-v6.13-jiffies-Define-secs_to_jiffies.patch => 200-01-v6.13-jiffies-Define-secs_to_jiffies.patch} (100%) rename lede/target/linux/generic/backport-6.12/{331-v6.14-jiffies-Cast-to-unsigned-long-in-secs_to_jiffies-con.patch => 200-02-v6.14-jiffies-Cast-to-unsigned-long-in-secs_to_jiffies-con.patch} (100%) delete mode 100644 lede/target/linux/generic/backport-6.12/200-v6.14-compiler.h-add-const_true.patch create mode 100644 lede/target/linux/generic/backport-6.12/201-v6.13-of-property-add-of_graph_get_next_port.patch delete mode 100644 lede/target/linux/generic/backport-6.12/201-v6.16-bitfield-Add-FIELD_MODIFY-helper.patch create mode 100644 lede/target/linux/generic/backport-6.12/203-01-v6.13-of-address-Rework-bus-matching-to-avoid-warnings.patch create mode 100644 lede/target/linux/generic/backport-6.12/203-02-v6.13-of-address-Fix-WARN-when-attempting-translating-non-.patch delete mode 100644 lede/target/linux/generic/backport-6.12/203-v6.15-drivers-base-component-add-function-to-query-the-bound.patch create mode 100644 lede/target/linux/generic/backport-6.12/205-v6.16-of-reserved_mem-Add-functions-to-parse-memory-region.patch rename lede/target/linux/generic/backport-6.12/{902-v6.13-fortify-Hide-run-time-copy-size-from-value-range-tracking.patch => 210-v6.13-fortify-Hide-run-time-copy-size-from-value-range-tracking.patch} (100%) create mode 100644 lede/target/linux/generic/backport-6.12/212-v6.17-of-reserved_mem-Add-missing-IORESOURCE_MEM-flag-on-r.patch rename lede/target/linux/generic/backport-6.12/{412-v6.14-mtd-spinand-add-support-for-FORESEE-F35SQA001G.patch => 400-v6.14-mtd-spinand-add-support-for-FORESEE-F35SQA001G.patch} (100%) create mode 100644 lede/target/linux/generic/backport-6.12/401-v6.17-mtd-spinand-add-support-for-FudanMicro-FM25S01A.patch create mode 100644 lede/target/linux/generic/backport-6.12/402-v6.18-mtd-nand-move-chunk-to-core.patch create mode 100644 lede/target/linux/generic/backport-6.12/404-v6.19-mtd-spinand-fmsh-remove-QE-bit-for-FM25S01A-flash.patch rename lede/target/linux/generic/backport-6.12/{413-01-v6.14-mtd-rawnand-qcom-cleanup-qcom_nandc-driver.patch => 410-01-v6.14-mtd-rawnand-qcom-cleanup-qcom_nandc-driver.patch} (98%) rename lede/target/linux/generic/backport-6.12/{413-02-v6.14-mtd-rawnand-qcom-Add-qcom-prefix-to-common-api.patch => 410-02-v6.14-mtd-rawnand-qcom-Add-qcom-prefix-to-common-api.patch} (100%) rename lede/target/linux/generic/backport-6.12/{413-03-v6.14-mtd-nand-Add-qpic_common-API-file.patch => 410-03-v6.14-mtd-nand-Add-qpic_common-API-file.patch} (100%) rename lede/target/linux/generic/backport-6.12/{413-04-v6.14-mtd-rawnand-qcom-use-FIELD_PREP-and-GENMASK.patch => 410-04-v6.14-mtd-rawnand-qcom-use-FIELD_PREP-and-GENMASK.patch} (100%) rename lede/target/linux/generic/backport-6.12/{414-v6.14-mtd-rawnand-qcom-fix-broken-config-in-qcom_param_pag.patch => 410-05-v6.14-mtd-rawnand-qcom-fix-broken-config-in-qcom_param_pag.patch} (100%) rename lede/target/linux/generic/backport-6.12/{415-v6.14-mtd-rawnand-qcom-Fix-build-issue-on-x86-architecture.patch => 410-06-v6.14-mtd-rawnand-qcom-Fix-build-issue-on-x86-architecture.patch} (100%) rename lede/target/linux/generic/backport-6.12/{416-v6.15-01-spi-spi-qpic-add-driver-for-QCOM-SPI-NAND-flash-Inte.patch => 410-07-v6.15-spi-spi-qpic-add-driver-for-QCOM-SPI-NAND-flash-Inte.patch} (100%) rename lede/target/linux/generic/backport-6.12/{416-v6.15-02-spi-spi-qpic-snand-Fix-ECC_CFG_ECC_DISABLE-shift-in-.patch => 410-08-v6.15-spi-spi-qpic-snand-Fix-ECC_CFG_ECC_DISABLE-shift-in-.patch} (100%) rename lede/target/linux/generic/backport-6.12/{416-v6.15-03-spi-spi-qpic-snand-avoid-memleak-in-qcom_spi_ecc_ini.patch => 410-09-v6.15-spi-spi-qpic-snand-avoid-memleak-in-qcom_spi_ecc_ini.patch} (100%) rename lede/target/linux/generic/backport-6.12/{416-v6.15-04-spi-SPI_QPIC_SNAND-should-be-tristate-and-depend-on-.patch => 410-10-v6.15-spi-SPI_QPIC_SNAND-should-be-tristate-and-depend-on-.patch} (100%) rename lede/target/linux/generic/backport-6.12/{416-v6.15-05-spi-spi-qpic-snand-propagate-errors-from-qcom_spi_block_erase.patch => 410-11-v6.15-spi-spi-qpic-snand-propagate-errors-from-qcom_spi_block_erase.patch} (100%) rename lede/target/linux/generic/backport-6.12/{416-v6.15-06-spi-spi-qpic-snand-fix-NAND_READ_LOCATION_2-register-handling.patch => 410-12-v6.15-spi-spi-qpic-snand-fix-NAND_READ_LOCATION_2-register-handling.patch} (100%) rename lede/target/linux/generic/backport-6.12/{416-v6.15-07-spi-spi-qpic-snand-use-kmalloc-for-OOB-buffer-alloca.patch => 410-13-v6.15-spi-spi-qpic-snand-use-kmalloc-for-OOB-buffer-alloca.patch} (100%) rename lede/target/linux/generic/backport-6.12/{416-v6.16-08-spi-spi-qpic-snand-remove-unused-wlen-member-of-struct-qpic_spi_nand.patch => 410-14-v6.16-spi-spi-qpic-snand-remove-unused-wlen-member-of-struct-qpic_spi_nand.patch} (100%) create mode 100644 lede/target/linux/generic/backport-6.12/411-v6.15-mtd-nand-Drop-explicit-test-for-built-in-CONFIG_SPI_.patch rename lede/target/linux/generic/{pending-6.12/416-09-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch => backport-6.12/412-v6.16-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch} (94%) delete mode 100644 lede/target/linux/generic/backport-6.12/413-05-v6.14-mtd-nand-change-to-qpic_version2.patch create mode 100644 lede/target/linux/generic/backport-6.12/413-v6.16-spi-spi-qpic-snand-use-CW_PER_PAGE_MASK-bitmask.patch create mode 100644 lede/target/linux/generic/backport-6.12/414-v6.16-spi-spi-qpic-snand-reallocate-BAM-transactions.patch create mode 100644 lede/target/linux/generic/backport-6.12/415-v6.16-spi-spi-qpic-snand-don-t-hardcode-ECC-steps.patch rename lede/target/linux/generic/{pending-6.12/416-10-next-1-2-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch => backport-6.12/416-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch} (83%) create mode 100644 lede/target/linux/generic/backport-6.12/417-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch create mode 100644 lede/target/linux/generic/backport-6.12/418-v6.17-spi-spi-qpic-snand-use-correct-CW_PER_PAGE-value-for.patch create mode 100644 lede/target/linux/generic/backport-6.12/419-v6.17-spi-spi-qpic-snand-fix-calculating-of-ECC-OOB-region.patch create mode 100644 lede/target/linux/generic/backport-6.12/420-01-v6.16-mtd-rawnand-brcmnand-remove-unused-parameters.patch create mode 100644 lede/target/linux/generic/backport-6.12/420-02-v6.16-mtd-nand-brcmnand-fix-NAND-timeout-when-accessing-eM.patch create mode 100644 lede/target/linux/generic/backport-6.12/420-03-v6.16-mtd-rawnand-brcmnand-legacy-exec_op-implementation.patch create mode 100644 lede/target/linux/generic/backport-6.12/422-v6.17-spi-spi-qpic-snand-unregister-ECC-engine-on-probe-er.patch create mode 100644 lede/target/linux/generic/backport-6.12/429-01-v6.18-mtd-spinand-fix-direct-mapping-creation-sizes.patch create mode 100644 lede/target/linux/generic/backport-6.12/429-02-v6.18-mtd-spinand-try-a-regular-dirmap-if-creating-a-di.patch create mode 100644 lede/target/linux/generic/backport-6.12/429-03-v6.18-mtd-spinand-repeat-reading-in-regular-mode-if-con.patch rename lede/target/linux/generic/backport-6.12/{422-v6.19-mtd-spinand-esmt-add-support-for-F50L1G41LC.patch => 434-v6.19-mtd-spinand-esmt-add-support-for-F50L1G41LC.patch} (98%) create mode 100644 lede/target/linux/generic/backport-6.12/435-v6.19-mtd-spinand-add-support-for-FudanMicro-FM25S01BI3.patch rename lede/target/linux/generic/backport-6.12/{410-v6.13-01-block-add-support-for-defining-read-only-partitions.patch => 500-01-v6.13-block-add-support-for-defining-read-only-partitions.patch} (96%) rename lede/target/linux/generic/backport-6.12/{410-v6.13-03-block-introduce-add_disk_fwnode.patch => 500-02-v6.13-block-introduce-add_disk_fwnode.patch} (100%) rename lede/target/linux/generic/backport-6.12/{410-v6.13-04-mmc-block-attach-partitions-fwnode-if-found-in-mmc-c.patch => 500-03-v6.13-mmc-block-attach-partitions-fwnode-if-found-in-mmc-c.patch} (100%) rename lede/target/linux/generic/backport-6.12/{410-v6.13-05-block-add-support-for-partition-table-defined-in-OF.patch => 500-04-v6.13-block-add-support-for-partition-table-defined-in-OF.patch} (100%) create mode 100644 lede/target/linux/generic/backport-6.12/600-01-v6.13-net-phylink-move-manual-flow-control-setting.patch create mode 100644 lede/target/linux/generic/backport-6.12/600-02-v6.13-net-phylink-move-MLO_AN_FIXED-resolve-handling-to-if.patch create mode 100644 lede/target/linux/generic/backport-6.12/600-03-v6.13-net-phylink-move-MLO_AN_PHY-resolve-handling-to-if-s.patch create mode 100644 lede/target/linux/generic/backport-6.12/600-04-v6.13-net-phylink-remove-switch-statement-in-resolve-handl.patch create mode 100644 lede/target/linux/generic/backport-6.12/600-05-v6.13-net-phylink-clean-up-phylink_resolve.patch create mode 100644 lede/target/linux/generic/backport-6.12/601-01-v6.14-net-phylink-pass-phylink-and-pcs-into-phylink_pcs_ne.patch create mode 100644 lede/target/linux/generic/backport-6.12/601-02-v6.14-net-phylink-split-cur_link_an_mode-into-requested-an.patch create mode 100644 lede/target/linux/generic/backport-6.12/601-03-v6.14-net-phylink-add-debug-for-phylink_major_config.patch create mode 100644 lede/target/linux/generic/backport-6.12/601-04-v6.14-net-phy-add-phy_inband_caps.patch create mode 100644 lede/target/linux/generic/backport-6.12/601-05-v6.14-net-phy-bcm84881-implement-phy_inband_caps-method.patch create mode 100644 lede/target/linux/generic/backport-6.12/601-06-v6.14-net-phy-marvell-implement-phy_inband_caps-method.patch create mode 100644 lede/target/linux/generic/backport-6.12/601-07-v6.14-net-phy-add-phy_config_inband.patch create mode 100644 lede/target/linux/generic/backport-6.12/601-08-v6.14-net-phy-marvell-implement-config_inband-method.patch create mode 100644 lede/target/linux/generic/backport-6.12/601-09-v6.14-net-phylink-add-pcs_inband_caps-method.patch create mode 100644 lede/target/linux/generic/backport-6.12/601-10-v6.14-net-mvneta-implement-pcs_inband_caps-method.patch create mode 100644 lede/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch create mode 100644 lede/target/linux/generic/backport-6.12/601-12-v6.14-net-phylink-add-negotiation-of-in-band-capabilities.patch create mode 100644 lede/target/linux/generic/backport-6.12/601-13-v6.14-net-phylink-remove-phylink_phy_no_inband.patch create mode 100644 lede/target/linux/generic/backport-6.12/602-01-v6.14-net-pcs-pcs-lynx-implement-pcs_inband_caps-method.patch create mode 100644 lede/target/linux/generic/backport-6.12/602-02-v6.14-net-pcs-pcs-mtk-lynxi-implement-pcs_inband_caps-meth.patch create mode 100644 lede/target/linux/generic/backport-6.12/602-03-v6.14-net-pcs-xpcs-implement-pcs_inband_caps-method.patch create mode 100644 lede/target/linux/generic/backport-6.12/605-02-v6.17-net-phylink-provide-phylink_get_inband_type.patch create mode 100644 lede/target/linux/generic/backport-6.12/605-03-v6.17-net-phylink-disable-autoneg-for-interfaces-that-have.patch create mode 100644 lede/target/linux/generic/backport-6.12/610-01-v6.13-net-dsa-use-ethtool-string-helpers.patch create mode 100644 lede/target/linux/generic/backport-6.12/610-02-v6.15-net-dsa-b53-mdio-add-support-for-BCM53101.patch create mode 100644 lede/target/linux/generic/backport-6.12/610-03-v6.16-net-dsa-b53-implement-setting-ageing-time.patch create mode 100644 lede/target/linux/generic/backport-6.12/610-04-v6.16-net-dsa-b53-do-not-configure-bcm63xx-s-IMP-port-inte.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-01-v6.17-net-dsa-tag_brcm-add-support-for-legacy-FCS-tags.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-02-v6.17-net-dsa-b53-support-legacy-FCS-tags.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-03-v6.17-net-dsa-b53-detect-BCM5325-variants.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-04-v6.17-net-dsa-b53-add-support-for-FDB-operations-on-5325-5365.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-05-v6.17-net-dsa-b53-prevent-FAST_AGE-access-on-BCM5325.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-06-v6.17-net-dsa-b53-prevent-BRCM_HDR-access-on-older-devices.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-07-v6.17-net-dsa-b53-fix-unicast-multicast-flooding-on-BCM5325.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-08-v6.18-net-dsa-b53-Add-phy_enable-phy_disable-methods.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-09-v6.18-net-dsa-b53-Define-chip-IDs-for-more-bcm63xx-SoCs.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-10-v6.18-net-dsa-b53-mmap-Add-syscon-reference-and-register-layout-for-bcm63268.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-11-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6318.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-12-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6368.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-13-v6.18-net-dsa-b53-mmap-Implement-bcm63xx-ephy-power-control.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-14-v6.18-net-dsa-b53-mmap-Add-gphy-port-to-phy-info-for-bcm63268.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-15-v6.18-net-dsa-b53-mmap-Implement-bcm63268-gphy-power-control.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-16-v6.18-net-dsa-b53-fix-reserved-register-access-in-b53_fdb_dump.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-17-v6.18-net-dsa-b53-fix-ageing-time-for-BCM53101.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-18-v6.18-net-dsa-b53-properly-bound-ARL-searches-for-4-ARL-bin-chips.patch create mode 100644 lede/target/linux/generic/backport-6.12/611-19-v6.18-net-dsa-tag_brcm-do-not-mark-link-local-traffic-as-offloaded.patch create mode 100644 lede/target/linux/generic/backport-6.12/612-01-v6.19-net-dsa-b53-b53_arl_read-25-use-the-entry-for-comparision.patch create mode 100644 lede/target/linux/generic/backport-6.12/612-02-v6.19-net-dsa-b53-move-reading-ARL-entries-into-their-own-function.patch create mode 100644 lede/target/linux/generic/backport-6.12/612-03-v6.19-net-dsa-b53-move-writing-ARL-entries-into-their-own-functions.patch create mode 100644 lede/target/linux/generic/backport-6.12/612-04-v6.19-net-dsa-b53-provide-accessors-for-accessing-ARL_SRCH_CTL.patch create mode 100644 lede/target/linux/generic/backport-6.12/612-05-v6.19-net-dsa-b53-split-reading-search-entry-into-their-own-functions.patch create mode 100644 lede/target/linux/generic/backport-6.12/612-06-v6.19-net-dsa-b53-move-ARL-entry-functions-into-ops-struct.patch create mode 100644 lede/target/linux/generic/backport-6.12/612-07-v6.19-net-dsa-b53-add-support-for-5389-5397-5398-ARL-entry-format.patch create mode 100644 lede/target/linux/generic/backport-6.12/612-08-v6.19-net-dsa-b53-add-support-for-bcm63xx-ARL-entry-format.patch create mode 100644 lede/target/linux/generic/backport-6.12/613-01-v6.19-net-dsa-b53-fix-VLAN_ID_IDX-write-size-for-BCM5325-65.patch create mode 100644 lede/target/linux/generic/backport-6.12/613-02-v6.19-net-dsa-b53-fix-extracting-VID-from-entry-for-BCM5325-65.patch create mode 100644 lede/target/linux/generic/backport-6.12/613-03-v6.19-net-dsa-b53-use-same-ARL-search-result-offset-for-BCM5325-65.patch create mode 100644 lede/target/linux/generic/backport-6.12/613-04-v6.19-net-dsa-b53-fix-CPU-port-unicast-ARL-entries-for-BCM5325-65.patch create mode 100644 lede/target/linux/generic/backport-6.12/613-05-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-multicast-port-masks.patch create mode 100644 lede/target/linux/generic/backport-6.12/613-06-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-VIDs.patch create mode 100644 lede/target/linux/generic/backport-6.12/613-07-v6.19-net-dsa-b53-allow-VID-0-for-BCM5325-65.patch create mode 100644 lede/target/linux/generic/backport-6.12/626-v6.16-net-bridge-locally-receive-all-multicast-packets-if-.patch create mode 100644 lede/target/linux/generic/backport-6.12/630-v6.13-net-usb-qmi_wwan-add-Quectel-RG255C.patch create mode 100644 lede/target/linux/generic/backport-6.12/630-v6.14-PM-sleep-wakeirq-Introduce-device-managed-variant-of.patch create mode 100644 lede/target/linux/generic/backport-6.12/700-01-v7.0-net-sched-Export-mq-functions-for-reuse.patch create mode 100644 lede/target/linux/generic/backport-6.12/700-02-v7.0-net-sched-sch_cake-Factor-out-config-variables-into-.patch create mode 100644 lede/target/linux/generic/backport-6.12/700-03-v7.0-net-sched-sch_cake-Add-cake_mq-qdisc-for-using-cake-.patch create mode 100644 lede/target/linux/generic/backport-6.12/700-04-v7.0-net-sched-sch_cake-Share-config-across-cake_mq-sub-q.patch create mode 100644 lede/target/linux/generic/backport-6.12/700-05-v7.0-net-sched-sch_cake-share-shaper-state-across-sub-ins.patch create mode 100644 lede/target/linux/generic/backport-6.12/700-06-v7.0-selftests-tc-testing-add-selftests-for-cake_mq-qdisc.patch create mode 100644 lede/target/linux/generic/backport-6.12/700-07-v7.0-net-sched-cake-avoid-separate-allocation-of-struct-c.patch create mode 100644 lede/target/linux/generic/backport-6.12/701-01-v7.0-net-sched-sch_cake-avoid-sync-overhead-when-unlimite.patch create mode 100644 lede/target/linux/generic/backport-6.12/701-02-v7.0-net-sched-sch_cake-fixup-cake_mq-rate-adjustment-for.patch rename lede/target/linux/generic/backport-6.12/{792-v6.16-igc-enable-HW-vlan-tag-insertion-stripping-by-defaul.patch => 710-v6.16-igc-enable-HW-vlan-tag-insertion-stripping-by-defaul.patch} (100%) rename lede/target/linux/generic/backport-6.12/{720-v6.13-net-phy-mediatek-ge-soc-Fix-coding-style.patch => 720-01-v6.13-net-phy-mediatek-ge-soc-Fix-coding-style.patch} (100%) rename lede/target/linux/generic/backport-6.12/{721-v6.13-net-phy-mediatek-ge-soc-Shrink-line-wrapping-to-80-c.patch => 720-02-v6.13-net-phy-mediatek-ge-soc-Shrink-line-wrapping-to-80-c.patch} (100%) rename lede/target/linux/generic/backport-6.12/{722-v6.13-net-phy-mediatek-ge-soc-Propagate-error-code-correct.patch => 720-03-v6.13-net-phy-mediatek-ge-soc-Propagate-error-code-correct.patch} (100%) rename lede/target/linux/generic/backport-6.12/{723-v6.13-net-phy-mediatek-Re-organize-MediaTek-ethernet-phy-d.patch => 720-04-v6.13-net-phy-mediatek-Re-organize-MediaTek-ethernet-phy-d.patch} (100%) rename lede/target/linux/generic/backport-6.12/{724-v6.13-net-phy-mediatek-Move-LED-helper-functions-into-mtk-.patch => 720-05-v6.13-net-phy-mediatek-Move-LED-helper-functions-into-mtk-.patch} (100%) rename lede/target/linux/generic/backport-6.12/{725-v6.13-net-phy-mediatek-Improve-readability-of-mtk-phy-lib..patch => 720-06-v6.13-net-phy-mediatek-Improve-readability-of-mtk-phy-lib..patch} (100%) rename lede/target/linux/generic/backport-6.12/{726-v6.13-net-phy-mediatek-Integrate-read-write-page-helper-fu.patch => 720-07-v6.13-net-phy-mediatek-Integrate-read-write-page-helper-fu.patch} (100%) rename lede/target/linux/generic/backport-6.12/{727-v6.13-net-phy-mediatek-add-MT7530-MT7531-s-PHY-ID-macros.patch => 720-08-v6.13-net-phy-mediatek-add-MT7530-MT7531-s-PHY-ID-macros.patch} (100%) rename lede/target/linux/generic/backport-6.12/{728-v6.14-net-phy-Constify-struct-mdio_device_id.patch => 720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch} (99%) rename lede/target/linux/generic/backport-6.12/{729-v6.15-net-phy-mediatek-Change-to-more-meaningful-macros.patch => 720-10-v6.15-net-phy-mediatek-Change-to-more-meaningful-macros.patch} (100%) rename lede/target/linux/generic/backport-6.12/{730-v6.15-net-phy-mediatek-Add-token-ring-access-helper-functi.patch => 720-11-v6.15-net-phy-mediatek-Add-token-ring-access-helper-functi.patch} (100%) rename lede/target/linux/generic/backport-6.12/{731-v6.15-net-phy-mediatek-Add-token-ring-set-bit-operation-su.patch => 720-12-v6.15-net-phy-mediatek-Add-token-ring-set-bit-operation-su.patch} (100%) rename lede/target/linux/generic/backport-6.12/{732-v6.15-net-phy-mediatek-Add-token-ring-clear-bit-operation-.patch => 720-13-v6.15-net-phy-mediatek-Add-token-ring-clear-bit-operation-.patch} (100%) rename lede/target/linux/generic/backport-6.12/{733-v6.15-net-phy-mediatek-Move-some-macros-to-phy-lib-for-lat.patch => 720-14-v6.15-net-phy-mediatek-Move-some-macros-to-phy-lib-for-lat.patch} (100%) rename lede/target/linux/generic/backport-6.12/{735-v6.16-net-phy-mediatek-permit-to-compile-test-GE-SOC-PHY-d.patch => 720-15-v6.16-net-phy-mediatek-permit-to-compile-test-GE-SOC-PHY-d.patch} (100%) rename lede/target/linux/generic/backport-6.12/{736-v6.16-net-phy-mediatek-add-Airoha-PHY-ID-to-SoC-driver.patch => 720-16-v6.16-net-phy-mediatek-add-Airoha-PHY-ID-to-SoC-driver.patch} (100%) rename lede/target/linux/generic/backport-6.12/{737-v6.16-net-phy-mediatek-init-val-in-.phy_led_polarity_set-f.patch => 720-17-v6.16-net-phy-mediatek-init-val-in-.phy_led_polarity_set-f.patch} (100%) rename lede/target/linux/generic/backport-6.12/{753-v6.15-net-ethernet-mediatek-add-EEE-support.patch => 721-01-v6.15-net-ethernet-mediatek-add-EEE-support.patch} (96%) rename lede/target/linux/generic/backport-6.12/{839-v6.13-net-phy-aquantia-allow-forcing-order-of-MDI-pairs.patch => 730-01-v6.13-net-phy-aquantia-allow-forcing-order-of-MDI-pairs.patch} (100%) rename lede/target/linux/generic/backport-6.12/{840-v6.13-net-phy-aquantia-fix-return-value-check-in-aqr107_co.patch => 730-02-v6.13-net-phy-aquantia-fix-return-value-check-in-aqr107_co.patch} (100%) rename lede/target/linux/generic/backport-6.12/{841-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch => 730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch} (97%) rename lede/target/linux/generic/backport-6.12/{842-v6.13-net-phy-aquantia-correctly-describe-LED-polarity-ove.patch => 730-04-v6.13-net-phy-aquantia-correctly-describe-LED-polarity-ove.patch} (100%) rename lede/target/linux/generic/backport-6.12/{843-v6.13-net-phy-mxl-gpy-add-basic-LED-support.patch => 730-05-v6.13-net-phy-mxl-gpy-add-basic-LED-support.patch} (100%) rename lede/target/linux/generic/backport-6.12/{844-v6.13-net-phy-mxl-gpy-add-missing-support-for-TRIGGER_NETD.patch => 730-06-v6.13-net-phy-mxl-gpy-add-missing-support-for-TRIGGER_NETD.patch} (100%) rename lede/target/linux/generic/backport-6.12/{845-v6.13-net-phy-mxl-gpy-correctly-describe-LED-polarity.patch => 730-07-v6.13-net-phy-mxl-gpy-correctly-describe-LED-polarity.patch} (100%) rename lede/target/linux/generic/backport-6.12/{846-v6.13-net-phy-intel-xway-add-support-for-PHY-LEDs.patch => 730-08-v6.13-net-phy-intel-xway-add-support-for-PHY-LEDs.patch} (100%) create mode 100644 lede/target/linux/generic/backport-6.12/735-v6.13-net-phy-avoid-undefined-behavior-in-_led_polarity_se.patch rename lede/target/linux/generic/backport-6.12/{901-v6.13-net-dsa-mv88e6xxx-Support-LED-control.patch => 740-v6.13-net-dsa-mv88e6xxx-Support-LED-control.patch} (100%) create mode 100644 lede/target/linux/generic/backport-6.12/741-v6.13-net-dsa-mv88e6xxx-fix-unreleased-fwnode_handle-in-se.patch create mode 100644 lede/target/linux/generic/backport-6.12/742-v6.17-net-dsa-mv88e6xxx-Fix-fwnode-reference-leaks-in-mv88.patch create mode 100644 lede/target/linux/generic/backport-6.12/781-28-v6.18-net-phy-realtek-convert-RTL8226-CG-to-c45-only.patch create mode 100644 lede/target/linux/generic/backport-6.12/781-29-v6.18-net-phy-realtek-enable-serdes-option-mode-for-RTL8226-CG.patch create mode 100644 lede/target/linux/generic/backport-6.12/783-01-v6.18-net-dsa-Move-KS8995-to-the-DSA-subsystem.patch create mode 100644 lede/target/linux/generic/backport-6.12/783-02-v6.18-net-dsa-ks8995-Add-proper-RESET-delay.patch create mode 100644 lede/target/linux/generic/backport-6.12/783-03-v6.18-net-dsa-ks8995-Delete-sysfs-register-access.patch create mode 100644 lede/target/linux/generic/backport-6.12/783-04-v6.18-net-dsa-ks8995-Add-basic-switch-set-up.patch create mode 100644 lede/target/linux/generic/backport-6.12/784-01-v6.17-net-phy-realtek-add-error-handling-to-rtl8211f_get_w.patch create mode 100644 lede/target/linux/generic/backport-6.12/784-02-v6.18-net-phy-realtek-Avoid-PHYCR2-access-if-PHYCR2-not-pr.patch create mode 100644 lede/target/linux/generic/backport-6.12/784-02-v6.18-net-phy-realtek-fix-RTL8211F-wake-on-lan-support.patch create mode 100644 lede/target/linux/generic/backport-6.12/784-03-v6.18-net-phy-realtek-fix-rtl8221b-vm-cg-name.patch create mode 100644 lede/target/linux/generic/backport-6.12/784-03-v6.18-net-phy-realtek-support-for-TRIGGER_NETDEV_LINK-on-R.patch create mode 100644 lede/target/linux/generic/backport-6.12/784-06-v6.19-net-phy-realtek-Add-RTL8224-cable-testing-support.patch create mode 100644 lede/target/linux/generic/backport-6.12/784-07-v6.19-net-phy-realtek-add-interrupt-support-for-RTL8221B.patch create mode 100644 lede/target/linux/generic/backport-6.12/784-08-v6.19-net-phy-realtek-create-rtl8211f_config_rgmii_delay.patch create mode 100644 lede/target/linux/generic/backport-6.12/784-09-v6.19-net-phy-realtek-eliminate-priv-phycr2-variable.patch create mode 100644 lede/target/linux/generic/backport-6.12/784-10-v6.19-net-phy-realtek-eliminate-has_phycr2-variable.patch create mode 100644 lede/target/linux/generic/backport-6.12/784-11-v6.19-net-phy-realtek-allow-CLKOUT-to-be-disabled-on-RTL82.patch create mode 100644 lede/target/linux/generic/backport-6.12/784-12-v6.19-net-phy-realtek-eliminate-priv-phycr1-variable.patch create mode 100644 lede/target/linux/generic/backport-6.12/784-13-v6.19-net-phy-realtek-create-rtl8211f_config_phy_eee-helpe.patch create mode 100644 lede/target/linux/generic/backport-6.12/786-01-v6.18-net-phy-introduce-phy_id_compare_vendor-PHY-ID-helpe.patch create mode 100644 lede/target/linux/generic/backport-6.12/786-02-v6.18-net-phy-as21xxx-better-handle-PHY-HW-reset-on-soft-r.patch create mode 100644 lede/target/linux/generic/backport-6.12/787-v6.19-net-phy-RTL8211FVD-Restore-disabling-of-PHY-mode-EEE.patch create mode 100644 lede/target/linux/generic/backport-6.12/801-01-v6.13-dt-bindings-clocks-add-binding-for-gated-fixed-clock.patch rename lede/target/linux/generic/backport-6.12/{880-v6.14-gpio-regmap-Use-generic-request-free-ops.patch => 810-v6.14-gpio-regmap-Use-generic-request-free-ops.patch} (95%) create mode 100644 lede/target/linux/generic/backport-6.12/820-v6.15-power-supply-sysfs-remove-duplicate-nul-termination-to-fix-build-with-GCC15.patch rename lede/target/linux/generic/{pending-6.12/891-dt-bindings-leds-Add-LED1202-LED-Controller.patch => backport-6.12/891-v6.14-dt-bindings-leds-Add-LED1202-LED-Controller.patch} (76%) rename lede/target/linux/generic/{pending-6.12/892-leds-Add-LED1202-I2C-driver.patch => backport-6.12/892-v6.14-leds-Add-LED1202-I2C-driver.patch} (86%) rename lede/target/linux/generic/{pending-6.12/893-leds_st1202-Fix-NULL-pointer-access-error.patch => backport-6.12/893-v6.14-leds_st1202-Fix-NULL-pointer-access-error.patch} (77%) create mode 100644 lede/target/linux/generic/files/drivers/bcma/fallback-sprom.h create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/Kconfig create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/Makefile create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/construct/conf_rtl8261n_c.c create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/construct/conf_rtl8264b.c create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/error.h create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_patch.c create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_patch.h create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_rtl826xb_patch.c create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_rtl826xb_patch.h create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_osal.c create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_osal.h create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phy.c create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib.c create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib.h create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib_def.h create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib_rtl826xb.c create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib_rtl826xb.h create mode 100644 lede/target/linux/generic/files/drivers/net/phy/rtl8261n/type.h create mode 100644 lede/target/linux/generic/files/drivers/ssb/fallback-sprom.h create mode 100644 lede/target/linux/generic/hack-6.12/249-udp-tunnel-selection.patch create mode 100644 lede/target/linux/generic/hack-6.12/735-net-phy-realtek-rtl8261n.patch create mode 100644 lede/target/linux/generic/hack-6.12/755-net-phy-motorcomm-yt8821-bus-collision-workaround.patch create mode 100644 lede/target/linux/generic/pending-6.12/303-Revert-powerpc-dts-mpc85xx-remove-simple-bus-compatible-from-ifc-node.patch create mode 100644 lede/target/linux/generic/pending-6.12/360-Revert-MIPS-mm-kmalloc-tlb_vpn-array-to-avoid-stack-.patch create mode 100644 lede/target/linux/generic/pending-6.12/361-Revert-MIPS-mm-Prevent-a-TLB-shutdown-on-initial-uni.patch delete mode 100644 lede/target/linux/generic/pending-6.12/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch delete mode 100644 lede/target/linux/generic/pending-6.12/416-11-next-2-2-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch create mode 100644 lede/target/linux/generic/pending-6.12/417-mtd-spi-nand-macronix-disable-continuous-read-for-MX.patch create mode 100644 lede/target/linux/generic/pending-6.12/620-net-sfp-improve-Huawei-MA5671a-fixup.patch delete mode 100644 lede/target/linux/generic/pending-6.12/642-net-bridge-locally-receive-all-multicast-packets-if-.patch create mode 100644 lede/target/linux/generic/pending-6.12/704-net-phy-register-phy-led_triggers-during-probe-to-av.patch delete mode 100644 lede/target/linux/generic/pending-6.12/720-06-net-phy-realtek-support-interrupt-of-RTL8221B.patch create mode 100644 lede/target/linux/generic/pending-6.12/720-08-net-phy-realtek-work-around-broken-serdes.patch delete mode 100644 lede/target/linux/generic/pending-6.12/732-02-net-ethernet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch create mode 100644 lede/target/linux/generic/pending-6.12/732-03-net-ethernet-mtk_eth_soc-optimize-dma-ring-address-i.patch create mode 100644 lede/target/linux/generic/pending-6.12/732-04-net-ethernet-mtk_eth_soc-shrink-struct-mtk_tx_buf.patch create mode 100644 lede/target/linux/generic/pending-6.12/732-05-net-ethernet-mtk_eth_soc-add-support-for-sending-fra.patch create mode 100644 lede/target/linux/generic/pending-6.12/736-05-net-ethernet-mtk_eth_soc-zero-initialize-PPE-flow-ta.patch delete mode 100644 lede/target/linux/generic/pending-6.12/750-net-sfp-add-quirk-for-FlyPro-10Gbase-T-module.patch create mode 100644 lede/target/linux/generic/pending-6.12/812-PCI-sysfs-enforce-single-creation-of-sysfs-entry-for.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/051-v6.16-hwrng-mtk-Add-struct-device-pointer-to-device-contex.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/061-v6.19-arm64-dts-mediatek-mt7986-bpi-r3-Change-fan-PWM-valu.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/070-v7.0-pinctrl-mediatek-enable-ies_present-flag-for-MT798x.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/119-pinctrl-mediatek-MT7981-some-register-map-fixes.patch rename lede/target/linux/mediatek/patches-6.12/{171-arm64-dts-mediatek-mt7988a-Add-xsphy-for-ssusb0-pcie2.patch => 171-v6.16-arm64-dts-mediatek-mt7988-Add-xsphy-for-ssusb0-pcie2.patch} (89%) rename lede/target/linux/mediatek/patches-6.12/{172-arm64-dts-mediatek-mt7988a-bpi-r4-enable-xsphy.patch => 172-v6.16-arm64-dts-mediatek-mt7988a-bpi-r4-enable-xsphy.patch} (82%) delete mode 100644 lede/target/linux/mediatek/patches-6.12/174-arm64-dts-mediatek-mt7988-add-spi-controllers.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/174-v6.16-arm64-dts-mediatek-mt7988-add-spi-controllers.patch delete mode 100644 lede/target/linux/mediatek/patches-6.12/175-arm64-dts-mediatek-mt7988-move-uart0-and-spi1-pins-to-soc-dtsi.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/175-v6.16-arm64-dts-mediatek-mt7988-move-uart0-and-spi1-pins-t.patch delete mode 100644 lede/target/linux/mediatek/patches-6.12/176-arm64-dts-mediatek-mt7988-add-cci-node.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/176-v6.17-arm64-dts-mediatek-mt7988-add-cci-node.patch delete mode 100644 lede/target/linux/mediatek/patches-6.12/177-arm64-dts-mediatek-mt7988-add-phy-calibration-efuse-subnodes.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/177-v6.16-arm64-dts-mediatek-mt7988-add-phy-calibration-efuse-.patch delete mode 100644 lede/target/linux/mediatek/patches-6.12/180-arm64-dts-mediatek-mt7988a-bpi-r4-Add-fan-and-coolingmaps.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/180-v6.16-arm64-dts-mediatek-mt7988a-bpi-r4-Add-fan-and-coolin.patch delete mode 100644 lede/target/linux/mediatek/patches-6.12/181-arm64-dts-mediatek-mt7988a-bpi-r4-configure-spi-nodes.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/181-v6.16-arm64-dts-mediatek-mt7988a-bpi-r4-configure-spi-node.patc delete mode 100644 lede/target/linux/mediatek/patches-6.12/182-arm64-dts-mediatek-mt7988a-bpi-r4-add-proc-supply-for-cci.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/182-v6.17-arm64-dts-mediatek-mt7988a-bpi-r4-add-proc-supply-fo.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/187-arm64-dts-mediatek-fix-mt7981-spim-clock.patch delete mode 100644 lede/target/linux/mediatek/patches-6.12/197-dts-mt7986a-bpi-r3-mini-wifi-eeprom.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/198-dts-mt7988a-enable-wed.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/199-arm64-dts-mediatek-mt7986-increase-ATF-reserved-memo.patch delete mode 100644 lede/target/linux/mediatek/patches-6.12/320-hwrng-add-driver-for-MediaTek-TRNG-SMC.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/320-hwrng-mtk-add-support-for-hw-access-via-SMCC.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/411-mtd-spinand-fix-support-for-FORESEE.patch delete mode 100644 lede/target/linux/mediatek/patches-6.12/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch delete mode 100644 lede/target/linux/mediatek/patches-6.12/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch delete mode 100644 lede/target/linux/mediatek/patches-6.12/739-net-add-negotiation-of-in-band-capabilities.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/955-dts-mt7968a-bpi-r3-add-label-to-gmac-for-sfp1-port.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/960-asus-hack-u-boot-ignore-mtdparts.patch create mode 100644 lede/target/linux/mediatek/patches-6.12/966-pcie-mediatek-gen3-Add-WIFI-HW-reset-flow.patch create mode 100644 openwrt-packages/adguardhome/files/adguardhome.conf delete mode 100644 openwrt-packages/adguardhome/files/adguardhome.config create mode 100644 openwrt-packages/adguardhome/files/adguardhome.defaults create mode 100644 openwrt-packages/adguardhome/files/adguardhome.json create mode 100644 openwrt-packages/adguardhome/files/adguardhome.sysctl create mode 100644 openwrt-packages/luci-app-adguardhome/README.md create mode 100644 openwrt-packages/luci-app-fileassistant/README.md delete mode 100755 openwrt-packages/luci-app-guest-wifi/htdocs/luci-static/resources/view/guest-wifi.js create mode 120000 openwrt-packages/luci-app-guest-wifi/po/zh-cn delete mode 120000 openwrt-packages/luci-app-guest-wifi/po/zh_Hans rename openwrt-packages/luci-app-guest-wifi/po/{zh-cn => zh_Hans}/guest-wifi.po (68%) delete mode 100755 openwrt-packages/luci-app-guest-wifi/root/etc/config/guest-wifi delete mode 100755 openwrt-packages/luci-app-guest-wifi/root/etc/uci-defaults/luci-i18n-guest-wifi-zh-cn delete mode 100755 openwrt-packages/luci-app-guest-wifi/root/usr/lib/lua/luci/controller/guest-wifi.lua delete mode 100755 openwrt-packages/luci-app-guest-wifi/root/usr/sbin/guest-wifi delete mode 100644 openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css.bak delete mode 100644 openwrt-packages/luci-theme-alpha/luasrc/style/catatan.txt delete mode 100644 openwrt-packages/luci-theme-ifit/Makefile delete mode 100644 openwrt-packages/luci-theme-ifit/files/10_luci-theme-ifit delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/css/style.css delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/favicon.ico delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/fonts/Roboto-Medium-webfont.woff delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/fonts/Roboto-Regular-webfont.woff delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/fonts/font.eot delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/fonts/font.svg delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/fonts/font.ttf delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/fonts/font.woff delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/fonts/icomoon.eot delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/fonts/icomoon.svg delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/fonts/icomoon.ttf delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/fonts/icomoon.woff delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/images/main_bg.jpg delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/images/main_bg_5k.jpg delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/js/jquery.min.js delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/js/script.js delete mode 100644 openwrt-packages/luci-theme-ifit/files/htdocs/logo.png delete mode 100644 openwrt-packages/luci-theme-ifit/files/templates/footer.htm delete mode 100644 openwrt-packages/luci-theme-ifit/files/templates/header.htm create mode 100644 shadowsocks-rust/.cursor/rules/shadowsocks-rust-orientation.mdc create mode 100644 small/luci-app-ssr-plus/htdocs/luci-static/resources/view/shadowsocksr/Sortable.min.js create mode 100755 small/luci-app-ssr-plus/root/usr/share/shadowsocksr/hy2_test.sh diff --git a/.github/update.log b/.github/update.log index 0969a2e638..ccc6c35875 100644 --- a/.github/update.log +++ b/.github/update.log @@ -1306,3 +1306,4 @@ Update On Wed Mar 18 20:13:21 CET 2026 Update On Thu Mar 19 20:11:34 CET 2026 Update On Fri Mar 20 20:03:22 CET 2026 Update On Sat Mar 21 19:50:06 CET 2026 +Update On Sun Mar 22 19:50:55 CET 2026 diff --git a/clash-meta/dns/util.go b/clash-meta/dns/util.go index ef57a7c24f..de0f65e2db 100644 --- a/clash-meta/dns/util.go +++ b/clash-meta/dns/util.go @@ -64,6 +64,13 @@ func putMsgToCache(c dnsCache, q D.Question, msg *D.Msg) { return } + msg = msg.Copy() // never modify the original msg + + // OPT RRs MUST NOT be cached, forwarded, or stored in or loaded from master files. + msg.Extra = lo.Filter(msg.Extra, func(rr D.RR, index int) bool { + return rr.Header().Rrtype != D.TypeOPT + }) + var ttl uint32 if msg.Rcode == D.RcodeServerFailure { // [...] a resolver MAY cache a server failure response. @@ -76,13 +83,6 @@ func putMsgToCache(c dnsCache, q D.Question, msg *D.Msg) { return } - msg = msg.Copy() // never modify the original msg - - // OPT RRs MUST NOT be cached, forwarded, or stored in or loaded from master files. - msg.Extra = lo.Filter(msg.Extra, func(rr D.RR, index int) bool { - return rr.Header().Rrtype != D.TypeOPT - }) - c.SetWithExpire(q.String(), msg, time.Now().Add(time.Duration(ttl)*time.Second)) } diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index 8015265208..5725e53c46 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -379,7 +379,7 @@ dependencies = [ "objc2-foundation 0.3.2", "parking_lot", "percent-encoding", - "windows-sys 0.60.2", + "windows-sys 0.52.0", "wl-clipboard-rs", "x11rb", ] @@ -1692,7 +1692,7 @@ dependencies = [ "windows-registry 0.5.3", "windows-sys 0.60.2", "winreg 0.55.0", - "zip 8.3.0", + "zip 8.3.1", "zip-extensions", ] @@ -1743,7 +1743,7 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] @@ -2360,7 +2360,7 @@ dependencies = [ "libc", "option-ext", "redox_users 0.5.2", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -2394,9 +2394,9 @@ dependencies = [ [[package]] name = "display-info" -version = "0.5.7" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35269e5d1f477f90f9f6c353943e3464466271369ac8499cc17b8dbb82289f3" +checksum = "9e0aca670967c2528799e316f9f97913efcc034867614d55681dd41a1c2f7830" dependencies = [ "fxhash", "log", @@ -2430,7 +2430,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.8", + "libloading 0.7.4", ] [[package]] @@ -2889,7 +2889,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -4913,7 +4913,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.53.3", + "windows-targets 0.48.5", ] [[package]] @@ -6323,7 +6323,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.45.0", ] [[package]] @@ -7305,7 +7305,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -7961,7 +7961,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -8019,7 +8019,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -9709,7 +9709,7 @@ dependencies = [ "getrandom 0.4.1", "once_cell", "rustix 1.1.4", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -11501,7 +11501,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] @@ -12480,9 +12480,9 @@ dependencies = [ [[package]] name = "xcb" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f07c123b796139bfe0603e654eaf08e132e52387ba95b252c78bad3640ba37ea" +checksum = "ee4c580d8205abb0a5cf4eb7e927bd664e425b6c3263f9c5310583da96970cf6" dependencies = [ "bitflags 1.3.2", "libc", @@ -12802,9 +12802,9 @@ dependencies = [ [[package]] name = "zip" -version = "8.3.0" +version = "8.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a243cfad17427fc077f529da5a95abe4e94fd2bfdb601611870a6557cc67657" +checksum = "5c546feb4481b0fbafb4ef0d79b6204fc41c6f9884b1b73b1d73f82442fc0845" dependencies = [ "aes", "bzip2", diff --git a/clash-nyanpasu/frontend/interface/package.json b/clash-nyanpasu/frontend/interface/package.json index 0152d524a5..b0f08e03ef 100644 --- a/clash-nyanpasu/frontend/interface/package.json +++ b/clash-nyanpasu/frontend/interface/package.json @@ -11,7 +11,7 @@ "build": "tsc" }, "dependencies": { - "@tanstack/react-query": "5.91.3", + "@tanstack/react-query": "5.94.5", "@tauri-apps/api": "2.10.1", "ahooks": "3.9.6", "dayjs": "1.11.20", diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 43e7aeda94..4c44ac212f 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -43,7 +43,7 @@ "country-emoji": "1.5.6", "dayjs": "1.11.20", "framer-motion": "12.38.0", - "i18next": "25.9.0", + "i18next": "25.10.4", "jotai": "2.18.1", "json-schema": "0.4.0", "material-react-table": "3.2.1", @@ -71,7 +71,7 @@ "@emotion/react": "11.14.0", "@iconify/json": "2.2.453", "@monaco-editor/react": "4.7.0", - "@tanstack/react-query": "5.91.3", + "@tanstack/react-query": "5.94.5", "@tanstack/react-router": "1.167.5", "@tanstack/react-router-devtools": "1.166.9", "@tanstack/router-plugin": "1.166.14", diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index bf13f65f2a..99b290a3a7 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,7 +2,7 @@ "manifest_version": 1, "latest": { "mihomo": "v1.19.21", - "mihomo_alpha": "alpha-ae374f6", + "mihomo_alpha": "alpha-4f93c93", "clash_rs": "v0.9.6", "clash_premium": "2023-09-05-gdcc8d87", "clash_rs_alpha": "0.9.6-alpha+sha.b17ba0a" @@ -69,5 +69,5 @@ "linux-armv7hf": "clash-rs-armv7-unknown-linux-gnueabihf" } }, - "updated_at": "2026-03-20T22:22:49.611Z" + "updated_at": "2026-03-21T22:22:12.076Z" } diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index 94814241de..d8e366b823 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -128,8 +128,8 @@ importers: frontend/interface: dependencies: '@tanstack/react-query': - specifier: 5.91.3 - version: 5.91.3(react@19.2.4) + specifier: 5.94.5 + version: 5.94.5(react@19.2.4) '@tauri-apps/api': specifier: 2.10.1 version: 2.10.1 @@ -238,7 +238,7 @@ importers: version: 2.4.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@uiw/react-color': specifier: 2.9.6 - version: 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) ahooks: specifier: 3.9.6 version: 3.9.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -261,8 +261,8 @@ importers: specifier: 12.38.0 version: 12.38.0(@emotion/is-prop-valid@1.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) i18next: - specifier: 25.9.0 - version: 25.9.0(typescript@5.9.3) + specifier: 25.10.4 + version: 25.10.4(typescript@5.9.3) jotai: specifier: 2.18.1 version: 2.18.1(@babel/core@7.29.0)(@babel/template@7.28.6)(@types/react@19.2.14)(react@19.2.4) @@ -301,7 +301,7 @@ importers: version: 8.2.0(e309558cb1df3652b39c2e76ceb9cee4) react-i18next: specifier: 15.7.4 - version: 15.7.4(i18next@25.9.0(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + version: 15.7.4(i18next@25.10.4(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) react-markdown: specifier: 10.1.0 version: 10.1.0(@types/react@19.2.14)(react@19.2.4) @@ -340,8 +340,8 @@ importers: specifier: 4.7.0 version: 4.7.0(monaco-editor@0.55.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@tanstack/react-query': - specifier: 5.91.3 - version: 5.91.3(react@19.2.4) + specifier: 5.94.5 + version: 5.94.5(react@19.2.4) '@tanstack/react-router': specifier: 1.167.5 version: 1.167.5(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -500,7 +500,7 @@ importers: version: 6.0.0(react@19.2.4) react-i18next: specifier: 15.7.4 - version: 15.7.4(i18next@25.9.0(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + version: 15.7.4(i18next@25.10.4(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) react-use: specifier: 17.6.0 version: 17.6.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -1213,6 +1213,10 @@ packages: resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.29.2': + resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} + engines: {node: '>=6.9.0'} + '@babel/template@7.28.6': resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} engines: {node: '>=6.9.0'} @@ -3979,11 +3983,11 @@ packages: resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==} engines: {node: '>=12'} - '@tanstack/query-core@5.91.2': - resolution: {integrity: sha512-Uz2pTgPC1mhqrrSGg18RKCWT/pkduAYtxbcyIyKBhw7dTWjXZIzqmpzO2lBkyWr4hlImQgpu1m1pei3UnkFRWw==} + '@tanstack/query-core@5.94.5': + resolution: {integrity: sha512-Vx1JJiBURW/wdNGP45afjrqn0LfxYwL7K/bSrQvNRtyLGF1bxQPgUXCpzscG29e+UeFOh9hz1KOVala0N+bZiA==} - '@tanstack/react-query@5.91.3': - resolution: {integrity: sha512-D8jsCexxS5crZxAeiH6VlLHOUzmHOxeW5c11y8rZu0c34u/cy18hUKQXA/gn1Ila3ZIFzP+Pzv76YnliC0EtZQ==} + '@tanstack/react-query@5.94.5': + resolution: {integrity: sha512-1wmrxKFkor+q8l+ygdHmv0Sq5g84Q3p4xvuJ7AdSIAhQQ7udOt+ZSZ19g1Jea3mHqtlTslLGJsmC4vHFgP0P3A==} peerDependencies: react: ^18 || ^19 @@ -5797,8 +5801,8 @@ packages: hyphenate-style-name@1.1.0: resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==} - i18next@25.9.0: - resolution: {integrity: sha512-mJ4rVRNWOTkqh5xnaGR6iMFT5vEw3Y2MTJhcjinR/7u8cRv6dAfC0ofuePh5fVPxoh395p6JdrJTStCcNW66gg==} + i18next@25.10.4: + resolution: {integrity: sha512-XsE/6eawy090meuFU0BTY9BtmWr1m9NSwLr0NK7/A04LA58wdAvDsi9WNOJ40Qb1E9NIPbvnVLZEN2fWDd3/3Q==} peerDependencies: typescript: ^5 peerDependenciesMeta: @@ -8953,6 +8957,8 @@ snapshots: '@babel/runtime@7.28.6': {} + '@babel/runtime@7.29.2': {} + '@babel/template@7.28.6': dependencies: '@babel/code-frame': 7.29.0 @@ -9680,7 +9686,7 @@ snapshots: '@mui/private-theming@7.3.2(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@mui/utils': 7.3.8(@types/react@19.2.14)(react@19.2.4) prop-types: 15.8.1 react: 19.2.4 @@ -9689,7 +9695,7 @@ snapshots: '@mui/private-theming@7.3.9(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@mui/utils': 7.3.9(@types/react@19.2.14)(react@19.2.4) prop-types: 15.8.1 react: 19.2.4 @@ -9698,7 +9704,7 @@ snapshots: '@mui/styled-engine@7.3.2(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@emotion/cache': 11.14.0 '@emotion/serialize': 1.3.3 '@emotion/sheet': 1.4.0 @@ -9711,7 +9717,7 @@ snapshots: '@mui/styled-engine@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@emotion/cache': 11.14.0 '@emotion/serialize': 1.3.3 '@emotion/sheet': 1.4.0 @@ -9724,7 +9730,7 @@ snapshots: '@mui/system@7.3.2(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@mui/private-theming': 7.3.2(@types/react@19.2.14)(react@19.2.4) '@mui/styled-engine': 7.3.2(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4) '@mui/types': 7.4.11(@types/react@19.2.14) @@ -9740,7 +9746,7 @@ snapshots: '@mui/system@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@mui/private-theming': 7.3.9(@types/react@19.2.14)(react@19.2.4) '@mui/styled-engine': 7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4) '@mui/types': 7.4.12(@types/react@19.2.14) @@ -9756,25 +9762,25 @@ snapshots: '@mui/types@7.4.11(@types/react@19.2.14)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 optionalDependencies: '@types/react': 19.2.14 '@mui/types@7.4.12(@types/react@19.2.14)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 optionalDependencies: '@types/react': 19.2.14 '@mui/types@7.4.6(@types/react@19.2.14)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 optionalDependencies: '@types/react': 19.2.14 '@mui/utils@7.3.2(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@mui/types': 7.4.11(@types/react@19.2.14) '@types/prop-types': 15.7.15 clsx: 2.1.1 @@ -9786,7 +9792,7 @@ snapshots: '@mui/utils@7.3.8(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@mui/types': 7.4.11(@types/react@19.2.14) '@types/prop-types': 15.7.15 clsx: 2.1.1 @@ -9798,7 +9804,7 @@ snapshots: '@mui/utils@7.3.9(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@mui/types': 7.4.12(@types/react@19.2.14) '@types/prop-types': 15.7.15 clsx: 2.1.1 @@ -9830,7 +9836,7 @@ snapshots: '@mui/x-internals@8.26.0(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@mui/utils': 7.3.8(@types/react@19.2.14)(react@19.2.4) react: 19.2.4 reselect: 5.1.1 @@ -11572,11 +11578,11 @@ snapshots: dependencies: remove-accents: 0.5.0 - '@tanstack/query-core@5.91.2': {} + '@tanstack/query-core@5.94.5': {} - '@tanstack/react-query@5.91.3(react@19.2.4)': + '@tanstack/react-query@5.94.5(react@19.2.4)': dependencies: - '@tanstack/query-core': 5.91.2 + '@tanstack/query-core': 5.94.5 react: 19.2.4 '@tanstack/react-router-devtools@1.166.9(@tanstack/react-router@1.167.5(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.167.5)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': @@ -12056,203 +12062,203 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/color-convert@2.9.6(@babel/runtime@7.28.6)': + '@uiw/color-convert@2.9.6(@babel/runtime@7.29.2)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 - '@uiw/react-color-alpha@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-alpha@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-drag-event-interactive': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-drag-event-interactive': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-block@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-block@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-editable-input': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-swatch': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-editable-input': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-swatch': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-chrome@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-chrome@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-alpha': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-editable-input': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-editable-input-hsla': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-editable-input-rgba': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-github': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-hue': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-saturation': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-alpha': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-editable-input': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-editable-input-hsla': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-editable-input-rgba': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-github': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-hue': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-saturation': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-circle@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-circle@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-swatch': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-swatch': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-colorful@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-colorful@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-alpha': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-hue': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-saturation': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-alpha': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-hue': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-saturation': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-compact@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-compact@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-editable-input': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-editable-input-rgba': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-swatch': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-editable-input': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-editable-input-rgba': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-swatch': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-editable-input-hsla@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-editable-input-hsla@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-editable-input-rgba': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-editable-input-rgba': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-editable-input-rgba@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-editable-input-rgba@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-editable-input': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-editable-input': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-editable-input@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-editable-input@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-github@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-github@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-swatch': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-swatch': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-hue@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-hue@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-alpha': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-alpha': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-material@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-material@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-editable-input': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-editable-input-rgba': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-editable-input': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-editable-input-rgba': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-name@2.9.6(@babel/runtime@7.28.6)': + '@uiw/react-color-name@2.9.6(@babel/runtime@7.29.2)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 colors-named: 1.0.4 colors-named-hex: 1.0.3 - '@uiw/react-color-saturation@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-saturation@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-drag-event-interactive': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-drag-event-interactive': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-shade-slider@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-shade-slider@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-alpha': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-alpha': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-sketch@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-sketch@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-alpha': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-editable-input': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-editable-input-rgba': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-hue': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-saturation': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-swatch': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-alpha': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-editable-input': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-editable-input-rgba': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-hue': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-saturation': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-swatch': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-slider@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-slider@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-alpha': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-alpha': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-swatch@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-swatch@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color-wheel@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color-wheel@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-drag-event-interactive': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-drag-event-interactive': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-color@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-color@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 - '@uiw/color-convert': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-alpha': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-block': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-chrome': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-circle': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-colorful': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-compact': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-editable-input': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-editable-input-hsla': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-editable-input-rgba': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-github': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-hue': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-material': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-name': 2.9.6(@babel/runtime@7.28.6) - '@uiw/react-color-saturation': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-shade-slider': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-sketch': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-slider': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-swatch': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@uiw/react-color-wheel': 2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@uiw/color-convert': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-alpha': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-block': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-chrome': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-circle': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-colorful': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-compact': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-editable-input': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-editable-input-hsla': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-editable-input-rgba': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-github': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-hue': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-material': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-name': 2.9.6(@babel/runtime@7.29.2) + '@uiw/react-color-saturation': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-shade-slider': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-sketch': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-slider': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-swatch': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@uiw/react-color-wheel': 2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@uiw/react-drag-event-interactive@2.9.6(@babel/runtime@7.28.6)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@uiw/react-drag-event-interactive@2.9.6(@babel/runtime@7.29.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) @@ -12474,7 +12480,7 @@ snapshots: babel-plugin-macros@3.1.0: dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 cosmiconfig: 7.1.0 resolve: 1.22.10 @@ -13052,7 +13058,7 @@ snapshots: dom-helpers@5.2.1: dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 csstype: 3.2.3 dom-serializer@1.4.1: @@ -13517,9 +13523,9 @@ snapshots: hyphenate-style-name@1.1.0: {} - i18next@25.9.0(typescript@5.9.3): + i18next@25.10.4(typescript@5.9.3): dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 optionalDependencies: typescript: 5.9.3 @@ -14773,11 +14779,11 @@ snapshots: dependencies: react: 19.2.4 - react-i18next@15.7.4(i18next@25.9.0(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3): + react-i18next@15.7.4(i18next@25.10.4(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3): dependencies: '@babel/runtime': 7.28.3 html-parse-stringify: 3.0.1 - i18next: 25.9.0(typescript@5.9.3) + i18next: 25.10.4(typescript@5.9.3) react: 19.2.4 optionalDependencies: react-dom: 19.2.4(react@19.2.4) @@ -14842,7 +14848,7 @@ snapshots: react-transition-group@4.4.5(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -15030,7 +15036,7 @@ snapshots: rtl-css-js@1.16.1: dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 run-parallel@1.2.0: dependencies: diff --git a/lede/include/kernel-5.10 b/lede/include/kernel-5.10 index 2b57d8fe53..0f0e466c73 100644 --- a/lede/include/kernel-5.10 +++ b/lede/include/kernel-5.10 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.10 = .251 -LINUX_KERNEL_HASH-5.10.251 = e6857625fee3b587b0279b445adc3940a5c40723385fa1055ac7af16ff4b4c01 +LINUX_VERSION-5.10 = .252 +LINUX_KERNEL_HASH-5.10.252 = 34b3fbe2c9eeb767fc7eea4b9516e0dd44b79401ceb13e41713096b8eb270afb diff --git a/lede/include/kernel-5.15 b/lede/include/kernel-5.15 index 063c9f9573..fd6baf85d2 100644 --- a/lede/include/kernel-5.15 +++ b/lede/include/kernel-5.15 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.15 = .201 -LINUX_KERNEL_HASH-5.15.201 = 4f2afffbeddaad6b8527d41a3e3a82646d3cf5dfd0acbb6c4e8a99fc70461b96 +LINUX_VERSION-5.15 = .202 +LINUX_KERNEL_HASH-5.15.202 = 0bc1bdf74957e276793691865ffb71505809706d9243a42e9704aad0f128cdd4 diff --git a/lede/include/kernel-6.1 b/lede/include/kernel-6.1 index 1e62805fc2..818916f756 100644 --- a/lede/include/kernel-6.1 +++ b/lede/include/kernel-6.1 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.1 = .164 -LINUX_KERNEL_HASH-6.1.164 = 33bf087f7bbf7f626873dd7d955eb44182a93695db41f5f89a6bd3d233a39d1c +LINUX_VERSION-6.1 = .166 +LINUX_KERNEL_HASH-6.1.166 = 818dfc742158d18f70a6abccd77b7e4366cb7f26a88687f94dae392a9f089449 diff --git a/lede/include/kernel-6.12 b/lede/include/kernel-6.12 index 3b9c474086..848f89c66c 100644 --- a/lede/include/kernel-6.12 +++ b/lede/include/kernel-6.12 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.12 = .74 -LINUX_KERNEL_HASH-6.12.74 = 3b56eeb1dc9a437f189ca56b823be3769994f59a4ea0895b08ec0d20acaca13e +LINUX_VERSION-6.12 = .77 +LINUX_KERNEL_HASH-6.12.77 = 358836ebe5caef41e7ae9492e7fbcdf5be6e53ee43c99752aebda81e1b2cff67 diff --git a/lede/include/kernel-6.6 b/lede/include/kernel-6.6 index 55a5b8c57c..44dfecfe1e 100644 --- a/lede/include/kernel-6.6 +++ b/lede/include/kernel-6.6 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.6 = .127 -LINUX_KERNEL_HASH-6.6.127 = a7cd9c97b4f0b31cc030bcdc60abe5434fffb2556e293f7438ce7909dff8c9fe +LINUX_VERSION-6.6 = .129 +LINUX_KERNEL_HASH-6.6.129 = caa08f0122224fbbfab177e2a37cc2a94a0046bd2e7e87f03f8913f2b812448a diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0004-Revert-spi-spidev-Fix-CS-polarity-if-GPIO-descriptor.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0004-Revert-spi-spidev-Fix-CS-polarity-if-GPIO-descriptor.patch index 26bc183419..5fed553c91 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0004-Revert-spi-spidev-Fix-CS-polarity-if-GPIO-descriptor.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0004-Revert-spi-spidev-Fix-CS-polarity-if-GPIO-descriptor.patch @@ -11,7 +11,7 @@ This reverts commit 83b2a8fe43bda0c11981ad6afa5dd0104d78be28. --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c -@@ -428,7 +428,7 @@ spidev_ioctl(struct file *filp, unsigned +@@ -415,7 +415,7 @@ spidev_ioctl(struct file *filp, unsigned } if (ctlr->use_gpio_descriptors && spi_get_csgpiod(spi, 0)) diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0041-spi-spidev-Completely-disable-the-spidev-warning.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0041-spi-spidev-Completely-disable-the-spidev-warning.patch index 5e486f8d63..aa9601502a 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0041-spi-spidev-Completely-disable-the-spidev-warning.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0041-spi-spidev-Completely-disable-the-spidev-warning.patch @@ -13,7 +13,7 @@ Signed-off-by: Phil Elwell --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c -@@ -721,7 +721,7 @@ MODULE_DEVICE_TABLE(spi, spidev_spi_ids) +@@ -703,7 +703,7 @@ MODULE_DEVICE_TABLE(spi, spidev_spi_ids) */ static int spidev_of_check(struct device *dev) { diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0069-Improve-__copy_to_user-and-__copy_from_user-performa.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0069-Improve-__copy_to_user-and-__copy_from_user-performa.patch index ca4add41e7..794d02ad91 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0069-Improve-__copy_to_user-and-__copy_from_user-performa.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0069-Improve-__copy_to_user-and-__copy_from_user-performa.patch @@ -86,7 +86,7 @@ Signed-off-by: Phil Elwell --- a/arch/arm/include/asm/string.h +++ b/arch/arm/include/asm/string.h -@@ -65,4 +65,9 @@ static inline void *memset64(uint64_t *p +@@ -72,4 +72,9 @@ static inline void *memset64(uint64_t *p #endif diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0071-drivers-mfd-sensehat-Add-Raspberry-Pi-Sense-HAT-to-s.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0071-drivers-mfd-sensehat-Add-Raspberry-Pi-Sense-HAT-to-s.patch index 59f27ca0b9..7b7848efae 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0071-drivers-mfd-sensehat-Add-Raspberry-Pi-Sense-HAT-to-s.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0071-drivers-mfd-sensehat-Add-Raspberry-Pi-Sense-HAT-to-s.patch @@ -19,10 +19,10 @@ Signed-off-by: Charles Mirabile --- a/drivers/mfd/simple-mfd-i2c.c +++ b/drivers/mfd/simple-mfd-i2c.c -@@ -88,6 +88,7 @@ static const struct of_device_id simple_ +@@ -119,6 +119,7 @@ static const struct of_device_id simple_ + { .compatible = "maxim,max77705-battery", .data = &maxim_mon_max77705}, { .compatible = "silergy,sy7636a", .data = &silergy_sy7636a}, - { .compatible = "maxim,max5970", .data = &maxim_max5970}, - { .compatible = "maxim,max5978", .data = &maxim_max5970}, + { .compatible = "spacemit,p1", .data = &spacemit_p1, }, + { .compatible = "raspberrypi,sensehat" }, {} }; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0073-ASoC-Add-support-for-all-the-downstream-rpi-sound-ca.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0073-ASoC-Add-support-for-all-the-downstream-rpi-sound-ca.patch index 3bf4122503..fdb67cea01 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0073-ASoC-Add-support-for-all-the-downstream-rpi-sound-ca.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0073-ASoC-Add-support-for-all-the-downstream-rpi-sound-ca.patch @@ -18626,7 +18626,7 @@ Signed-off-by: j-schambacher * For devices with more than one control interface, we assume the --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c -@@ -2385,6 +2385,8 @@ static const struct usb_audio_quirk_flag +@@ -2395,6 +2395,8 @@ static const struct usb_audio_quirk_flag QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */ QUIRK_FLAG_ALIGN_TRANSFER), diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0075-bcm2835-virtgpio-Virtual-GPIO-driver.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0075-bcm2835-virtgpio-Virtual-GPIO-driver.patch index a2cd2ee89d..9b2d505dfb 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0075-bcm2835-virtgpio-Virtual-GPIO-driver.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0075-bcm2835-virtgpio-Virtual-GPIO-driver.patch @@ -50,7 +50,7 @@ Signed-off-by: Phil Elwell default y if (ARCH_BRCMSTB || BMIPS_GENERIC) --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile -@@ -39,6 +39,7 @@ obj-$(CONFIG_GPIO_ASPEED_SGPIO) += gpio +@@ -40,6 +40,7 @@ obj-$(CONFIG_GPIO_ASPEED_SGPIO) += gpio obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o obj-$(CONFIG_GPIO_BCM_XGS_IPROC) += gpio-xgs-iproc.o diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0087-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0087-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch index 875dfdeca6..32e5eab786 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0087-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0087-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch @@ -25,7 +25,7 @@ Signed-off-by: Jonathan Bell module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); -@@ -1117,7 +1117,9 @@ static int usbhid_start(struct hid_devic +@@ -1132,7 +1132,9 @@ static int usbhid_start(struct hid_devic */ switch (hid->collection->usage) { case HID_GD_MOUSE: @@ -36,7 +36,7 @@ Signed-off-by: Jonathan Bell interval = hid_mousepoll_interval; break; case HID_GD_JOYSTICK: -@@ -1129,6 +1131,7 @@ static int usbhid_start(struct hid_devic +@@ -1144,6 +1146,7 @@ static int usbhid_start(struct hid_devic interval = hid_kbpoll_interval; break; } diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0094-net-lan78xx-Disable-TCP-Segmentation-Offload-TSO.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0094-net-lan78xx-Disable-TCP-Segmentation-Offload-TSO.patch index 9d9b3dcb50..50c86eba3c 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0094-net-lan78xx-Disable-TCP-Segmentation-Offload-TSO.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0094-net-lan78xx-Disable-TCP-Segmentation-Offload-TSO.patch @@ -37,7 +37,7 @@ Signed-off-by: Dave Stevenson static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data) { u32 *buf; -@@ -3464,8 +3473,14 @@ static int lan78xx_bind(struct lan78xx_n +@@ -3462,8 +3471,14 @@ static int lan78xx_bind(struct lan78xx_n if (DEFAULT_RX_CSUM_ENABLE) dev->net->features |= NETIF_F_RXCSUM; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0096-lan78xx-Debounce-link-events-to-minimize-poll-storm.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0096-lan78xx-Debounce-link-events-to-minimize-poll-storm.patch index 79881ca14c..c885918f8f 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0096-lan78xx-Debounce-link-events-to-minimize-poll-storm.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0096-lan78xx-Debounce-link-events-to-minimize-poll-storm.patch @@ -28,7 +28,7 @@ See: https://github.com/raspberrypi/linux/issues/2447 static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data) { u32 *buf; -@@ -4448,7 +4453,13 @@ static int lan78xx_probe(struct usb_inte +@@ -4446,7 +4451,13 @@ static int lan78xx_probe(struct usb_inte if (ret < 0) goto out4; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0099-lan78xx-Enable-LEDs-and-auto-negotiation.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0099-lan78xx-Enable-LEDs-and-auto-negotiation.patch index 4137adb1fb..8b0be11deb 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0099-lan78xx-Enable-LEDs-and-auto-negotiation.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0099-lan78xx-Enable-LEDs-and-auto-negotiation.patch @@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c -@@ -2915,6 +2915,11 @@ static int lan78xx_reset(struct lan78xx_ +@@ -2913,6 +2913,11 @@ static int lan78xx_reset(struct lan78xx_ int ret; u32 buf; u8 sig; @@ -26,7 +26,7 @@ Signed-off-by: Phil Elwell ret = lan78xx_read_reg(dev, HW_CFG, &buf); if (ret < 0) -@@ -2983,6 +2988,10 @@ static int lan78xx_reset(struct lan78xx_ +@@ -2981,6 +2986,10 @@ static int lan78xx_reset(struct lan78xx_ buf |= HW_CFG_CLK125_EN_; buf |= HW_CFG_REFCLK25_EN_; @@ -37,7 +37,7 @@ Signed-off-by: Phil Elwell ret = lan78xx_write_reg(dev, HW_CFG, buf); if (ret < 0) return ret; -@@ -3085,6 +3094,9 @@ static int lan78xx_reset(struct lan78xx_ +@@ -3083,6 +3092,9 @@ static int lan78xx_reset(struct lan78xx_ buf |= MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_; } } diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0103-media-adv7180-Default-to-the-first-valid-input.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0103-media-adv7180-Default-to-the-first-valid-input.patch index c294e5286a..420170ed39 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0103-media-adv7180-Default-to-the-first-valid-input.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0103-media-adv7180-Default-to-the-first-valid-input.patch @@ -16,7 +16,7 @@ Signed-off-by: Dave Stevenson --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c -@@ -1352,6 +1352,7 @@ static const struct adv7180_chip_info ad +@@ -1359,6 +1359,7 @@ static const struct adv7180_chip_info ad static int init_device(struct adv7180_state *state) { int ret; @@ -24,7 +24,7 @@ Signed-off-by: Dave Stevenson mutex_lock(&state->mutex); -@@ -1399,6 +1400,18 @@ static int init_device(struct adv7180_st +@@ -1406,6 +1407,18 @@ static int init_device(struct adv7180_st goto out_unlock; } diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0104-media-adv7180-Add-YPrPb-support-for-ADV7282M.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0104-media-adv7180-Add-YPrPb-support-for-ADV7282M.patch index 1552f6358c..b06058610b 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0104-media-adv7180-Add-YPrPb-support-for-ADV7282M.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0104-media-adv7180-Add-YPrPb-support-for-ADV7282M.patch @@ -14,7 +14,7 @@ Signed-off-by: Dave Stevenson --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c -@@ -1341,6 +1341,7 @@ static const struct adv7180_chip_info ad +@@ -1348,6 +1348,7 @@ static const struct adv7180_chip_info ad BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) | BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) | BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) | diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0130-drm-v3d-Clock-V3D-down-when-not-in-use.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0130-drm-v3d-Clock-V3D-down-when-not-in-use.patch index bedd6f52a6..b0bede587d 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0130-drm-v3d-Clock-V3D-down-when-not-in-use.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0130-drm-v3d-Clock-V3D-down-when-not-in-use.patch @@ -37,7 +37,7 @@ Signed-off-by: popcornmix --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c -@@ -331,6 +331,21 @@ static int v3d_platform_drm_probe(struct +@@ -333,6 +333,21 @@ static int v3d_platform_drm_probe(struct } } @@ -59,7 +59,7 @@ Signed-off-by: popcornmix if (v3d->ver < 41) { ret = map_regs(v3d, &v3d->gca_regs, "gca"); if (ret) -@@ -360,6 +375,8 @@ static int v3d_platform_drm_probe(struct +@@ -362,6 +377,8 @@ static int v3d_platform_drm_probe(struct ret = v3d_sysfs_init(dev); if (ret) goto drm_unregister; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0131-drm-v3d-Switch-clock-setting-to-new-api.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0131-drm-v3d-Switch-clock-setting-to-new-api.patch index 6bdc6483e7..da230d2a39 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0131-drm-v3d-Switch-clock-setting-to-new-api.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0131-drm-v3d-Switch-clock-setting-to-new-api.patch @@ -41,7 +41,7 @@ Signed-off-by: Maxime Ripard struct drm_device *drm; struct v3d_dev *v3d; int ret; -@@ -337,7 +343,20 @@ static int v3d_platform_drm_probe(struct +@@ -339,7 +345,20 @@ static int v3d_platform_drm_probe(struct dev_err(dev, "Failed to get clock (%ld)\n", PTR_ERR(v3d->clk)); return PTR_ERR(v3d->clk); } @@ -63,7 +63,7 @@ Signed-off-by: Maxime Ripard /* For downclocking, drop it to the minimum frequency we can get from * the CPRMAN clock generator dividing off our parent. The divider is * 4 bits, but ask for just higher than that so that rounding doesn't -@@ -375,7 +394,7 @@ static int v3d_platform_drm_probe(struct +@@ -377,7 +396,7 @@ static int v3d_platform_drm_probe(struct ret = v3d_sysfs_init(dev); if (ret) goto drm_unregister; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0132-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0132-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch index 1b1b8d7746..c38edf1184 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0132-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0132-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch @@ -32,7 +32,7 @@ Signed-off-by: Jonathan Bell #define USB_VENDOR_ID_BELKIN 0x050d #define USB_DEVICE_ID_FLIP_KVM 0x3201 -@@ -1471,6 +1474,9 @@ +@@ -1480,6 +1483,9 @@ #define USB_VENDOR_ID_XIAOMI 0x2717 #define USB_DEVICE_ID_MI_SILENT_MOUSE 0x5014 @@ -52,7 +52,7 @@ Signed-off-by: Jonathan Bell { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE2), HID_QUIRK_ALWAYS_POLL }, -@@ -215,6 +216,7 @@ static const struct hid_device_id hid_qu +@@ -216,6 +217,7 @@ static const struct hid_device_id hid_qu { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_GROUP_AUDIO), HID_QUIRK_NOGET }, diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0136-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0136-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch index d2b8704308..63664a201c 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0136-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0136-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch @@ -426,7 +426,7 @@ Signed-off-by: Naushir Patuck +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -21550,6 +21550,14 @@ T: git git://linuxtv.org/media.git +@@ -21563,6 +21563,14 @@ T: git git://linuxtv.org/media.git F: Documentation/devicetree/bindings/media/i2c/sony,imx415.yaml F: drivers/media/i2c/imx415.c diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0137-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0137-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch index 3b90b2ee86..cb68d30eda 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0137-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0137-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch @@ -193,7 +193,7 @@ media: i2c: imx519: Squash fixes +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -21558,6 +21558,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -21571,6 +21571,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/imx477.yaml F: drivers/media/i2c/imx477.c diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0147-Documentation-devicetree-Add-documentation-for-imx37.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0147-Documentation-devicetree-Add-documentation-for-imx37.patch index e66b500f3a..7ac0a456de 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0147-Documentation-devicetree-Add-documentation-for-imx37.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0147-Documentation-devicetree-Add-documentation-for-imx37.patch @@ -132,7 +132,7 @@ Signed-off-by: David Plowman +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -21555,6 +21555,7 @@ M: Raspberry Pi Kernel Maintenance +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -4374,6 +4374,13 @@ S: Maintained +@@ -4380,6 +4380,13 @@ S: Maintained F: Documentation/devicetree/bindings/media/brcm,bcm2835-unicam.yaml F: drivers/media/platform/broadcom/bcm2835-unicam* diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0205-staging-vc04_services-ISP-Add-a-more-complex-ISP-pro.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0205-staging-vc04_services-ISP-Add-a-more-complex-ISP-pro.patch index 279d17de7b..3269e8a7f9 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0205-staging-vc04_services-ISP-Add-a-more-complex-ISP-pro.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0205-staging-vc04_services-ISP-Add-a-more-complex-ISP-pro.patch @@ -331,7 +331,7 @@ Signed-off-by: Kieran Bingham --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -4374,6 +4374,15 @@ S: Maintained +@@ -4380,6 +4380,15 @@ S: Maintained F: Documentation/devicetree/bindings/media/brcm,bcm2835-unicam.yaml F: drivers/media/platform/broadcom/bcm2835-unicam* diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0221-media-i2c-ov5647-Parse-and-register-properties.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0221-media-i2c-ov5647-Parse-and-register-properties.patch index a80f7697e8..8429b3985e 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0221-media-i2c-ov5647-Parse-and-register-properties.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0221-media-i2c-ov5647-Parse-and-register-properties.patch @@ -26,7 +26,7 @@ Signed-off-by: Laurent Pinchart v4l2_ctrl_handler_init(&sensor->ctrls, 9); -@@ -1351,6 +1352,11 @@ static int ov5647_init_controls(struct o +@@ -1353,6 +1354,11 @@ static int ov5647_init_controls(struct o ARRAY_SIZE(ov5647_test_pattern_menu) - 1, 0, 0, ov5647_test_pattern_menu); @@ -38,9 +38,9 @@ Signed-off-by: Laurent Pinchart if (sensor->ctrls.error) goto handler_free; -@@ -1434,7 +1440,7 @@ static int ov5647_probe(struct i2c_clien - - sensor->mode = OV5647_DEFAULT_MODE; +@@ -1441,7 +1447,7 @@ static int ov5647_probe(struct i2c_clien + sd->internal_ops = &ov5647_subdev_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; - ret = ov5647_init_controls(sensor); + ret = ov5647_init_controls(sensor, dev); diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0225-media-i2c-ov5647-Correct-pixel-array-offset.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0225-media-i2c-ov5647-Correct-pixel-array-offset.patch deleted file mode 100644 index 0a4b8bd412..0000000000 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0225-media-i2c-ov5647-Correct-pixel-array-offset.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 70c32664e555b0641cc187eebf0d738eb10a33a0 Mon Sep 17 00:00:00 2001 -From: David Plowman -Date: Tue, 11 May 2021 12:52:26 +0100 -Subject: [PATCH] media: i2c: ov5647: Correct pixel array offset - -The top offset in the pixel array is actually 6 (see page 3-1 of the -OV5647 data sheet). - -Fixes: f2f7ad5ce5e52 ("media: i2c: ov5647: Selection compliance fixes") -Signed-off-by: David Plowman ---- - drivers/media/i2c/ov5647.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/media/i2c/ov5647.c -+++ b/drivers/media/i2c/ov5647.c -@@ -69,7 +69,7 @@ - #define OV5647_NATIVE_HEIGHT 1956U - - #define OV5647_PIXEL_ARRAY_LEFT 16U --#define OV5647_PIXEL_ARRAY_TOP 16U -+#define OV5647_PIXEL_ARRAY_TOP 6U - #define OV5647_PIXEL_ARRAY_WIDTH 2592U - #define OV5647_PIXEL_ARRAY_HEIGHT 1944U - diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0226-media-i2c-ov5647-Correct-minimum-VBLANK-value.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0226-media-i2c-ov5647-Correct-minimum-VBLANK-value.patch deleted file mode 100644 index 05dedae1a4..0000000000 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0226-media-i2c-ov5647-Correct-minimum-VBLANK-value.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 3a415d5da89b4a2d83f5590820fa649293eef6ba Mon Sep 17 00:00:00 2001 -From: David Plowman -Date: Tue, 11 May 2021 12:57:22 +0100 -Subject: [PATCH] media: i2c: ov5647: Correct minimum VBLANK value - -Trial and error reveals that the minimum vblank value appears to be 24 -(the OV5647 data sheet does not give any clues). This fixes streaming -lock-ups in full resolution mode. - -Fixes: 9b5a5ebedc303 ("media: i2c: ov5647: Add support for V4L2_CID_VBLANK") -Signed-off-by: David Plowman ---- - drivers/media/i2c/ov5647.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/media/i2c/ov5647.c -+++ b/drivers/media/i2c/ov5647.c -@@ -73,7 +73,7 @@ - #define OV5647_PIXEL_ARRAY_WIDTH 2592U - #define OV5647_PIXEL_ARRAY_HEIGHT 1944U - --#define OV5647_VBLANK_MIN 4 -+#define OV5647_VBLANK_MIN 24 - #define OV5647_VTS_MAX 32767 - - #define OV5647_EXPOSURE_MIN 4 diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0231-drm-panel-simple-Add-a-timing-for-the-Raspberry-Pi-7.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0231-drm-panel-simple-Add-a-timing-for-the-Raspberry-Pi-7.patch index 7145016cc4..c94cc72766 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0231-drm-panel-simple-Add-a-timing-for-the-Raspberry-Pi-7.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0231-drm-panel-simple-Add-a-timing-for-the-Raspberry-Pi-7.patch @@ -315,7 +315,7 @@ Signed-off-by: Dave Stevenson ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0); if (ddc) { panel->ddc = of_find_i2c_adapter_by_node(ddc); -@@ -2263,6 +2244,32 @@ static const struct panel_desc friendlya +@@ -2264,6 +2245,32 @@ static const struct panel_desc friendlya }, }; @@ -348,7 +348,7 @@ Signed-off-by: Dave Stevenson static const struct drm_display_mode giantplus_gpg482739qs5_mode = { .clock = 9000, .hdisplay = 480, -@@ -2443,6 +2450,38 @@ static const struct panel_desc innolux_a +@@ -2444,6 +2451,38 @@ static const struct panel_desc innolux_a .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE, }; @@ -387,7 +387,7 @@ Signed-off-by: Dave Stevenson static const struct drm_display_mode innolux_at070tn92_mode = { .clock = 33333, .hdisplay = 800, -@@ -3856,6 +3895,31 @@ static const struct panel_desc rocktech_ +@@ -3857,6 +3896,31 @@ static const struct panel_desc rocktech_ .connector_type = DRM_MODE_CONNECTOR_DPI, }; @@ -419,7 +419,7 @@ Signed-off-by: Dave Stevenson static const struct display_timing rocktech_rk070er9427_timing = { .pixelclock = { 26400000, 33300000, 46800000 }, .hactive = { 800, 800, 800 }, -@@ -4800,6 +4864,9 @@ static const struct of_device_id platfor +@@ -4801,6 +4865,9 @@ static const struct of_device_id platfor .compatible = "friendlyarm,hd702e", .data = &friendlyarm_hd702e, }, { @@ -429,7 +429,7 @@ Signed-off-by: Dave Stevenson .compatible = "giantplus,gpg482739qs5", .data = &giantplus_gpg482739qs5 }, { -@@ -4821,6 +4888,9 @@ static const struct of_device_id platfor +@@ -4822,6 +4889,9 @@ static const struct of_device_id platfor .compatible = "innolux,at043tn24", .data = &innolux_at043tn24, }, { @@ -439,7 +439,7 @@ Signed-off-by: Dave Stevenson .compatible = "innolux,at070tn92", .data = &innolux_at070tn92, }, { -@@ -4980,6 +5050,9 @@ static const struct of_device_id platfor +@@ -4981,6 +5051,9 @@ static const struct of_device_id platfor .compatible = "rocktech,rk043fn48h", .data = &rocktech_rk043fn48h, }, { @@ -449,7 +449,7 @@ Signed-off-by: Dave Stevenson .compatible = "rocktech,rk070er9427", .data = &rocktech_rk070er9427, }, { -@@ -5336,6 +5409,9 @@ static const struct panel_desc_dsi osd10 +@@ -5337,6 +5410,9 @@ static const struct panel_desc_dsi osd10 .lanes = 4, }; @@ -459,7 +459,7 @@ Signed-off-by: Dave Stevenson static const struct of_device_id dsi_of_match[] = { { .compatible = "auo,b080uan01", -@@ -5359,20 +5435,137 @@ static const struct of_device_id dsi_of_ +@@ -5360,20 +5436,137 @@ static const struct of_device_id dsi_of_ .compatible = "osddisplays,osd101t2045-53ts", .data = &osd101t2045_53ts }, { diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0247-drivers-gpio-Add-a-driver-that-wraps-the-PWM-API-as-.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0247-drivers-gpio-Add-a-driver-that-wraps-the-PWM-API-as-.patch index 2a42d719c6..fabce2b139 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0247-drivers-gpio-Add-a-driver-that-wraps-the-PWM-API-as-.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0247-drivers-gpio-Add-a-driver-that-wraps-the-PWM-API-as-.patch @@ -40,7 +40,7 @@ Signed-off-by: Ratchanan Srirattanamet depends on ARCH_PXA || ARCH_MMP || COMPILE_TEST --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile -@@ -136,6 +136,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio- +@@ -137,6 +137,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio- obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0248-media-i2c-ov5647-Sensor-should-report-RAW-color-spac.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0248-media-i2c-ov5647-Sensor-should-report-RAW-color-spac.patch deleted file mode 100644 index 150e3e7867..0000000000 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0248-media-i2c-ov5647-Sensor-should-report-RAW-color-spac.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 2469a06f61b88939d92fd8e61a32afd5566c0be0 Mon Sep 17 00:00:00 2001 -From: David Plowman -Date: Thu, 21 Oct 2021 14:47:00 +0100 -Subject: [PATCH] media: i2c: ov5647: Sensor should report RAW color space - -Tested on Raspberry Pi running libcamera. - -Signed-off-by: David Plowman ---- - drivers/media/i2c/ov5647.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/media/i2c/ov5647.c -+++ b/drivers/media/i2c/ov5647.c -@@ -508,7 +508,7 @@ static const struct ov5647_mode ov5647_m - { - .format = { - .code = MEDIA_BUS_FMT_SBGGR10_1X10, -- .colorspace = V4L2_COLORSPACE_SRGB, -+ .colorspace = V4L2_COLORSPACE_RAW, - .field = V4L2_FIELD_NONE, - .width = 2592, - .height = 1944 -@@ -529,7 +529,7 @@ static const struct ov5647_mode ov5647_m - { - .format = { - .code = MEDIA_BUS_FMT_SBGGR10_1X10, -- .colorspace = V4L2_COLORSPACE_SRGB, -+ .colorspace = V4L2_COLORSPACE_RAW, - .field = V4L2_FIELD_NONE, - .width = 1920, - .height = 1080 -@@ -550,7 +550,7 @@ static const struct ov5647_mode ov5647_m - { - .format = { - .code = MEDIA_BUS_FMT_SBGGR10_1X10, -- .colorspace = V4L2_COLORSPACE_SRGB, -+ .colorspace = V4L2_COLORSPACE_RAW, - .field = V4L2_FIELD_NONE, - .width = 1296, - .height = 972 -@@ -571,7 +571,7 @@ static const struct ov5647_mode ov5647_m - { - .format = { - .code = MEDIA_BUS_FMT_SBGGR10_1X10, -- .colorspace = V4L2_COLORSPACE_SRGB, -+ .colorspace = V4L2_COLORSPACE_RAW, - .field = V4L2_FIELD_NONE, - .width = 640, - .height = 480 diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0254-media-i2c-ov5647-Support-HFLIP-and-VFLIP.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0254-media-i2c-ov5647-Support-HFLIP-and-VFLIP.patch index 1ae2ef809f..54bda1ee55 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0254-media-i2c-ov5647-Support-HFLIP-and-VFLIP.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0254-media-i2c-ov5647-Support-HFLIP-and-VFLIP.patch @@ -170,7 +170,7 @@ Signed-off-by: David Plowman default: dev_info(&client->dev, "Control (id:0x%x, val:0x%x) not supported\n", -@@ -1354,6 +1408,16 @@ static int ov5647_init_controls(struct o +@@ -1356,6 +1410,16 @@ static int ov5647_init_controls(struct o ARRAY_SIZE(ov5647_test_pattern_menu) - 1, 0, 0, ov5647_test_pattern_menu); diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0255-spi-spidev-Restore-loading-from-Device-Tree.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0255-spi-spidev-Restore-loading-from-Device-Tree.patch index 5517c11fa6..cbd07355da 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0255-spi-spidev-Restore-loading-from-Device-Tree.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0255-spi-spidev-Restore-loading-from-Device-Tree.patch @@ -15,7 +15,7 @@ Signed-off-by: Phil Elwell --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c -@@ -711,6 +711,7 @@ static const struct spi_device_id spidev +@@ -693,6 +693,7 @@ static const struct spi_device_id spidev { .name = "spi-authenta" }, { .name = "em3581" }, { .name = "si3210" }, diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0259-media-i2c-ov5647-Add-support-for-regulator-control.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0259-media-i2c-ov5647-Add-support-for-regulator-control.patch index 10eefaaf96..a3395643d9 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0259-media-i2c-ov5647-Add-support-for-regulator-control.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0259-media-i2c-ov5647-Add-support-for-regulator-control.patch @@ -95,7 +95,7 @@ Signed-off-by: Dave Stevenson static int ov5647_init_controls(struct ov5647 *sensor, struct device *dev) { struct i2c_client *client = v4l2_get_subdevdata(&sensor->sd); -@@ -1502,6 +1533,12 @@ static int ov5647_probe(struct i2c_clien +@@ -1504,6 +1535,12 @@ static int ov5647_probe(struct i2c_clien return -EINVAL; } diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0262-mfd-simple-mfd-i2c-Add-configuration-for-RPi-POE-HAT.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0262-mfd-simple-mfd-i2c-Add-configuration-for-RPi-POE-HAT.patch index e366e93da8..9081c605f5 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0262-mfd-simple-mfd-i2c-Add-configuration-for-RPi-POE-HAT.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0262-mfd-simple-mfd-i2c-Add-configuration-for-RPi-POE-HAT.patch @@ -17,7 +17,7 @@ Signed-off-by: Dave Stevenson --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig -@@ -1186,6 +1186,16 @@ config MFD_SY7636A +@@ -1210,6 +1210,16 @@ config MFD_SY7636A To enable support for building sub-devices as modules, choose M here. @@ -52,10 +52,10 @@ Signed-off-by: Dave Stevenson static int simple_mfd_i2c_probe(struct i2c_client *i2c) { const struct simple_mfd_data *simple_mfd_data; -@@ -88,6 +97,7 @@ static const struct of_device_id simple_ +@@ -119,6 +128,7 @@ static const struct of_device_id simple_ + { .compatible = "maxim,max77705-battery", .data = &maxim_mon_max77705}, { .compatible = "silergy,sy7636a", .data = &silergy_sy7636a}, - { .compatible = "maxim,max5970", .data = &maxim_max5970}, - { .compatible = "maxim,max5978", .data = &maxim_max5970}, + { .compatible = "spacemit,p1", .data = &spacemit_p1, }, + { .compatible = "raspberrypi,poe-core", &rpi_poe_core }, { .compatible = "raspberrypi,sensehat" }, {} diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0276-media-i2c-ov5647-Use-v4l2_async_register_subdev_sens.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0276-media-i2c-ov5647-Use-v4l2_async_register_subdev_sens.patch index 259c515d59..4734238175 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0276-media-i2c-ov5647-Use-v4l2_async_register_subdev_sens.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0276-media-i2c-ov5647-Use-v4l2_async_register_subdev_sens.patch @@ -15,7 +15,7 @@ Signed-off-by: Dave Stevenson --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c -@@ -1566,7 +1566,7 @@ static int ov5647_probe(struct i2c_clien +@@ -1568,7 +1568,7 @@ static int ov5647_probe(struct i2c_clien if (ret < 0) goto power_off; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0277-mm-page_alloc-cma-introduce-a-customisable-threshold.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0277-mm-page_alloc-cma-introduce-a-customisable-threshold.patch index 2c1cb09a6d..4fc8d93545 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0277-mm-page_alloc-cma-introduce-a-customisable-threshold.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0277-mm-page_alloc-cma-introduce-a-customisable-threshold.patch @@ -20,7 +20,7 @@ Signed-off-by: David Plowman --- a/mm/page_alloc.c +++ b/mm/page_alloc.c -@@ -207,6 +207,27 @@ EXPORT_SYMBOL(node_states); +@@ -234,6 +234,27 @@ EXPORT_SYMBOL(node_states); gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK; @@ -48,7 +48,7 @@ Signed-off-by: David Plowman #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE unsigned int pageblock_order __read_mostly; #endif -@@ -2265,12 +2286,13 @@ __rmqueue(struct zone *zone, unsigned in +@@ -2292,12 +2313,13 @@ __rmqueue(struct zone *zone, unsigned in if (IS_ENABLED(CONFIG_CMA)) { /* * Balance movable allocations between regular and CMA areas by diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0280-media-dt-bindings-media-i2c-Add-Arducam-Pivariety-Se.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0280-media-dt-bindings-media-i2c-Add-Arducam-Pivariety-Se.patch index 4b19a89827..4248edb63a 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0280-media-dt-bindings-media-i2c-Add-Arducam-Pivariety-Se.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0280-media-dt-bindings-media-i2c-Add-Arducam-Pivariety-Se.patch @@ -131,7 +131,7 @@ Signed-off-by: Lee Jackson +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -1752,6 +1752,14 @@ S: Maintained +@@ -1758,6 +1758,14 @@ S: Maintained F: drivers/net/arcnet/ F: include/uapi/linux/if_arcnet.h diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0286-random-do-not-use-jump-labels-before-they-are-initia.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0286-random-do-not-use-jump-labels-before-they-are-initia.patch index 76662197f0..97a849c853 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0286-random-do-not-use-jump-labels-before-they-are-initia.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0286-random-do-not-use-jump-labels-before-they-are-initia.patch @@ -68,7 +68,7 @@ Signed-off-by: Jason A. Donenfeld --- a/drivers/char/random.c +++ b/drivers/char/random.c -@@ -867,6 +867,14 @@ void __init random_init_early(const char +@@ -857,6 +857,14 @@ void __init random_init_early(const char unsigned long entropy[BLAKE2S_BLOCK_SIZE / sizeof(long)]; size_t i, longs, arch_bits; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0287-media-dt-bindings-media-i2c-Add-Arducam-64MP-CMOS-se.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0287-media-dt-bindings-media-i2c-Add-Arducam-64MP-CMOS-se.patch index e1f00a0391..d349e8775d 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0287-media-dt-bindings-media-i2c-Add-Arducam-64MP-CMOS-se.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0287-media-dt-bindings-media-i2c-Add-Arducam-64MP-CMOS-se.patch @@ -134,7 +134,7 @@ Signed-off-by: Lee Jackson +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -1752,6 +1752,14 @@ S: Maintained +@@ -1758,6 +1758,14 @@ S: Maintained F: drivers/net/arcnet/ F: include/uapi/linux/if_arcnet.h diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0295-media-adv7180-Nasty-hack-to-allow-input-selection.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0295-media-adv7180-Nasty-hack-to-allow-input-selection.patch index fca52578af..99874abcc3 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0295-media-adv7180-Nasty-hack-to-allow-input-selection.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0295-media-adv7180-Nasty-hack-to-allow-input-selection.patch @@ -78,7 +78,7 @@ Signed-off-by: Dave Stevenson *norm = state->curr_norm; return 0; -@@ -890,6 +914,8 @@ static int adv7180_s_stream(struct v4l2_ +@@ -897,6 +921,8 @@ static int adv7180_s_stream(struct v4l2_ return 0; } diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0303-dtbindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0303-dtbindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch index 6329c752e6..c0be6414cc 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0303-dtbindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0303-dtbindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch @@ -137,7 +137,7 @@ Signed-off-by: Dave Stevenson +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -21599,6 +21599,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -21612,6 +21612,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/imx519.yaml F: drivers/media/i2c/imx519.c diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0308-gpio-pca953x-Add-ti-tca9554-compatible-string.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0308-gpio-pca953x-Add-ti-tca9554-compatible-string.patch index e7363a9079..37bf2fb81a 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0308-gpio-pca953x-Add-ti-tca9554-compatible-string.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0308-gpio-pca953x-Add-ti-tca9554-compatible-string.patch @@ -10,7 +10,7 @@ Signed-off-by: Phil Elwell --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c -@@ -1306,6 +1306,7 @@ static const struct of_device_id pca953x +@@ -1353,6 +1353,7 @@ static const struct of_device_id pca953x { .compatible = "ti,tca9535", .data = OF_953X(16, PCA_INT), }, { .compatible = "ti,tca9538", .data = OF_953X( 8, PCA_INT), }, { .compatible = "ti,tca9539", .data = OF_953X(16, PCA_INT), }, diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0309-hwmon-aht10-Add-DT-compatible-string.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0309-hwmon-aht10-Add-DT-compatible-string.patch index 6fac3b1364..ab5cfc745e 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0309-hwmon-aht10-Add-DT-compatible-string.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0309-hwmon-aht10-Add-DT-compatible-string.patch @@ -10,7 +10,7 @@ Signed-off-by: Phil Elwell --- a/drivers/hwmon/aht10.c +++ b/drivers/hwmon/aht10.c -@@ -57,6 +57,12 @@ static const struct i2c_device_id aht10_ +@@ -62,6 +62,12 @@ static const struct i2c_device_id aht10_ }; MODULE_DEVICE_TABLE(i2c, aht10_id); @@ -23,7 +23,7 @@ Signed-off-by: Phil Elwell /** * struct aht10_data - All the data required to operate an AHT10/AHT20 chip * @client: the i2c client associated with the AHT10/AHT20 -@@ -380,6 +386,7 @@ static int aht10_probe(struct i2c_client +@@ -395,6 +401,7 @@ static int aht10_probe(struct i2c_client static struct i2c_driver aht10_driver = { .driver = { .name = "aht10", diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0318-dt-bindings-media-i2c-Replace-IMX708-sensor-binding-.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0318-dt-bindings-media-i2c-Replace-IMX708-sensor-binding-.patch index ae1b01f6d5..597fad73fe 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0318-dt-bindings-media-i2c-Replace-IMX708-sensor-binding-.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0318-dt-bindings-media-i2c-Replace-IMX708-sensor-binding-.patch @@ -271,7 +271,7 @@ Signed-off-by: Naushir Patuck +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -21604,7 +21604,7 @@ M: Raspberry Pi Kernel Maintenance static void macb_init_buffers(struct macb *bp) { struct macb_queue *queue; -@@ -977,6 +993,7 @@ static int macb_mii_init(struct macb *bp +@@ -974,6 +990,7 @@ static int macb_mii_init(struct macb *bp bp->mii_bus->write = &macb_mdio_write_c22; bp->mii_bus->read_c45 = &macb_mdio_read_c45; bp->mii_bus->write_c45 = &macb_mdio_write_c45; @@ -199,7 +199,7 @@ Signed-off-by: Jonathan Bell snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", bp->pdev->name, bp->pdev->id); bp->mii_bus->priv = bp; -@@ -1642,6 +1659,11 @@ static int macb_rx(struct macb_queue *qu +@@ -1639,6 +1656,11 @@ static int macb_rx(struct macb_queue *qu macb_init_rx_ring(queue); queue_writel(queue, RBQP, queue->rx_ring_dma); @@ -211,7 +211,7 @@ Signed-off-by: Jonathan Bell macb_writel(bp, NCR, ctrl | MACB_BIT(RE)); -@@ -1944,8 +1966,9 @@ static irqreturn_t macb_interrupt(int ir +@@ -1941,8 +1963,9 @@ static irqreturn_t macb_interrupt(int ir queue_writel(queue, ISR, MACB_BIT(TCOMP) | MACB_BIT(TXUBR)); @@ -222,7 +222,7 @@ Signed-off-by: Jonathan Bell wmb(); // ensure softirq can see update } -@@ -2401,6 +2424,11 @@ static netdev_tx_t macb_start_xmit(struc +@@ -2398,6 +2421,11 @@ static netdev_tx_t macb_start_xmit(struc skb_tx_timestamp(skb); spin_lock(&bp->lock); @@ -234,7 +234,7 @@ Signed-off-by: Jonathan Bell macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); spin_unlock(&bp->lock); -@@ -2807,6 +2835,37 @@ static void macb_configure_dma(struct ma +@@ -2804,6 +2832,37 @@ static void macb_configure_dma(struct ma } } @@ -272,7 +272,7 @@ Signed-off-by: Jonathan Bell static void macb_init_hw(struct macb *bp) { u32 config; -@@ -2835,6 +2894,11 @@ static void macb_init_hw(struct macb *bp +@@ -2832,6 +2891,11 @@ static void macb_init_hw(struct macb *bp if (bp->caps & MACB_CAPS_JUMBO) bp->rx_frm_len_mask = MACB_RX_JFRMLEN_MASK; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0348-usb-dwc3-Set-DMA-and-coherent-masks-early.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0348-usb-dwc3-Set-DMA-and-coherent-masks-early.patch index d93a73f7f6..1f188450ab 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0348-usb-dwc3-Set-DMA-and-coherent-masks-early.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0348-usb-dwc3-Set-DMA-and-coherent-masks-early.patch @@ -212,7 +212,7 @@ Signed-off-by: Jonathan Bell }, --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c -@@ -1320,6 +1320,24 @@ static void dwc3_config_threshold(struct +@@ -1322,6 +1322,24 @@ static void dwc3_config_threshold(struct } } @@ -237,7 +237,7 @@ Signed-off-by: Jonathan Bell /** * dwc3_core_init - Low-level initialization of DWC3 Core * @dwc: Pointer to our controller context structure -@@ -1387,6 +1405,8 @@ static int dwc3_core_init(struct dwc3 *d +@@ -1389,6 +1407,8 @@ static int dwc3_core_init(struct dwc3 *d dwc3_config_soc_bus(dwc); @@ -246,7 +246,7 @@ Signed-off-by: Jonathan Bell ret = dwc3_phy_power_on(dwc); if (ret) goto err_exit_phy; -@@ -1491,6 +1511,24 @@ static int dwc3_core_init(struct dwc3 *d +@@ -1493,6 +1513,24 @@ static int dwc3_core_init(struct dwc3 *d dwc3_writel(dwc->regs, DWC3_LLUCTL, reg); } @@ -271,7 +271,7 @@ Signed-off-by: Jonathan Bell return 0; err_power_off_phy: -@@ -1676,6 +1714,7 @@ static void dwc3_get_properties(struct d +@@ -1678,6 +1716,7 @@ static void dwc3_get_properties(struct d u8 tx_thr_num_pkt_prd = 0; u8 tx_max_burst_prd = 0; u8 tx_fifo_resize_max_num; @@ -279,7 +279,7 @@ Signed-off-by: Jonathan Bell /* default to highest possible threshold */ lpm_nyet_threshold = 0xf; -@@ -1696,6 +1735,9 @@ static void dwc3_get_properties(struct d +@@ -1698,6 +1737,9 @@ static void dwc3_get_properties(struct d */ tx_fifo_resize_max_num = 6; @@ -289,7 +289,7 @@ Signed-off-by: Jonathan Bell dwc->maximum_speed = usb_get_maximum_speed(dev); dwc->max_ssp_rate = usb_get_maximum_ssp_rate(dev); dwc->dr_mode = usb_get_dr_mode(dev); -@@ -1810,6 +1852,9 @@ static void dwc3_get_properties(struct d +@@ -1812,6 +1854,9 @@ static void dwc3_get_properties(struct d dwc->dis_split_quirk = device_property_read_bool(dev, "snps,dis-split-quirk"); @@ -299,7 +299,7 @@ Signed-off-by: Jonathan Bell dwc->lpm_nyet_threshold = lpm_nyet_threshold; dwc->tx_de_emphasis = tx_de_emphasis; -@@ -1827,6 +1872,8 @@ static void dwc3_get_properties(struct d +@@ -1829,6 +1874,8 @@ static void dwc3_get_properties(struct d dwc->tx_thr_num_pkt_prd = tx_thr_num_pkt_prd; dwc->tx_max_burst_prd = tx_max_burst_prd; @@ -308,7 +308,7 @@ Signed-off-by: Jonathan Bell dwc->tx_fifo_resize_max_num = tx_fifo_resize_max_num; } -@@ -2185,6 +2232,12 @@ static int dwc3_probe(struct platform_de +@@ -2202,6 +2249,12 @@ static int dwc3_probe(struct platform_de if (IS_ERR(dwc->usb_psy)) return dev_err_probe(dev, PTR_ERR(dwc->usb_psy), "couldn't get usb power supply\n"); @@ -333,7 +333,7 @@ Signed-off-by: Jonathan Bell /* Global Debug LSP MUX Select */ #define DWC3_GDBGLSPMUX_ENDBC BIT(15) /* Host only */ #define DWC3_GDBGLSPMUX_HOSTSELECT(n) ((n) & 0x3fff) -@@ -1087,6 +1090,7 @@ struct dwc3_scratchpad_array { +@@ -1089,6 +1092,7 @@ struct dwc3_scratchpad_array { * @tx_max_burst_prd: max periodic ESS transmit burst size * @tx_fifo_resize_max_num: max number of fifos allocated during txfifo resize * @clear_stall_protocol: endpoint number that requires a delayed status phase @@ -341,7 +341,7 @@ Signed-off-by: Jonathan Bell * @hsphy_interface: "utmi" or "ulpi" * @connected: true when we're connected to a host, false otherwise * @softconnect: true when gadget connect is called, false when disconnect runs -@@ -1337,6 +1341,7 @@ struct dwc3 { +@@ -1342,6 +1346,7 @@ struct dwc3 { u8 tx_max_burst_prd; u8 tx_fifo_resize_max_num; u8 clear_stall_protocol; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0352-mfd-Add-rp1-driver.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0352-mfd-Add-rp1-driver.patch index fa25e0aea2..1912000f12 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0352-mfd-Add-rp1-driver.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0352-mfd-Add-rp1-driver.patch @@ -25,7 +25,7 @@ Signed-off-by: Phil Elwell --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig -@@ -2384,6 +2384,17 @@ config MFD_INTEL_M10_BMC_PMCI +@@ -2408,6 +2408,17 @@ config MFD_INTEL_M10_BMC_PMCI additional drivers must be enabled in order to use the functionality of the device. diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0358-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clocks.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0358-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clocks.patch index ebdb57af0a..2eee2bbc70 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0358-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clocks.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0358-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clocks.patch @@ -48,7 +48,7 @@ Signed-off-by: Jonathan Bell static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); -@@ -1143,10 +1155,11 @@ static int sg2042_init(struct device *de +@@ -1150,10 +1162,11 @@ static int sg2042_init(struct device *de } static const struct sdhci_ops sdhci_dwcmshc_ops = { @@ -61,7 +61,7 @@ Signed-off-by: Jonathan Bell .reset = dwcmshc_reset, .adma_write_desc = dwcmshc_adma_write_desc, .irq = dwcmshc_cqe_irq_handler, -@@ -1219,8 +1232,10 @@ static const struct sdhci_ops sdhci_dwcm +@@ -1226,8 +1239,10 @@ static const struct sdhci_ops sdhci_dwcm static const struct dwcmshc_pltfm_data sdhci_dwcmshc_pdata = { .pdata = { .ops = &sdhci_dwcmshc_ops, @@ -74,7 +74,7 @@ Signed-off-by: Jonathan Bell }, }; -@@ -1235,6 +1250,15 @@ static const struct dwcmshc_pltfm_data s +@@ -1242,6 +1257,15 @@ static const struct dwcmshc_pltfm_data s }; #endif @@ -90,7 +90,7 @@ Signed-off-by: Jonathan Bell static const struct dwcmshc_pltfm_data sdhci_dwcmshc_rk35xx_pdata = { .pdata = { .ops = &sdhci_dwcmshc_rk35xx_ops, -@@ -1358,6 +1382,10 @@ dsbl_cqe_caps: +@@ -1365,6 +1389,10 @@ dsbl_cqe_caps: static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { { @@ -101,7 +101,7 @@ Signed-off-by: Jonathan Bell .compatible = "rockchip,rk3588-dwcmshc", .data = &sdhci_dwcmshc_rk35xx_pdata, }, -@@ -1450,13 +1478,32 @@ static int dwcmshc_probe(struct platform +@@ -1457,13 +1485,32 @@ static int dwcmshc_probe(struct platform priv->bus_clk = devm_clk_get(dev, "bus"); if (!IS_ERR(priv->bus_clk)) clk_prepare_enable(priv->bus_clk); @@ -134,7 +134,7 @@ Signed-off-by: Jonathan Bell priv->vendor_specific_area1 = sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK; -@@ -1516,6 +1563,7 @@ err_rpm: +@@ -1523,6 +1570,7 @@ err_rpm: pm_runtime_put_noidle(dev); err_clk: clk_disable_unprepare(pltfm_host->clk); diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0360-i2c-designware-Add-SMBUS-quick-command-support.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0360-i2c-designware-Add-SMBUS-quick-command-support.patch index 79be03dd06..d0b006e07a 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0360-i2c-designware-Add-SMBUS-quick-command-support.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0360-i2c-designware-Add-SMBUS-quick-command-support.patch @@ -17,7 +17,7 @@ Signed-off-by: Phil Elwell --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h -@@ -123,7 +123,9 @@ +@@ -124,7 +124,9 @@ #define DW_IC_ERR_TX_ABRT 0x1 @@ -29,7 +29,7 @@ Signed-off-by: Phil Elwell #define DW_IC_COMP_PARAM_1_SPEED_MODE_MASK GENMASK(3, 2) --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c -@@ -248,6 +248,10 @@ static void i2c_dw_xfer_init(struct dw_i +@@ -255,6 +255,10 @@ static void i2c_dw_xfer_init(struct dw_i ic_tar = DW_IC_TAR_10BITADDR_MASTER; } @@ -40,7 +40,7 @@ Signed-off-by: Phil Elwell regmap_update_bits(dev->map, DW_IC_CON, DW_IC_CON_10BITADDR_MASTER, ic_con); -@@ -457,6 +461,14 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev) +@@ -464,6 +468,14 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev) regmap_read(dev->map, DW_IC_RXFLR, &flr); rx_limit = dev->rx_fifo_depth - flr; @@ -55,7 +55,7 @@ Signed-off-by: Phil Elwell while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) { u32 cmd = 0; -@@ -895,14 +907,15 @@ static const struct i2c_algorithm i2c_dw +@@ -902,14 +914,15 @@ static const struct i2c_algorithm i2c_dw }; static const struct i2c_adapter_quirks i2c_dw_quirks = { diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0406-media-dt-bindings-i2c-Add-Rohm-BU64754-bindings.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0406-media-dt-bindings-i2c-Add-Rohm-BU64754-bindings.patch index 70e51011e4..36fc9164a1 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0406-media-dt-bindings-i2c-Add-Rohm-BU64754-bindings.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0406-media-dt-bindings-i2c-Add-Rohm-BU64754-bindings.patch @@ -67,7 +67,7 @@ Signed-off-by: Jacopo Mondi +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -20062,6 +20062,13 @@ S: Supported +@@ -20075,6 +20075,13 @@ S: Supported F: drivers/iio/light/rohm-bu27008.c F: drivers/iio/light/rohm-bu27034.c diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0407-media-i2c-Add-ROHM-BU64754-Camera-Autofocus-Actuator.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0407-media-i2c-Add-ROHM-BU64754-Camera-Autofocus-Actuator.patch index 1a2261aa34..b6fe8e95e3 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0407-media-i2c-Add-ROHM-BU64754-Camera-Autofocus-Actuator.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0407-media-i2c-Add-ROHM-BU64754-Camera-Autofocus-Actuator.patch @@ -37,7 +37,7 @@ Signed-off-by: Jacopo Mondi + config VIDEO_DW9714 tristate "DW9714 lens voice coil support" - depends on I2C && VIDEO_DEV + depends on GPIOLIB && I2C && VIDEO_DEV --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_VIDEO_ARDUCAM_PIVARIETY) += diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0409-media-i2c-adv7180-Use-MEDIA_BUS_FMT_UYVY8_1X16-for-C.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0409-media-i2c-adv7180-Use-MEDIA_BUS_FMT_UYVY8_1X16-for-C.patch index 9b86b31a5d..e56559b5af 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0409-media-i2c-adv7180-Use-MEDIA_BUS_FMT_UYVY8_1X16-for-C.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0409-media-i2c-adv7180-Use-MEDIA_BUS_FMT_UYVY8_1X16-for-C.patch @@ -17,7 +17,7 @@ Signed-off-by: Dave Stevenson --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c -@@ -732,10 +732,15 @@ static int adv7180_enum_mbus_code(struct +@@ -739,10 +739,15 @@ static int adv7180_enum_mbus_code(struct struct v4l2_subdev_state *sd_state, struct v4l2_subdev_mbus_code_enum *code) { @@ -34,7 +34,7 @@ Signed-off-by: Dave Stevenson return 0; } -@@ -745,7 +750,10 @@ static int adv7180_mbus_fmt(struct v4l2_ +@@ -752,7 +757,10 @@ static int adv7180_mbus_fmt(struct v4l2_ { struct adv7180_state *state = to_state(sd); diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0410-media-i2c-adv7180-Add-support-for-V4L2_CID_LINK_FREQ.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0410-media-i2c-adv7180-Add-support-for-V4L2_CID_LINK_FREQ.patch index 1ec30edc79..ce8320131c 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0410-media-i2c-adv7180-Add-support-for-V4L2_CID_LINK_FREQ.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0410-media-i2c-adv7180-Add-support-for-V4L2_CID_LINK_FREQ.patch @@ -36,7 +36,7 @@ This reverts commit 00ecb85c58501f8f7ae75fcb069bbbad5542e853. }; #define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \ struct adv7180_state, \ -@@ -625,6 +636,9 @@ static int adv7180_s_ctrl(struct v4l2_ct +@@ -632,6 +643,9 @@ static int adv7180_s_ctrl(struct v4l2_ct if (ret) return ret; @@ -46,7 +46,7 @@ This reverts commit 00ecb85c58501f8f7ae75fcb069bbbad5542e853. val = ctrl->val; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: -@@ -666,6 +680,7 @@ static int adv7180_s_ctrl(struct v4l2_ct +@@ -673,6 +687,7 @@ static int adv7180_s_ctrl(struct v4l2_ct ret = -EINVAL; } @@ -54,7 +54,7 @@ This reverts commit 00ecb85c58501f8f7ae75fcb069bbbad5542e853. mutex_unlock(&state->mutex); return ret; } -@@ -686,7 +701,7 @@ static const struct v4l2_ctrl_config adv +@@ -693,7 +708,7 @@ static const struct v4l2_ctrl_config adv static int adv7180_init_controls(struct adv7180_state *state) { @@ -63,7 +63,7 @@ This reverts commit 00ecb85c58501f8f7ae75fcb069bbbad5542e853. v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops, V4L2_CID_BRIGHTNESS, ADV7180_BRI_MIN, -@@ -712,6 +727,17 @@ static int adv7180_init_controls(struct +@@ -719,6 +734,17 @@ static int adv7180_init_controls(struct test_pattern_menu); } @@ -81,7 +81,7 @@ This reverts commit 00ecb85c58501f8f7ae75fcb069bbbad5542e853. state->sd.ctrl_handler = &state->ctrl_hdl; if (state->ctrl_hdl.error) { int err = state->ctrl_hdl.error; -@@ -839,7 +865,16 @@ static int adv7180_set_pad_format(struct +@@ -846,7 +872,16 @@ static int adv7180_set_pad_format(struct ret = adv7180_mbus_fmt(sd, &format->format); if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0413-drivers-usb-dwc3-add-FS-LS-bus-instance-parkmode-dis.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0413-drivers-usb-dwc3-add-FS-LS-bus-instance-parkmode-dis.patch index f8e80fc4d0..27e442afc0 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0413-drivers-usb-dwc3-add-FS-LS-bus-instance-parkmode-dis.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0413-drivers-usb-dwc3-add-FS-LS-bus-instance-parkmode-dis.patch @@ -16,7 +16,7 @@ Signed-off-by: Jonathan Bell --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c -@@ -1486,6 +1486,9 @@ static int dwc3_core_init(struct dwc3 *d +@@ -1488,6 +1488,9 @@ static int dwc3_core_init(struct dwc3 *d if (dwc->parkmode_disable_hs_quirk) reg |= DWC3_GUCTL1_PARKMODE_DISABLE_HS; @@ -26,7 +26,7 @@ Signed-off-by: Jonathan Bell if (DWC3_VER_IS_WITHIN(DWC3, 290A, ANY)) { if (dwc->maximum_speed == USB_SPEED_FULL || dwc->maximum_speed == USB_SPEED_HIGH) -@@ -1832,6 +1835,8 @@ static void dwc3_get_properties(struct d +@@ -1834,6 +1837,8 @@ static void dwc3_get_properties(struct d "snps,parkmode-disable-ss-quirk"); dwc->parkmode_disable_hs_quirk = device_property_read_bool(dev, "snps,parkmode-disable-hs-quirk"); @@ -45,7 +45,7 @@ Signed-off-by: Jonathan Bell #define DWC3_GUCTL1_RESUME_OPMODE_HS_HOST BIT(10) /* Global Status Register */ -@@ -1142,10 +1143,12 @@ struct dwc3_scratchpad_array { +@@ -1144,10 +1145,12 @@ struct dwc3_scratchpad_array { * generation after resume from suspend. * @ulpi_ext_vbus_drv: Set to confiure the upli chip to drives CPEN pin * VBUS with an external supply. @@ -62,7 +62,7 @@ Signed-off-by: Jonathan Bell * @gfladj_refclk_lpm_sel: set if we need to enable SOF/ITP counter * running based on ref_clk * @tx_de_emphasis_quirk: set if we enable Tx de-emphasis quirk -@@ -1385,6 +1388,7 @@ struct dwc3 { +@@ -1390,6 +1393,7 @@ struct dwc3 { unsigned ulpi_ext_vbus_drv:1; unsigned parkmode_disable_ss_quirk:1; unsigned parkmode_disable_hs_quirk:1; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0415-i2c-designware-Support-non-standard-bus-speeds.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0415-i2c-designware-Support-non-standard-bus-speeds.patch index 9e13743b00..2e2e80dbcb 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0415-i2c-designware-Support-non-standard-bus-speeds.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0415-i2c-designware-Support-non-standard-bus-speeds.patch @@ -59,7 +59,7 @@ Signed-off-by: Phil Elwell int i2c_dw_fw_parse_and_configure(struct dw_i2c_dev *dev) --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h -@@ -293,6 +293,7 @@ struct dw_i2c_dev { +@@ -294,6 +294,7 @@ struct dw_i2c_dev { u16 fp_lcnt; u16 hs_hcnt; u16 hs_lcnt; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0476-lan78xx-Read-initial-EEE-status-from-DT.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0476-lan78xx-Read-initial-EEE-status-from-DT.patch index 1c2ec17d50..9dddcb304a 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0476-lan78xx-Read-initial-EEE-status-from-DT.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0476-lan78xx-Read-initial-EEE-status-from-DT.patch @@ -15,7 +15,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c -@@ -2440,7 +2440,26 @@ static int lan78xx_phy_init(struct lan78 +@@ -2438,7 +2438,26 @@ static int lan78xx_phy_init(struct lan78 mii_adv_to_linkmode_adv_t(fc, mii_adv); linkmode_or(phydev->advertising, fc, phydev->advertising); diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0482-spi-dt-bindings-Add-RPI-RP2040-GPIO-Bridge.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0482-spi-dt-bindings-Add-RPI-RP2040-GPIO-Bridge.patch index 4a3fd18513..c8c25a770c 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0482-spi-dt-bindings-Add-RPI-RP2040-GPIO-Bridge.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0482-spi-dt-bindings-Add-RPI-RP2040-GPIO-Bridge.patch @@ -94,7 +94,7 @@ Signed-off-by: Richard Oliver + --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19355,6 +19355,11 @@ L: linux-edac@vger.kernel.org +@@ -19368,6 +19368,11 @@ L: linux-edac@vger.kernel.org S: Maintained F: drivers/ras/amd/fmpm.c diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0483-spi-Add-a-driver-for-the-RPI-RP2040-GPIO-bridge.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0483-spi-Add-a-driver-for-the-RPI-RP2040-GPIO-bridge.patch index 088410484b..c932a4c5c6 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0483-spi-Add-a-driver-for-the-RPI-RP2040-GPIO-bridge.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0483-spi-Add-a-driver-for-the-RPI-RP2040-GPIO-bridge.patch @@ -42,7 +42,7 @@ Signed-off-by: Richard Oliver --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19359,6 +19359,7 @@ RASPBERRY PI RP2040 GPIO BRIDGE DRIVER +@@ -19372,6 +19372,7 @@ RASPBERRY PI RP2040 GPIO BRIDGE DRIVER M: Raspberry Pi Kernel Maintenance S: Maintained F: Documentation/devicetree/bindings/spi/raspberrypi,rp2040-gpio-bridge.yaml diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0504-media-dt-bindings-i2c-Add-Sony-IMX500.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0504-media-dt-bindings-i2c-Add-Sony-IMX500.patch index 4818c64bf2..d9fb0d2651 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0504-media-dt-bindings-i2c-Add-Sony-IMX500.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0504-media-dt-bindings-i2c-Add-Sony-IMX500.patch @@ -150,7 +150,7 @@ Signed-off-by: Richard Oliver + --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -21604,6 +21604,13 @@ F: Documentation/devicetree/bindings/med +@@ -21617,6 +21617,13 @@ F: Documentation/devicetree/bindings/med F: Documentation/devicetree/bindings/media/i2c/imx477.yaml F: drivers/media/i2c/imx477.c diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0505-media-i2c-Add-driver-for-Sony-IMX500-sensor.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0505-media-i2c-Add-driver-for-Sony-IMX500-sensor.patch index 08b57ed3b0..123e88b0bf 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0505-media-i2c-Add-driver-for-Sony-IMX500-sensor.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0505-media-i2c-Add-driver-for-Sony-IMX500-sensor.patch @@ -58,7 +58,7 @@ Signed-off-by: Naushir Patuck --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -21610,6 +21610,7 @@ L: linux-media@vger.kernel.org +@@ -21623,6 +21623,7 @@ L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/sony,imx500.yaml diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0507-media-i2c-ov5647-Add-control-of-V4L2_CID_HBLANK.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0507-media-i2c-ov5647-Add-control-of-V4L2_CID_HBLANK.patch index 86e090057b..f8d66f61b0 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0507-media-i2c-ov5647-Add-control-of-V4L2_CID_HBLANK.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0507-media-i2c-ov5647-Add-control-of-V4L2_CID_HBLANK.patch @@ -102,7 +102,7 @@ Signed-off-by: Dave Stevenson /* Read-only, but we adjust it based on mode. */ break; -@@ -1421,10 +1421,11 @@ static int ov5647_init_controls(struct o +@@ -1423,10 +1423,11 @@ static int ov5647_init_controls(struct o sensor->mode->pixel_rate, 1, sensor->mode->pixel_rate); @@ -116,7 +116,7 @@ Signed-off-by: Dave Stevenson hblank); sensor->vblank = v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops, -@@ -1458,7 +1459,6 @@ static int ov5647_init_controls(struct o +@@ -1460,7 +1461,6 @@ static int ov5647_init_controls(struct o goto handler_free; sensor->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0516-media-i2c-ov5647-Add-V4L2_CID_LINK_FREQUENCY-control.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0516-media-i2c-ov5647-Add-V4L2_CID_LINK_FREQUENCY-control.patch index 192be95286..e122bba10b 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0516-media-i2c-ov5647-Add-V4L2_CID_LINK_FREQUENCY-control.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0516-media-i2c-ov5647-Add-V4L2_CID_LINK_FREQUENCY-control.patch @@ -70,7 +70,7 @@ Signed-off-by: Dave Stevenson @@ -439,6 +451,7 @@ static const struct ov5647_mode ov5647_m .height = 1920, }, - .pixel_rate = 55000000, + .pixel_rate = 58333000, + .link_freq_index = FREQ_INDEX_VGA, .hts = 1852, .vts = 0x1f8, @@ -91,9 +91,9 @@ Signed-off-by: Dave Stevenson - v4l2_ctrl_handler_init(&sensor->ctrls, 9); + v4l2_ctrl_handler_init(&sensor->ctrls, 10); - v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 0); -@@ -1302,6 +1317,14 @@ static int ov5647_init_controls(struct o + sensor->ctrls.lock = &sensor->lock; + +@@ -1304,6 +1319,14 @@ static int ov5647_init_controls(struct o if (sensor->vflip) sensor->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0519-numa-emulation-Check-emulated-zones-around-the-CMA-w.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0519-numa-emulation-Check-emulated-zones-around-the-CMA-w.patch index b7cd28f44c..30fde17d90 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0519-numa-emulation-Check-emulated-zones-around-the-CMA-w.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0519-numa-emulation-Check-emulated-zones-around-the-CMA-w.patch @@ -84,9 +84,9 @@ Signed-off-by: Tvrtko Ursulin #include +#include #include + #include - #define FAKE_NODE_MIN_SIZE ((u64)32 << 20) -@@ -51,6 +52,7 @@ static int __init emu_setup_memblk(struc +@@ -52,6 +53,7 @@ static int __init emu_setup_memblk(struc { struct numa_memblk *eb = &ei->blk[ei->nr_blks]; struct numa_memblk *pb = &pi->blk[phys_blk]; @@ -94,7 +94,7 @@ Signed-off-by: Tvrtko Ursulin if (ei->nr_blks >= NR_NODE_MEMBLKS) { pr_err("NUMA: Too many emulated memblks, failing emulation\n"); -@@ -62,6 +64,10 @@ static int __init emu_setup_memblk(struc +@@ -63,6 +65,10 @@ static int __init emu_setup_memblk(struc eb->end = pb->start + size; eb->nid = nid; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0524-usb-dwc3-core-add-support-for-setting-NAK-enhancemen.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0524-usb-dwc3-core-add-support-for-setting-NAK-enhancemen.patch index 92cb7e9481..2f79f27181 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0524-usb-dwc3-core-add-support-for-setting-NAK-enhancemen.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0524-usb-dwc3-core-add-support-for-setting-NAK-enhancemen.patch @@ -22,7 +22,7 @@ Signed-off-by: Jonathan Bell --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c -@@ -1480,6 +1480,12 @@ static int dwc3_core_init(struct dwc3 *d +@@ -1482,6 +1482,12 @@ static int dwc3_core_init(struct dwc3 *d if (dwc->dis_tx_ipgap_linecheck_quirk) reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS; @@ -35,7 +35,7 @@ Signed-off-by: Jonathan Bell if (dwc->parkmode_disable_ss_quirk) reg |= DWC3_GUCTL1_PARKMODE_DISABLE_SS; -@@ -1831,6 +1837,10 @@ static void dwc3_get_properties(struct d +@@ -1833,6 +1839,10 @@ static void dwc3_get_properties(struct d "snps,resume-hs-terminations"); dwc->ulpi_ext_vbus_drv = device_property_read_bool(dev, "snps,ulpi-ext-vbus-drv"); @@ -57,7 +57,7 @@ Signed-off-by: Jonathan Bell #define DWC3_GUCTL1_PARKMODE_DISABLE_SS BIT(17) #define DWC3_GUCTL1_PARKMODE_DISABLE_HS BIT(16) #define DWC3_GUCTL1_PARKMODE_DISABLE_FSLS BIT(15) -@@ -1143,6 +1145,8 @@ struct dwc3_scratchpad_array { +@@ -1145,6 +1147,8 @@ struct dwc3_scratchpad_array { * generation after resume from suspend. * @ulpi_ext_vbus_drv: Set to confiure the upli chip to drives CPEN pin * VBUS with an external supply. @@ -66,7 +66,7 @@ Signed-off-by: Jonathan Bell * @parkmode_disable_ss_quirk: If set, disable park mode feature for all * Superspeed instances. * @parkmode_disable_hs_quirk: If set, disable park mode feature for all -@@ -1386,6 +1390,8 @@ struct dwc3 { +@@ -1391,6 +1395,8 @@ struct dwc3 { unsigned dis_tx_ipgap_linecheck_quirk:1; unsigned resume_hs_terminations:1; unsigned ulpi_ext_vbus_drv:1; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0685-nvme-pci-Disable-Host-Memory-Buffer-usage.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0685-nvme-pci-Disable-Host-Memory-Buffer-usage.patch index a299c6c57e..ec963fd3e7 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0685-nvme-pci-Disable-Host-Memory-Buffer-usage.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0685-nvme-pci-Disable-Host-Memory-Buffer-usage.patch @@ -18,7 +18,7 @@ Signed-off-by: Phil Elwell --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c -@@ -2106,6 +2106,7 @@ static void nvme_free_host_mem(struct nv +@@ -2109,6 +2109,7 @@ static void nvme_free_host_mem(struct nv dev->nr_host_mem_descs = 0; } @@ -26,7 +26,7 @@ Signed-off-by: Phil Elwell static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred, u32 chunk_size) { -@@ -2174,9 +2175,11 @@ out: +@@ -2177,9 +2178,11 @@ out: dev->host_mem_descs = NULL; return -ENOMEM; } @@ -38,7 +38,7 @@ Signed-off-by: Phil Elwell u64 min_chunk = min_t(u64, preferred, PAGE_SIZE * MAX_ORDER_NR_PAGES); u64 hmminds = max_t(u32, dev->ctrl.hmminds * 4096, PAGE_SIZE * 2); u64 chunk_size; -@@ -2189,6 +2192,7 @@ static int nvme_alloc_host_mem(struct nv +@@ -2192,6 +2195,7 @@ static int nvme_alloc_host_mem(struct nv nvme_free_host_mem(dev); } } diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0724-Revert-PCI-Warn-if-no-host-bridge-NUMA-node-info.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0724-Revert-PCI-Warn-if-no-host-bridge-NUMA-node-info.patch index bc3ad640f5..97ecdd7c59 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0724-Revert-PCI-Warn-if-no-host-bridge-NUMA-node-info.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0724-Revert-PCI-Warn-if-no-host-bridge-NUMA-node-info.patch @@ -12,7 +12,7 @@ Signed-off-by: Phil Elwell --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c -@@ -992,9 +992,6 @@ static int pci_register_host_bridge(stru +@@ -994,9 +994,6 @@ static int pci_register_host_bridge(stru else pr_info("PCI host bridge to bus %s\n", name); diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0834-media-platform-Add-Raspberry-Pi-HEVC-decoder-driver.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0834-media-platform-Add-Raspberry-Pi-HEVC-decoder-driver.patch index 459c9ea358..6c36cda77d 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0834-media-platform-Add-Raspberry-Pi-HEVC-decoder-driver.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0834-media-platform-Add-Raspberry-Pi-HEVC-decoder-driver.patch @@ -36,7 +36,7 @@ Signed-off-by: Dave Stevenson --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19361,6 +19361,16 @@ S: Maintained +@@ -19374,6 +19374,16 @@ S: Maintained F: Documentation/devicetree/bindings/spi/raspberrypi,rp2040-gpio-bridge.yaml F: drivers/spi/spi-rp2040-gpio-bridge.c diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0860-drm-v3d-Associate-a-V3D-tech-revision-to-all-support.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0860-drm-v3d-Associate-a-V3D-tech-revision-to-all-support.patch index 176c04ec2b..5688745eba 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0860-drm-v3d-Associate-a-V3D-tech-revision-to-all-support.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0860-drm-v3d-Associate-a-V3D-tech-revision-to-all-support.patch @@ -301,7 +301,7 @@ Signed-off-by: Maíra Canal mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO); mask = DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH)); ret = dma_set_mask_and_coherent(dev, mask); -@@ -325,6 +366,11 @@ static int v3d_platform_drm_probe(struct +@@ -327,6 +368,11 @@ static int v3d_platform_drm_probe(struct ident1 = V3D_READ(V3D_HUB_IDENT1); v3d->ver = (V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_TVER) * 10 + V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_REV)); @@ -313,7 +313,7 @@ Signed-off-by: Maíra Canal v3d->cores = V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_NCORES); WARN_ON(v3d->cores > 1); /* multicore not yet implemented */ -@@ -377,7 +423,7 @@ static int v3d_platform_drm_probe(struct +@@ -379,7 +425,7 @@ static int v3d_platform_drm_probe(struct v3d->clk_down_rate = (clk_get_rate(clk_get_parent(v3d->clk)) / (1 << 4)) + 10000; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0863-drm-v3d-Use-V3D_SMS-registers-for-power-on-off-and-r.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0863-drm-v3d-Use-V3D_SMS-registers-for-power-on-off-and-r.patch index aa5c14271f..340ebadfee 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0863-drm-v3d-Use-V3D_SMS-registers-for-power-on-off-and-r.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0863-drm-v3d-Use-V3D_SMS-registers-for-power-on-off-and-r.patch @@ -29,7 +29,7 @@ Signed-off-by: Maíra Canal --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c -@@ -485,6 +485,8 @@ static void v3d_platform_drm_remove(stru +@@ -487,6 +487,8 @@ static void v3d_platform_drm_remove(stru dma_free_wc(v3d->drm.dev, 4096, v3d->mmu_scratch, v3d->mmu_scratch_paddr); diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0876-PCI-brcmstb-Adjust-PHY-PLL-setup-to-use-a-54MHz-inpu.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0876-PCI-brcmstb-Adjust-PHY-PLL-setup-to-use-a-54MHz-inpu.patch index 6e6cdc9d41..d6ff3dfe73 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0876-PCI-brcmstb-Adjust-PHY-PLL-setup-to-use-a-54MHz-inpu.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0876-PCI-brcmstb-Adjust-PHY-PLL-setup-to-use-a-54MHz-inpu.patch @@ -24,9 +24,9 @@ Reviewed-by: Florian Fainelli --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c -@@ -55,6 +55,10 @@ - #define PCIE_RC_DL_MDIO_WR_DATA 0x1104 - #define PCIE_RC_DL_MDIO_RD_DATA 0x1108 +@@ -58,6 +58,10 @@ + #define PCIE_RC_PL_REG_PHY_CTL_1 0x1804 + #define PCIE_RC_PL_REG_PHY_CTL_1_REG_P2_POWERDOWN_ENA_NOSYNC_MASK 0x8 +#define PCIE_RC_PL_PHY_CTL_15 0x184c +#define PCIE_RC_PL_PHY_CTL_15_DIS_PLL_PD_MASK 0x400000 @@ -35,7 +35,7 @@ Reviewed-by: Florian Fainelli #define PCIE_MISC_MISC_CTRL 0x4008 #define PCIE_MISC_MISC_CTRL_PCIE_RCB_64B_MODE_MASK 0x80 #define PCIE_MISC_MISC_CTRL_PCIE_RCB_MPS_MODE_MASK 0x400 -@@ -251,6 +255,7 @@ struct pcie_cfg_data { +@@ -254,6 +258,7 @@ struct pcie_cfg_data { u8 num_inbound_wins; int (*perst_set)(struct brcm_pcie *pcie, u32 val); int (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val); @@ -43,7 +43,7 @@ Reviewed-by: Florian Fainelli }; struct subdev_regulators { -@@ -826,6 +831,38 @@ static int brcm_pcie_perst_set_generic(s +@@ -829,6 +834,38 @@ static int brcm_pcie_perst_set_generic(s return 0; } @@ -82,7 +82,7 @@ Reviewed-by: Florian Fainelli static void add_inbound_win(struct inbound_win *b, u8 *count, u64 size, u64 cpu_addr, u64 pci_offset) { -@@ -1189,6 +1226,12 @@ static int brcm_pcie_setup(struct brcm_p +@@ -1210,6 +1247,12 @@ static int brcm_pcie_setup(struct brcm_p PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK); writel(tmp, base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1); @@ -95,7 +95,7 @@ Reviewed-by: Florian Fainelli return 0; } -@@ -1717,6 +1760,7 @@ static const struct pcie_cfg_data bcm271 +@@ -1738,6 +1781,7 @@ static const struct pcie_cfg_data bcm271 .soc_base = BCM7712, .perst_set = brcm_pcie_perst_set_7278, .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic, diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0884-PCI-brcmstb-Use-same-constant-table-for-config-space.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0884-PCI-brcmstb-Use-same-constant-table-for-config-space.patch index f3a0df29b2..90628d1bfe 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0884-PCI-brcmstb-Use-same-constant-table-for-config-space.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0884-PCI-brcmstb-Use-same-constant-table-for-config-space.patch @@ -20,7 +20,7 @@ Reviewed-by: Florian Fainelli --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c -@@ -150,9 +150,6 @@ +@@ -153,9 +153,6 @@ #define MSI_INT_MASK_SET 0x10 #define MSI_INT_MASK_CLR 0x14 @@ -30,7 +30,7 @@ Reviewed-by: Florian Fainelli #define PCIE_RGR1_SW_INIT_1_PERST_MASK 0x1 #define PCIE_RGR1_SW_INIT_1_PERST_SHIFT 0x0 -@@ -727,8 +724,8 @@ static void __iomem *brcm_pcie_map_bus(s +@@ -730,8 +727,8 @@ static void __iomem *brcm_pcie_map_bus(s /* For devices, write to the config space index register */ idx = PCIE_ECAM_OFFSET(bus->number, devfn, 0); @@ -41,7 +41,7 @@ Reviewed-by: Florian Fainelli } static void __iomem *brcm7425_pcie_map_bus(struct pci_bus *bus, -@@ -1711,7 +1708,7 @@ static void brcm_pcie_remove(struct plat +@@ -1732,7 +1729,7 @@ static void brcm_pcie_remove(struct plat static const int pcie_offsets[] = { [RGR1_SW_INIT_1] = 0x9210, [EXT_CFG_INDEX] = 0x9000, @@ -50,7 +50,7 @@ Reviewed-by: Florian Fainelli [PCIE_HARD_DEBUG] = 0x4204, [PCIE_INTR2_CPU_BASE] = 0x4300, }; -@@ -1719,7 +1716,7 @@ static const int pcie_offsets[] = { +@@ -1740,7 +1737,7 @@ static const int pcie_offsets[] = { static const int pcie_offsets_bcm7278[] = { [RGR1_SW_INIT_1] = 0xc010, [EXT_CFG_INDEX] = 0x9000, @@ -59,7 +59,7 @@ Reviewed-by: Florian Fainelli [PCIE_HARD_DEBUG] = 0x4204, [PCIE_INTR2_CPU_BASE] = 0x4300, }; -@@ -1733,8 +1730,9 @@ static const int pcie_offsets_bcm7425[] +@@ -1754,8 +1751,9 @@ static const int pcie_offsets_bcm7425[] }; static const int pcie_offsets_bcm7712[] = { diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0885-PCI-brcmstb-Make-two-changes-in-MDIO-register-fields.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0885-PCI-brcmstb-Make-two-changes-in-MDIO-register-fields.patch index 679cbd41d4..b15c7654b7 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0885-PCI-brcmstb-Make-two-changes-in-MDIO-register-fields.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0885-PCI-brcmstb-Make-two-changes-in-MDIO-register-fields.patch @@ -25,7 +25,7 @@ Reviewed-by: Florian Fainelli --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c -@@ -175,8 +175,9 @@ +@@ -178,8 +178,9 @@ #define MDIO_PORT0 0x0 #define MDIO_DATA_MASK 0x7fffffff #define MDIO_PORT_MASK 0xf0000 @@ -36,7 +36,7 @@ Reviewed-by: Florian Fainelli #define MDIO_CMD_READ 0x1 #define MDIO_CMD_WRITE 0x0 #define MDIO_DATA_DONE_MASK 0x80000000 -@@ -327,6 +328,7 @@ static u32 brcm_pcie_mdio_form_pkt(int p +@@ -330,6 +331,7 @@ static u32 brcm_pcie_mdio_form_pkt(int p { u32 pkt = 0; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0886-PCI-brcmstb-Clarify-conversion-of-irq_domain_set_inf.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0886-PCI-brcmstb-Clarify-conversion-of-irq_domain_set_inf.patch index bd33069c97..fd146e368e 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0886-PCI-brcmstb-Clarify-conversion-of-irq_domain_set_inf.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0886-PCI-brcmstb-Clarify-conversion-of-irq_domain_set_inf.patch @@ -16,7 +16,7 @@ Reviewed-by: Florian Fainelli --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c -@@ -559,7 +559,7 @@ static int brcm_irq_domain_alloc(struct +@@ -562,7 +562,7 @@ static int brcm_irq_domain_alloc(struct return hwirq; for (i = 0; i < nr_irqs; i++) diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0887-PCI-brcmstb-set-BCM7712-2712-specific-AXI-bridge-han.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0887-PCI-brcmstb-set-BCM7712-2712-specific-AXI-bridge-han.patch index 9204792bed..53b94164bc 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0887-PCI-brcmstb-set-BCM7712-2712-specific-AXI-bridge-han.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0887-PCI-brcmstb-set-BCM7712-2712-specific-AXI-bridge-han.patch @@ -18,7 +18,7 @@ Signed-off-by: Jonathan Bell --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c -@@ -209,6 +209,17 @@ +@@ -212,6 +212,17 @@ #define PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_PWRDN_MASK 0x1 #define PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_PWRDN_SHIFT 0x0 @@ -36,7 +36,7 @@ Signed-off-by: Jonathan Bell /* Forward declarations */ struct brcm_pcie; -@@ -859,6 +870,30 @@ static int brcm_pcie_post_setup_bcm2712( +@@ -862,6 +873,30 @@ static int brcm_pcie_post_setup_bcm2712( tmp |= 0x12; writel(tmp, pcie->base + PCIE_RC_PL_PHY_CTL_15); diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0889-PCI-brcmstb-Enable-CRS-software-visibility-after-lin.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0889-PCI-brcmstb-Enable-CRS-software-visibility-after-lin.patch index 92af159dfb..d8867af8c5 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0889-PCI-brcmstb-Enable-CRS-software-visibility-after-lin.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0889-PCI-brcmstb-Enable-CRS-software-visibility-after-lin.patch @@ -20,7 +20,7 @@ Signed-off-by: Jonathan Bell --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c -@@ -1358,7 +1358,7 @@ static int brcm_pcie_start_link(struct b +@@ -1375,7 +1375,7 @@ static int brcm_pcie_start_link(struct b { struct device *dev = pcie->dev; void __iomem *base = pcie->base; @@ -29,7 +29,7 @@ Signed-off-by: Jonathan Bell bool ssc_good = false; int ret, i; -@@ -1407,6 +1407,17 @@ static int brcm_pcie_start_link(struct b +@@ -1424,6 +1424,17 @@ static int brcm_pcie_start_link(struct b pci_speed_string(pcie_link_speed[cls]), nlw, ssc_good ? "(SSC)" : "(!SSC)"); diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0890-PCI-brcmstb-add-NO_SSC-quirk-for-BCM2712.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0890-PCI-brcmstb-add-NO_SSC-quirk-for-BCM2712.patch index 079e93a1c0..3500e224f1 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0890-PCI-brcmstb-add-NO_SSC-quirk-for-BCM2712.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0890-PCI-brcmstb-add-NO_SSC-quirk-for-BCM2712.patch @@ -29,7 +29,7 @@ Signed-off-by: Jonathan Bell struct pcie_cfg_data { const int *offsets; const enum pcie_soc_base soc_base; -@@ -1811,7 +1817,7 @@ static const struct pcie_cfg_data bcm271 +@@ -1828,7 +1834,7 @@ static const struct pcie_cfg_data bcm271 .perst_set = brcm_pcie_perst_set_7278, .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic, .post_setup = brcm_pcie_post_setup_bcm2712, @@ -38,7 +38,7 @@ Signed-off-by: Jonathan Bell .num_inbound_wins = 10, }; -@@ -1928,7 +1934,8 @@ static int brcm_pcie_probe(struct platfo +@@ -1945,7 +1951,8 @@ static int brcm_pcie_probe(struct platfo ret = of_pci_get_max_link_speed(np); pcie->gen = (ret < 0) ? 0 : ret; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0892-PCI-pcie-brcmstb-optionally-extend-Tperst_clk-time.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0892-PCI-pcie-brcmstb-optionally-extend-Tperst_clk-time.patch index 552a0b6b4e..4b8133eb22 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0892-PCI-pcie-brcmstb-optionally-extend-Tperst_clk-time.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0892-PCI-pcie-brcmstb-optionally-extend-Tperst_clk-time.patch @@ -44,7 +44,7 @@ Signed-off-by: Jonathan Bell }; static inline bool is_bmips(const struct brcm_pcie *pcie) -@@ -1487,13 +1489,32 @@ static int brcm_pcie_start_link(struct b +@@ -1504,13 +1506,32 @@ static int brcm_pcie_start_link(struct b u16 nlw, cls, lnksta, tmp16; bool ssc_good = false; int ret, i; @@ -78,7 +78,7 @@ Signed-off-by: Jonathan Bell if (ret) return ret; -@@ -2057,6 +2078,8 @@ static int brcm_pcie_probe(struct platfo +@@ -2074,6 +2095,8 @@ static int brcm_pcie_probe(struct platfo pcie->ssc = !(pcie->cfg->quirks & CFG_QUIRK_NO_SSC) && of_property_read_bool(np, "brcm,enable-ssc"); diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0947-fixup-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clock.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0947-fixup-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clock.patch index 727815eb9f..900f0f643b 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0947-fixup-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clock.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0947-fixup-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clock.patch @@ -19,7 +19,7 @@ Signed-off-by: Phil Elwell --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c -@@ -1250,13 +1250,15 @@ static const struct dwcmshc_pltfm_data s +@@ -1257,13 +1257,15 @@ static const struct dwcmshc_pltfm_data s }; #endif diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0948-PCI-pcie-brcmstb-add-more-safeguards-for-clkreq-safe.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0948-PCI-pcie-brcmstb-add-more-safeguards-for-clkreq-safe.patch index c72b52fc9f..52b713a0ae 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0948-PCI-pcie-brcmstb-add-more-safeguards-for-clkreq-safe.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0948-PCI-pcie-brcmstb-add-more-safeguards-for-clkreq-safe.patch @@ -40,7 +40,7 @@ Signed-off-by: Jonathan Bell PCIE_MISC_HARD_PCIE_HARD_DEBUG_L1SS_ENABLE_MASK) #define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP 0x40ac -@@ -1470,12 +1474,21 @@ static void brcm_config_clkreq(struct br +@@ -1487,12 +1491,21 @@ static void brcm_config_clkreq(struct br } else { /* diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0949-PCI-quirks-work-around-VL805-firmware-ASPM-meddling.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0949-PCI-quirks-work-around-VL805-firmware-ASPM-meddling.patch index acc981dc2e..f1a7c3c984 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0949-PCI-quirks-work-around-VL805-firmware-ASPM-meddling.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0949-PCI-quirks-work-around-VL805-firmware-ASPM-meddling.patch @@ -18,7 +18,7 @@ Signed-off-by: Jonathan Bell --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c -@@ -6256,6 +6256,22 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I +@@ -6283,6 +6283,22 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x56b1, aspm_l1_acceptable_latency); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x56c0, aspm_l1_acceptable_latency); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x56c1, aspm_l1_acceptable_latency); diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0955-hwmon-aht10-Fix-AHT20-initialization.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0955-hwmon-aht10-Fix-AHT20-initialization.patch index c30b1b779c..45a7dd4b55 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0955-hwmon-aht10-Fix-AHT20-initialization.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0955-hwmon-aht10-Fix-AHT20-initialization.patch @@ -17,16 +17,7 @@ Signed-off-by: Josh Martinez <8892161+joshermar@users.noreply.github.com> --- a/drivers/hwmon/aht10.c +++ b/drivers/hwmon/aht10.c -@@ -37,6 +37,8 @@ - #define AHT10_CMD_MEAS 0b10101100 - #define AHT10_CMD_RST 0b10111010 - -+#define AHT20_CMD_INIT 0b10111110 -+ - /* - * Flags in the answer byte/command - */ -@@ -59,6 +61,7 @@ MODULE_DEVICE_TABLE(i2c, aht10_id); +@@ -64,6 +64,7 @@ MODULE_DEVICE_TABLE(i2c, aht10_id); static const struct of_device_id aht10_of_id[] = { { .compatible = "aosong,aht10", }, @@ -34,19 +25,3 @@ Signed-off-by: Josh Martinez <8892161+joshermar@users.noreply.github.com> { } }; MODULE_DEVICE_TABLE(of, aht10_of_id); -@@ -107,8 +110,13 @@ struct aht10_data { - */ - static int aht10_init(struct aht10_data *data) - { -- const u8 cmd_init[] = {AHT10_CMD_INIT, AHT10_CAL_ENABLED | AHT10_MODE_CYC, -- 0x00}; -+ u8 cmd_init[] = {AHT10_CMD_INIT, AHT10_CAL_ENABLED | AHT10_MODE_CYC, 0x00}; -+ -+ if (data->crc8) { /* AHT20 */ -+ cmd_init[0] = AHT20_CMD_INIT; -+ cmd_init[1] = AHT10_CAL_ENABLED; -+ } -+ - int res; - u8 status; - struct i2c_client *client = data->client; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-0985-PCI-brcmstb-Add-link-statistics-debug-features.patch b/lede/target/linux/bcm27xx/patches-6.12/950-0985-PCI-brcmstb-Add-link-statistics-debug-features.patch index d514d0ae4d..7071bda58c 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-0985-PCI-brcmstb-Add-link-statistics-debug-features.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-0985-PCI-brcmstb-Add-link-statistics-debug-features.patch @@ -190,7 +190,7 @@ Signed-off-by: Jonathan Bell }; static inline bool is_bmips(const struct brcm_pcie *pcie) -@@ -1495,6 +1624,133 @@ static void brcm_config_clkreq(struct br +@@ -1512,6 +1641,133 @@ static void brcm_config_clkreq(struct br dev_info(pcie->dev, "clkreq-mode set to %s\n", mode); } @@ -324,7 +324,7 @@ Signed-off-by: Jonathan Bell static int brcm_pcie_start_link(struct brcm_pcie *pcie) { struct device *dev = pcie->dev; -@@ -1508,6 +1764,8 @@ static int brcm_pcie_start_link(struct b +@@ -1525,6 +1781,8 @@ static int brcm_pcie_start_link(struct b if (pcie->gen) brcm_pcie_set_gen(pcie, pcie->gen); @@ -333,7 +333,7 @@ Signed-off-by: Jonathan Bell /* Unassert the fundamental reset */ if (pcie->tperst_clk_ms) { /* -@@ -1531,6 +1789,8 @@ static int brcm_pcie_start_link(struct b +@@ -1548,6 +1806,8 @@ static int brcm_pcie_start_link(struct b if (ret) return ret; @@ -342,7 +342,7 @@ Signed-off-by: Jonathan Bell /* * Wait for 100ms after PERST# deassertion; see PCIe CEM specification * sections 2.2, PCIe r5.0, 6.6.1. -@@ -1567,6 +1827,9 @@ static int brcm_pcie_start_link(struct b +@@ -1584,6 +1844,9 @@ static int brcm_pcie_start_link(struct b pci_speed_string(pcie_link_speed[cls]), nlw, ssc_good ? "(SSC)" : "(!SSC)"); @@ -352,7 +352,7 @@ Signed-off-by: Jonathan Bell /* * RootCtl bits are reset by perst_n, which undoes pci_enable_crs() * called prior to pci_add_new_bus() during probe. Re-enable here. -@@ -1898,6 +2161,7 @@ err_disable_clk: +@@ -1915,6 +2178,7 @@ err_disable_clk: static void __brcm_pcie_remove(struct brcm_pcie *pcie) { @@ -360,7 +360,7 @@ Signed-off-by: Jonathan Bell brcm_msi_remove(pcie); brcm_pcie_turn_off(pcie); if (brcm_phy_stop(pcie)) -@@ -2054,6 +2318,98 @@ static struct pci_ops brcm7425_pcie_ops +@@ -2071,6 +2335,98 @@ static struct pci_ops brcm7425_pcie_ops .remove_bus = brcm_pcie_remove_bus, }; @@ -459,7 +459,7 @@ Signed-off-by: Jonathan Bell static int brcm_pcie_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; -@@ -2076,6 +2432,19 @@ static int brcm_pcie_probe(struct platfo +@@ -2093,6 +2449,19 @@ static int brcm_pcie_probe(struct platfo pcie->dev = &pdev->dev; pcie->np = np; pcie->cfg = data; diff --git a/lede/target/linux/bcm27xx/patches-6.12/950-1007-drm-v3d-Don-t-retrieve-the-clock-twice.patch b/lede/target/linux/bcm27xx/patches-6.12/950-1007-drm-v3d-Don-t-retrieve-the-clock-twice.patch index 5de9f5ccd4..7d9c5ecb02 100644 --- a/lede/target/linux/bcm27xx/patches-6.12/950-1007-drm-v3d-Don-t-retrieve-the-clock-twice.patch +++ b/lede/target/linux/bcm27xx/patches-6.12/950-1007-drm-v3d-Don-t-retrieve-the-clock-twice.patch @@ -17,7 +17,7 @@ Signed-off-by: Maíra Canal --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c -@@ -395,21 +395,18 @@ static int v3d_platform_drm_probe(struct +@@ -397,21 +397,18 @@ static int v3d_platform_drm_probe(struct } } diff --git a/lede/target/linux/generic/backport-6.12/010-v6.19-nvmem-layouts-u-boot-env-add-optional-env-size-property.patch b/lede/target/linux/generic/backport-6.12/010-v6.19-nvmem-layouts-u-boot-env-add-optional-env-size-property.patch new file mode 100644 index 0000000000..207161a40d --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/010-v6.19-nvmem-layouts-u-boot-env-add-optional-env-size-property.patch @@ -0,0 +1,62 @@ +From 06e92afca89075628b12c9b4085b4cc7320081ac Mon Sep 17 00:00:00 2001 +From: Jascha Sundaresan +Date: Thu, 23 Oct 2025 03:07:41 +0400 +Subject: nvmem: layouts: u-boot-env: add optional "env-size" property + +Some devices reserve a larger NVMEM region for the U-Boot environment +than the actual environment data length used by U-Boot itself. The CRC32 +in the U-Boot header is calculated over the smaller data length, causing +CRC validation to fail when Linux reads the full partition. + +Allow an optional device tree property "env-size" to specify the +environment data size to use for CRC computation. + +v2: add missing $ref line to DT binding + +Signed-off-by: Jascha Sundaresan +Reviewed-by: Rob Herring (Arm) +Signed-off-by: Srinivas Kandagatla +--- + Documentation/devicetree/bindings/nvmem/layouts/u-boot,env.yaml | 7 +++++++ + drivers/nvmem/layouts/u-boot-env.c | 4 +++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +--- a/Documentation/devicetree/bindings/nvmem/layouts/u-boot,env.yaml ++++ b/Documentation/devicetree/bindings/nvmem/layouts/u-boot,env.yaml +@@ -46,6 +46,12 @@ properties: + type: object + description: Command to use for automatic booting + ++ env-size: ++ description: ++ Size in bytes of the environment data used by U-Boot for CRC ++ calculation. If omitted, the full NVMEM region size is used. ++ $ref: /schemas/types.yaml#/definitions/uint32 ++ + ethaddr: + type: object + description: Ethernet interfaces base MAC address. +@@ -104,6 +110,7 @@ examples: + + partition-u-boot-env { + compatible = "brcm,env"; ++ env-size = <0x20000>; + + ethaddr { + }; +--- a/drivers/nvmem/layouts/u-boot-env.c ++++ b/drivers/nvmem/layouts/u-boot-env.c +@@ -99,10 +99,12 @@ int u_boot_env_parse(struct device *dev, + uint32_t crc32; + uint32_t calc; + uint8_t *buf; ++ u32 env_size; + int bytes; + int err; + +- dev_size = nvmem_dev_size(nvmem); ++ dev_size = device_property_read_u32(dev, "env-size", &env_size) ? ++ nvmem_dev_size(nvmem) : (size_t)env_size; + + buf = kzalloc(dev_size, GFP_KERNEL); + if (!buf) { diff --git a/lede/target/linux/generic/backport-6.12/152-v6.16-net-wireguard-add-nonstring-annotation-to-fix-build-with-GCC15.patch b/lede/target/linux/generic/backport-6.12/152-v6.16-net-wireguard-add-nonstring-annotation-to-fix-build-with-GCC15.patch new file mode 100644 index 0000000000..1fdf2f1dbd --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/152-v6.16-net-wireguard-add-nonstring-annotation-to-fix-build-with-GCC15.patch @@ -0,0 +1,63 @@ +From 71e5da46e78c1cd24e2feed251a2845327447ad8 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 21 May 2025 23:27:04 +0200 +Subject: wireguard: global: add __nonstring annotations for unterminated + strings + +When a character array without a terminating NUL character has a static +initializer, GCC 15's -Wunterminated-string-initialization will only +warn if the array lacks the "nonstring" attribute[1]. Mark the arrays +with __nonstring to correctly identify the char array as "not a C string" +and thereby eliminate the warning: + +../drivers/net/wireguard/cookie.c:29:56: warning: initializer-string for array of 'unsigned char' truncates NUL terminator but destination lacks 'nonstring' attribute (9 chars into 8 available) [-Wunterminated-string-initialization] + 29 | static const u8 mac1_key_label[COOKIE_KEY_LABEL_LEN] = "mac1----"; + | ^~~~~~~~~~ +../drivers/net/wireguard/cookie.c:30:58: warning: initializer-string for array of 'unsigned char' truncates NUL terminator but destination lacks 'nonstring' attribute (9 chars into 8 available) [-Wunterminated-string-initialization] + 30 | static const u8 cookie_key_label[COOKIE_KEY_LABEL_LEN] = "cookie--"; + | ^~~~~~~~~~ +../drivers/net/wireguard/noise.c:28:38: warning: initializer-string for array of 'unsigned char' truncates NUL terminator but destination lacks 'nonstring' attribute (38 chars into 37 available) [-Wunterminated-string-initialization] + 28 | static const u8 handshake_name[37] = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"; + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +../drivers/net/wireguard/noise.c:29:39: warning: initializer-string for array of 'unsigned char' truncates NUL terminator but destination lacks 'nonstring' attribute (35 chars into 34 available) [-Wunterminated-string-initialization] + 29 | static const u8 identifier_name[34] = "WireGuard v1 zx2c4 Jason@zx2c4.com"; + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The arrays are always used with their fixed size, so use __nonstring. + +Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117178 [1] +Signed-off-by: Kees Cook +Signed-off-by: Jason A. Donenfeld +Link: https://patch.msgid.link/20250521212707.1767879-3-Jason@zx2c4.com +Signed-off-by: Paolo Abeni +--- + drivers/net/wireguard/cookie.c | 4 ++-- + drivers/net/wireguard/noise.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireguard/cookie.c ++++ b/drivers/net/wireguard/cookie.c +@@ -26,8 +26,8 @@ void wg_cookie_checker_init(struct cooki + } + + enum { COOKIE_KEY_LABEL_LEN = 8 }; +-static const u8 mac1_key_label[COOKIE_KEY_LABEL_LEN] = "mac1----"; +-static const u8 cookie_key_label[COOKIE_KEY_LABEL_LEN] = "cookie--"; ++static const u8 mac1_key_label[COOKIE_KEY_LABEL_LEN] __nonstring = "mac1----"; ++static const u8 cookie_key_label[COOKIE_KEY_LABEL_LEN] __nonstring = "cookie--"; + + static void precompute_key(u8 key[NOISE_SYMMETRIC_KEY_LEN], + const u8 pubkey[NOISE_PUBLIC_KEY_LEN], +--- a/drivers/net/wireguard/noise.c ++++ b/drivers/net/wireguard/noise.c +@@ -25,8 +25,8 @@ + * <- e, ee, se, psk, {} + */ + +-static const u8 handshake_name[37] = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"; +-static const u8 identifier_name[34] = "WireGuard v1 zx2c4 Jason@zx2c4.com"; ++static const u8 handshake_name[37] __nonstring = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"; ++static const u8 identifier_name[34] __nonstring = "WireGuard v1 zx2c4 Jason@zx2c4.com"; + static u8 handshake_init_hash[NOISE_HASH_LEN] __ro_after_init; + static u8 handshake_init_chaining_key[NOISE_HASH_LEN] __ro_after_init; + static atomic64_t keypair_counter = ATOMIC64_INIT(0); diff --git a/lede/target/linux/generic/backport-6.12/330-v6.13-jiffies-Define-secs_to_jiffies.patch b/lede/target/linux/generic/backport-6.12/200-01-v6.13-jiffies-Define-secs_to_jiffies.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/330-v6.13-jiffies-Define-secs_to_jiffies.patch rename to lede/target/linux/generic/backport-6.12/200-01-v6.13-jiffies-Define-secs_to_jiffies.patch diff --git a/lede/target/linux/generic/backport-6.12/331-v6.14-jiffies-Cast-to-unsigned-long-in-secs_to_jiffies-con.patch b/lede/target/linux/generic/backport-6.12/200-02-v6.14-jiffies-Cast-to-unsigned-long-in-secs_to_jiffies-con.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/331-v6.14-jiffies-Cast-to-unsigned-long-in-secs_to_jiffies-con.patch rename to lede/target/linux/generic/backport-6.12/200-02-v6.14-jiffies-Cast-to-unsigned-long-in-secs_to_jiffies-con.patch diff --git a/lede/target/linux/generic/backport-6.12/200-v6.14-compiler.h-add-const_true.patch b/lede/target/linux/generic/backport-6.12/200-v6.14-compiler.h-add-const_true.patch deleted file mode 100644 index 8046f9895e..0000000000 --- a/lede/target/linux/generic/backport-6.12/200-v6.14-compiler.h-add-const_true.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 4f3d1be4c2f8a22470f3625cbc778ba2e2130def Mon Sep 17 00:00:00 2001 -From: Vincent Mailhol -Date: Thu, 14 Nov 2024 02:18:32 +0900 -Subject: [PATCH] compiler.h: add const_true() - -__builtin_constant_p() is known for not always being able to produce -constant expression [1] which led to the introduction of -__is_constexpr() [2]. Because of its dependency on -__builtin_constant_p(), statically_true() suffers from the same -issues. - -For example: - - void foo(int a) - { - /* fail on GCC */ - BUILD_BUG_ON_ZERO(statically_true(a)); - - /* fail on both clang and GCC */ - static char arr[statically_true(a) ? 1 : 2]; - } - -For the same reasons why __is_constexpr() was created to cover -__builtin_constant_p() edge cases, __is_constexpr() can be used to -resolve statically_true() limitations. - -Note that, somehow, GCC is not always able to fold this: - - __is_constexpr(x) && (x) - -It is OK in BUILD_BUG_ON_ZERO() but not in array declarations nor in -static_assert(): - - void bar(int a) - { - /* success */ - BUILD_BUG_ON_ZERO(__is_constexpr(a) && (a)); - - /* fail on GCC */ - static char arr[__is_constexpr(a) && (a) ? 1 : 2]; - - /* fail on GCC */ - static_assert(__is_constexpr(a) && (a)); - } - -Encapsulating the expression in a __builtin_choose_expr() switch -resolves all these failed tests. - -Define a new const_true() macro which, by making use of the -__builtin_choose_expr() and __is_constexpr(x) combo, always produces a -constant expression. - -It should be noted that statically_true() is the only one able to fold -tautological expressions in which at least one on the operands is not a -constant expression. For example: - - statically_true(true || var) - statically_true(var == var) - statically_true(var * 0 + 1) - statically_true(!(var * 8 % 4)) - -always evaluates to true, whereas all of these would be false under -const_true() if var is not a constant expression [3]. - -For this reason, usage of const_true() should be the exception. -Reflect in the documentation that const_true() is less powerful and -that statically_true() is the overall preferred solution. - -[1] __builtin_constant_p cannot resolve to const when optimizing -Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=19449 - -[2] commit 3c8ba0d61d04 ("kernel.h: Retain constant expression output for max()/min()") -Link: https://git.kernel.org/torvalds/c/3c8ba0d61d04 - -[3] https://godbolt.org/z/c61PMxqbK - -CC: Linus Torvalds -CC: Rasmus Villemoes -CC: Luc Van Oostenryck -Reviewed-by: Yury Norov , -Signed-off-by: Vincent Mailhol -Signed-off-by: Yury Norov ---- - include/linux/compiler.h | 22 ++++++++++++++++++++++ - 1 file changed, 22 insertions(+) - ---- a/include/linux/compiler.h -+++ b/include/linux/compiler.h -@@ -293,6 +293,28 @@ static inline void *offset_to_ptr(const - #define statically_true(x) (__builtin_constant_p(x) && (x)) - - /* -+ * Similar to statically_true() but produces a constant expression -+ * -+ * To be used in conjunction with macros, such as BUILD_BUG_ON_ZERO(), -+ * which require their input to be a constant expression and for which -+ * statically_true() would otherwise fail. -+ * -+ * This is a trade-off: const_true() requires all its operands to be -+ * compile time constants. Else, it would always returns false even on -+ * the most trivial cases like: -+ * -+ * true || non_const_var -+ * -+ * On the opposite, statically_true() is able to fold more complex -+ * tautologies and will return true on expressions such as: -+ * -+ * !(non_const_var * 8 % 4) -+ * -+ * For the general case, statically_true() is better. -+ */ -+#define const_true(x) __builtin_choose_expr(__is_constexpr(x), x, false) -+ -+/* - * This is needed in functions which generate the stack canary, see - * arch/x86/kernel/smpboot.c::start_secondary() for an example. - */ diff --git a/lede/target/linux/generic/backport-6.12/201-v6.13-of-property-add-of_graph_get_next_port.patch b/lede/target/linux/generic/backport-6.12/201-v6.13-of-property-add-of_graph_get_next_port.patch new file mode 100644 index 0000000000..5178dc83ae --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/201-v6.13-of-property-add-of_graph_get_next_port.patch @@ -0,0 +1,199 @@ +From 02ac5f9d6caec96071103f7c62b5117526e47b64 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto +Date: Thu, 24 Oct 2024 02:20:02 +0000 +Subject: [PATCH] of: property: add of_graph_get_next_port() + +We have endpoint base functions + - of_graph_get_next_endpoint() + - of_graph_get_endpoint_count() + - for_each_endpoint_of_node() + +Here, for_each_endpoint_of_node() loop finds each endpoints + + ports { + port@0 { +(1) endpoint {...}; + }; + port@1 { +(2) endpoint {...}; + }; + ... + }; + +In above case, it finds endpoint as (1) -> (2) -> ... + +Basically, user/driver knows which port is used for what, but not in +all cases. For example on flexible/generic driver case, how many ports +are used is not fixed. + +For example Sound Generic Card driver which is very flexible/generic and +used from many venders can't know how many ports are used, and used for +what, because it depends on each vender SoC and/or its used board. + +And more, the port can have multi endpoints. For example Generic Sound +Card case, it supports many type of connection between CPU / Codec, and +some of them uses multi endpoint in one port. see below. + + ports { +(A) port@0 { +(1) endpoint@0 {...}; +(2) endpoint@1 {...}; + }; +(B) port@1 { +(3) endpoint {...}; + }; + ... + }; + +Generic Sound Card want to handle each connection via "port" base instead +of "endpoint" base. But, it is very difficult to handle each "port" via +existing for_each_endpoint_of_node(). Because getting each "port" via +of_get_parent() from each "endpoint" doesn't work. For example in above +case, both (1) (2) endpoint has same "port" (= A). + +Add "port" base functions. + +Signed-off-by: Kuninori Morimoto +Link: https://lore.kernel.org/r/87ldyeb5t9.wl-kuninori.morimoto.gx@renesas.com +Signed-off-by: Rob Herring (Arm) +--- + drivers/of/property.c | 54 ++++++++++++++++++++++++++++++++++++++++ + include/linux/of_graph.h | 28 +++++++++++++++++++++ + 2 files changed, 82 insertions(+) + +--- a/drivers/of/property.c ++++ b/drivers/of/property.c +@@ -631,6 +631,43 @@ struct device_node *of_graph_get_port_by + EXPORT_SYMBOL(of_graph_get_port_by_id); + + /** ++ * of_graph_get_next_port() - get next port node. ++ * @parent: pointer to the parent device node, or parent ports node ++ * @prev: previous port node, or NULL to get first ++ * ++ * Parent device node can be used as @parent whether device node has ports node ++ * or not. It will work same as ports@0 node. ++ * ++ * Return: A 'port' node pointer with refcount incremented. Refcount ++ * of the passed @prev node is decremented. ++ */ ++struct device_node *of_graph_get_next_port(const struct device_node *parent, ++ struct device_node *prev) ++{ ++ if (!parent) ++ return NULL; ++ ++ if (!prev) { ++ struct device_node *node __free(device_node) = ++ of_get_child_by_name(parent, "ports"); ++ ++ if (node) ++ parent = node; ++ ++ return of_get_child_by_name(parent, "port"); ++ } ++ ++ do { ++ prev = of_get_next_child(parent, prev); ++ if (!prev) ++ break; ++ } while (!of_node_name_eq(prev, "port")); ++ ++ return prev; ++} ++EXPORT_SYMBOL(of_graph_get_next_port); ++ ++/** + * of_graph_get_next_endpoint() - get next endpoint node + * @parent: pointer to the parent device node + * @prev: previous endpoint node, or NULL to get first +@@ -824,6 +861,23 @@ unsigned int of_graph_get_endpoint_count + EXPORT_SYMBOL(of_graph_get_endpoint_count); + + /** ++ * of_graph_get_port_count() - get the number of port in a device or ports node ++ * @np: pointer to the device or ports node ++ * ++ * Return: count of port of this device or ports node ++ */ ++unsigned int of_graph_get_port_count(struct device_node *np) ++{ ++ unsigned int num = 0; ++ ++ for_each_of_graph_port(np, port) ++ num++; ++ ++ return num; ++} ++EXPORT_SYMBOL(of_graph_get_port_count); ++ ++/** + * of_graph_get_remote_node() - get remote parent device_node for given port/endpoint + * @node: pointer to parent device_node containing graph port/endpoint + * @port: identifier (value of reg property) of the parent port node +--- a/include/linux/of_graph.h ++++ b/include/linux/of_graph.h +@@ -11,6 +11,7 @@ + #ifndef __LINUX_OF_GRAPH_H + #define __LINUX_OF_GRAPH_H + ++#include + #include + #include + +@@ -37,14 +38,29 @@ struct of_endpoint { + for (child = of_graph_get_next_endpoint(parent, NULL); child != NULL; \ + child = of_graph_get_next_endpoint(parent, child)) + ++/** ++ * for_each_of_graph_port - iterate over every port in a device or ports node ++ * @parent: parent device or ports node containing port ++ * @child: loop variable pointing to the current port node ++ * ++ * When breaking out of the loop, and continue to use the @child, you need to ++ * use return_ptr(@child) or no_free_ptr(@child) not to call __free() for it. ++ */ ++#define for_each_of_graph_port(parent, child) \ ++ for (struct device_node *child __free(device_node) = of_graph_get_next_port(parent, NULL);\ ++ child != NULL; child = of_graph_get_next_port(parent, child)) ++ + #ifdef CONFIG_OF + bool of_graph_is_present(const struct device_node *node); + int of_graph_parse_endpoint(const struct device_node *node, + struct of_endpoint *endpoint); + unsigned int of_graph_get_endpoint_count(const struct device_node *np); ++unsigned int of_graph_get_port_count(struct device_node *np); + struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id); + struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, + struct device_node *previous); ++struct device_node *of_graph_get_next_port(const struct device_node *parent, ++ struct device_node *port); + struct device_node *of_graph_get_endpoint_by_regs( + const struct device_node *parent, int port_reg, int reg); + struct device_node *of_graph_get_remote_endpoint( +@@ -73,6 +89,11 @@ static inline unsigned int of_graph_get_ + return 0; + } + ++static inline unsigned int of_graph_get_port_count(struct device_node *np) ++{ ++ return 0; ++} ++ + static inline struct device_node *of_graph_get_port_by_id( + struct device_node *node, u32 id) + { +@@ -83,6 +104,13 @@ static inline struct device_node *of_gra + const struct device_node *parent, + struct device_node *previous) + { ++ return NULL; ++} ++ ++static inline struct device_node *of_graph_get_next_port( ++ const struct device_node *parent, ++ struct device_node *previous) ++{ + return NULL; + } + diff --git a/lede/target/linux/generic/backport-6.12/201-v6.16-bitfield-Add-FIELD_MODIFY-helper.patch b/lede/target/linux/generic/backport-6.12/201-v6.16-bitfield-Add-FIELD_MODIFY-helper.patch deleted file mode 100644 index a0a7138a61..0000000000 --- a/lede/target/linux/generic/backport-6.12/201-v6.16-bitfield-Add-FIELD_MODIFY-helper.patch +++ /dev/null @@ -1,70 +0,0 @@ -From a256ae22570ee4c3427fdc703a58a89afee6a332 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Thu, 17 Apr 2025 18:47:08 +0800 -Subject: [PATCH] bitfield: Add FIELD_MODIFY() helper - -Add a helper for replacing the contents of bitfield in memory -with the specified value. - -Even though a helper xxx_replace_bits() is available, it is not -well documented, and only reports errors at the run time, which -will not be helpful to catch possible overflow errors due to -incorrect parameter types used. - -FIELD_MODIFY(REG_FIELD_C, ®, c) is the wrapper to the code below. - - reg &= ~REG_FIELD_C; - reg |= FIELD_PREP(REG_FIELD_C, c); - -Yury: trim commit message, align backslashes. - -Signed-off-by: Luo Jie -Signed-off-by: Yury Norov ---- - include/linux/bitfield.h | 21 +++++++++++++++++++-- - 1 file changed, 19 insertions(+), 2 deletions(-) - ---- a/include/linux/bitfield.h -+++ b/include/linux/bitfield.h -@@ -8,6 +8,7 @@ - #define _LINUX_BITFIELD_H - - #include -+#include - #include - - /* -@@ -38,8 +39,7 @@ - * FIELD_PREP(REG_FIELD_D, 0x40); - * - * Modify: -- * reg &= ~REG_FIELD_C; -- * reg |= FIELD_PREP(REG_FIELD_C, c); -+ * FIELD_MODIFY(REG_FIELD_C, ®, c); - */ - - #define __bf_shf(x) (__builtin_ffsll(x) - 1) -@@ -156,6 +156,23 @@ - (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \ - }) - -+/** -+ * FIELD_MODIFY() - modify a bitfield element -+ * @_mask: shifted mask defining the field's length and position -+ * @_reg_p: pointer to the memory that should be updated -+ * @_val: value to store in the bitfield -+ * -+ * FIELD_MODIFY() modifies the set of bits in @_reg_p specified by @_mask, -+ * by replacing them with the bitfield value passed in as @_val. -+ */ -+#define FIELD_MODIFY(_mask, _reg_p, _val) \ -+ ({ \ -+ typecheck_pointer(_reg_p); \ -+ __BF_FIELD_CHECK(_mask, *(_reg_p), _val, "FIELD_MODIFY: "); \ -+ *(_reg_p) &= ~(_mask); \ -+ *(_reg_p) |= (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)); \ -+ }) -+ - extern void __compiletime_error("value doesn't fit into mask") - __field_overflow(void); - extern void __compiletime_error("bad bitfield mask") diff --git a/lede/target/linux/generic/backport-6.12/203-01-v6.13-of-address-Rework-bus-matching-to-avoid-warnings.patch b/lede/target/linux/generic/backport-6.12/203-01-v6.13-of-address-Rework-bus-matching-to-avoid-warnings.patch new file mode 100644 index 0000000000..d7a6751861 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/203-01-v6.13-of-address-Rework-bus-matching-to-avoid-warnings.patch @@ -0,0 +1,61 @@ +From 64ee3cf096ac590e7da2ceac1c390546bff5e240 Mon Sep 17 00:00:00 2001 +From: "Rob Herring (Arm)" +Date: Fri, 8 Nov 2024 13:35:48 -0600 +Subject: [PATCH] of/address: Rework bus matching to avoid warnings + +With warnings added for deprecated #address-cells/#size-cells handling, +the DT address handling code causes warnings when used on nodes with no +address. This happens frequently with calls to of_platform_populate() as +it is perfectly acceptable to have devices without a 'reg' property. The +desired behavior is to just silently return an error when retrieving an +address. + +The warnings can be avoided by checking for "#address-cells" presence +first and checking for an address property before fetching +"#address-cells" and "#size-cells". + +Reported-by: Marek Szyprowski +Reported-by: Steven Price +Tested-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20241108193547.2647986-2-robh@kernel.org +Signed-off-by: Rob Herring (Arm) +--- + drivers/of/address.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +--- a/drivers/of/address.c ++++ b/drivers/of/address.c +@@ -331,7 +331,11 @@ static unsigned int of_bus_isa_get_flags + + static int of_bus_default_flags_match(struct device_node *np) + { +- return of_bus_n_addr_cells(np) == 3; ++ /* ++ * Check for presence first since of_bus_n_addr_cells() will warn when ++ * walking parent nodes. ++ */ ++ return of_property_present(np, "#address-cells") && (of_bus_n_addr_cells(np) == 3); + } + + /* +@@ -700,16 +704,16 @@ const __be32 *__of_get_address(struct de + if (strcmp(bus->name, "pci") && (bar_no >= 0)) + return NULL; + +- bus->count_cells(dev, &na, &ns); +- if (!OF_CHECK_ADDR_COUNT(na)) +- return NULL; +- + /* Get "reg" or "assigned-addresses" property */ + prop = of_get_property(dev, bus->addresses, &psize); + if (prop == NULL) + return NULL; + psize /= 4; + ++ bus->count_cells(dev, &na, &ns); ++ if (!OF_CHECK_ADDR_COUNT(na)) ++ return NULL; ++ + onesize = na + ns; + for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) { + u32 val = be32_to_cpu(prop[0]); diff --git a/lede/target/linux/generic/backport-6.12/203-02-v6.13-of-address-Fix-WARN-when-attempting-translating-non-.patch b/lede/target/linux/generic/backport-6.12/203-02-v6.13-of-address-Fix-WARN-when-attempting-translating-non-.patch new file mode 100644 index 0000000000..2ad67cbde7 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/203-02-v6.13-of-address-Fix-WARN-when-attempting-translating-non-.patch @@ -0,0 +1,85 @@ +From 6e5773d52f4a2d9c80692245f295069260cff6fc Mon Sep 17 00:00:00 2001 +From: "Rob Herring (Arm)" +Date: Fri, 10 Jan 2025 15:50:29 -0600 +Subject: [PATCH] of/address: Fix WARN when attempting translating + non-translatable addresses + +The recently added WARN() for deprecated #address-cells and #size-cells +triggered a WARN when of_platform_populate() (which calls +of_address_to_resource()) is used on nodes with non-translatable +addresses. This case is expected to return an error. + +Rework the bus matching to allow no match and make the default require +an #address-cells property. That should be safe to do as any platform +missing #address-cells would have a warning already. + +Fixes: 045b14ca5c36 ("of: WARN on deprecated #address-cells/#size-cells handling") +Tested-by: Sean Anderson +Link: https://lore.kernel.org/r/20250110215030.3637845-2-robh@kernel.org +Signed-off-by: Rob Herring (Arm) +--- + drivers/of/address.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +--- a/drivers/of/address.c ++++ b/drivers/of/address.c +@@ -338,6 +338,15 @@ static int of_bus_default_flags_match(st + return of_property_present(np, "#address-cells") && (of_bus_n_addr_cells(np) == 3); + } + ++static int of_bus_default_match(struct device_node *np) ++{ ++ /* ++ * Check for presence first since of_bus_n_addr_cells() will warn when ++ * walking parent nodes. ++ */ ++ return of_property_present(np, "#address-cells"); ++} ++ + /* + * Array of bus specific translators + */ +@@ -382,7 +391,7 @@ static struct of_bus of_busses[] = { + { + .name = "default", + .addresses = "reg", +- .match = NULL, ++ .match = of_bus_default_match, + .count_cells = of_bus_default_count_cells, + .map = of_bus_default_map, + .translate = of_bus_default_translate, +@@ -397,7 +406,6 @@ static struct of_bus *of_match_bus(struc + for (i = 0; i < ARRAY_SIZE(of_busses); i++) + if (!of_busses[i].match || of_busses[i].match(np)) + return &of_busses[i]; +- BUG(); + return NULL; + } + +@@ -519,6 +527,8 @@ static u64 __of_translate_address(struct + if (parent == NULL) + return OF_BAD_ADDR; + bus = of_match_bus(parent); ++ if (!bus) ++ return OF_BAD_ADDR; + + /* Count address cells & copy address locally */ + bus->count_cells(dev, &na, &ns); +@@ -562,6 +572,8 @@ static u64 __of_translate_address(struct + + /* Get new parent bus and counts */ + pbus = of_match_bus(parent); ++ if (!pbus) ++ return OF_BAD_ADDR; + pbus->count_cells(dev, &pna, &pns); + if (!OF_CHECK_COUNTS(pna, pns)) { + pr_err("Bad cell count for %pOF\n", dev); +@@ -701,7 +713,7 @@ const __be32 *__of_get_address(struct de + + /* match the parent's bus type */ + bus = of_match_bus(parent); +- if (strcmp(bus->name, "pci") && (bar_no >= 0)) ++ if (!bus || (strcmp(bus->name, "pci") && (bar_no >= 0))) + return NULL; + + /* Get "reg" or "assigned-addresses" property */ diff --git a/lede/target/linux/generic/backport-6.12/203-v6.15-drivers-base-component-add-function-to-query-the-bound.patch b/lede/target/linux/generic/backport-6.12/203-v6.15-drivers-base-component-add-function-to-query-the-bound.patch deleted file mode 100644 index 201bd229aa..0000000000 --- a/lede/target/linux/generic/backport-6.12/203-v6.15-drivers-base-component-add-function-to-query-the-bound.patch +++ /dev/null @@ -1,69 +0,0 @@ -From a6ba2dad0aa4f623ab0def8b6e6888ac00639055 Mon Sep 17 00:00:00 2001 -From: Heiko Stuebner -Date: Fri, 21 Feb 2025 00:41:40 +0100 -Subject: [PATCH] drivers: base: component: add function to query the bound - status - -The component helpers already expose the bound status in debugfs, but at -times it might be necessary to also check that state in the kernel and -act differently depending on the result. - -For example the shutdown handler of a drm-driver might need to stop -a whole output pipeline if the drm device is up and running, but may -run into problems if that drm-device has never been set up before, -for example because the binding deferred. - -So add a little helper that returns the bound status for a componet -device. - -Acked-by: Greg Kroah-Hartman -Signed-off-by: Heiko Stuebner -Link: https://patchwork.freedesktop.org/patch/msgid/20250220234141.2788785-2-heiko@sntech.de ---- - drivers/base/component.c | 14 ++++++++++++++ - include/linux/component.h | 4 +++- - 2 files changed, 17 insertions(+), 1 deletion(-) - ---- a/drivers/base/component.c -+++ b/drivers/base/component.c -@@ -569,6 +569,20 @@ void component_master_del(struct device - } - EXPORT_SYMBOL_GPL(component_master_del); - -+bool component_master_is_bound(struct device *parent, -+ const struct component_master_ops *ops) -+{ -+ struct aggregate_device *adev; -+ -+ guard(mutex)(&component_mutex); -+ adev = __aggregate_find(parent, ops); -+ if (!adev) -+ return 0; -+ -+ return adev->bound; -+} -+EXPORT_SYMBOL_GPL(component_master_is_bound); -+ - static void component_unbind(struct component *component, - struct aggregate_device *adev, void *data) - { ---- a/include/linux/component.h -+++ b/include/linux/component.h -@@ -3,7 +3,7 @@ - #define COMPONENT_H - - #include -- -+#include - - struct device; - -@@ -90,6 +90,8 @@ int component_compare_dev_name(struct de - - void component_master_del(struct device *, - const struct component_master_ops *); -+bool component_master_is_bound(struct device *parent, -+ const struct component_master_ops *ops); - - struct component_match; - diff --git a/lede/target/linux/generic/backport-6.12/205-v6.16-of-reserved_mem-Add-functions-to-parse-memory-region.patch b/lede/target/linux/generic/backport-6.12/205-v6.16-of-reserved_mem-Add-functions-to-parse-memory-region.patch new file mode 100644 index 0000000000..b5bbb6e723 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/205-v6.16-of-reserved_mem-Add-functions-to-parse-memory-region.patch @@ -0,0 +1,163 @@ +From f4fcfdda2fd8834c62dcb9bfddcf1f89d190b70e Mon Sep 17 00:00:00 2001 +From: "Rob Herring (Arm)" +Date: Wed, 23 Apr 2025 14:42:13 -0500 +Subject: [PATCH] of: reserved_mem: Add functions to parse "memory-region" + +Drivers with "memory-region" properties currently have to do their own +parsing of "memory-region" properties. The result is all the drivers +have similar patterns of a call to parse "memory-region" and then get +the region's address and size. As this is a standard property, it should +have common functions for drivers to use. Add new functions to count the +number of regions and retrieve the region's address as a resource. + +Reviewed-by: Daniel Baluta +Acked-by: Arnaud Pouliquen +Link: https://lore.kernel.org/r/20250423-dt-memory-region-v2-v2-1-2fbd6ebd3c88@kernel.org +Signed-off-by: Rob Herring (Arm) +--- + drivers/of/of_reserved_mem.c | 80 +++++++++++++++++++++++++++++++++ + include/linux/of_reserved_mem.h | 26 +++++++++++ + 2 files changed, 106 insertions(+) + +--- a/drivers/of/of_reserved_mem.c ++++ b/drivers/of/of_reserved_mem.c +@@ -12,6 +12,7 @@ + #define pr_fmt(fmt) "OF: reserved mem: " fmt + + #include ++#include + #include + #include + #include +@@ -694,3 +695,82 @@ struct reserved_mem *of_reserved_mem_loo + return NULL; + } + EXPORT_SYMBOL_GPL(of_reserved_mem_lookup); ++ ++/** ++ * of_reserved_mem_region_to_resource() - Get a reserved memory region as a resource ++ * @np: node containing 'memory-region' property ++ * @idx: index of 'memory-region' property to lookup ++ * @res: Pointer to a struct resource to fill in with reserved region ++ * ++ * This function allows drivers to lookup a node's 'memory-region' property ++ * entries by index and return a struct resource for the entry. ++ * ++ * Returns 0 on success with @res filled in. Returns -ENODEV if 'memory-region' ++ * is missing or unavailable, -EINVAL for any other error. ++ */ ++int of_reserved_mem_region_to_resource(const struct device_node *np, ++ unsigned int idx, struct resource *res) ++{ ++ struct reserved_mem *rmem; ++ ++ if (!np) ++ return -EINVAL; ++ ++ struct device_node __free(device_node) *target = of_parse_phandle(np, "memory-region", idx); ++ if (!target || !of_device_is_available(target)) ++ return -ENODEV; ++ ++ rmem = of_reserved_mem_lookup(target); ++ if (!rmem) ++ return -EINVAL; ++ ++ resource_set_range(res, rmem->base, rmem->size); ++ res->name = rmem->name; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(of_reserved_mem_region_to_resource); ++ ++/** ++ * of_reserved_mem_region_to_resource_byname() - Get a reserved memory region as a resource ++ * @np: node containing 'memory-region' property ++ * @name: name of 'memory-region' property entry to lookup ++ * @res: Pointer to a struct resource to fill in with reserved region ++ * ++ * This function allows drivers to lookup a node's 'memory-region' property ++ * entries by name and return a struct resource for the entry. ++ * ++ * Returns 0 on success with @res filled in, or a negative error-code on ++ * failure. ++ */ ++int of_reserved_mem_region_to_resource_byname(const struct device_node *np, ++ const char *name, ++ struct resource *res) ++{ ++ int idx; ++ ++ if (!name) ++ return -EINVAL; ++ ++ idx = of_property_match_string(np, "memory-region-names", name); ++ if (idx < 0) ++ return idx; ++ ++ return of_reserved_mem_region_to_resource(np, idx, res); ++} ++EXPORT_SYMBOL_GPL(of_reserved_mem_region_to_resource_byname); ++ ++/** ++ * of_reserved_mem_region_count() - Return the number of 'memory-region' entries ++ * @np: node containing 'memory-region' property ++ * ++ * This function allows drivers to retrieve the number of entries for a node's ++ * 'memory-region' property. ++ * ++ * Returns the number of entries on success, or negative error code on a ++ * malformed property. ++ */ ++int of_reserved_mem_region_count(const struct device_node *np) ++{ ++ return of_count_phandle_with_args(np, "memory-region", NULL); ++} ++EXPORT_SYMBOL_GPL(of_reserved_mem_region_count); +--- a/include/linux/of_reserved_mem.h ++++ b/include/linux/of_reserved_mem.h +@@ -7,6 +7,7 @@ + + struct of_phandle_args; + struct reserved_mem_ops; ++struct resource; + + struct reserved_mem { + const char *name; +@@ -39,6 +40,12 @@ int of_reserved_mem_device_init_by_name( + void of_reserved_mem_device_release(struct device *dev); + + struct reserved_mem *of_reserved_mem_lookup(struct device_node *np); ++int of_reserved_mem_region_to_resource(const struct device_node *np, ++ unsigned int idx, struct resource *res); ++int of_reserved_mem_region_to_resource_byname(const struct device_node *np, ++ const char *name, struct resource *res); ++int of_reserved_mem_region_count(const struct device_node *np); ++ + #else + + #define RESERVEDMEM_OF_DECLARE(name, compat, init) \ +@@ -63,6 +70,25 @@ static inline struct reserved_mem *of_re + { + return NULL; + } ++ ++static inline int of_reserved_mem_region_to_resource(const struct device_node *np, ++ unsigned int idx, ++ struct resource *res) ++{ ++ return -ENOSYS; ++} ++ ++static inline int of_reserved_mem_region_to_resource_byname(const struct device_node *np, ++ const char *name, ++ struct resource *res) ++{ ++ return -ENOSYS; ++} ++ ++static inline int of_reserved_mem_region_count(const struct device_node *np) ++{ ++ return 0; ++} + #endif + + /** diff --git a/lede/target/linux/generic/backport-6.12/902-v6.13-fortify-Hide-run-time-copy-size-from-value-range-tracking.patch b/lede/target/linux/generic/backport-6.12/210-v6.13-fortify-Hide-run-time-copy-size-from-value-range-tracking.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/902-v6.13-fortify-Hide-run-time-copy-size-from-value-range-tracking.patch rename to lede/target/linux/generic/backport-6.12/210-v6.13-fortify-Hide-run-time-copy-size-from-value-range-tracking.patch diff --git a/lede/target/linux/generic/backport-6.12/212-v6.17-of-reserved_mem-Add-missing-IORESOURCE_MEM-flag-on-r.patch b/lede/target/linux/generic/backport-6.12/212-v6.17-of-reserved_mem-Add-missing-IORESOURCE_MEM-flag-on-r.patch new file mode 100644 index 0000000000..1f2d52af9a --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/212-v6.17-of-reserved_mem-Add-missing-IORESOURCE_MEM-flag-on-r.patch @@ -0,0 +1,32 @@ +From aea70964b5a7ca491a3701f2dde6c9d05d51878d Mon Sep 17 00:00:00 2001 +From: "Rob Herring (Arm)" +Date: Wed, 20 Aug 2025 14:28:04 -0500 +Subject: of: reserved_mem: Add missing IORESOURCE_MEM flag on resources + +Commit f4fcfdda2fd8 ('of: reserved_mem: Add functions to parse +"memory-region"') failed to set IORESOURCE_MEM flag on the resources. +The result is functions such as devm_ioremap_resource_wc() will fail. +Add the missing flag. + +Fixes: f4fcfdda2fd8 ('of: reserved_mem: Add functions to parse "memory-region"') +Reported-by: Iuliana Prodan +Reported-by: Daniel Baluta +Tested-by: Iuliana Prodan +Reviewed-by: Iuliana Prodan +Reviewed-by: Saravana Kannan +Link: https://lore.kernel.org/r/20250820192805.565568-1-robh@kernel.org +Signed-off-by: Rob Herring (Arm) +--- + drivers/of/of_reserved_mem.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/of/of_reserved_mem.c ++++ b/drivers/of/of_reserved_mem.c +@@ -725,6 +725,7 @@ int of_reserved_mem_region_to_resource(c + return -EINVAL; + + resource_set_range(res, rmem->base, rmem->size); ++ res->flags = IORESOURCE_MEM; + res->name = rmem->name; + return 0; + } diff --git a/lede/target/linux/generic/backport-6.12/412-v6.14-mtd-spinand-add-support-for-FORESEE-F35SQA001G.patch b/lede/target/linux/generic/backport-6.12/400-v6.14-mtd-spinand-add-support-for-FORESEE-F35SQA001G.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/412-v6.14-mtd-spinand-add-support-for-FORESEE-F35SQA001G.patch rename to lede/target/linux/generic/backport-6.12/400-v6.14-mtd-spinand-add-support-for-FORESEE-F35SQA001G.patch diff --git a/lede/target/linux/generic/backport-6.12/401-v6.17-mtd-spinand-add-support-for-FudanMicro-FM25S01A.patch b/lede/target/linux/generic/backport-6.12/401-v6.17-mtd-spinand-add-support-for-FudanMicro-FM25S01A.patch new file mode 100644 index 0000000000..a27933ca7a --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/401-v6.17-mtd-spinand-add-support-for-FudanMicro-FM25S01A.patch @@ -0,0 +1,124 @@ +From 5f284dc15ca8695d0394414045ac64616a3b0e69 Mon Sep 17 00:00:00 2001 +From: Tianling Shen +Date: Mon, 25 Aug 2025 01:00:13 +0800 +Subject: [PATCH] mtd: spinand: add support for FudanMicro FM25S01A + +Add support for FudanMicro FM25S01A SPI NAND. +Datasheet: http://eng.fmsh.com/nvm/FM25S01A_ds_eng.pdf + +Signed-off-by: Tianling Shen +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20250824170013.3328777-1-cnsztl@gmail.com +--- + drivers/mtd/nand/spi/Makefile | 2 +- + drivers/mtd/nand/spi/core.c | 1 + + drivers/mtd/nand/spi/fmsh.c | 74 +++++++++++++++++++++++++++++++++++ + include/linux/mtd/spinand.h | 1 + + 4 files changed, 77 insertions(+), 1 deletion(-) + create mode 100644 drivers/mtd/nand/spi/fmsh.c + +--- a/drivers/mtd/nand/spi/Makefile ++++ b/drivers/mtd/nand/spi/Makefile +@@ -1,4 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 +-spinand-objs := core.o alliancememory.o ato.o esmt.o foresee.o gigadevice.o macronix.o ++spinand-objs := core.o alliancememory.o ato.o esmt.o fmsh.o foresee.o gigadevice.o macronix.o + spinand-objs += micron.o paragon.o toshiba.o winbond.o xtx.o + obj-$(CONFIG_MTD_SPI_NAND) += spinand.o +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -1115,6 +1115,7 @@ static const struct spinand_manufacturer + &alliancememory_spinand_manufacturer, + &ato_spinand_manufacturer, + &esmt_c8_spinand_manufacturer, ++ &fmsh_spinand_manufacturer, + &foresee_spinand_manufacturer, + &gigadevice_spinand_manufacturer, + ¯onix_spinand_manufacturer, +--- /dev/null ++++ b/drivers/mtd/nand/spi/fmsh.c +@@ -0,0 +1,74 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd. ++ * ++ * Author: Dingqiang Lin ++ */ ++ ++#include ++#include ++#include ++ ++#define SPINAND_MFR_FMSH 0xA1 ++ ++static SPINAND_OP_VARIANTS(read_cache_variants, ++ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(write_cache_variants, ++ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), ++ SPINAND_PROG_LOAD(true, 0, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(update_cache_variants, ++ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), ++ SPINAND_PROG_LOAD(false, 0, NULL, 0)); ++ ++static int fm25s01a_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ return -ERANGE; ++} ++ ++static int fm25s01a_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section) ++ return -ERANGE; ++ ++ region->offset = 2; ++ region->length = 62; ++ ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops fm25s01a_ooblayout = { ++ .ecc = fm25s01a_ooblayout_ecc, ++ .free = fm25s01a_ooblayout_free, ++}; ++ ++static const struct spinand_info fmsh_spinand_table[] = { ++ SPINAND_INFO("FM25S01A", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4), ++ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), ++ NAND_ECCREQ(1, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&fm25s01a_ooblayout, NULL)), ++}; ++ ++static const struct spinand_manufacturer_ops fmsh_spinand_manuf_ops = { ++}; ++ ++const struct spinand_manufacturer fmsh_spinand_manufacturer = { ++ .id = SPINAND_MFR_FMSH, ++ .name = "Fudan Micro", ++ .chips = fmsh_spinand_table, ++ .nchips = ARRAY_SIZE(fmsh_spinand_table), ++ .ops = &fmsh_spinand_manuf_ops, ++}; +--- a/include/linux/mtd/spinand.h ++++ b/include/linux/mtd/spinand.h +@@ -263,6 +263,7 @@ struct spinand_manufacturer { + extern const struct spinand_manufacturer alliancememory_spinand_manufacturer; + extern const struct spinand_manufacturer ato_spinand_manufacturer; + extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; ++extern const struct spinand_manufacturer fmsh_spinand_manufacturer; + extern const struct spinand_manufacturer foresee_spinand_manufacturer; + extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; + extern const struct spinand_manufacturer macronix_spinand_manufacturer; diff --git a/lede/target/linux/generic/backport-6.12/402-v6.18-mtd-nand-move-chunk-to-core.patch b/lede/target/linux/generic/backport-6.12/402-v6.18-mtd-nand-move-chunk-to-core.patch new file mode 100644 index 0000000000..7933874d01 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/402-v6.18-mtd-nand-move-chunk-to-core.patch @@ -0,0 +1,329 @@ +From 6b88293aae7fb78872e5cc1ec36e2f750ae12e38 Mon Sep 17 00:00:00 2001 +From: Markus Stockhausen +Date: Wed, 10 Sep 2025 14:32:58 -0400 +Subject: mtd: nand: move nand_check_erased_ecc_chunk() to nand/core + +The check function for bitflips in erased blocks will be needed +by the Realtek ECC engine driver (which is currently under +development). Right now it is located in raw/nand_base.c. +While this is sufficient for the current usecases, there is +no real dependency for an ECC engine on the raw nand library. + +Move the function over to a more generic place in core library. + +Suggested-by: Miquel Raynal +Signed-off-by: Markus Stockhausen +Signed-off-by: Miquel Raynal +--- + drivers/mtd/nand/core.c | 131 +++++++++++++++++++++++++++++++++++++++ + drivers/mtd/nand/raw/nand_base.c | 131 --------------------------------------- + include/linux/mtd/nand.h | 5 ++ + include/linux/mtd/rawnand.h | 5 -- + 4 files changed, 136 insertions(+), 136 deletions(-) + +--- a/drivers/mtd/nand/core.c ++++ b/drivers/mtd/nand/core.c +@@ -13,6 +13,137 @@ + #include + + /** ++ * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data ++ * @buf: buffer to test ++ * @len: buffer length ++ * @bitflips_threshold: maximum number of bitflips ++ * ++ * Check if a buffer contains only 0xff, which means the underlying region ++ * has been erased and is ready to be programmed. ++ * The bitflips_threshold specify the maximum number of bitflips before ++ * considering the region is not erased. ++ * Note: The logic of this function has been extracted from the memweight ++ * implementation, except that nand_check_erased_buf function exit before ++ * testing the whole buffer if the number of bitflips exceed the ++ * bitflips_threshold value. ++ * ++ * Returns a positive number of bitflips less than or equal to ++ * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the ++ * threshold. ++ */ ++static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold) ++{ ++ const unsigned char *bitmap = buf; ++ int bitflips = 0; ++ int weight; ++ ++ for (; len && ((uintptr_t)bitmap) % sizeof(long); ++ len--, bitmap++) { ++ weight = hweight8(*bitmap); ++ bitflips += BITS_PER_BYTE - weight; ++ if (unlikely(bitflips > bitflips_threshold)) ++ return -EBADMSG; ++ } ++ ++ for (; len >= sizeof(long); ++ len -= sizeof(long), bitmap += sizeof(long)) { ++ unsigned long d = *((unsigned long *)bitmap); ++ if (d == ~0UL) ++ continue; ++ weight = hweight_long(d); ++ bitflips += BITS_PER_LONG - weight; ++ if (unlikely(bitflips > bitflips_threshold)) ++ return -EBADMSG; ++ } ++ ++ for (; len > 0; len--, bitmap++) { ++ weight = hweight8(*bitmap); ++ bitflips += BITS_PER_BYTE - weight; ++ if (unlikely(bitflips > bitflips_threshold)) ++ return -EBADMSG; ++ } ++ ++ return bitflips; ++} ++ ++/** ++ * nand_check_erased_ecc_chunk - check if an ECC chunk contains (almost) only ++ * 0xff data ++ * @data: data buffer to test ++ * @datalen: data length ++ * @ecc: ECC buffer ++ * @ecclen: ECC length ++ * @extraoob: extra OOB buffer ++ * @extraooblen: extra OOB length ++ * @bitflips_threshold: maximum number of bitflips ++ * ++ * Check if a data buffer and its associated ECC and OOB data contains only ++ * 0xff pattern, which means the underlying region has been erased and is ++ * ready to be programmed. ++ * The bitflips_threshold specify the maximum number of bitflips before ++ * considering the region as not erased. ++ * ++ * Note: ++ * 1/ ECC algorithms are working on pre-defined block sizes which are usually ++ * different from the NAND page size. When fixing bitflips, ECC engines will ++ * report the number of errors per chunk, and the NAND core infrastructure ++ * expect you to return the maximum number of bitflips for the whole page. ++ * This is why you should always use this function on a single chunk and ++ * not on the whole page. After checking each chunk you should update your ++ * max_bitflips value accordingly. ++ * 2/ When checking for bitflips in erased pages you should not only check ++ * the payload data but also their associated ECC data, because a user might ++ * have programmed almost all bits to 1 but a few. In this case, we ++ * shouldn't consider the chunk as erased, and checking ECC bytes prevent ++ * this case. ++ * 3/ The extraoob argument is optional, and should be used if some of your OOB ++ * data are protected by the ECC engine. ++ * It could also be used if you support subpages and want to attach some ++ * extra OOB data to an ECC chunk. ++ * ++ * Returns a positive number of bitflips less than or equal to ++ * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the ++ * threshold. In case of success, the passed buffers are filled with 0xff. ++ */ ++int nand_check_erased_ecc_chunk(void *data, int datalen, ++ void *ecc, int ecclen, ++ void *extraoob, int extraooblen, ++ int bitflips_threshold) ++{ ++ int data_bitflips = 0, ecc_bitflips = 0, extraoob_bitflips = 0; ++ ++ data_bitflips = nand_check_erased_buf(data, datalen, ++ bitflips_threshold); ++ if (data_bitflips < 0) ++ return data_bitflips; ++ ++ bitflips_threshold -= data_bitflips; ++ ++ ecc_bitflips = nand_check_erased_buf(ecc, ecclen, bitflips_threshold); ++ if (ecc_bitflips < 0) ++ return ecc_bitflips; ++ ++ bitflips_threshold -= ecc_bitflips; ++ ++ extraoob_bitflips = nand_check_erased_buf(extraoob, extraooblen, ++ bitflips_threshold); ++ if (extraoob_bitflips < 0) ++ return extraoob_bitflips; ++ ++ if (data_bitflips) ++ memset(data, 0xff, datalen); ++ ++ if (ecc_bitflips) ++ memset(ecc, 0xff, ecclen); ++ ++ if (extraoob_bitflips) ++ memset(extraoob, 0xff, extraooblen); ++ ++ return data_bitflips + ecc_bitflips + extraoob_bitflips; ++} ++EXPORT_SYMBOL(nand_check_erased_ecc_chunk); ++ ++/** + * nanddev_isbad() - Check if a block is bad + * @nand: NAND device + * @pos: position pointing to the block we want to check +--- a/drivers/mtd/nand/raw/nand_base.c ++++ b/drivers/mtd/nand/raw/nand_base.c +@@ -2784,137 +2784,6 @@ int nand_set_features(struct nand_chip * + } + + /** +- * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data +- * @buf: buffer to test +- * @len: buffer length +- * @bitflips_threshold: maximum number of bitflips +- * +- * Check if a buffer contains only 0xff, which means the underlying region +- * has been erased and is ready to be programmed. +- * The bitflips_threshold specify the maximum number of bitflips before +- * considering the region is not erased. +- * Note: The logic of this function has been extracted from the memweight +- * implementation, except that nand_check_erased_buf function exit before +- * testing the whole buffer if the number of bitflips exceed the +- * bitflips_threshold value. +- * +- * Returns a positive number of bitflips less than or equal to +- * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the +- * threshold. +- */ +-static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold) +-{ +- const unsigned char *bitmap = buf; +- int bitflips = 0; +- int weight; +- +- for (; len && ((uintptr_t)bitmap) % sizeof(long); +- len--, bitmap++) { +- weight = hweight8(*bitmap); +- bitflips += BITS_PER_BYTE - weight; +- if (unlikely(bitflips > bitflips_threshold)) +- return -EBADMSG; +- } +- +- for (; len >= sizeof(long); +- len -= sizeof(long), bitmap += sizeof(long)) { +- unsigned long d = *((unsigned long *)bitmap); +- if (d == ~0UL) +- continue; +- weight = hweight_long(d); +- bitflips += BITS_PER_LONG - weight; +- if (unlikely(bitflips > bitflips_threshold)) +- return -EBADMSG; +- } +- +- for (; len > 0; len--, bitmap++) { +- weight = hweight8(*bitmap); +- bitflips += BITS_PER_BYTE - weight; +- if (unlikely(bitflips > bitflips_threshold)) +- return -EBADMSG; +- } +- +- return bitflips; +-} +- +-/** +- * nand_check_erased_ecc_chunk - check if an ECC chunk contains (almost) only +- * 0xff data +- * @data: data buffer to test +- * @datalen: data length +- * @ecc: ECC buffer +- * @ecclen: ECC length +- * @extraoob: extra OOB buffer +- * @extraooblen: extra OOB length +- * @bitflips_threshold: maximum number of bitflips +- * +- * Check if a data buffer and its associated ECC and OOB data contains only +- * 0xff pattern, which means the underlying region has been erased and is +- * ready to be programmed. +- * The bitflips_threshold specify the maximum number of bitflips before +- * considering the region as not erased. +- * +- * Note: +- * 1/ ECC algorithms are working on pre-defined block sizes which are usually +- * different from the NAND page size. When fixing bitflips, ECC engines will +- * report the number of errors per chunk, and the NAND core infrastructure +- * expect you to return the maximum number of bitflips for the whole page. +- * This is why you should always use this function on a single chunk and +- * not on the whole page. After checking each chunk you should update your +- * max_bitflips value accordingly. +- * 2/ When checking for bitflips in erased pages you should not only check +- * the payload data but also their associated ECC data, because a user might +- * have programmed almost all bits to 1 but a few. In this case, we +- * shouldn't consider the chunk as erased, and checking ECC bytes prevent +- * this case. +- * 3/ The extraoob argument is optional, and should be used if some of your OOB +- * data are protected by the ECC engine. +- * It could also be used if you support subpages and want to attach some +- * extra OOB data to an ECC chunk. +- * +- * Returns a positive number of bitflips less than or equal to +- * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the +- * threshold. In case of success, the passed buffers are filled with 0xff. +- */ +-int nand_check_erased_ecc_chunk(void *data, int datalen, +- void *ecc, int ecclen, +- void *extraoob, int extraooblen, +- int bitflips_threshold) +-{ +- int data_bitflips = 0, ecc_bitflips = 0, extraoob_bitflips = 0; +- +- data_bitflips = nand_check_erased_buf(data, datalen, +- bitflips_threshold); +- if (data_bitflips < 0) +- return data_bitflips; +- +- bitflips_threshold -= data_bitflips; +- +- ecc_bitflips = nand_check_erased_buf(ecc, ecclen, bitflips_threshold); +- if (ecc_bitflips < 0) +- return ecc_bitflips; +- +- bitflips_threshold -= ecc_bitflips; +- +- extraoob_bitflips = nand_check_erased_buf(extraoob, extraooblen, +- bitflips_threshold); +- if (extraoob_bitflips < 0) +- return extraoob_bitflips; +- +- if (data_bitflips) +- memset(data, 0xff, datalen); +- +- if (ecc_bitflips) +- memset(ecc, 0xff, ecclen); +- +- if (extraoob_bitflips) +- memset(extraoob, 0xff, extraooblen); +- +- return data_bitflips + ecc_bitflips + extraoob_bitflips; +-} +-EXPORT_SYMBOL(nand_check_erased_ecc_chunk); +- +-/** + * nand_read_page_raw_notsupp - dummy read raw page function + * @chip: nand chip info structure + * @buf: buffer to store read data +--- a/include/linux/mtd/nand.h ++++ b/include/linux/mtd/nand.h +@@ -1136,4 +1136,9 @@ static inline bool nanddev_bbt_is_initia + int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo); + int nanddev_mtd_max_bad_blocks(struct mtd_info *mtd, loff_t offs, size_t len); + ++int nand_check_erased_ecc_chunk(void *data, int datalen, ++ void *ecc, int ecclen, ++ void *extraoob, int extraooblen, ++ int threshold); ++ + #endif /* __LINUX_MTD_NAND_H */ +--- a/include/linux/mtd/rawnand.h ++++ b/include/linux/mtd/rawnand.h +@@ -1519,11 +1519,6 @@ int rawnand_sw_bch_correct(struct nand_c + unsigned char *read_ecc, unsigned char *calc_ecc); + void rawnand_sw_bch_cleanup(struct nand_chip *chip); + +-int nand_check_erased_ecc_chunk(void *data, int datalen, +- void *ecc, int ecclen, +- void *extraoob, int extraooblen, +- int threshold); +- + int nand_ecc_choose_conf(struct nand_chip *chip, + const struct nand_ecc_caps *caps, int oobavail); + diff --git a/lede/target/linux/generic/backport-6.12/404-v6.19-mtd-spinand-fmsh-remove-QE-bit-for-FM25S01A-flash.patch b/lede/target/linux/generic/backport-6.12/404-v6.19-mtd-spinand-fmsh-remove-QE-bit-for-FM25S01A-flash.patch new file mode 100644 index 0000000000..7f9ec6aca4 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/404-v6.19-mtd-spinand-fmsh-remove-QE-bit-for-FM25S01A-flash.patch @@ -0,0 +1,28 @@ +From a1d3bc606bf5c3b3ea811cc2019df6285d75b00f Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Mon, 3 Nov 2025 04:01:48 +0300 +Subject: [PATCH] mtd: spinand: fmsh: remove QE bit for FM25S01A flash + +According to datasheet (http://eng.fmsh.com/nvm/FM25S01A_ds_eng.pdf) +there is no QE (Quad Enable) bit for FM25S01A flash, so remove it. + +Fixes: 5f284dc15ca86 ("mtd: spinand: add support for FudanMicro FM25S01A") +Signed-off-by: Mikhail Kshevetskiy +Tested-by: Tianling Shen +Signed-off-by: Miquel Raynal +Link: Link: https://lore.kernel.org/linux-mtd/176216634975.908445.2776312239779833518.b4-ty@bootlin.com +--- + drivers/mtd/nand/spi/fmsh.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mtd/nand/spi/fmsh.c ++++ b/drivers/mtd/nand/spi/fmsh.c +@@ -58,7 +58,7 @@ static const struct spinand_info fmsh_sp + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), +- SPINAND_HAS_QE_BIT, ++ 0, + SPINAND_ECCINFO(&fm25s01a_ooblayout, NULL)), + }; + diff --git a/lede/target/linux/generic/backport-6.12/413-01-v6.14-mtd-rawnand-qcom-cleanup-qcom_nandc-driver.patch b/lede/target/linux/generic/backport-6.12/410-01-v6.14-mtd-rawnand-qcom-cleanup-qcom_nandc-driver.patch similarity index 98% rename from lede/target/linux/generic/backport-6.12/413-01-v6.14-mtd-rawnand-qcom-cleanup-qcom_nandc-driver.patch rename to lede/target/linux/generic/backport-6.12/410-01-v6.14-mtd-rawnand-qcom-cleanup-qcom_nandc-driver.patch index 07b031a094..1d1288e832 100644 --- a/lede/target/linux/generic/backport-6.12/413-01-v6.14-mtd-rawnand-qcom-cleanup-qcom_nandc-driver.patch +++ b/lede/target/linux/generic/backport-6.12/410-01-v6.14-mtd-rawnand-qcom-cleanup-qcom_nandc-driver.patch @@ -815,7 +815,15 @@ Signed-off-by: Miquel Raynal read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL); ret = submit_descs(nandc); -@@ -2869,7 +2820,7 @@ static int qcom_param_page_type_exec(str +@@ -2862,14 +2813,14 @@ static int qcom_param_page_type_exec(str + + reg_base = NAND_READ_LOCATION_0; + +- if (nandc->props->qpic_v2) ++ if (nandc->props->qpic_version2) + reg_base = NAND_READ_LOCATION_LAST_CW_0; + + ret = qcom_parse_instructions(chip, subop, &q_op); if (ret) return ret; @@ -824,7 +832,7 @@ Signed-off-by: Miquel Raynal nandc->buf_count = 0; nandc->buf_start = 0; -@@ -2877,38 +2828,38 @@ static int qcom_param_page_type_exec(str +@@ -2877,52 +2828,52 @@ static int qcom_param_page_type_exec(str clear_read_regs(nandc); clear_bam_transaction(nandc); @@ -890,7 +898,12 @@ Signed-off-by: Miquel Raynal } instr = q_op.data_instr; -@@ -2920,9 +2871,9 @@ static int qcom_param_page_type_exec(str + op_id = q_op.data_instr_idx; + len = nand_subop_get_data_len(subop, op_id); + +- if (nandc->props->qpic_v2) ++ if (nandc->props->qpic_version2) + nandc_set_read_loc_last(chip, reg_base, 0, len, 1); else nandc_set_read_loc_first(chip, reg_base, 0, len, 1); diff --git a/lede/target/linux/generic/backport-6.12/413-02-v6.14-mtd-rawnand-qcom-Add-qcom-prefix-to-common-api.patch b/lede/target/linux/generic/backport-6.12/410-02-v6.14-mtd-rawnand-qcom-Add-qcom-prefix-to-common-api.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/413-02-v6.14-mtd-rawnand-qcom-Add-qcom-prefix-to-common-api.patch rename to lede/target/linux/generic/backport-6.12/410-02-v6.14-mtd-rawnand-qcom-Add-qcom-prefix-to-common-api.patch diff --git a/lede/target/linux/generic/backport-6.12/413-03-v6.14-mtd-nand-Add-qpic_common-API-file.patch b/lede/target/linux/generic/backport-6.12/410-03-v6.14-mtd-nand-Add-qpic_common-API-file.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/413-03-v6.14-mtd-nand-Add-qpic_common-API-file.patch rename to lede/target/linux/generic/backport-6.12/410-03-v6.14-mtd-nand-Add-qpic_common-API-file.patch diff --git a/lede/target/linux/generic/backport-6.12/413-04-v6.14-mtd-rawnand-qcom-use-FIELD_PREP-and-GENMASK.patch b/lede/target/linux/generic/backport-6.12/410-04-v6.14-mtd-rawnand-qcom-use-FIELD_PREP-and-GENMASK.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/413-04-v6.14-mtd-rawnand-qcom-use-FIELD_PREP-and-GENMASK.patch rename to lede/target/linux/generic/backport-6.12/410-04-v6.14-mtd-rawnand-qcom-use-FIELD_PREP-and-GENMASK.patch diff --git a/lede/target/linux/generic/backport-6.12/414-v6.14-mtd-rawnand-qcom-fix-broken-config-in-qcom_param_pag.patch b/lede/target/linux/generic/backport-6.12/410-05-v6.14-mtd-rawnand-qcom-fix-broken-config-in-qcom_param_pag.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/414-v6.14-mtd-rawnand-qcom-fix-broken-config-in-qcom_param_pag.patch rename to lede/target/linux/generic/backport-6.12/410-05-v6.14-mtd-rawnand-qcom-fix-broken-config-in-qcom_param_pag.patch diff --git a/lede/target/linux/generic/backport-6.12/415-v6.14-mtd-rawnand-qcom-Fix-build-issue-on-x86-architecture.patch b/lede/target/linux/generic/backport-6.12/410-06-v6.14-mtd-rawnand-qcom-Fix-build-issue-on-x86-architecture.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/415-v6.14-mtd-rawnand-qcom-Fix-build-issue-on-x86-architecture.patch rename to lede/target/linux/generic/backport-6.12/410-06-v6.14-mtd-rawnand-qcom-Fix-build-issue-on-x86-architecture.patch diff --git a/lede/target/linux/generic/backport-6.12/416-v6.15-01-spi-spi-qpic-add-driver-for-QCOM-SPI-NAND-flash-Inte.patch b/lede/target/linux/generic/backport-6.12/410-07-v6.15-spi-spi-qpic-add-driver-for-QCOM-SPI-NAND-flash-Inte.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/416-v6.15-01-spi-spi-qpic-add-driver-for-QCOM-SPI-NAND-flash-Inte.patch rename to lede/target/linux/generic/backport-6.12/410-07-v6.15-spi-spi-qpic-add-driver-for-QCOM-SPI-NAND-flash-Inte.patch diff --git a/lede/target/linux/generic/backport-6.12/416-v6.15-02-spi-spi-qpic-snand-Fix-ECC_CFG_ECC_DISABLE-shift-in-.patch b/lede/target/linux/generic/backport-6.12/410-08-v6.15-spi-spi-qpic-snand-Fix-ECC_CFG_ECC_DISABLE-shift-in-.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/416-v6.15-02-spi-spi-qpic-snand-Fix-ECC_CFG_ECC_DISABLE-shift-in-.patch rename to lede/target/linux/generic/backport-6.12/410-08-v6.15-spi-spi-qpic-snand-Fix-ECC_CFG_ECC_DISABLE-shift-in-.patch diff --git a/lede/target/linux/generic/backport-6.12/416-v6.15-03-spi-spi-qpic-snand-avoid-memleak-in-qcom_spi_ecc_ini.patch b/lede/target/linux/generic/backport-6.12/410-09-v6.15-spi-spi-qpic-snand-avoid-memleak-in-qcom_spi_ecc_ini.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/416-v6.15-03-spi-spi-qpic-snand-avoid-memleak-in-qcom_spi_ecc_ini.patch rename to lede/target/linux/generic/backport-6.12/410-09-v6.15-spi-spi-qpic-snand-avoid-memleak-in-qcom_spi_ecc_ini.patch diff --git a/lede/target/linux/generic/backport-6.12/416-v6.15-04-spi-SPI_QPIC_SNAND-should-be-tristate-and-depend-on-.patch b/lede/target/linux/generic/backport-6.12/410-10-v6.15-spi-SPI_QPIC_SNAND-should-be-tristate-and-depend-on-.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/416-v6.15-04-spi-SPI_QPIC_SNAND-should-be-tristate-and-depend-on-.patch rename to lede/target/linux/generic/backport-6.12/410-10-v6.15-spi-SPI_QPIC_SNAND-should-be-tristate-and-depend-on-.patch diff --git a/lede/target/linux/generic/backport-6.12/416-v6.15-05-spi-spi-qpic-snand-propagate-errors-from-qcom_spi_block_erase.patch b/lede/target/linux/generic/backport-6.12/410-11-v6.15-spi-spi-qpic-snand-propagate-errors-from-qcom_spi_block_erase.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/416-v6.15-05-spi-spi-qpic-snand-propagate-errors-from-qcom_spi_block_erase.patch rename to lede/target/linux/generic/backport-6.12/410-11-v6.15-spi-spi-qpic-snand-propagate-errors-from-qcom_spi_block_erase.patch diff --git a/lede/target/linux/generic/backport-6.12/416-v6.15-06-spi-spi-qpic-snand-fix-NAND_READ_LOCATION_2-register-handling.patch b/lede/target/linux/generic/backport-6.12/410-12-v6.15-spi-spi-qpic-snand-fix-NAND_READ_LOCATION_2-register-handling.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/416-v6.15-06-spi-spi-qpic-snand-fix-NAND_READ_LOCATION_2-register-handling.patch rename to lede/target/linux/generic/backport-6.12/410-12-v6.15-spi-spi-qpic-snand-fix-NAND_READ_LOCATION_2-register-handling.patch diff --git a/lede/target/linux/generic/backport-6.12/416-v6.15-07-spi-spi-qpic-snand-use-kmalloc-for-OOB-buffer-alloca.patch b/lede/target/linux/generic/backport-6.12/410-13-v6.15-spi-spi-qpic-snand-use-kmalloc-for-OOB-buffer-alloca.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/416-v6.15-07-spi-spi-qpic-snand-use-kmalloc-for-OOB-buffer-alloca.patch rename to lede/target/linux/generic/backport-6.12/410-13-v6.15-spi-spi-qpic-snand-use-kmalloc-for-OOB-buffer-alloca.patch diff --git a/lede/target/linux/generic/backport-6.12/416-v6.16-08-spi-spi-qpic-snand-remove-unused-wlen-member-of-struct-qpic_spi_nand.patch b/lede/target/linux/generic/backport-6.12/410-14-v6.16-spi-spi-qpic-snand-remove-unused-wlen-member-of-struct-qpic_spi_nand.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/416-v6.16-08-spi-spi-qpic-snand-remove-unused-wlen-member-of-struct-qpic_spi_nand.patch rename to lede/target/linux/generic/backport-6.12/410-14-v6.16-spi-spi-qpic-snand-remove-unused-wlen-member-of-struct-qpic_spi_nand.patch diff --git a/lede/target/linux/generic/backport-6.12/411-v6.15-mtd-nand-Drop-explicit-test-for-built-in-CONFIG_SPI_.patch b/lede/target/linux/generic/backport-6.12/411-v6.15-mtd-nand-Drop-explicit-test-for-built-in-CONFIG_SPI_.patch new file mode 100644 index 0000000000..8019d2ccac --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/411-v6.15-mtd-nand-Drop-explicit-test-for-built-in-CONFIG_SPI_.patch @@ -0,0 +1,37 @@ +From 36c6468724aa98d33fea9a1d7e07ddda6302f5d4 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Fri, 28 Mar 2025 09:24:01 +0100 +Subject: mtd: nand: Drop explicit test for built-in CONFIG_SPI_QPIC_SNAND + +If CONFIG_SPI_QPIC_SNAND=m, but CONFIG_MTD_NAND_QCOM=n: + + ERROR: modpost: "qcom_nandc_unalloc" [drivers/spi/spi-qpic-snand.ko] undefined! + ... + +Fix this by dropping the explicit test for a built-in +CONFIG_SPI_QPIC_SNAND completely. Kbuild handles multiple and mixed +obj-y/obj-m rules for the same object file fine. + +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202503280759.XhwLcV7m-lkp@intel.com/ +Fixes: 7304d1909080ef0c ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Miquel Raynal +--- + drivers/mtd/nand/Makefile | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -3,11 +3,8 @@ + nandcore-objs := core.o bbt.o + obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o + obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o +-ifeq ($(CONFIG_SPI_QPIC_SNAND),y) + obj-$(CONFIG_SPI_QPIC_SNAND) += qpic_common.o +-else + obj-$(CONFIG_MTD_NAND_QCOM) += qpic_common.o +-endif + obj-y += onenand/ + obj-y += raw/ + obj-y += spi/ diff --git a/lede/target/linux/generic/pending-6.12/416-09-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch b/lede/target/linux/generic/backport-6.12/412-v6.16-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch similarity index 94% rename from lede/target/linux/generic/pending-6.12/416-09-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch rename to lede/target/linux/generic/backport-6.12/412-v6.16-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch index c03a529963..2f951564c1 100644 --- a/lede/target/linux/generic/pending-6.12/416-09-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch +++ b/lede/target/linux/generic/backport-6.12/412-v6.16-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch @@ -1,7 +1,7 @@ +From 65cb56d49f6edea409600a3c61effc70ee5d43d8 Mon Sep 17 00:00:00 2001 From: Gabor Juhos -Date: Thu, 01 May 2025 18:19:16 +0200 -Subject: [PATCH next] spi: spi-qpic-snand: validate user/chip specific ECC - properties +Date: Thu, 1 May 2025 18:19:16 +0200 +Subject: spi: spi-qpic-snand: validate user/chip specific ECC properties The driver only supports 512 bytes ECC step size and 4 bit ECC strength at the moment, however it does not reject unsupported step/strength @@ -81,20 +81,12 @@ strength gets implemented. Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") Signed-off-by: Gabor Juhos +Link: https://patch.msgid.link/20250501-qpic-snand-validate-ecc-v1-1-532776581a66@gmail.com +Signed-off-by: Mark Brown --- -Marked for next because it depends on commit f48d80503504 ("spi: spi-qpic-snand: -use kmalloc() for OOB buffer allocation"). ---- - drivers/spi/spi-qpic-snand.c | 42 +++++++++++++++++++++++++++++++++++++----- + drivers/spi/spi-qpic-snand.c | 42 +++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) - ---- -base-commit: a7f035c2c72496cf7ac34bfaa8c289e0d4c45836 -change-id: 20250501-qpic-snand-validate-ecc-383b3e33e238 - -Best regards, - --- a/drivers/spi/spi-qpic-snand.c +++ b/drivers/spi/spi-qpic-snand.c @@ -249,9 +249,11 @@ static const struct mtd_ooblayout_ops qc diff --git a/lede/target/linux/generic/backport-6.12/413-05-v6.14-mtd-nand-change-to-qpic_version2.patch b/lede/target/linux/generic/backport-6.12/413-05-v6.14-mtd-nand-change-to-qpic_version2.patch deleted file mode 100644 index 863fa65cb2..0000000000 --- a/lede/target/linux/generic/backport-6.12/413-05-v6.14-mtd-nand-change-to-qpic_version2.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/drivers/mtd/nand/raw/qcom_nandc.c -+++ b/drivers/mtd/nand/raw/qcom_nandc.c -@@ -1867,7 +1867,7 @@ static int qcom_param_page_type_exec(str - - reg_base = NAND_READ_LOCATION_0; - -- if (nandc->props->qpic_v2) -+ if (nandc->props->qpic_version2) - reg_base = NAND_READ_LOCATION_LAST_CW_0; - - ret = qcom_parse_instructions(chip, subop, &q_op); -@@ -1920,7 +1920,7 @@ static int qcom_param_page_type_exec(str - op_id = q_op.data_instr_idx; - len = nand_subop_get_data_len(subop, op_id); - -- if (nandc->props->qpic_v2) -+ if (nandc->props->qpic_version2) - nandc_set_read_loc_last(chip, reg_base, 0, len, 1); - else - nandc_set_read_loc_first(chip, reg_base, 0, len, 1); diff --git a/lede/target/linux/generic/backport-6.12/413-v6.16-spi-spi-qpic-snand-use-CW_PER_PAGE_MASK-bitmask.patch b/lede/target/linux/generic/backport-6.12/413-v6.16-spi-spi-qpic-snand-use-CW_PER_PAGE_MASK-bitmask.patch new file mode 100644 index 0000000000..10c1651b3b --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/413-v6.16-spi-spi-qpic-snand-use-CW_PER_PAGE_MASK-bitmask.patch @@ -0,0 +1,113 @@ +From 2abf107dcd797c60c86e9f17319cd1658862f6b2 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Thu, 15 May 2025 20:58:05 +0200 +Subject: spi: spi-qpic-snand: use CW_PER_PAGE_MASK bitmask + +Change the code to use the already defined CW_PER_PAGE_MASK +bitmask along with the FIELD_PREP() macro instead of using +magic values. + +This makes the code more readable. It also syncs the affected +codes with their counterparts in the 'qcom_nandc' driver, so it +makes it easier to spot the differences between the two +implementations. + +No functional changes intended. + +Signed-off-by: Gabor Juhos +Reviewed-by: Md Sadre Alam +Link: https://patch.msgid.link/20250515-qpic-snand-use-bitmasks-v1-1-11729aeae73b@gmail.com +Signed-off-by: Mark Brown +--- + drivers/spi/spi-qpic-snand.c | 31 ++++++++++++++++--------------- + 1 file changed, 16 insertions(+), 15 deletions(-) + +--- a/drivers/spi/spi-qpic-snand.c ++++ b/drivers/spi/spi-qpic-snand.c +@@ -483,7 +483,8 @@ static int qcom_spi_block_erase(struct q + snandc->regs->cmd = snandc->qspi->cmd; + snandc->regs->addr0 = snandc->qspi->addr1; + snandc->regs->addr1 = snandc->qspi->addr2; +- snandc->regs->cfg0 = cpu_to_le32(ecc_cfg->cfg0_raw & ~(7 << CW_PER_PAGE)); ++ snandc->regs->cfg0 = cpu_to_le32((ecc_cfg->cfg0_raw & ~CW_PER_PAGE_MASK) | ++ FIELD_PREP(CW_PER_PAGE_MASK, 0)); + snandc->regs->cfg1 = cpu_to_le32(ecc_cfg->cfg1_raw); + snandc->regs->exec = cpu_to_le32(1); + +@@ -544,8 +545,8 @@ static int qcom_spi_read_last_cw(struct + snandc->regs->addr0 = (snandc->qspi->addr1 | cpu_to_le32(col)); + snandc->regs->addr1 = snandc->qspi->addr2; + +- cfg0 = (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) | +- 0 << CW_PER_PAGE; ++ cfg0 = (ecc_cfg->cfg0_raw & ~CW_PER_PAGE_MASK) | ++ FIELD_PREP(CW_PER_PAGE_MASK, 0); + cfg1 = ecc_cfg->cfg1_raw; + ecc_bch_cfg = ECC_CFG_ECC_DISABLE; + +@@ -687,8 +688,8 @@ static int qcom_spi_read_cw_raw(struct q + qcom_clear_bam_transaction(snandc); + raw_cw = num_cw - 1; + +- cfg0 = (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) | +- 0 << CW_PER_PAGE; ++ cfg0 = (ecc_cfg->cfg0_raw & ~CW_PER_PAGE_MASK) | ++ FIELD_PREP(CW_PER_PAGE_MASK, 0); + cfg1 = ecc_cfg->cfg1_raw; + ecc_bch_cfg = ECC_CFG_ECC_DISABLE; + +@@ -808,8 +809,8 @@ static int qcom_spi_read_page_ecc(struct + snandc->buf_start = 0; + qcom_clear_read_regs(snandc); + +- cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | +- (num_cw - 1) << CW_PER_PAGE; ++ cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) | ++ FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); + cfg1 = ecc_cfg->cfg1; + ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; + +@@ -904,8 +905,8 @@ static int qcom_spi_read_page_oob(struct + qcom_clear_read_regs(snandc); + qcom_clear_bam_transaction(snandc); + +- cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | +- (num_cw - 1) << CW_PER_PAGE; ++ cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) | ++ FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); + cfg1 = ecc_cfg->cfg1; + ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; + +@@ -1015,8 +1016,8 @@ static int qcom_spi_program_raw(struct q + int num_cw = snandc->qspi->num_cw; + u32 cfg0, cfg1, ecc_bch_cfg; + +- cfg0 = (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) | +- (num_cw - 1) << CW_PER_PAGE; ++ cfg0 = (ecc_cfg->cfg0_raw & ~CW_PER_PAGE_MASK) | ++ FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); + cfg1 = ecc_cfg->cfg1_raw; + ecc_bch_cfg = ECC_CFG_ECC_DISABLE; + +@@ -1098,8 +1099,8 @@ static int qcom_spi_program_ecc(struct q + int num_cw = snandc->qspi->num_cw; + u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg; + +- cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | +- (num_cw - 1) << CW_PER_PAGE; ++ cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) | ++ FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); + cfg1 = ecc_cfg->cfg1; + ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; + ecc_buf_cfg = ecc_cfg->ecc_buf_cfg; +@@ -1175,8 +1176,8 @@ static int qcom_spi_program_oob(struct q + int num_cw = snandc->qspi->num_cw; + u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg; + +- cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | +- (num_cw - 1) << CW_PER_PAGE; ++ cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) | ++ FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); + cfg1 = ecc_cfg->cfg1; + ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; + ecc_buf_cfg = ecc_cfg->ecc_buf_cfg; diff --git a/lede/target/linux/generic/backport-6.12/414-v6.16-spi-spi-qpic-snand-reallocate-BAM-transactions.patch b/lede/target/linux/generic/backport-6.12/414-v6.16-spi-spi-qpic-snand-reallocate-BAM-transactions.patch new file mode 100644 index 0000000000..6d61016556 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/414-v6.16-spi-spi-qpic-snand-reallocate-BAM-transactions.patch @@ -0,0 +1,81 @@ +From d85d0380292a7e618915069c3579ae23c7c80339 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Wed, 18 Jun 2025 22:22:49 +0200 +Subject: spi: spi-qpic-snand: reallocate BAM transactions + +Using the mtd_nandbiterrs module for testing the driver occasionally +results in weird things like below. + +1. swiotlb mapping fails with the following message: + + [ 85.926216] qcom_snand 79b0000.spi: swiotlb buffer is full (sz: 4294967294 bytes), total 512 (slots), used 0 (slots) + [ 85.932937] qcom_snand 79b0000.spi: failure in mapping desc + [ 87.999314] qcom_snand 79b0000.spi: failure to write raw page + [ 87.999352] mtd_nandbiterrs: error: write_oob failed (-110) + + Rebooting the board after this causes a panic due to a NULL pointer + dereference. + +2. If the swiotlb mapping does not fail, rebooting the board may result + in a different panic due to a bad spinlock magic: + + [ 256.104459] BUG: spinlock bad magic on CPU#3, procd/2241 + [ 256.104488] Unable to handle kernel paging request at virtual address ffffffff0000049b + ... + +Investigating the issue revealed that these symptoms are results of +memory corruption which is caused by out of bounds access within the +driver. + +The driver uses a dynamically allocated structure for BAM transactions, +which structure must have enough space for all possible variations of +different flash operations initiated by the driver. The required space +heavily depends on the actual number of 'codewords' which is calculated +from the pagesize of the actual NAND chip. + +Although the qcom_nandc_alloc() function allocates memory for the BAM +transactions during probe, but since the actual number of 'codewords' +is not yet know the allocation is done for one 'codeword' only. + +Because of this, whenever the driver does a flash operation, and the +number of the required transactions exceeds the size of the allocated +arrays the driver accesses memory out of the allocated range. + +To avoid this, change the code to free the initially allocated BAM +transactions memory, and allocate a new one once the actual number of +'codewords' required for a given NAND chip is known. + +Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") +Reviewed-by: Md Sadre Alam +Signed-off-by: Gabor Juhos +Link: https://patch.msgid.link/20250618-qpic-snand-avoid-mem-corruption-v3-1-319c71296cda@gmail.com +Signed-off-by: Mark Brown +--- + drivers/spi/spi-qpic-snand.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/spi/spi-qpic-snand.c ++++ b/drivers/spi/spi-qpic-snand.c +@@ -315,6 +315,22 @@ static int qcom_spi_ecc_init_ctx_pipelin + + mtd_set_ooblayout(mtd, &qcom_spi_ooblayout); + ++ /* ++ * Free the temporary BAM transaction allocated initially by ++ * qcom_nandc_alloc(), and allocate a new one based on the ++ * updated max_cwperpage value. ++ */ ++ qcom_free_bam_transaction(snandc); ++ ++ snandc->max_cwperpage = cwperpage; ++ ++ snandc->bam_txn = qcom_alloc_bam_transaction(snandc); ++ if (!snandc->bam_txn) { ++ dev_err(snandc->dev, "failed to allocate BAM transaction\n"); ++ ret = -ENOMEM; ++ goto err_free_ecc_cfg; ++ } ++ + ecc_cfg->cfg0 = FIELD_PREP(CW_PER_PAGE_MASK, (cwperpage - 1)) | + FIELD_PREP(UD_SIZE_BYTES_MASK, ecc_cfg->cw_data) | + FIELD_PREP(DISABLE_STATUS_AFTER_WRITE, 1) | diff --git a/lede/target/linux/generic/backport-6.12/415-v6.16-spi-spi-qpic-snand-don-t-hardcode-ECC-steps.patch b/lede/target/linux/generic/backport-6.12/415-v6.16-spi-spi-qpic-snand-don-t-hardcode-ECC-steps.patch new file mode 100644 index 0000000000..eab7b792aa --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/415-v6.16-spi-spi-qpic-snand-don-t-hardcode-ECC-steps.patch @@ -0,0 +1,31 @@ +From f820034864dd463cdcd2bebe7940f2eca0eb4223 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Wed, 23 Jul 2025 10:06:43 +0200 +Subject: spi: spi-qpic-snand: don't hardcode ECC steps + +NAND devices with different page sizes requires different number +of ECC steps, yet the qcom_spi_ecc_init_ctx_pipelined() function +sets 4 steps in 'ecc_cfg' unconditionally. + +The correct number of the steps is calculated earlier in the +function already, so use that instead of the hardcoded value. + +Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") +Signed-off-by: Gabor Juhos +Link: https://patch.msgid.link/20250723-qpic-snand-fix-steps-v1-1-d800695dde4c@gmail.com +Signed-off-by: Mark Brown +--- + drivers/spi/spi-qpic-snand.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/spi/spi-qpic-snand.c ++++ b/drivers/spi/spi-qpic-snand.c +@@ -308,7 +308,7 @@ static int qcom_spi_ecc_init_ctx_pipelin + ecc_cfg->bch_enabled = true; + ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size; + +- ecc_cfg->steps = 4; ++ ecc_cfg->steps = cwperpage; + ecc_cfg->cw_data = 516; + ecc_cfg->cw_size = ecc_cfg->cw_data + ecc_cfg->bytes; + bad_block_byte = mtd->writesize - ecc_cfg->cw_size * (cwperpage - 1) + 1; diff --git a/lede/target/linux/generic/pending-6.12/416-10-next-1-2-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch b/lede/target/linux/generic/backport-6.12/416-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch similarity index 83% rename from lede/target/linux/generic/pending-6.12/416-10-next-1-2-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch rename to lede/target/linux/generic/backport-6.12/416-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch index 8029e4992e..7ddf15ef70 100644 --- a/lede/target/linux/generic/pending-6.12/416-10-next-1-2-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch +++ b/lede/target/linux/generic/backport-6.12/416-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch @@ -1,7 +1,7 @@ +From 0dc7e656ddd54c3267b7cc18c1ac8ec1297ed02f Mon Sep 17 00:00:00 2001 From: Gabor Juhos -Date: Fri, 02 May 2025 21:31:16 +0200 -Subject: [PATCH next 1/2] mtd: nand: qpic-common: add defines for ECC_MODE - values +Date: Wed, 2 Jul 2025 14:35:23 +0200 +Subject: mtd: nand: qpic-common: add defines for ECC_MODE values Add defines for the values of the ECC_MODE field of the NAND_DEV0_ECC_CFG register and change both the 'qcom-nandc' and 'spi-qpic-snand' drivers to @@ -10,7 +10,11 @@ use those instead of magic numbers. No functional changes. This is in preparation for adding 8 bit ECC strength support for the 'spi-qpic-snand' driver. +Reviewed-by: Md Sadre Alam Signed-off-by: Gabor Juhos +Acked-by: Miquel Raynal +Link: https://patch.msgid.link/20250702-qpic-snand-8bit-ecc-v2-1-ae2c17a30bb7@gmail.com +Signed-off-by: Mark Brown --- drivers/mtd/nand/raw/qcom_nandc.c | 6 +++--- drivers/spi/spi-qpic-snand.c | 2 +- @@ -48,7 +52,7 @@ Signed-off-by: Gabor Juhos host->ecc_bytes_hw = 8; --- a/drivers/spi/spi-qpic-snand.c +++ b/drivers/spi/spi-qpic-snand.c -@@ -349,7 +349,7 @@ static int qcom_spi_ecc_init_ctx_pipelin +@@ -365,7 +365,7 @@ static int qcom_spi_ecc_init_ctx_pipelin FIELD_PREP(ECC_SW_RESET, 0) | FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, ecc_cfg->cw_data) | FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) | diff --git a/lede/target/linux/generic/backport-6.12/417-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch b/lede/target/linux/generic/backport-6.12/417-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch new file mode 100644 index 0000000000..4eff84f419 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/417-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch @@ -0,0 +1,66 @@ +From 913bf8d50cbd144c87e9660b591781179182ff59 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Wed, 2 Jul 2025 14:35:24 +0200 +Subject: spi: spi-qpic-snand: add support for 8 bits ECC strength + +Even though the hardware supports 8 bits ECC strength, but that is not +handled in the driver yet. This change adds the missing bits in order +to allow using the driver with chips which require 8 bits ECC strength. + +No functional changes intended with regard to the existing 4 bits ECC +strength support. + +Tested on an IPQ9574 platform using a GigaDevice GD5F2GM7REYIG chip. + +Signed-off-by: Gabor Juhos +Link: https://patch.msgid.link/20250702-qpic-snand-8bit-ecc-v2-2-ae2c17a30bb7@gmail.com +Signed-off-by: Mark Brown +--- + drivers/spi/spi-qpic-snand.c | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +--- a/drivers/spi/spi-qpic-snand.c ++++ b/drivers/spi/spi-qpic-snand.c +@@ -283,9 +283,22 @@ static int qcom_spi_ecc_init_ctx_pipelin + goto err_free_ecc_cfg; + } + +- if (ecc_cfg->strength != 4) { ++ switch (ecc_cfg->strength) { ++ case 4: ++ ecc_cfg->ecc_mode = ECC_MODE_4BIT; ++ ecc_cfg->ecc_bytes_hw = 7; ++ ecc_cfg->spare_bytes = 4; ++ break; ++ ++ case 8: ++ ecc_cfg->ecc_mode = ECC_MODE_8BIT; ++ ecc_cfg->ecc_bytes_hw = 13; ++ ecc_cfg->spare_bytes = 2; ++ break; ++ ++ default: + dev_err(snandc->dev, +- "only 4 bits ECC strength is supported\n"); ++ "only 4 or 8 bits ECC strength is supported\n"); + ret = -EOPNOTSUPP; + goto err_free_ecc_cfg; + } +@@ -302,8 +315,6 @@ static int qcom_spi_ecc_init_ctx_pipelin + nand->ecc.ctx.priv = ecc_cfg; + snandc->qspi->mtd = mtd; + +- ecc_cfg->ecc_bytes_hw = 7; +- ecc_cfg->spare_bytes = 4; + ecc_cfg->bbm_size = 1; + ecc_cfg->bch_enabled = true; + ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size; +@@ -365,7 +376,7 @@ static int qcom_spi_ecc_init_ctx_pipelin + FIELD_PREP(ECC_SW_RESET, 0) | + FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, ecc_cfg->cw_data) | + FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) | +- FIELD_PREP(ECC_MODE_MASK, ECC_MODE_4BIT) | ++ FIELD_PREP(ECC_MODE_MASK, ecc_cfg->ecc_mode) | + FIELD_PREP(ECC_PARITY_SIZE_BYTES_BCH_MASK, ecc_cfg->ecc_bytes_hw); + + ecc_cfg->ecc_buf_cfg = 0x203 << NUM_STEPS; diff --git a/lede/target/linux/generic/backport-6.12/418-v6.17-spi-spi-qpic-snand-use-correct-CW_PER_PAGE-value-for.patch b/lede/target/linux/generic/backport-6.12/418-v6.17-spi-spi-qpic-snand-use-correct-CW_PER_PAGE-value-for.patch new file mode 100644 index 0000000000..b67645e07c --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/418-v6.17-spi-spi-qpic-snand-use-correct-CW_PER_PAGE-value-for.patch @@ -0,0 +1,56 @@ +From 6bc829220b33da8522572cc50fdf5067c51d3bf3 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Fri, 1 Aug 2025 09:58:35 +0200 +Subject: spi: spi-qpic-snand: use correct CW_PER_PAGE value for OOB write + +The qcom_spi_program_oob() function uses only the last codeword to write +the OOB data into the flash, but it sets the CW_PER_PAGE field in the +CFG0 register as it would use all codewords. + +It seems that this confuses the hardware somehow, and any access to the +flash fails with a timeout error after the function is called. The problem +can be easily reproduced with the following commands: + + # dd if=/dev/zero bs=2176 count=1 > /tmp/test.bin + 1+0 records in + 1+0 records out + # flash_erase /dev/mtd4 0 0 + Erasing 128 Kibyte @ 0 -- 100 % complete + # nandwrite -O /dev/mtd4 /tmp/test.bin + Writing data to block 0 at offset 0x0 + # nanddump -o /dev/mtd4 >/dev/null + ECC failed: 0 + ECC corrected: 0 + Number of bad blocks: 0 + Number of bbt blocks: 0 + Block size 131072, page size 2048, OOB size 128 + Dumping data starting at 0x00000000 and ending at 0x00020000... + [ 33.197605] qcom_snand 79b0000.spi: failure to read oob + libmtd: error!: MEMREADOOB64 ioctl failed for mtd4, offset 0 (eraseblock 0) + error 110 (Operation timed out) + [ 35.277582] qcom_snand 79b0000.spi: failure in submitting cmd descriptor + libmtd: error!: cannot read 2048 bytes from mtd4 (eraseblock 0, offset 2048) + error 110 (Operation timed out) + nanddump: error!: mtd_read + +Change the code to use the correct CW_PER_PAGE value to avoid this. + +Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") +Signed-off-by: Gabor Juhos +Link: https://patch.msgid.link/20250801-qpic-snand-oob-cwpp-fix-v1-1-f5a41b86af2e@gmail.com +Signed-off-by: Mark Brown +--- + drivers/spi/spi-qpic-snand.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/spi/spi-qpic-snand.c ++++ b/drivers/spi/spi-qpic-snand.c +@@ -1204,7 +1204,7 @@ static int qcom_spi_program_oob(struct q + u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg; + + cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) | +- FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); ++ FIELD_PREP(CW_PER_PAGE_MASK, 0); + cfg1 = ecc_cfg->cfg1; + ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; + ecc_buf_cfg = ecc_cfg->ecc_buf_cfg; diff --git a/lede/target/linux/generic/backport-6.12/419-v6.17-spi-spi-qpic-snand-fix-calculating-of-ECC-OOB-region.patch b/lede/target/linux/generic/backport-6.12/419-v6.17-spi-spi-qpic-snand-fix-calculating-of-ECC-OOB-region.patch new file mode 100644 index 0000000000..35d5d30232 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/419-v6.17-spi-spi-qpic-snand-fix-calculating-of-ECC-OOB-region.patch @@ -0,0 +1,69 @@ +From 13d0fe84a214658254a7412b2b46ec1507dc51f0 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Tue, 5 Aug 2025 18:05:42 +0200 +Subject: spi: spi-qpic-snand: fix calculating of ECC OOB regions' properties + +The OOB layout used by the driver has two distinct regions which contains +hardware specific ECC data, yet the qcom_spi_ooblayout_ecc() function sets +the same offset and length values for both regions which is clearly wrong. + +Change the code to calculate the correct values for both regions. + +For reference, the following table shows the computed offset and length +values for various OOB size/ECC strength configurations: + + +-----------------+-----------------+ + |before the change| after the change| + +-------+----------+--------+--------+--------+--------+--------+ + | OOB | ECC | region | region | region | region | region | + | size | strength | index | offset | length | offset | length | + +-------+----------+--------+--------+--------+--------+--------+ + | 128 | 8 | 0 | 113 | 15 | 0 | 49 | + | | | 1 | 113 | 15 | 65 | 63 | + +-------+----------+--------+--------+--------+--------+--------+ + | 128 | 4 | 0 | 117 | 11 | 0 | 37 | + | | | 1 | 117 | 11 | 53 | 75 | + +-------+----------+--------+--------+--------+--------+--------+ + | 64 | 4 | 0 | 53 | 11 | 0 | 37 | + | | | 1 | 53 | 11 | 53 | 11 | + +-------+----------+--------+--------+--------+--------+--------+ + +Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") +Signed-off-by: Gabor Juhos +Reviewed-by: Konrad Dybcio +Link: https://patch.msgid.link/20250805-qpic-snand-oob-ecc-fix-v2-1-e6f811c70d6f@gmail.com +Signed-off-by: Mark Brown +--- + drivers/spi/spi-qpic-snand.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +--- a/drivers/spi/spi-qpic-snand.c ++++ b/drivers/spi/spi-qpic-snand.c +@@ -216,13 +216,21 @@ static int qcom_spi_ooblayout_ecc(struct + struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand); + struct qpic_ecc *qecc = snandc->qspi->ecc; + +- if (section > 1) +- return -ERANGE; ++ switch (section) { ++ case 0: ++ oobregion->offset = 0; ++ oobregion->length = qecc->bytes * (qecc->steps - 1) + ++ qecc->bbm_size; ++ return 0; ++ case 1: ++ oobregion->offset = qecc->bytes * (qecc->steps - 1) + ++ qecc->bbm_size + ++ qecc->steps * 4; ++ oobregion->length = mtd->oobsize - oobregion->offset; ++ return 0; ++ } + +- oobregion->length = qecc->ecc_bytes_hw + qecc->spare_bytes; +- oobregion->offset = mtd->oobsize - oobregion->length; +- +- return 0; ++ return -ERANGE; + } + + static int qcom_spi_ooblayout_free(struct mtd_info *mtd, int section, diff --git a/lede/target/linux/generic/backport-6.12/420-01-v6.16-mtd-rawnand-brcmnand-remove-unused-parameters.patch b/lede/target/linux/generic/backport-6.12/420-01-v6.16-mtd-rawnand-brcmnand-remove-unused-parameters.patch new file mode 100644 index 0000000000..3bc6038711 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/420-01-v6.16-mtd-rawnand-brcmnand-remove-unused-parameters.patch @@ -0,0 +1,88 @@ +From 56fce75470041b5b0d92ae10637416e1a4cceb1b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Wed, 14 May 2025 08:14:54 +0200 +Subject: [PATCH] mtd: rawnand: brcmnand: remove unused parameters +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +last_cmd and last_byte are now unused brcmnand_host members. +last_addr is only written and never read so we can remove it too. + +Signed-off-by: Álvaro Fernández Rojas +Reviewed-by: Florian Fainelli +Reviewed-by: William Zhang +Signed-off-by: Miquel Raynal +--- + drivers/mtd/nand/raw/brcmnand/brcmnand.c | 24 ++++++------------------ + 1 file changed, 6 insertions(+), 18 deletions(-) + +--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c ++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c +@@ -310,9 +310,6 @@ struct brcmnand_host { + struct platform_device *pdev; + int cs; + +- unsigned int last_cmd; +- unsigned int last_byte; +- u64 last_addr; + struct brcmnand_cfg hwcfg; + struct brcmnand_controller *ctrl; + }; +@@ -2233,14 +2230,11 @@ static int brcmnand_read_page(struct nan + int oob_required, int page) + { + struct mtd_info *mtd = nand_to_mtd(chip); +- struct brcmnand_host *host = nand_get_controller_data(chip); + u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL; + u64 addr = (u64)page << chip->page_shift; + +- host->last_addr = addr; +- +- return brcmnand_read(mtd, chip, host->last_addr, +- mtd->writesize >> FC_SHIFT, (u32 *)buf, oob); ++ return brcmnand_read(mtd, chip, addr, mtd->writesize >> FC_SHIFT, ++ (u32 *)buf, oob); + } + + static int brcmnand_read_page_raw(struct nand_chip *chip, uint8_t *buf, +@@ -2252,11 +2246,9 @@ static int brcmnand_read_page_raw(struct + int ret; + u64 addr = (u64)page << chip->page_shift; + +- host->last_addr = addr; +- + brcmnand_set_ecc_enabled(host, 0); +- ret = brcmnand_read(mtd, chip, host->last_addr, +- mtd->writesize >> FC_SHIFT, (u32 *)buf, oob); ++ ret = brcmnand_read(mtd, chip, addr, mtd->writesize >> FC_SHIFT, ++ (u32 *)buf, oob); + brcmnand_set_ecc_enabled(host, 1); + return ret; + } +@@ -2363,13 +2355,10 @@ static int brcmnand_write_page(struct na + int oob_required, int page) + { + struct mtd_info *mtd = nand_to_mtd(chip); +- struct brcmnand_host *host = nand_get_controller_data(chip); + void *oob = oob_required ? chip->oob_poi : NULL; + u64 addr = (u64)page << chip->page_shift; + +- host->last_addr = addr; +- +- return brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob); ++ return brcmnand_write(mtd, chip, addr, (const u32 *)buf, oob); + } + + static int brcmnand_write_page_raw(struct nand_chip *chip, const uint8_t *buf, +@@ -2381,9 +2370,8 @@ static int brcmnand_write_page_raw(struc + u64 addr = (u64)page << chip->page_shift; + int ret = 0; + +- host->last_addr = addr; + brcmnand_set_ecc_enabled(host, 0); +- ret = brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob); ++ ret = brcmnand_write(mtd, chip, addr, (const u32 *)buf, oob); + brcmnand_set_ecc_enabled(host, 1); + + return ret; diff --git a/lede/target/linux/generic/backport-6.12/420-02-v6.16-mtd-nand-brcmnand-fix-NAND-timeout-when-accessing-eM.patch b/lede/target/linux/generic/backport-6.12/420-02-v6.16-mtd-nand-brcmnand-fix-NAND-timeout-when-accessing-eM.patch new file mode 100644 index 0000000000..d3dbde8b9e --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/420-02-v6.16-mtd-nand-brcmnand-fix-NAND-timeout-when-accessing-eM.patch @@ -0,0 +1,30 @@ +From 528b541b71cf03e263272b051b70696f92258e9d Mon Sep 17 00:00:00 2001 +From: David Regan +Date: Thu, 22 May 2025 10:25:17 -0700 +Subject: [PATCH] mtd: nand: brcmnand: fix NAND timeout when accessing eMMC + +When booting a board to NAND and accessing NAND while eMMC +transactions are occurring the NAND will sometimes timeout. This +is due to both NAND and eMMC controller sharing the same data bus +on BCMBCA chips. Fix is to extend NAND timeout to allow eMMC +transactions time to complete. + +Signed-off-by: David Regan +Reviewed-by: William Zhang +Reviewed-by: Florian Fainelli +Signed-off-by: Miquel Raynal +--- + drivers/mtd/nand/raw/brcmnand/brcmnand.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c ++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c +@@ -101,7 +101,7 @@ struct brcm_nand_dma_desc { + #define BRCMNAND_MIN_DEVSIZE (4ULL * 1024 * 1024) + + #define NAND_CTRL_RDY (INTFC_CTLR_READY | INTFC_FLASH_READY) +-#define NAND_POLL_STATUS_TIMEOUT_MS 100 ++#define NAND_POLL_STATUS_TIMEOUT_MS 500 + + #define EDU_CMD_WRITE 0x00 + #define EDU_CMD_READ 0x01 diff --git a/lede/target/linux/generic/backport-6.12/420-03-v6.16-mtd-rawnand-brcmnand-legacy-exec_op-implementation.patch b/lede/target/linux/generic/backport-6.12/420-03-v6.16-mtd-rawnand-brcmnand-legacy-exec_op-implementation.patch new file mode 100644 index 0000000000..6c75c2bbf2 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/420-03-v6.16-mtd-rawnand-brcmnand-legacy-exec_op-implementation.patch @@ -0,0 +1,299 @@ +From 3bfb22cecfe6b6f0d8ee56ef4b533cf68599c5d9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Wed, 21 May 2025 10:03:25 +0200 +Subject: [PATCH] mtd: rawnand: brcmnand: legacy exec_op implementation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit 3c8260ce7663 ("mtd: rawnand: brcmnand: exec_op implementation") +removed legacy interface functions, breaking < v5.0 controllers support. +In order to fix older controllers we need to add an alternative exec_op +implementation which doesn't rely on low level registers. + +Fixes: 3c8260ce7663 ("mtd: rawnand: brcmnand: exec_op implementation") +Signed-off-by: Álvaro Fernández Rojas +Reviewed-by: David Regan +Reviewed-by: Florian Fainelli +Reviewed-by: William Zhang +Signed-off-by: Miquel Raynal +--- + drivers/mtd/nand/raw/brcmnand/brcmnand.c | 222 ++++++++++++++++++++++- + 1 file changed, 215 insertions(+), 7 deletions(-) + +--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c ++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c +@@ -65,6 +65,7 @@ module_param(wp_on, int, 0444); + #define CMD_PARAMETER_READ 0x0e + #define CMD_PARAMETER_CHANGE_COL 0x0f + #define CMD_LOW_LEVEL_OP 0x10 ++#define CMD_NOT_SUPPORTED 0xff + + struct brcm_nand_dma_desc { + u32 next_desc; +@@ -199,6 +200,30 @@ static const u16 flash_dma_regs_v4[] = { + [FLASH_DMA_CURRENT_DESC_EXT] = 0x34, + }; + ++/* Native command conversion for legacy controllers (< v5.0) */ ++static const u8 native_cmd_conv[] = { ++ [NAND_CMD_READ0] = CMD_NOT_SUPPORTED, ++ [NAND_CMD_READ1] = CMD_NOT_SUPPORTED, ++ [NAND_CMD_RNDOUT] = CMD_PARAMETER_CHANGE_COL, ++ [NAND_CMD_PAGEPROG] = CMD_NOT_SUPPORTED, ++ [NAND_CMD_READOOB] = CMD_NOT_SUPPORTED, ++ [NAND_CMD_ERASE1] = CMD_BLOCK_ERASE, ++ [NAND_CMD_STATUS] = CMD_NOT_SUPPORTED, ++ [NAND_CMD_SEQIN] = CMD_NOT_SUPPORTED, ++ [NAND_CMD_RNDIN] = CMD_NOT_SUPPORTED, ++ [NAND_CMD_READID] = CMD_DEVICE_ID_READ, ++ [NAND_CMD_ERASE2] = CMD_NULL, ++ [NAND_CMD_PARAM] = CMD_PARAMETER_READ, ++ [NAND_CMD_GET_FEATURES] = CMD_NOT_SUPPORTED, ++ [NAND_CMD_SET_FEATURES] = CMD_NOT_SUPPORTED, ++ [NAND_CMD_RESET] = CMD_NOT_SUPPORTED, ++ [NAND_CMD_READSTART] = CMD_NOT_SUPPORTED, ++ [NAND_CMD_READCACHESEQ] = CMD_NOT_SUPPORTED, ++ [NAND_CMD_READCACHEEND] = CMD_NOT_SUPPORTED, ++ [NAND_CMD_RNDOUTSTART] = CMD_NULL, ++ [NAND_CMD_CACHEDPROG] = CMD_NOT_SUPPORTED, ++}; ++ + /* Controller feature flags */ + enum { + BRCMNAND_HAS_1K_SECTORS = BIT(0), +@@ -237,6 +262,12 @@ struct brcmnand_controller { + /* List of NAND hosts (one for each chip-select) */ + struct list_head host_list; + ++ /* Functions to be called from exec_op */ ++ int (*check_instr)(struct nand_chip *chip, ++ const struct nand_operation *op); ++ int (*exec_instr)(struct nand_chip *chip, ++ const struct nand_operation *op); ++ + /* EDU info, per-transaction */ + const u16 *edu_offsets; + void __iomem *edu_base; +@@ -2478,18 +2509,190 @@ static int brcmnand_op_is_reset(const st + return 0; + } + ++static int brcmnand_check_instructions(struct nand_chip *chip, ++ const struct nand_operation *op) ++{ ++ return 0; ++} ++ ++static int brcmnand_exec_instructions(struct nand_chip *chip, ++ const struct nand_operation *op) ++{ ++ struct brcmnand_host *host = nand_get_controller_data(chip); ++ unsigned int i; ++ int ret = 0; ++ ++ for (i = 0; i < op->ninstrs; i++) { ++ ret = brcmnand_exec_instr(host, i, op); ++ if (ret) ++ break; ++ } ++ ++ return ret; ++} ++ ++static int brcmnand_check_instructions_legacy(struct nand_chip *chip, ++ const struct nand_operation *op) ++{ ++ const struct nand_op_instr *instr; ++ unsigned int i; ++ u8 cmd; ++ ++ for (i = 0; i < op->ninstrs; i++) { ++ instr = &op->instrs[i]; ++ ++ switch (instr->type) { ++ case NAND_OP_CMD_INSTR: ++ cmd = native_cmd_conv[instr->ctx.cmd.opcode]; ++ if (cmd == CMD_NOT_SUPPORTED) ++ return -EOPNOTSUPP; ++ break; ++ case NAND_OP_ADDR_INSTR: ++ case NAND_OP_DATA_IN_INSTR: ++ case NAND_OP_WAITRDY_INSTR: ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ } ++ ++ return 0; ++} ++ ++static int brcmnand_exec_instructions_legacy(struct nand_chip *chip, ++ const struct nand_operation *op) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ struct brcmnand_host *host = nand_get_controller_data(chip); ++ struct brcmnand_controller *ctrl = host->ctrl; ++ const struct nand_op_instr *instr; ++ unsigned int i, j; ++ u8 cmd = CMD_NULL, last_cmd = CMD_NULL; ++ int ret = 0; ++ u64 last_addr; ++ ++ for (i = 0; i < op->ninstrs; i++) { ++ instr = &op->instrs[i]; ++ ++ if (instr->type == NAND_OP_CMD_INSTR) { ++ cmd = native_cmd_conv[instr->ctx.cmd.opcode]; ++ if (cmd == CMD_NOT_SUPPORTED) { ++ dev_err(ctrl->dev, "unsupported cmd=%d\n", ++ instr->ctx.cmd.opcode); ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ } else if (instr->type == NAND_OP_ADDR_INSTR) { ++ u64 addr = 0; ++ ++ if (cmd == CMD_NULL) ++ continue; ++ ++ if (instr->ctx.addr.naddrs > 8) { ++ dev_err(ctrl->dev, "unsupported naddrs=%u\n", ++ instr->ctx.addr.naddrs); ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ ++ for (j = 0; j < instr->ctx.addr.naddrs; j++) ++ addr |= (instr->ctx.addr.addrs[j]) << (j << 3); ++ ++ if (cmd == CMD_BLOCK_ERASE) ++ addr <<= chip->page_shift; ++ else if (cmd == CMD_PARAMETER_CHANGE_COL) ++ addr &= ~((u64)(FC_BYTES - 1)); ++ ++ brcmnand_set_cmd_addr(mtd, addr); ++ brcmnand_send_cmd(host, cmd); ++ last_addr = addr; ++ last_cmd = cmd; ++ cmd = CMD_NULL; ++ brcmnand_waitfunc(chip); ++ ++ if (last_cmd == CMD_PARAMETER_READ || ++ last_cmd == CMD_PARAMETER_CHANGE_COL) { ++ /* Copy flash cache word-wise */ ++ u32 *flash_cache = (u32 *)ctrl->flash_cache; ++ ++ brcmnand_soc_data_bus_prepare(ctrl->soc, true); ++ ++ /* ++ * Must cache the FLASH_CACHE now, since changes in ++ * SECTOR_SIZE_1K may invalidate it ++ */ ++ for (j = 0; j < FC_WORDS; j++) ++ /* ++ * Flash cache is big endian for parameter pages, at ++ * least on STB SoCs ++ */ ++ flash_cache[j] = be32_to_cpu(brcmnand_read_fc(ctrl, j)); ++ ++ brcmnand_soc_data_bus_unprepare(ctrl->soc, true); ++ } ++ } else if (instr->type == NAND_OP_DATA_IN_INSTR) { ++ u8 *in = instr->ctx.data.buf.in; ++ ++ if (last_cmd == CMD_DEVICE_ID_READ) { ++ u32 val; ++ ++ if (instr->ctx.data.len > 8) { ++ dev_err(ctrl->dev, "unsupported len=%u\n", ++ instr->ctx.data.len); ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ ++ for (j = 0; j < instr->ctx.data.len; j++) { ++ if (j == 0) ++ val = brcmnand_read_reg(ctrl, BRCMNAND_ID); ++ else if (j == 4) ++ val = brcmnand_read_reg(ctrl, BRCMNAND_ID_EXT); ++ ++ in[j] = (val >> (24 - ((j % 4) << 3))) & 0xff; ++ } ++ } else if (last_cmd == CMD_PARAMETER_READ || ++ last_cmd == CMD_PARAMETER_CHANGE_COL) { ++ u64 addr; ++ u32 offs; ++ ++ for (j = 0; j < instr->ctx.data.len; j++) { ++ addr = last_addr + j; ++ offs = addr & (FC_BYTES - 1); ++ ++ if (j > 0 && offs == 0) ++ nand_change_read_column_op(chip, addr, NULL, 0, ++ false); ++ ++ in[j] = ctrl->flash_cache[offs]; ++ } ++ } ++ } else if (instr->type == NAND_OP_WAITRDY_INSTR) { ++ ret = bcmnand_ctrl_poll_status(host, NAND_CTRL_RDY, NAND_CTRL_RDY, 0); ++ if (ret) ++ break; ++ } else { ++ dev_err(ctrl->dev, "unsupported instruction type: %d\n", instr->type); ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ } ++ ++ return ret; ++} ++ + static int brcmnand_exec_op(struct nand_chip *chip, + const struct nand_operation *op, + bool check_only) + { + struct brcmnand_host *host = nand_get_controller_data(chip); ++ struct brcmnand_controller *ctrl = host->ctrl; + struct mtd_info *mtd = nand_to_mtd(chip); + u8 *status; +- unsigned int i; + int ret = 0; + + if (check_only) +- return 0; ++ return ctrl->check_instr(chip, op); + + if (brcmnand_op_is_status(op)) { + status = op->instrs[1].ctx.data.buf.in; +@@ -2513,11 +2716,7 @@ static int brcmnand_exec_op(struct nand_ + if (op->deassert_wp) + brcmnand_wp(mtd, 0); + +- for (i = 0; i < op->ninstrs; i++) { +- ret = brcmnand_exec_instr(host, i, op); +- if (ret) +- break; +- } ++ ret = ctrl->exec_instr(chip, op); + + if (op->deassert_wp) + brcmnand_wp(mtd, 1); +@@ -3130,6 +3329,15 @@ int brcmnand_probe(struct platform_devic + if (ret) + goto err; + ++ /* Only v5.0+ controllers have low level ops support */ ++ if (ctrl->nand_version >= 0x0500) { ++ ctrl->check_instr = brcmnand_check_instructions; ++ ctrl->exec_instr = brcmnand_exec_instructions; ++ } else { ++ ctrl->check_instr = brcmnand_check_instructions_legacy; ++ ctrl->exec_instr = brcmnand_exec_instructions_legacy; ++ } ++ + /* + * Most chips have this cache at a fixed offset within 'nand' block. + * Some must specify this region separately. diff --git a/lede/target/linux/generic/backport-6.12/422-v6.17-spi-spi-qpic-snand-unregister-ECC-engine-on-probe-er.patch b/lede/target/linux/generic/backport-6.12/422-v6.17-spi-spi-qpic-snand-unregister-ECC-engine-on-probe-er.patch new file mode 100644 index 0000000000..46184b53c5 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/422-v6.17-spi-spi-qpic-snand-unregister-ECC-engine-on-probe-er.patch @@ -0,0 +1,48 @@ +From 1991a458528588ff34e98b6365362560d208710f Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Wed, 3 Sep 2025 13:56:24 +0200 +Subject: spi: spi-qpic-snand: unregister ECC engine on probe error and device + remove + +The on-host hardware ECC engine remains registered both when +the spi_register_controller() function returns with an error +and also on device removal. + +Change the qcom_spi_probe() function to unregister the engine +on the error path, and add the missing unregistering call to +qcom_spi_remove() to avoid possible use-after-free issues. + +Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") +Signed-off-by: Gabor Juhos +Message-ID: <20250903-qpic-snand-unregister-ecceng-v1-1-ef5387b0abdc@gmail.com> +Signed-off-by: Mark Brown +--- + drivers/spi/spi-qpic-snand.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/spi/spi-qpic-snand.c ++++ b/drivers/spi/spi-qpic-snand.c +@@ -1632,11 +1632,13 @@ static int qcom_spi_probe(struct platfor + ret = spi_register_controller(ctlr); + if (ret) { + dev_err(&pdev->dev, "spi_register_controller failed.\n"); +- goto err_spi_init; ++ goto err_register_controller; + } + + return 0; + ++err_register_controller: ++ nand_ecc_unregister_on_host_hw_engine(&snandc->qspi->ecc_eng); + err_spi_init: + qcom_nandc_unalloc(snandc); + err_snand_alloc: +@@ -1658,7 +1660,7 @@ static void qcom_spi_remove(struct platf + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + spi_unregister_controller(ctlr); +- ++ nand_ecc_unregister_on_host_hw_engine(&snandc->qspi->ecc_eng); + qcom_nandc_unalloc(snandc); + + clk_disable_unprepare(snandc->aon_clk); diff --git a/lede/target/linux/generic/backport-6.12/429-01-v6.18-mtd-spinand-fix-direct-mapping-creation-sizes.patch b/lede/target/linux/generic/backport-6.12/429-01-v6.18-mtd-spinand-fix-direct-mapping-creation-sizes.patch new file mode 100644 index 0000000000..994e06e4fe --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/429-01-v6.18-mtd-spinand-fix-direct-mapping-creation-sizes.patch @@ -0,0 +1,63 @@ +From e4a0cf9f1d90e6888e5373da3314f761024f6c97 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Thu, 18 Sep 2025 00:53:59 +0300 +Subject: mtd: spinand: fix direct mapping creation sizes + +Continuous mode is only supported for data reads, thus writing +requires only single flash page mapping. + +Signed-off-by: Mikhail Kshevetskiy +Signed-off-by: Miquel Raynal +--- + drivers/mtd/nand/spi/core.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -1028,18 +1028,13 @@ static int spinand_create_dirmap(struct + unsigned int plane) + { + struct nand_device *nand = spinand_to_nand(spinand); +- struct spi_mem_dirmap_info info = { +- .length = nanddev_page_size(nand) + +- nanddev_per_page_oobsize(nand), +- }; ++ struct spi_mem_dirmap_info info = { 0 }; + struct spi_mem_dirmap_desc *desc; + +- if (spinand->cont_read_possible) +- info.length = nanddev_eraseblock_size(nand); +- + /* The plane number is passed in MSB just above the column address */ + info.offset = plane << fls(nand->memorg.pagesize); + ++ info.length = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); + info.op_tmpl = *spinand->op_templates.update_cache; + desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, + spinand->spimem, &info); +@@ -1048,6 +1043,8 @@ static int spinand_create_dirmap(struct + + spinand->dirmaps[plane].wdesc = desc; + ++ if (spinand->cont_read_possible) ++ info.length = nanddev_eraseblock_size(nand); + info.op_tmpl = *spinand->op_templates.read_cache; + desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, + spinand->spimem, &info); +@@ -1063,6 +1060,7 @@ static int spinand_create_dirmap(struct + return 0; + } + ++ info.length = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); + info.op_tmpl = *spinand->op_templates.update_cache; + info.op_tmpl.data.ecc = true; + desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, +@@ -1072,6 +1070,8 @@ static int spinand_create_dirmap(struct + + spinand->dirmaps[plane].wdesc_ecc = desc; + ++ if (spinand->cont_read_possible) ++ info.length = nanddev_eraseblock_size(nand); + info.op_tmpl = *spinand->op_templates.read_cache; + info.op_tmpl.data.ecc = true; + desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, diff --git a/lede/target/linux/generic/backport-6.12/429-02-v6.18-mtd-spinand-try-a-regular-dirmap-if-creating-a-di.patch b/lede/target/linux/generic/backport-6.12/429-02-v6.18-mtd-spinand-try-a-regular-dirmap-if-creating-a-di.patch new file mode 100644 index 0000000000..005c0aa9a1 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/429-02-v6.18-mtd-spinand-try-a-regular-dirmap-if-creating-a-di.patch @@ -0,0 +1,98 @@ +From 004f8ea0d9917398aabff7388b3bf62a84a4088b Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Thu, 18 Sep 2025 00:54:00 +0300 +Subject: mtd: spinand: try a regular dirmap if creating a dirmap for + continuous reading fails + +Continuous reading may result in multiple flash pages reading in one +operation. Typically only one flash page has read/written (a little bit +more than 2-4 Kb), but continuous reading requires the spi controller +to read up to 512 Kb in one operation without toggling CS in beetween. + +Roughly speaking spi controllers can be divided on 2 categories: + * spi controllers without dirmap acceleration support + * spi controllers with dirmap acceleration support + +Firt of them will have issues with continuous reading if restriction on +the transfer length is implemented in the adjust_op_size() handler. +Second group often supports acceleration of single page only reading. +Thus enabling of continuous reading can break flash reading. + +This patch tries to create dirmap for continuous reading first and +fallback to regular reading if spi controller refuses to create it. + +Signed-off-by: Mikhail Kshevetskiy +Signed-off-by: Miquel Raynal +--- + drivers/mtd/nand/spi/core.c | 43 ++++++++++++++++++++++++++++++------- + 1 file changed, 35 insertions(+), 8 deletions(-) + +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -1024,6 +1024,39 @@ static int spinand_mtd_block_isreserved( + return ret; + } + ++static struct spi_mem_dirmap_desc *spinand_create_rdesc( ++ struct spinand_device *spinand, ++ struct spi_mem_dirmap_info *info) ++{ ++ struct nand_device *nand = spinand_to_nand(spinand); ++ struct spi_mem_dirmap_desc *desc = NULL; ++ ++ if (spinand->cont_read_possible) { ++ /* ++ * spi controller may return an error if info->length is ++ * too large ++ */ ++ info->length = nanddev_eraseblock_size(nand); ++ desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, ++ spinand->spimem, info); ++ } ++ ++ if (IS_ERR_OR_NULL(desc)) { ++ /* ++ * continuous reading is not supported by flash or ++ * its spi controller, use regular reading ++ */ ++ spinand->cont_read_possible = false; ++ ++ info->length = nanddev_page_size(nand) + ++ nanddev_per_page_oobsize(nand); ++ desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, ++ spinand->spimem, info); ++ } ++ ++ return desc; ++} ++ + static int spinand_create_dirmap(struct spinand_device *spinand, + unsigned int plane) + { +@@ -1043,11 +1076,8 @@ static int spinand_create_dirmap(struct + + spinand->dirmaps[plane].wdesc = desc; + +- if (spinand->cont_read_possible) +- info.length = nanddev_eraseblock_size(nand); + info.op_tmpl = *spinand->op_templates.read_cache; +- desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, +- spinand->spimem, &info); ++ desc = spinand_create_rdesc(spinand, &info); + if (IS_ERR(desc)) + return PTR_ERR(desc); + +@@ -1070,12 +1100,9 @@ static int spinand_create_dirmap(struct + + spinand->dirmaps[plane].wdesc_ecc = desc; + +- if (spinand->cont_read_possible) +- info.length = nanddev_eraseblock_size(nand); + info.op_tmpl = *spinand->op_templates.read_cache; + info.op_tmpl.data.ecc = true; +- desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, +- spinand->spimem, &info); ++ desc = spinand_create_rdesc(spinand, &info); + if (IS_ERR(desc)) + return PTR_ERR(desc); + diff --git a/lede/target/linux/generic/backport-6.12/429-03-v6.18-mtd-spinand-repeat-reading-in-regular-mode-if-con.patch b/lede/target/linux/generic/backport-6.12/429-03-v6.18-mtd-spinand-repeat-reading-in-regular-mode-if-con.patch new file mode 100644 index 0000000000..af53d2065e --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/429-03-v6.18-mtd-spinand-repeat-reading-in-regular-mode-if-con.patch @@ -0,0 +1,64 @@ +From 010dc7f2dd6a0078ade3f88f627ed5fbf45ceb94 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Thu, 18 Sep 2025 00:54:01 +0300 +Subject: mtd: spinand: repeat reading in regular mode if continuous reading + fails + +Continuous reading may result in multiple flash pages reading in one +operation. Unfortunately, not all spinand controllers support such +large reading. They will read less data. Unfortunately, the operation +can't be continued. + +In this case: + * disable continuous reading on this (not good enough) spi controller + * repeat reading in regular mode. + +Signed-off-by: Mikhail Kshevetskiy +Signed-off-by: Miquel Raynal +--- + drivers/mtd/nand/spi/core.c | 25 +++++++++++++++++++++---- + 1 file changed, 21 insertions(+), 4 deletions(-) + +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -427,8 +427,16 @@ static int spinand_read_from_cache_op(st + * Dirmap accesses are allowed to toggle the CS. + * Toggling the CS during a continuous read is forbidden. + */ +- if (nbytes && req->continuous) +- return -EIO; ++ if (nbytes && req->continuous) { ++ /* ++ * Spi controller with broken support of continuous ++ * reading was detected. Disable future use of ++ * continuous reading and return -EAGAIN to retry ++ * reading within regular mode. ++ */ ++ spinand->cont_read_possible = false; ++ return -EAGAIN; ++ } + } + + if (req->datalen) +@@ -841,10 +849,19 @@ static int spinand_mtd_read(struct mtd_i + + old_stats = mtd->ecc_stats; + +- if (spinand_use_cont_read(mtd, from, ops)) ++ if (spinand_use_cont_read(mtd, from, ops)) { + ret = spinand_mtd_continuous_page_read(mtd, from, ops, &max_bitflips); +- else ++ if (ret == -EAGAIN && !spinand->cont_read_possible) { ++ /* ++ * Spi controller with broken support of continuous ++ * reading was detected (see spinand_read_from_cache_op()), ++ * repeat reading in regular mode. ++ */ ++ ret = spinand_mtd_regular_page_read(mtd, from, ops, &max_bitflips); ++ } ++ } else { + ret = spinand_mtd_regular_page_read(mtd, from, ops, &max_bitflips); ++ } + + if (ops->stats) { + ops->stats->uncorrectable_errors += diff --git a/lede/target/linux/generic/backport-6.12/422-v6.19-mtd-spinand-esmt-add-support-for-F50L1G41LC.patch b/lede/target/linux/generic/backport-6.12/434-v6.19-mtd-spinand-esmt-add-support-for-F50L1G41LC.patch similarity index 98% rename from lede/target/linux/generic/backport-6.12/422-v6.19-mtd-spinand-esmt-add-support-for-F50L1G41LC.patch rename to lede/target/linux/generic/backport-6.12/434-v6.19-mtd-spinand-esmt-add-support-for-F50L1G41LC.patch index b65df4ea91..8350f148a3 100644 --- a/lede/target/linux/generic/backport-6.12/422-v6.19-mtd-spinand-esmt-add-support-for-F50L1G41LC.patch +++ b/lede/target/linux/generic/backport-6.12/434-v6.19-mtd-spinand-esmt-add-support-for-F50L1G41LC.patch @@ -19,7 +19,7 @@ Signed-off-by: Miquel Raynal --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c -@@ -1114,6 +1114,7 @@ static const struct nand_ops spinand_ops +@@ -1158,6 +1158,7 @@ static const struct nand_ops spinand_ops static const struct spinand_manufacturer *spinand_manufacturers[] = { &alliancememory_spinand_manufacturer, &ato_spinand_manufacturer, diff --git a/lede/target/linux/generic/backport-6.12/435-v6.19-mtd-spinand-add-support-for-FudanMicro-FM25S01BI3.patch b/lede/target/linux/generic/backport-6.12/435-v6.19-mtd-spinand-add-support-for-FudanMicro-FM25S01BI3.patch new file mode 100644 index 0000000000..7355efe36b --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/435-v6.19-mtd-spinand-add-support-for-FudanMicro-FM25S01BI3.patch @@ -0,0 +1,115 @@ +From f6dffe2a9ed1bdcee1879e2728310fb1e08602cf Mon Sep 17 00:00:00 2001 +From: Mikhail Zhilkin +Date: Thu, 27 Nov 2025 22:59:00 +0300 +Subject: mtd: spinand: add support for FudanMicro FM25S01BI3 + +Add support for FudanMicro FM25S01BI3 SPI NAND. + +Link: https://www.fmsh.com/nvm/FM25S01BI3_ds_eng.pdf + +Signed-off-by: Mikhail Zhilkin +Signed-off-by: Miquel Raynal +--- + drivers/mtd/nand/spi/fmsh.c | 72 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 72 insertions(+) + +--- a/drivers/mtd/nand/spi/fmsh.c ++++ b/drivers/mtd/nand/spi/fmsh.c +@@ -9,6 +9,13 @@ + #include + #include + ++#define FM25S01BI3_STATUS_ECC_MASK (7 << 4) ++ #define FM25S01BI3_STATUS_ECC_NO_BITFLIPS (0 << 4) ++ #define FM25S01BI3_STATUS_ECC_1_3_BITFLIPS (1 << 4) ++ #define FM25S01BI3_STATUS_ECC_UNCOR_ERROR (2 << 4) ++ #define FM25S01BI3_STATUS_ECC_4_6_BITFLIPS (3 << 4) ++ #define FM25S01BI3_STATUS_ECC_7_8_BITFLIPS (5 << 4) ++ + #define SPINAND_MFR_FMSH 0xA1 + + static SPINAND_OP_VARIANTS(read_cache_variants, +@@ -45,11 +52,66 @@ static int fm25s01a_ooblayout_free(struc + return 0; + } + ++static int fm25s01bi3_ecc_get_status(struct spinand_device *spinand, ++ u8 status) ++{ ++ switch (status & FM25S01BI3_STATUS_ECC_MASK) { ++ case FM25S01BI3_STATUS_ECC_NO_BITFLIPS: ++ return 0; ++ ++ case FM25S01BI3_STATUS_ECC_UNCOR_ERROR: ++ return -EBADMSG; ++ ++ case FM25S01BI3_STATUS_ECC_1_3_BITFLIPS: ++ return 3; ++ ++ case FM25S01BI3_STATUS_ECC_4_6_BITFLIPS: ++ return 6; ++ ++ case FM25S01BI3_STATUS_ECC_7_8_BITFLIPS: ++ return 8; ++ ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++ ++static int fm25s01bi3_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section) ++ return -ERANGE; ++ ++ region->offset = 64; ++ region->length = 64; ++ ++ return 0; ++} ++ ++static int fm25s01bi3_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section > 3) ++ return -ERANGE; ++ ++ region->offset = (16 * section) + 4; ++ region->length = 12; ++ ++ return 0; ++} ++ + static const struct mtd_ooblayout_ops fm25s01a_ooblayout = { + .ecc = fm25s01a_ooblayout_ecc, + .free = fm25s01a_ooblayout_free, + }; + ++static const struct mtd_ooblayout_ops fm25s01bi3_ooblayout = { ++ .ecc = fm25s01bi3_ooblayout_ecc, ++ .free = fm25s01bi3_ooblayout_free, ++}; ++ + static const struct spinand_info fmsh_spinand_table[] = { + SPINAND_INFO("FM25S01A", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4), +@@ -60,6 +122,16 @@ static const struct spinand_info fmsh_sp + &update_cache_variants), + 0, + SPINAND_ECCINFO(&fm25s01a_ooblayout, NULL)), ++ SPINAND_INFO("FM25S01BI3", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xd4), ++ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&fm25s01bi3_ooblayout, ++ fm25s01bi3_ecc_get_status)), + }; + + static const struct spinand_manufacturer_ops fmsh_spinand_manuf_ops = { diff --git a/lede/target/linux/generic/backport-6.12/410-v6.13-01-block-add-support-for-defining-read-only-partitions.patch b/lede/target/linux/generic/backport-6.12/500-01-v6.13-block-add-support-for-defining-read-only-partitions.patch similarity index 96% rename from lede/target/linux/generic/backport-6.12/410-v6.13-01-block-add-support-for-defining-read-only-partitions.patch rename to lede/target/linux/generic/backport-6.12/500-01-v6.13-block-add-support-for-defining-read-only-partitions.patch index 7dd0031264..9e2977f3a7 100644 --- a/lede/target/linux/generic/backport-6.12/410-v6.13-01-block-add-support-for-defining-read-only-partitions.patch +++ b/lede/target/linux/generic/backport-6.12/500-01-v6.13-block-add-support-for-defining-read-only-partitions.patch @@ -19,7 +19,7 @@ Signed-off-by: Jens Axboe --- a/block/blk.h +++ b/block/blk.h -@@ -556,6 +556,7 @@ void blk_free_ext_minor(unsigned int min +@@ -570,6 +570,7 @@ void blk_free_ext_minor(unsigned int min #define ADDPART_FLAG_NONE 0 #define ADDPART_FLAG_RAID 1 #define ADDPART_FLAG_WHOLEDISK 2 diff --git a/lede/target/linux/generic/backport-6.12/410-v6.13-03-block-introduce-add_disk_fwnode.patch b/lede/target/linux/generic/backport-6.12/500-02-v6.13-block-introduce-add_disk_fwnode.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/410-v6.13-03-block-introduce-add_disk_fwnode.patch rename to lede/target/linux/generic/backport-6.12/500-02-v6.13-block-introduce-add_disk_fwnode.patch diff --git a/lede/target/linux/generic/backport-6.12/410-v6.13-04-mmc-block-attach-partitions-fwnode-if-found-in-mmc-c.patch b/lede/target/linux/generic/backport-6.12/500-03-v6.13-mmc-block-attach-partitions-fwnode-if-found-in-mmc-c.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/410-v6.13-04-mmc-block-attach-partitions-fwnode-if-found-in-mmc-c.patch rename to lede/target/linux/generic/backport-6.12/500-03-v6.13-mmc-block-attach-partitions-fwnode-if-found-in-mmc-c.patch diff --git a/lede/target/linux/generic/backport-6.12/410-v6.13-05-block-add-support-for-partition-table-defined-in-OF.patch b/lede/target/linux/generic/backport-6.12/500-04-v6.13-block-add-support-for-partition-table-defined-in-OF.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/410-v6.13-05-block-add-support-for-partition-table-defined-in-OF.patch rename to lede/target/linux/generic/backport-6.12/500-04-v6.13-block-add-support-for-partition-table-defined-in-OF.patch diff --git a/lede/target/linux/generic/backport-6.12/600-01-v6.13-net-phylink-move-manual-flow-control-setting.patch b/lede/target/linux/generic/backport-6.12/600-01-v6.13-net-phylink-move-manual-flow-control-setting.patch new file mode 100644 index 0000000000..a9b86c2508 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/600-01-v6.13-net-phylink-move-manual-flow-control-setting.patch @@ -0,0 +1,41 @@ +From 8cc5f4cb94c0b1c7c1ba8013c14fd02ffb1a25f3 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 8 Nov 2024 16:01:44 +0000 +Subject: [PATCH 1/5] net: phylink: move manual flow control setting + +Move the handling of manual flow control configuration to a common +location during resolve. We currently evaluate this for all but +fixed links. + +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1t9RQe-002Feh-T1@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1484,7 +1484,6 @@ static void phylink_resolve(struct work_ + switch (pl->cur_link_an_mode) { + case MLO_AN_PHY: + link_state = pl->phy_state; +- phylink_apply_manual_flow(pl, &link_state); + mac_config = link_state.link; + break; + +@@ -1545,11 +1544,13 @@ static void phylink_resolve(struct work_ + link_state.pause = pl->phy_state.pause; + mac_config = true; + } +- phylink_apply_manual_flow(pl, &link_state); + break; + } + } + ++ if (pl->cur_link_an_mode != MLO_AN_FIXED) ++ phylink_apply_manual_flow(pl, &link_state); ++ + if (mac_config) { + if (link_state.interface != pl->link_config.interface) { + /* The interface has changed, force the link down and diff --git a/lede/target/linux/generic/backport-6.12/600-02-v6.13-net-phylink-move-MLO_AN_FIXED-resolve-handling-to-if.patch b/lede/target/linux/generic/backport-6.12/600-02-v6.13-net-phylink-move-MLO_AN_FIXED-resolve-handling-to-if.patch new file mode 100644 index 0000000000..7ff091e85f --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/600-02-v6.13-net-phylink-move-MLO_AN_FIXED-resolve-handling-to-if.patch @@ -0,0 +1,42 @@ +From 92abfcb4ced482afbe65d18980e6734fe1e62a34 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 8 Nov 2024 16:01:50 +0000 +Subject: [PATCH 2/5] net: phylink: move MLO_AN_FIXED resolve handling to if() + statement + +The switch() statement doesn't sit very well with the preceeding if() +statements, and results in excessive indentation that spoils code +readability. Begin cleaning this up by converting the MLO_AN_FIXED case +to an if() statement. + +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1t9RQk-002Fen-1A@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1480,6 +1480,9 @@ static void phylink_resolve(struct work_ + } else if (pl->link_failed) { + link_state.link = false; + retrigger = true; ++ } else if (pl->cur_link_an_mode == MLO_AN_FIXED) { ++ phylink_get_fixed_state(pl, &link_state); ++ mac_config = link_state.link; + } else { + switch (pl->cur_link_an_mode) { + case MLO_AN_PHY: +@@ -1487,11 +1490,6 @@ static void phylink_resolve(struct work_ + mac_config = link_state.link; + break; + +- case MLO_AN_FIXED: +- phylink_get_fixed_state(pl, &link_state); +- mac_config = link_state.link; +- break; +- + case MLO_AN_INBAND: + phylink_mac_pcs_get_state(pl, &link_state); + diff --git a/lede/target/linux/generic/backport-6.12/600-03-v6.13-net-phylink-move-MLO_AN_PHY-resolve-handling-to-if-s.patch b/lede/target/linux/generic/backport-6.12/600-03-v6.13-net-phylink-move-MLO_AN_PHY-resolve-handling-to-if-s.patch new file mode 100644 index 0000000000..76e76fbba1 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/600-03-v6.13-net-phylink-move-MLO_AN_PHY-resolve-handling-to-if-s.patch @@ -0,0 +1,37 @@ +From f0f46c2a3d8ea9d1427298c8103a777d9e616c29 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 8 Nov 2024 16:01:55 +0000 +Subject: [PATCH 3/5] net: phylink: move MLO_AN_PHY resolve handling to if() + statement + +The switch() statement doesn't sit very well with the preceeding if() +statements, and results in excessive indentation that spoils code +readability. Continue cleaning this up by converting the MLO_AN_PHY +case to use an if() statmeent. + +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1t9RQp-002Fet-5W@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1483,13 +1483,11 @@ static void phylink_resolve(struct work_ + } else if (pl->cur_link_an_mode == MLO_AN_FIXED) { + phylink_get_fixed_state(pl, &link_state); + mac_config = link_state.link; ++ } else if (pl->cur_link_an_mode == MLO_AN_PHY) { ++ link_state = pl->phy_state; ++ mac_config = link_state.link; + } else { + switch (pl->cur_link_an_mode) { +- case MLO_AN_PHY: +- link_state = pl->phy_state; +- mac_config = link_state.link; +- break; +- + case MLO_AN_INBAND: + phylink_mac_pcs_get_state(pl, &link_state); + diff --git a/lede/target/linux/generic/backport-6.12/600-04-v6.13-net-phylink-remove-switch-statement-in-resolve-handl.patch b/lede/target/linux/generic/backport-6.12/600-04-v6.13-net-phylink-remove-switch-statement-in-resolve-handl.patch new file mode 100644 index 0000000000..989fc10b71 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/600-04-v6.13-net-phylink-remove-switch-statement-in-resolve-handl.patch @@ -0,0 +1,127 @@ +From d1a16dbbd84e02d2a6dcfcb8d5c4b8b2c0289f00 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 8 Nov 2024 16:02:00 +0000 +Subject: [PATCH 4/5] net: phylink: remove switch() statement in resolve + handling + +The switch() statement doesn't sit very well with the preceeding if() +statements, so let's just convert everything to if()s. As a result of +the two preceding commits, there is now only one case in the switch() +statement. Remove the switch statement and reduce the code indentation. +Code reformatting will be in the following commit. + +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1t9RQu-002Fez-AA@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 94 +++++++++++++++++++-------------------- + 1 file changed, 45 insertions(+), 49 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1487,60 +1487,56 @@ static void phylink_resolve(struct work_ + link_state = pl->phy_state; + mac_config = link_state.link; + } else { +- switch (pl->cur_link_an_mode) { +- case MLO_AN_INBAND: +- phylink_mac_pcs_get_state(pl, &link_state); +- +- /* The PCS may have a latching link-fail indicator. +- * If the link was up, bring the link down and +- * re-trigger the resolve. Otherwise, re-read the +- * PCS state to get the current status of the link. ++ phylink_mac_pcs_get_state(pl, &link_state); ++ ++ /* The PCS may have a latching link-fail indicator. ++ * If the link was up, bring the link down and ++ * re-trigger the resolve. Otherwise, re-read the ++ * PCS state to get the current status of the link. ++ */ ++ if (!link_state.link) { ++ if (cur_link_state) ++ retrigger = true; ++ else ++ phylink_mac_pcs_get_state(pl, ++ &link_state); ++ } ++ ++ /* If we have a phy, the "up" state is the union of ++ * both the PHY and the MAC ++ */ ++ if (pl->phydev) ++ link_state.link &= pl->phy_state.link; ++ ++ /* Only update if the PHY link is up */ ++ if (pl->phydev && pl->phy_state.link) { ++ /* If the interface has changed, force a ++ * link down event if the link isn't already ++ * down, and re-resolve. + */ +- if (!link_state.link) { +- if (cur_link_state) +- retrigger = true; +- else +- phylink_mac_pcs_get_state(pl, +- &link_state); ++ if (link_state.interface != ++ pl->phy_state.interface) { ++ retrigger = true; ++ link_state.link = false; + } ++ link_state.interface = pl->phy_state.interface; + +- /* If we have a phy, the "up" state is the union of +- * both the PHY and the MAC ++ /* If we are doing rate matching, then the ++ * link speed/duplex comes from the PHY + */ +- if (pl->phydev) +- link_state.link &= pl->phy_state.link; +- +- /* Only update if the PHY link is up */ +- if (pl->phydev && pl->phy_state.link) { +- /* If the interface has changed, force a +- * link down event if the link isn't already +- * down, and re-resolve. +- */ +- if (link_state.interface != +- pl->phy_state.interface) { +- retrigger = true; +- link_state.link = false; +- } +- link_state.interface = pl->phy_state.interface; +- +- /* If we are doing rate matching, then the +- * link speed/duplex comes from the PHY +- */ +- if (pl->phy_state.rate_matching) { +- link_state.rate_matching = +- pl->phy_state.rate_matching; +- link_state.speed = pl->phy_state.speed; +- link_state.duplex = +- pl->phy_state.duplex; +- } +- +- /* If we have a PHY, we need to update with +- * the PHY flow control bits. +- */ +- link_state.pause = pl->phy_state.pause; +- mac_config = true; ++ if (pl->phy_state.rate_matching) { ++ link_state.rate_matching = ++ pl->phy_state.rate_matching; ++ link_state.speed = pl->phy_state.speed; ++ link_state.duplex = ++ pl->phy_state.duplex; + } +- break; ++ ++ /* If we have a PHY, we need to update with ++ * the PHY flow control bits. ++ */ ++ link_state.pause = pl->phy_state.pause; ++ mac_config = true; + } + } + diff --git a/lede/target/linux/generic/backport-6.12/600-05-v6.13-net-phylink-clean-up-phylink_resolve.patch b/lede/target/linux/generic/backport-6.12/600-05-v6.13-net-phylink-clean-up-phylink_resolve.patch new file mode 100644 index 0000000000..285eea862e --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/600-05-v6.13-net-phylink-clean-up-phylink_resolve.patch @@ -0,0 +1,85 @@ +From bc08ce37d99a3992e975a0f397503cb23404f25a Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 8 Nov 2024 16:02:05 +0000 +Subject: [PATCH 5/5] net: phylink: clean up phylink_resolve() + +Now that we have reduced the indentation level, clean up the code +formatting. + +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1t9RQz-002Ff5-EA@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 35 ++++++++++++++++------------------- + 1 file changed, 16 insertions(+), 19 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1489,51 +1489,48 @@ static void phylink_resolve(struct work_ + } else { + phylink_mac_pcs_get_state(pl, &link_state); + +- /* The PCS may have a latching link-fail indicator. +- * If the link was up, bring the link down and +- * re-trigger the resolve. Otherwise, re-read the +- * PCS state to get the current status of the link. ++ /* The PCS may have a latching link-fail indicator. If the link ++ * was up, bring the link down and re-trigger the resolve. ++ * Otherwise, re-read the PCS state to get the current status ++ * of the link. + */ + if (!link_state.link) { + if (cur_link_state) + retrigger = true; + else +- phylink_mac_pcs_get_state(pl, +- &link_state); ++ phylink_mac_pcs_get_state(pl, &link_state); + } + +- /* If we have a phy, the "up" state is the union of +- * both the PHY and the MAC ++ /* If we have a phy, the "up" state is the union of both the ++ * PHY and the MAC + */ + if (pl->phydev) + link_state.link &= pl->phy_state.link; + + /* Only update if the PHY link is up */ + if (pl->phydev && pl->phy_state.link) { +- /* If the interface has changed, force a +- * link down event if the link isn't already +- * down, and re-resolve. ++ /* If the interface has changed, force a link down ++ * event if the link isn't already down, and re-resolve. + */ +- if (link_state.interface != +- pl->phy_state.interface) { ++ if (link_state.interface != pl->phy_state.interface) { + retrigger = true; + link_state.link = false; + } ++ + link_state.interface = pl->phy_state.interface; + +- /* If we are doing rate matching, then the +- * link speed/duplex comes from the PHY ++ /* If we are doing rate matching, then the link ++ * speed/duplex comes from the PHY + */ + if (pl->phy_state.rate_matching) { + link_state.rate_matching = + pl->phy_state.rate_matching; + link_state.speed = pl->phy_state.speed; +- link_state.duplex = +- pl->phy_state.duplex; ++ link_state.duplex = pl->phy_state.duplex; + } + +- /* If we have a PHY, we need to update with +- * the PHY flow control bits. ++ /* If we have a PHY, we need to update with the PHY ++ * flow control bits. + */ + link_state.pause = pl->phy_state.pause; + mac_config = true; diff --git a/lede/target/linux/generic/backport-6.12/601-01-v6.14-net-phylink-pass-phylink-and-pcs-into-phylink_pcs_ne.patch b/lede/target/linux/generic/backport-6.12/601-01-v6.14-net-phylink-pass-phylink-and-pcs-into-phylink_pcs_ne.patch new file mode 100644 index 0000000000..6868cd1518 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/601-01-v6.14-net-phylink-pass-phylink-and-pcs-into-phylink_pcs_ne.patch @@ -0,0 +1,95 @@ +From 17ed1911f9c8d4f9af8e13b2c95103ee06dadc0f Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 3 Dec 2024 15:30:47 +0000 +Subject: [PATCH 01/13] net: phylink: pass phylink and pcs into + phylink_pcs_neg_mode() + +Move the call to phylink_pcs_neg_mode() in phylink_major_config() after +we have selected the appropriate PCS to allow the PCS to be passed in. + +Add struct phylink and struct phylink_pcs pointers to +phylink_pcs_neg_mode() and pass in the appropriate structures. Set +pl->pcs_neg_mode before returning, and remove the return value. + +This will allow the capabilities of the PCS and any PHY to be used when +deciding which pcs_neg_mode should be used. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUrP-006ITh-6u@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1102,7 +1102,8 @@ static void phylink_pcs_an_restart(struc + + /** + * phylink_pcs_neg_mode() - helper to determine PCS inband mode +- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. ++ * @pl: a pointer to a &struct phylink returned from phylink_create() ++ * @pcs: a pointer to &struct phylink_pcs + * @interface: interface mode to be used + * @advertising: adertisement ethtool link mode mask + * +@@ -1119,11 +1120,13 @@ static void phylink_pcs_an_restart(struc + * Note: this is for cases where the PCS itself is involved in negotiation + * (e.g. Clause 37, SGMII and similar) not Clause 73. + */ +-static unsigned int phylink_pcs_neg_mode(unsigned int mode, +- phy_interface_t interface, +- const unsigned long *advertising) ++static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs, ++ phy_interface_t interface, ++ const unsigned long *advertising) + { +- unsigned int neg_mode; ++ unsigned int neg_mode, mode; ++ ++ mode = pl->cur_link_an_mode; + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: +@@ -1164,7 +1167,7 @@ static unsigned int phylink_pcs_neg_mode + break; + } + +- return neg_mode; ++ pl->pcs_neg_mode = neg_mode; + } + + static void phylink_major_config(struct phylink *pl, bool restart, +@@ -1178,10 +1181,6 @@ static void phylink_major_config(struct + + 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)) { +@@ -1194,6 +1193,8 @@ static void phylink_major_config(struct + pcs_changed = pcs && pl->pcs != pcs; + } + ++ phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising); ++ + phylink_pcs_poll_stop(pl); + + if (pl->mac_ops->mac_prepare) { +@@ -1284,9 +1285,8 @@ static int phylink_change_inband_advert( + 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); ++ phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface, ++ pl->link_config.advertising); + + neg_mode = pl->cur_link_an_mode; + if (pl->pcs->neg_mode) diff --git a/lede/target/linux/generic/backport-6.12/601-02-v6.14-net-phylink-split-cur_link_an_mode-into-requested-an.patch b/lede/target/linux/generic/backport-6.12/601-02-v6.14-net-phylink-split-cur_link_an_mode-into-requested-an.patch new file mode 100644 index 0000000000..76f4d5a48b --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/601-02-v6.14-net-phylink-split-cur_link_an_mode-into-requested-an.patch @@ -0,0 +1,290 @@ +From 1f92ead7e15003f632b5f138e8138095e0997d3d Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 3 Dec 2024 15:30:52 +0000 +Subject: [PATCH 02/13] net: phylink: split cur_link_an_mode into requested and + active + +There is an interdependence between the current link_an_mode and +pcs_neg_mode that some drivers rely upon to know whether inband or PHY +mode will be used. + +In order to support detection of PCS and PHY inband capabilities +resulting in automatic selection of inband or PHY mode, we need to +cater for this, and support changing the MAC link_an_mode. However, we +end up with an inter-dependency between the current link_an_mode and +pcs_neg_mode. + +To solve this, split the current link_an_mode into the requested +link_an_mode and active link_an_mode. The requested link_an_mode will +always be passed to phylink_pcs_neg_mode(), and the active link_an_mode +will be used for everything else, and only updated during +phylink_major_config(). This will ensure that phylink_pcs_neg_mode()'s +link_an_mode will not depend on the active link_an_mode that will, +in a future patch, depend on pcs_neg_mode. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUrU-006ITn-Ai@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 60 ++++++++++++++++++++------------------- + 1 file changed, 31 insertions(+), 29 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -56,7 +56,8 @@ struct phylink { + struct phy_device *phydev; + phy_interface_t link_interface; /* PHY_INTERFACE_xxx */ + u8 cfg_link_an_mode; /* MLO_AN_xxx */ +- u8 cur_link_an_mode; ++ u8 req_link_an_mode; /* Requested MLO_AN_xxx mode */ ++ u8 act_link_an_mode; /* Active MLO_AN_xxx mode */ + u8 link_port; /* The current non-phy ethtool port */ + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); + +@@ -1082,13 +1083,13 @@ static void phylink_mac_config(struct ph + + phylink_dbg(pl, + "%s: mode=%s/%s/%s adv=%*pb pause=%02x\n", +- __func__, phylink_an_mode_str(pl->cur_link_an_mode), ++ __func__, phylink_an_mode_str(pl->act_link_an_mode), + phy_modes(st.interface), + phy_rate_matching_to_str(st.rate_matching), + __ETHTOOL_LINK_MODE_MASK_NBITS, st.advertising, + st.pause); + +- pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, &st); ++ pl->mac_ops->mac_config(pl->config, pl->act_link_an_mode, &st); + } + + static void phylink_pcs_an_restart(struct phylink *pl) +@@ -1096,7 +1097,7 @@ static void phylink_pcs_an_restart(struc + if (pl->pcs && 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)) ++ phylink_autoneg_inband(pl->act_link_an_mode)) + pl->pcs->ops->pcs_an_restart(pl->pcs); + } + +@@ -1126,7 +1127,7 @@ static void phylink_pcs_neg_mode(struct + { + unsigned int neg_mode, mode; + +- mode = pl->cur_link_an_mode; ++ mode = pl->req_link_an_mode; + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: +@@ -1168,6 +1169,7 @@ static void phylink_pcs_neg_mode(struct + } + + pl->pcs_neg_mode = neg_mode; ++ pl->act_link_an_mode = mode; + } + + static void phylink_major_config(struct phylink *pl, bool restart, +@@ -1198,7 +1200,7 @@ static void phylink_major_config(struct + phylink_pcs_poll_stop(pl); + + if (pl->mac_ops->mac_prepare) { +- err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode, ++ err = pl->mac_ops->mac_prepare(pl->config, pl->act_link_an_mode, + state->interface); + if (err < 0) { + phylink_err(pl, "mac_prepare failed: %pe\n", +@@ -1232,7 +1234,7 @@ static void phylink_major_config(struct + if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed) + phylink_pcs_enable(pl->pcs); + +- neg_mode = pl->cur_link_an_mode; ++ neg_mode = pl->act_link_an_mode; + if (pl->pcs && pl->pcs->neg_mode) + neg_mode = pl->pcs_neg_mode; + +@@ -1248,7 +1250,7 @@ static void phylink_major_config(struct + phylink_pcs_an_restart(pl); + + if (pl->mac_ops->mac_finish) { +- err = pl->mac_ops->mac_finish(pl->config, pl->cur_link_an_mode, ++ err = pl->mac_ops->mac_finish(pl->config, pl->act_link_an_mode, + state->interface); + if (err < 0) + phylink_err(pl, "mac_finish failed: %pe\n", +@@ -1279,7 +1281,7 @@ static int phylink_change_inband_advert( + return 0; + + phylink_dbg(pl, "%s: mode=%s/%s adv=%*pb pause=%02x\n", __func__, +- phylink_an_mode_str(pl->cur_link_an_mode), ++ phylink_an_mode_str(pl->req_link_an_mode), + phy_modes(pl->link_config.interface), + __ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising, + pl->link_config.pause); +@@ -1288,7 +1290,7 @@ static int phylink_change_inband_advert( + phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface, + pl->link_config.advertising); + +- neg_mode = pl->cur_link_an_mode; ++ neg_mode = pl->act_link_an_mode; + if (pl->pcs->neg_mode) + neg_mode = pl->pcs_neg_mode; + +@@ -1353,7 +1355,7 @@ static void phylink_mac_initial_config(s + { + struct phylink_link_state link_state; + +- switch (pl->cur_link_an_mode) { ++ switch (pl->req_link_an_mode) { + case MLO_AN_PHY: + link_state = pl->phy_state; + break; +@@ -1427,14 +1429,14 @@ static void phylink_link_up(struct phyli + + pl->cur_interface = link_state.interface; + +- neg_mode = pl->cur_link_an_mode; ++ neg_mode = pl->act_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->mac_ops->mac_link_up(pl->config, pl->phydev, pl->act_link_an_mode, + pl->cur_interface, speed, duplex, + !!(link_state.pause & MLO_PAUSE_TX), rx_pause); + +@@ -1454,7 +1456,7 @@ static void phylink_link_down(struct phy + + if (ndev) + netif_carrier_off(ndev); +- pl->mac_ops->mac_link_down(pl->config, pl->cur_link_an_mode, ++ pl->mac_ops->mac_link_down(pl->config, pl->act_link_an_mode, + pl->cur_interface); + phylink_info(pl, "Link is Down\n"); + } +@@ -1480,10 +1482,10 @@ static void phylink_resolve(struct work_ + } else if (pl->link_failed) { + link_state.link = false; + retrigger = true; +- } else if (pl->cur_link_an_mode == MLO_AN_FIXED) { ++ } else if (pl->act_link_an_mode == MLO_AN_FIXED) { + phylink_get_fixed_state(pl, &link_state); + mac_config = link_state.link; +- } else if (pl->cur_link_an_mode == MLO_AN_PHY) { ++ } else if (pl->act_link_an_mode == MLO_AN_PHY) { + link_state = pl->phy_state; + mac_config = link_state.link; + } else { +@@ -1537,7 +1539,7 @@ static void phylink_resolve(struct work_ + } + } + +- if (pl->cur_link_an_mode != MLO_AN_FIXED) ++ if (pl->act_link_an_mode != MLO_AN_FIXED) + phylink_apply_manual_flow(pl, &link_state); + + if (mac_config) { +@@ -1661,7 +1663,7 @@ int phylink_set_fixed_link(struct phylin + pl->link_config.an_complete = 1; + + pl->cfg_link_an_mode = MLO_AN_FIXED; +- pl->cur_link_an_mode = pl->cfg_link_an_mode; ++ pl->req_link_an_mode = pl->cfg_link_an_mode; + + return 0; + } +@@ -1756,7 +1758,7 @@ struct phylink *phylink_create(struct ph + } + } + +- pl->cur_link_an_mode = pl->cfg_link_an_mode; ++ pl->req_link_an_mode = pl->cfg_link_an_mode; + + ret = phylink_register_sfp(pl, fwnode); + if (ret < 0) { +@@ -2213,7 +2215,7 @@ void phylink_start(struct phylink *pl) + ASSERT_RTNL(); + + phylink_info(pl, "configuring for %s/%s link mode\n", +- phylink_an_mode_str(pl->cur_link_an_mode), ++ phylink_an_mode_str(pl->req_link_an_mode), + phy_modes(pl->link_config.interface)); + + /* Always set the carrier off */ +@@ -2472,7 +2474,7 @@ int phylink_ethtool_ksettings_get(struct + + linkmode_copy(kset->link_modes.supported, pl->supported); + +- switch (pl->cur_link_an_mode) { ++ switch (pl->act_link_an_mode) { + case MLO_AN_FIXED: + /* We are using fixed settings. Report these as the + * current link settings - and note that these also +@@ -2564,7 +2566,7 @@ int phylink_ethtool_ksettings_set(struct + /* If we have a fixed link, refuse to change link parameters. + * If the link parameters match, accept them but do nothing. + */ +- if (pl->cur_link_an_mode == MLO_AN_FIXED) { ++ if (pl->req_link_an_mode == MLO_AN_FIXED) { + if (s->speed != pl->link_config.speed || + s->duplex != pl->link_config.duplex) + return -EINVAL; +@@ -2580,7 +2582,7 @@ int phylink_ethtool_ksettings_set(struct + * is our default case) but do not allow the advertisement to + * be changed. If the advertisement matches, simply return. + */ +- if (pl->cur_link_an_mode == MLO_AN_FIXED) { ++ if (pl->req_link_an_mode == MLO_AN_FIXED) { + if (!linkmode_equal(config.advertising, + pl->link_config.advertising)) + return -EINVAL; +@@ -2620,7 +2622,7 @@ int phylink_ethtool_ksettings_set(struct + linkmode_copy(support, pl->supported); + if (phylink_validate(pl, support, &config)) { + phylink_err(pl, "validation of %s/%s with support %*pb failed\n", +- phylink_an_mode_str(pl->cur_link_an_mode), ++ phylink_an_mode_str(pl->req_link_an_mode), + phy_modes(config.interface), + __ETHTOOL_LINK_MODE_MASK_NBITS, support); + return -EINVAL; +@@ -2720,7 +2722,7 @@ int phylink_ethtool_set_pauseparam(struc + + ASSERT_RTNL(); + +- if (pl->cur_link_an_mode == MLO_AN_FIXED) ++ if (pl->req_link_an_mode == MLO_AN_FIXED) + return -EOPNOTSUPP; + + if (!phylink_test(pl->supported, Pause) && +@@ -2984,7 +2986,7 @@ static int phylink_mii_read(struct phyli + struct phylink_link_state state; + int val = 0xffff; + +- switch (pl->cur_link_an_mode) { ++ switch (pl->act_link_an_mode) { + case MLO_AN_FIXED: + if (phy_id == 0) { + phylink_get_fixed_state(pl, &state); +@@ -3009,7 +3011,7 @@ static int phylink_mii_read(struct phyli + static int phylink_mii_write(struct phylink *pl, unsigned int phy_id, + unsigned int reg, unsigned int val) + { +- switch (pl->cur_link_an_mode) { ++ switch (pl->act_link_an_mode) { + case MLO_AN_FIXED: + break; + +@@ -3199,9 +3201,9 @@ static void phylink_sfp_set_config(struc + changed = true; + } + +- if (pl->cur_link_an_mode != mode || ++ if (pl->req_link_an_mode != mode || + pl->link_config.interface != state->interface) { +- pl->cur_link_an_mode = mode; ++ pl->req_link_an_mode = mode; + pl->link_config.interface = state->interface; + + changed = true; diff --git a/lede/target/linux/generic/backport-6.12/601-03-v6.14-net-phylink-add-debug-for-phylink_major_config.patch b/lede/target/linux/generic/backport-6.12/601-03-v6.14-net-phylink-add-debug-for-phylink_major_config.patch new file mode 100644 index 0000000000..ee625c7486 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/601-03-v6.14-net-phylink-add-debug-for-phylink_major_config.patch @@ -0,0 +1,66 @@ +From 4e7d000286fe8e12f2d88032711ffab3ab658b12 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 3 Dec 2024 15:30:57 +0000 +Subject: [PATCH 03/13] net: phylink: add debug for phylink_major_config() + +Now that we have a more complexity in phylink_major_config(), augment +the debugging so we can see what's going on there. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUrZ-006ITt-Fa@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 27 ++++++++++++++++++++++++++- + 1 file changed, 26 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -176,6 +176,24 @@ static const char *phylink_an_mode_str(u + return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown"; + } + ++static const char *phylink_pcs_mode_str(unsigned int mode) ++{ ++ if (!mode) ++ return "none"; ++ ++ if (mode & PHYLINK_PCS_NEG_OUTBAND) ++ return "outband"; ++ ++ if (mode & PHYLINK_PCS_NEG_INBAND) { ++ if (mode & PHYLINK_PCS_NEG_ENABLED) ++ return "inband,an-enabled"; ++ else ++ return "inband,an-disabled"; ++ } ++ ++ return "unknown"; ++} ++ + static unsigned int phylink_interface_signal_rate(phy_interface_t interface) + { + switch (interface) { +@@ -1181,7 +1199,9 @@ static void phylink_major_config(struct + unsigned int neg_mode; + int err; + +- phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); ++ phylink_dbg(pl, "major config, requested %s/%s\n", ++ phylink_an_mode_str(pl->req_link_an_mode), ++ phy_modes(state->interface)); + + if (pl->using_mac_select_pcs) { + pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); +@@ -1197,6 +1217,11 @@ static void phylink_major_config(struct + + phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising); + ++ phylink_dbg(pl, "major config, active %s/%s/%s\n", ++ phylink_an_mode_str(pl->act_link_an_mode), ++ phylink_pcs_mode_str(pl->pcs_neg_mode), ++ phy_modes(state->interface)); ++ + phylink_pcs_poll_stop(pl); + + if (pl->mac_ops->mac_prepare) { diff --git a/lede/target/linux/generic/backport-6.12/601-04-v6.14-net-phy-add-phy_inband_caps.patch b/lede/target/linux/generic/backport-6.12/601-04-v6.14-net-phy-add-phy_inband_caps.patch new file mode 100644 index 0000000000..0cd38f086c --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/601-04-v6.14-net-phy-add-phy_inband_caps.patch @@ -0,0 +1,118 @@ +From b4c7698dd95f253c6958d8c6ac219098009bf28a Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 3 Dec 2024 15:31:02 +0000 +Subject: [PATCH 04/13] net: phy: add phy_inband_caps() + +Add a method to query the PHY's in-band capabilities for a PHY +interface mode. + +Where the interface mode does not have in-band capability, or the PHY +driver has not been updated to return this information, then +phy_inband_caps() should return zero. Otherwise, PHY drivers will +return a value consisting of the following flags: + +LINK_INBAND_DISABLE indicates that the hardware does not support +in-band signalling, or can have in-band signalling configured via +software to be disabled. + +LINK_INBAND_ENABLE indicates that the hardware will use in-band +signalling, or can have in-band signalling configured via software +to be enabled. + +LINK_INBAND_BYPASS indicates that the hardware has the ability to +bypass in-band signalling when enabled after a timeout if the link +partner does not respond to its in-band signalling. + +This reports the PHY capabilities for the particular interface mode, +not the current configuration. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUre-006ITz-KF@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phy.c | 21 +++++++++++++++++++++ + include/linux/phy.h | 28 ++++++++++++++++++++++++++++ + 2 files changed, 49 insertions(+) + +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -1049,6 +1049,27 @@ static int phy_check_link_status(struct + } + + /** ++ * phy_inband_caps - query which in-band signalling modes are supported ++ * @phydev: a pointer to a &struct phy_device ++ * @interface: the interface mode for the PHY ++ * ++ * Returns zero if it is unknown what in-band signalling is supported by the ++ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise, ++ * returns a bit mask of the LINK_INBAND_* values from ++ * &enum link_inband_signalling to describe which inband modes are supported ++ * by the PHY for this interface mode. ++ */ ++unsigned int phy_inband_caps(struct phy_device *phydev, ++ phy_interface_t interface) ++{ ++ if (phydev->drv && phydev->drv->inband_caps) ++ return phydev->drv->inband_caps(phydev, interface); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(phy_inband_caps); ++ ++/** + * _phy_start_aneg - start auto-negotiation for this PHY device + * @phydev: the phy_device struct + * +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -826,6 +826,24 @@ struct phy_tdr_config { + #define PHY_PAIR_ALL -1 + + /** ++ * enum link_inband_signalling - in-band signalling modes that are supported ++ * ++ * @LINK_INBAND_DISABLE: in-band signalling can be disabled ++ * @LINK_INBAND_ENABLE: in-band signalling can be enabled without bypass ++ * @LINK_INBAND_BYPASS: in-band signalling can be enabled with bypass ++ * ++ * The possible and required bits can only be used if the valid bit is set. ++ * If possible is clear, that means inband signalling can not be used. ++ * Required is only valid when possible is set, and means that inband ++ * signalling must be used. ++ */ ++enum link_inband_signalling { ++ LINK_INBAND_DISABLE = BIT(0), ++ LINK_INBAND_ENABLE = BIT(1), ++ LINK_INBAND_BYPASS = BIT(2), ++}; ++ ++/** + * struct phy_plca_cfg - Configuration of the PLCA (Physical Layer Collision + * Avoidance) Reconciliation Sublayer. + * +@@ -964,6 +982,14 @@ struct phy_driver { + int (*get_features)(struct phy_device *phydev); + + /** ++ * @inband_caps: query whether in-band is supported for the given PHY ++ * interface mode. Returns a bitmask of bits defined by enum ++ * link_inband_signalling. ++ */ ++ unsigned int (*inband_caps)(struct phy_device *phydev, ++ phy_interface_t interface); ++ ++ /** + * @get_rate_matching: Get the supported type of rate matching for a + * particular phy interface. This is used by phy consumers to determine + * whether to advertise lower-speed modes for that interface. It is +@@ -1842,6 +1868,8 @@ int phy_config_aneg(struct phy_device *p + int _phy_start_aneg(struct phy_device *phydev); + int phy_start_aneg(struct phy_device *phydev); + int phy_aneg_done(struct phy_device *phydev); ++unsigned int phy_inband_caps(struct phy_device *phydev, ++ phy_interface_t interface); + int phy_speed_down(struct phy_device *phydev, bool sync); + int phy_speed_up(struct phy_device *phydev); + bool phy_check_valid(int speed, int duplex, unsigned long *features); diff --git a/lede/target/linux/generic/backport-6.12/601-05-v6.14-net-phy-bcm84881-implement-phy_inband_caps-method.patch b/lede/target/linux/generic/backport-6.12/601-05-v6.14-net-phy-bcm84881-implement-phy_inband_caps-method.patch new file mode 100644 index 0000000000..0ba3cd2802 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/601-05-v6.14-net-phy-bcm84881-implement-phy_inband_caps-method.patch @@ -0,0 +1,41 @@ +From c64c7fa0a774d9da72071a8517e359992baac982 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 3 Dec 2024 15:31:07 +0000 +Subject: [PATCH 05/13] net: phy: bcm84881: implement phy_inband_caps() method + +BCM84881 has no support for inband signalling, so this is a trivial +implementation that returns no support for inband. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Acked-by: Florian Fainelli +Link: https://patch.msgid.link/E1tIUrj-006IU6-ON@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/bcm84881.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/net/phy/bcm84881.c ++++ b/drivers/net/phy/bcm84881.c +@@ -235,11 +235,21 @@ static int bcm84881_read_status(struct p + return genphy_c45_read_mdix(phydev); + } + ++/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII ++ * or 802.3z control word, so inband will not work. ++ */ ++static unsigned int bcm84881_inband_caps(struct phy_device *phydev, ++ phy_interface_t interface) ++{ ++ return LINK_INBAND_DISABLE; ++} ++ + static struct phy_driver bcm84881_drivers[] = { + { + .phy_id = 0xae025150, + .phy_id_mask = 0xfffffff0, + .name = "Broadcom BCM84881", ++ .inband_caps = bcm84881_inband_caps, + .config_init = bcm84881_config_init, + .probe = bcm84881_probe, + .get_features = bcm84881_get_features, diff --git a/lede/target/linux/generic/backport-6.12/601-06-v6.14-net-phy-marvell-implement-phy_inband_caps-method.patch b/lede/target/linux/generic/backport-6.12/601-06-v6.14-net-phy-marvell-implement-phy_inband_caps-method.patch new file mode 100644 index 0000000000..e2dfeba1d5 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/601-06-v6.14-net-phy-marvell-implement-phy_inband_caps-method.patch @@ -0,0 +1,63 @@ +From 1c86828dff88e28b8ade6bddeee0163a023faf91 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 3 Dec 2024 15:31:12 +0000 +Subject: [PATCH 06/13] net: phy: marvell: implement phy_inband_caps() method + +Provide an implementation for phy_inband_caps() for Marvell PHYs used +on SFP modules, so that phylink knows the PHYs capabilities. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUro-006IUC-Rq@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/marvell.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/drivers/net/phy/marvell.c ++++ b/drivers/net/phy/marvell.c +@@ -716,6 +716,20 @@ static int marvell_config_aneg_fiber(str + return genphy_check_and_restart_aneg(phydev, changed); + } + ++static unsigned int m88e1111_inband_caps(struct phy_device *phydev, ++ phy_interface_t interface) ++{ ++ /* In 1000base-X and SGMII modes, the inband mode can be changed ++ * through the Fibre page BMCR ANENABLE bit. ++ */ ++ if (interface == PHY_INTERFACE_MODE_1000BASEX || ++ interface == PHY_INTERFACE_MODE_SGMII) ++ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE | ++ LINK_INBAND_BYPASS; ++ ++ return 0; ++} ++ + static int m88e1111_config_aneg(struct phy_device *phydev) + { + int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR); +@@ -3704,6 +3718,7 @@ static struct phy_driver marvell_drivers + .name = "Marvell 88E1112", + /* PHY_GBIT_FEATURES */ + .probe = marvell_probe, ++ .inband_caps = m88e1111_inband_caps, + .config_init = m88e1112_config_init, + .config_aneg = marvell_config_aneg, + .config_intr = marvell_config_intr, +@@ -3725,6 +3740,7 @@ static struct phy_driver marvell_drivers + /* PHY_GBIT_FEATURES */ + .flags = PHY_POLL_CABLE_TEST, + .probe = marvell_probe, ++ .inband_caps = m88e1111_inband_caps, + .config_init = m88e1111gbe_config_init, + .config_aneg = m88e1111_config_aneg, + .read_status = marvell_read_status, +@@ -3748,6 +3764,7 @@ static struct phy_driver marvell_drivers + .name = "Marvell 88E1111 (Finisar)", + /* PHY_GBIT_FEATURES */ + .probe = marvell_probe, ++ .inband_caps = m88e1111_inband_caps, + .config_init = m88e1111gbe_config_init, + .config_aneg = m88e1111_config_aneg, + .read_status = marvell_read_status, diff --git a/lede/target/linux/generic/backport-6.12/601-07-v6.14-net-phy-add-phy_config_inband.patch b/lede/target/linux/generic/backport-6.12/601-07-v6.14-net-phy-add-phy_config_inband.patch new file mode 100644 index 0000000000..d667bcbec0 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/601-07-v6.14-net-phy-add-phy_config_inband.patch @@ -0,0 +1,79 @@ +From 5d58a890c02770ba8d790b1f3c6e8c0e20514dc2 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 3 Dec 2024 15:31:18 +0000 +Subject: [PATCH 07/13] net: phy: add phy_config_inband() + +Add a method to configure the PHY's in-band mode. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUru-006IUI-08@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phy.c | 32 ++++++++++++++++++++++++++++++++ + include/linux/phy.h | 6 ++++++ + 2 files changed, 38 insertions(+) + +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -1070,6 +1070,38 @@ unsigned int phy_inband_caps(struct phy_ + EXPORT_SYMBOL_GPL(phy_inband_caps); + + /** ++ * phy_config_inband - configure the desired PHY in-band mode ++ * @phydev: the phy_device struct ++ * @modes: in-band modes to configure ++ * ++ * Description: disables, enables or enables-with-bypass in-band signalling ++ * between the PHY and host system. ++ * ++ * Returns: zero on success, or negative errno value. ++ */ ++int phy_config_inband(struct phy_device *phydev, unsigned int modes) ++{ ++ int err; ++ ++ if (!!(modes & LINK_INBAND_DISABLE) + ++ !!(modes & LINK_INBAND_ENABLE) + ++ !!(modes & LINK_INBAND_BYPASS) != 1) ++ return -EINVAL; ++ ++ mutex_lock(&phydev->lock); ++ if (!phydev->drv) ++ err = -EIO; ++ else if (!phydev->drv->config_inband) ++ err = -EOPNOTSUPP; ++ else ++ err = phydev->drv->config_inband(phydev, modes); ++ mutex_unlock(&phydev->lock); ++ ++ return err; ++} ++EXPORT_SYMBOL(phy_config_inband); ++ ++/** + * _phy_start_aneg - start auto-negotiation for this PHY device + * @phydev: the phy_device struct + * +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -990,6 +990,11 @@ struct phy_driver { + phy_interface_t interface); + + /** ++ * @config_inband: configure in-band mode for the PHY ++ */ ++ int (*config_inband)(struct phy_device *phydev, unsigned int modes); ++ ++ /** + * @get_rate_matching: Get the supported type of rate matching for a + * particular phy interface. This is used by phy consumers to determine + * whether to advertise lower-speed modes for that interface. It is +@@ -1870,6 +1875,7 @@ int phy_start_aneg(struct phy_device *ph + int phy_aneg_done(struct phy_device *phydev); + unsigned int phy_inband_caps(struct phy_device *phydev, + phy_interface_t interface); ++int phy_config_inband(struct phy_device *phydev, unsigned int modes); + int phy_speed_down(struct phy_device *phydev, bool sync); + int phy_speed_up(struct phy_device *phydev); + bool phy_check_valid(int speed, int duplex, unsigned long *features); diff --git a/lede/target/linux/generic/backport-6.12/601-08-v6.14-net-phy-marvell-implement-config_inband-method.patch b/lede/target/linux/generic/backport-6.12/601-08-v6.14-net-phy-marvell-implement-config_inband-method.patch new file mode 100644 index 0000000000..4531c507e2 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/601-08-v6.14-net-phy-marvell-implement-config_inband-method.patch @@ -0,0 +1,77 @@ +From a219912e0fec73c346e64ef47013cb2e152f88fc Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 3 Dec 2024 15:31:23 +0000 +Subject: [PATCH 08/13] net: phy: marvell: implement config_inband() method + +Implement the config_inband() method for Marvell 88E1112, 88E1111, +and Finisar's 88E1111 variant. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUrz-006IUO-3r@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/marvell.c | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +--- a/drivers/net/phy/marvell.c ++++ b/drivers/net/phy/marvell.c +@@ -730,6 +730,34 @@ static unsigned int m88e1111_inband_caps + return 0; + } + ++static int m88e1111_config_inband(struct phy_device *phydev, unsigned int modes) ++{ ++ u16 extsr, bmcr; ++ int err; ++ ++ if (phydev->interface != PHY_INTERFACE_MODE_1000BASEX && ++ phydev->interface != PHY_INTERFACE_MODE_SGMII) ++ return -EINVAL; ++ ++ if (modes == LINK_INBAND_BYPASS) ++ extsr = MII_M1111_HWCFG_SERIAL_AN_BYPASS; ++ else ++ extsr = 0; ++ ++ if (modes == LINK_INBAND_DISABLE) ++ bmcr = 0; ++ else ++ bmcr = BMCR_ANENABLE; ++ ++ err = phy_modify(phydev, MII_M1111_PHY_EXT_SR, ++ MII_M1111_HWCFG_SERIAL_AN_BYPASS, extsr); ++ if (err < 0) ++ return extsr; ++ ++ return phy_modify_paged(phydev, MII_MARVELL_FIBER_PAGE, MII_BMCR, ++ BMCR_ANENABLE, bmcr); ++} ++ + static int m88e1111_config_aneg(struct phy_device *phydev) + { + int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR); +@@ -3719,6 +3747,7 @@ static struct phy_driver marvell_drivers + /* PHY_GBIT_FEATURES */ + .probe = marvell_probe, + .inband_caps = m88e1111_inband_caps, ++ .config_inband = m88e1111_config_inband, + .config_init = m88e1112_config_init, + .config_aneg = marvell_config_aneg, + .config_intr = marvell_config_intr, +@@ -3741,6 +3770,7 @@ static struct phy_driver marvell_drivers + .flags = PHY_POLL_CABLE_TEST, + .probe = marvell_probe, + .inband_caps = m88e1111_inband_caps, ++ .config_inband = m88e1111_config_inband, + .config_init = m88e1111gbe_config_init, + .config_aneg = m88e1111_config_aneg, + .read_status = marvell_read_status, +@@ -3765,6 +3795,7 @@ static struct phy_driver marvell_drivers + /* PHY_GBIT_FEATURES */ + .probe = marvell_probe, + .inband_caps = m88e1111_inband_caps, ++ .config_inband = m88e1111_config_inband, + .config_init = m88e1111gbe_config_init, + .config_aneg = m88e1111_config_aneg, + .read_status = marvell_read_status, diff --git a/lede/target/linux/generic/backport-6.12/601-09-v6.14-net-phylink-add-pcs_inband_caps-method.patch b/lede/target/linux/generic/backport-6.12/601-09-v6.14-net-phylink-add-pcs_inband_caps-method.patch new file mode 100644 index 0000000000..422802457e --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/601-09-v6.14-net-phylink-add-pcs_inband_caps-method.patch @@ -0,0 +1,159 @@ +From df874f9e52c340cc6f0a0014a97b778f67d46849 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 3 Dec 2024 15:31:28 +0000 +Subject: [PATCH 09/13] net: phylink: add pcs_inband_caps() method + +Add a pcs_inband_caps() method to query the PCS for its inband link +capabilities, and use this to determine whether link modes used with +optical SFPs can be supported. + +When a PCS does not provide a method, we allow inband negotiation to +be either on or off, making this a no-op until the pcs_inband_caps() +method is implemented by a PCS driver. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUs4-006IUU-7K@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 60 +++++++++++++++++++++++++++++++++++++++ + include/linux/phylink.h | 17 +++++++++++ + 2 files changed, 77 insertions(+) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1007,6 +1007,15 @@ static void phylink_resolve_an_pause(str + } + } + ++static unsigned int phylink_pcs_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface) ++{ ++ if (pcs && pcs->ops->pcs_inband_caps) ++ return pcs->ops->pcs_inband_caps(pcs, interface); ++ ++ return 0; ++} ++ + static void phylink_pcs_pre_config(struct phylink_pcs *pcs, + phy_interface_t interface) + { +@@ -1060,6 +1069,24 @@ static void phylink_pcs_link_up(struct p + pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex); + } + ++/* Query inband for a specific interface mode, asking the MAC for the ++ * PCS which will be used to handle the interface mode. ++ */ ++static unsigned int phylink_inband_caps(struct phylink *pl, ++ phy_interface_t interface) ++{ ++ struct phylink_pcs *pcs; ++ ++ if (!pl->mac_ops->mac_select_pcs) ++ return 0; ++ ++ pcs = pl->mac_ops->mac_select_pcs(pl->config, interface); ++ if (!pcs) ++ return 0; ++ ++ return phylink_pcs_inband_caps(pcs, interface); ++} ++ + static void phylink_pcs_poll_stop(struct phylink *pl) + { + if (pl->cfg_link_an_mode == MLO_AN_INBAND) +@@ -2530,6 +2557,26 @@ int phylink_ethtool_ksettings_get(struct + } + EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_get); + ++static bool phylink_validate_pcs_inband_autoneg(struct phylink *pl, ++ phy_interface_t interface, ++ unsigned long *adv) ++{ ++ unsigned int inband = phylink_inband_caps(pl, interface); ++ unsigned int mask; ++ ++ /* If the PCS doesn't implement inband support, be permissive. */ ++ if (!inband) ++ return true; ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, adv)) ++ mask = LINK_INBAND_ENABLE; ++ else ++ mask = LINK_INBAND_DISABLE; ++ ++ /* Check whether the PCS implements the required mode */ ++ return !!(inband & mask); ++} ++ + /** + * phylink_ethtool_ksettings_set() - set the link settings + * @pl: a pointer to a &struct phylink returned from phylink_create() +@@ -2665,6 +2712,13 @@ int phylink_ethtool_ksettings_set(struct + phylink_is_empty_linkmode(config.advertising)) + return -EINVAL; + ++ /* Validate the autonegotiation state. We don't have a PHY in this ++ * situation, so the PCS is the media-facing entity. ++ */ ++ if (!phylink_validate_pcs_inband_autoneg(pl, config.interface, ++ config.advertising)) ++ return -EINVAL; ++ + mutex_lock(&pl->state_mutex); + pl->link_config.speed = config.speed; + pl->link_config.duplex = config.duplex; +@@ -3349,6 +3403,12 @@ static int phylink_sfp_config_optical(st + phylink_dbg(pl, "optical SFP: chosen %s interface\n", + phy_modes(interface)); + ++ if (!phylink_validate_pcs_inband_autoneg(pl, interface, ++ config.advertising)) { ++ phylink_err(pl, "autoneg setting not compatible with PCS"); ++ return -EINVAL; ++ } ++ + config.interface = interface; + + /* Ignore errors if we're expecting a PHY to attach later */ +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -419,6 +419,7 @@ struct phylink_pcs { + /** + * struct phylink_pcs_ops - MAC PCS operations structure. + * @pcs_validate: validate the link configuration. ++ * @pcs_inband_caps: query inband support for interface mode. + * @pcs_enable: enable the PCS. + * @pcs_disable: disable the PCS. + * @pcs_pre_config: pre-mac_config method (for errata) +@@ -434,6 +435,8 @@ struct phylink_pcs { + struct phylink_pcs_ops { + int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported, + const struct phylink_link_state *state); ++ unsigned int (*pcs_inband_caps)(struct phylink_pcs *pcs, ++ phy_interface_t interface); + int (*pcs_enable)(struct phylink_pcs *pcs); + void (*pcs_disable)(struct phylink_pcs *pcs); + void (*pcs_pre_config)(struct phylink_pcs *pcs, +@@ -471,6 +474,20 @@ int pcs_validate(struct phylink_pcs *pcs + const struct phylink_link_state *state); + + /** ++ * pcs_inband_caps - query PCS in-band capabilities for interface mode. ++ * @pcs: a pointer to a &struct phylink_pcs. ++ * @interface: interface mode to be queried ++ * ++ * Returns zero if it is unknown what in-band signalling is supported by the ++ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise, ++ * returns a bit mask of the LINK_INBAND_* values from ++ * &enum link_inband_signalling to describe which inband modes are supported ++ * for this interface mode. ++ */ ++unsigned int pcs_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface); ++ ++/** + * pcs_enable() - enable the PCS. + * @pcs: a pointer to a &struct phylink_pcs. + */ diff --git a/lede/target/linux/generic/backport-6.12/601-10-v6.14-net-mvneta-implement-pcs_inband_caps-method.patch b/lede/target/linux/generic/backport-6.12/601-10-v6.14-net-mvneta-implement-pcs_inband_caps-method.patch new file mode 100644 index 0000000000..0937ad1388 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/601-10-v6.14-net-mvneta-implement-pcs_inband_caps-method.patch @@ -0,0 +1,64 @@ +From 513e8fb8fa32035b3325e2e14fb9598f8cb545e9 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 3 Dec 2024 15:31:33 +0000 +Subject: [PATCH 10/13] net: mvneta: implement pcs_inband_caps() method + +Report the PCS in-band capabilities to phylink for Marvell NETA +interfaces. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUs9-006IUb-Au@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/marvell/mvneta.c | 27 +++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -3960,20 +3960,27 @@ static struct mvneta_port *mvneta_pcs_to + return container_of(pcs, struct mvneta_port, phylink_pcs); + } + +-static int mvneta_pcs_validate(struct phylink_pcs *pcs, +- unsigned long *supported, +- const struct phylink_link_state *state) ++static unsigned int mvneta_pcs_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface) + { +- /* We only support QSGMII, SGMII, 802.3z and RGMII modes. +- * When in 802.3z mode, we must have AN enabled: ++ /* When operating in an 802.3z mode, we must have AN enabled: + * "Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ... + * When = 1 (1000BASE-X) this field must be set to 1." ++ * Therefore, inband is "required". + */ +- if (phy_interface_mode_is_8023z(state->interface) && +- !phylink_test(state->advertising, Autoneg)) +- return -EINVAL; ++ if (phy_interface_mode_is_8023z(interface)) ++ return LINK_INBAND_ENABLE; + +- return 0; ++ /* QSGMII, SGMII and RGMII can be configured to use inband ++ * signalling of the AN result. Indicate these as "possible". ++ */ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ interface == PHY_INTERFACE_MODE_QSGMII || ++ phy_interface_mode_is_rgmii(interface)) ++ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; ++ ++ /* For any other modes, indicate that inband is not supported. */ ++ return LINK_INBAND_DISABLE; + } + + static void mvneta_pcs_get_state(struct phylink_pcs *pcs, +@@ -4071,7 +4078,7 @@ static void mvneta_pcs_an_restart(struct + } + + static const struct phylink_pcs_ops mvneta_phylink_pcs_ops = { +- .pcs_validate = mvneta_pcs_validate, ++ .pcs_inband_caps = mvneta_pcs_inband_caps, + .pcs_get_state = mvneta_pcs_get_state, + .pcs_config = mvneta_pcs_config, + .pcs_an_restart = mvneta_pcs_an_restart, diff --git a/lede/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch b/lede/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch new file mode 100644 index 0000000000..846d9df36d --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch @@ -0,0 +1,62 @@ +From d4169f0c7665afb8d8adb5e1b1df3db88517d0ad Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 3 Dec 2024 15:31:38 +0000 +Subject: [PATCH 11/13] net: mvpp2: implement pcs_inband_caps() method + +Report the PCS in-band capabilities to phylink for Marvell PP2 +interfaces. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUsE-006IUh-E7@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + .../net/ethernet/marvell/mvpp2/mvpp2_main.c | 25 ++++++++++++------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +@@ -6237,19 +6237,26 @@ static const struct phylink_pcs_ops mvpp + .pcs_config = mvpp2_xlg_pcs_config, + }; + +-static int mvpp2_gmac_pcs_validate(struct phylink_pcs *pcs, +- unsigned long *supported, +- const struct phylink_link_state *state) ++static unsigned int mvpp2_gmac_pcs_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface) + { +- /* When in 802.3z mode, we must have AN enabled: ++ /* When operating in an 802.3z mode, we must have AN enabled: + * Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ... + * When = 1 (1000BASE-X) this field must be set to 1. ++ * Therefore, inband is "required". + */ +- if (phy_interface_mode_is_8023z(state->interface) && +- !phylink_test(state->advertising, Autoneg)) +- return -EINVAL; ++ if (phy_interface_mode_is_8023z(interface)) ++ return LINK_INBAND_ENABLE; + +- return 0; ++ /* SGMII and RGMII can be configured to use inband signalling of the ++ * AN result. Indicate these as "possible". ++ */ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ phy_interface_mode_is_rgmii(interface)) ++ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; ++ ++ /* For any other modes, indicate that inband is not supported. */ ++ return LINK_INBAND_DISABLE; + } + + static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs, +@@ -6356,7 +6363,7 @@ static void mvpp2_gmac_pcs_an_restart(st + } + + static const struct phylink_pcs_ops mvpp2_phylink_gmac_pcs_ops = { +- .pcs_validate = mvpp2_gmac_pcs_validate, ++ .pcs_inband_caps = mvpp2_gmac_pcs_inband_caps, + .pcs_get_state = mvpp2_gmac_pcs_get_state, + .pcs_config = mvpp2_gmac_pcs_config, + .pcs_an_restart = mvpp2_gmac_pcs_an_restart, diff --git a/lede/target/linux/generic/backport-6.12/601-12-v6.14-net-phylink-add-negotiation-of-in-band-capabilities.patch b/lede/target/linux/generic/backport-6.12/601-12-v6.14-net-phylink-add-negotiation-of-in-band-capabilities.patch new file mode 100644 index 0000000000..f629133013 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/601-12-v6.14-net-phylink-add-negotiation-of-in-band-capabilities.patch @@ -0,0 +1,228 @@ +From 5fd0f1a02e750e2db4038dee60edea669ce5aab1 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 3 Dec 2024 15:31:43 +0000 +Subject: [PATCH 12/13] net: phylink: add negotiation of in-band capabilities + +Support for in-band signalling with Serdes links is uncertain. Some +PHYs do not support in-band for e.g. SGMII. Some PCS do not support +in-band for 2500Base-X. Some PCS require in-band for Base-X protocols. + +Simply using what is in DT is insufficient when we have hot-pluggable +PHYs e.g. in the form of SFP modules, which may not provide the +in-band signalling. + +In order to address this, we have introduced phy_inband_caps() and +pcs_inband_caps() functions to allow phylink to retrieve the +capabilities from each end of the PCS/PHY link. This commit adds code +to resolve whether in-band will be used in the various scenarios that +we have: In-band not being used, PHY present using SGMII or Base-X, +PHY not present. We also deal with no capabilties provided. + +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUsJ-006IUn-H3@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 154 +++++++++++++++++++++++++++++++++++--- + 1 file changed, 144 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -75,6 +75,7 @@ struct phylink { + + struct mutex state_mutex; + struct phylink_link_state phy_state; ++ unsigned int phy_ib_mode; + struct work_struct resolve; + unsigned int pcs_neg_mode; + unsigned int pcs_state; +@@ -1170,10 +1171,18 @@ static void phylink_pcs_neg_mode(struct + phy_interface_t interface, + const unsigned long *advertising) + { ++ unsigned int pcs_ib_caps = 0; ++ unsigned int phy_ib_caps = 0; + unsigned int neg_mode, mode; ++ enum { ++ INBAND_CISCO_SGMII, ++ INBAND_BASEX, ++ } type; + + mode = pl->req_link_an_mode; + ++ pl->phy_ib_mode = 0; ++ + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: +@@ -1185,10 +1194,7 @@ static void phylink_pcs_neg_mode(struct + * 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; ++ type = INBAND_CISCO_SGMII; + break; + + case PHY_INTERFACE_MODE_1000BASEX: +@@ -1199,18 +1205,139 @@ static void phylink_pcs_neg_mode(struct + * as well, but drivers may not support this, so may + * need to override this. + */ +- if (!phylink_autoneg_inband(mode)) ++ type = INBAND_BASEX; ++ break; ++ ++ default: ++ pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE; ++ pl->act_link_an_mode = mode; ++ return; ++ } ++ ++ if (pcs) ++ pcs_ib_caps = phylink_pcs_inband_caps(pcs, interface); ++ ++ if (pl->phydev) ++ phy_ib_caps = phy_inband_caps(pl->phydev, interface); ++ ++ phylink_dbg(pl, "interface %s inband modes: pcs=%02x phy=%02x\n", ++ phy_modes(interface), pcs_ib_caps, phy_ib_caps); ++ ++ if (!phylink_autoneg_inband(mode)) { ++ bool pcs_ib_only = false; ++ bool phy_ib_only = false; ++ ++ if (pcs_ib_caps && pcs_ib_caps != LINK_INBAND_DISABLE) { ++ /* PCS supports reporting in-band capabilities, and ++ * supports more than disable mode. ++ */ ++ if (pcs_ib_caps & LINK_INBAND_DISABLE) ++ neg_mode = PHYLINK_PCS_NEG_OUTBAND; ++ else if (pcs_ib_caps & LINK_INBAND_ENABLE) ++ pcs_ib_only = true; ++ } ++ ++ if (phy_ib_caps && phy_ib_caps != LINK_INBAND_DISABLE) { ++ /* PHY supports in-band capabilities, and supports ++ * more than disable mode. ++ */ ++ if (phy_ib_caps & LINK_INBAND_DISABLE) ++ pl->phy_ib_mode = LINK_INBAND_DISABLE; ++ else if (phy_ib_caps & LINK_INBAND_BYPASS) ++ pl->phy_ib_mode = LINK_INBAND_BYPASS; ++ else if (phy_ib_caps & LINK_INBAND_ENABLE) ++ phy_ib_only = true; ++ } ++ ++ /* If either the PCS or PHY requires inband to be enabled, ++ * this is an invalid configuration. Provide a diagnostic ++ * message for this case, but don't try to force the issue. ++ */ ++ if (pcs_ib_only || phy_ib_only) ++ phylink_warn(pl, ++ "firmware wants %s mode, but %s%s%s requires inband\n", ++ phylink_an_mode_str(mode), ++ pcs_ib_only ? "PCS" : "", ++ pcs_ib_only && phy_ib_only ? " and " : "", ++ phy_ib_only ? "PHY" : ""); ++ ++ neg_mode = PHYLINK_PCS_NEG_OUTBAND; ++ } else if (type == INBAND_CISCO_SGMII || pl->phydev) { ++ /* For SGMII modes which are designed to be used with PHYs, or ++ * Base-X with a PHY, we try to use in-band mode where-ever ++ * possible. However, there are some PHYs e.g. BCM84881 which ++ * do not support in-band. ++ */ ++ const unsigned int inband_ok = LINK_INBAND_ENABLE | ++ LINK_INBAND_BYPASS; ++ const unsigned int outband_ok = LINK_INBAND_DISABLE | ++ LINK_INBAND_BYPASS; ++ /* PCS PHY ++ * D E D E ++ * 0 0 0 0 no information inband enabled ++ * 1 0 0 0 pcs doesn't support outband ++ * 0 1 0 0 pcs required inband enabled ++ * 1 1 0 0 pcs optional inband enabled ++ * 0 0 1 0 phy doesn't support outband ++ * 1 0 1 0 pcs+phy doesn't support outband ++ * 0 1 1 0 pcs required, phy doesn't support, invalid ++ * 1 1 1 0 pcs optional, phy doesn't support, outband ++ * 0 0 0 1 phy required inband enabled ++ * 1 0 0 1 pcs doesn't support, phy required, invalid ++ * 0 1 0 1 pcs+phy required inband enabled ++ * 1 1 0 1 pcs optional, phy required inband enabled ++ * 0 0 1 1 phy optional inband enabled ++ * 1 0 1 1 pcs doesn't support, phy optional, outband ++ * 0 1 1 1 pcs required, phy optional inband enabled ++ * 1 1 1 1 pcs+phy optional inband enabled ++ */ ++ if ((!pcs_ib_caps || pcs_ib_caps & inband_ok) && ++ (!phy_ib_caps || phy_ib_caps & inband_ok)) { ++ /* In-band supported or unknown at both ends. Enable ++ * in-band mode with or without bypass at the PHY. ++ */ ++ if (phy_ib_caps & LINK_INBAND_ENABLE) ++ pl->phy_ib_mode = LINK_INBAND_ENABLE; ++ else if (phy_ib_caps & LINK_INBAND_BYPASS) ++ pl->phy_ib_mode = LINK_INBAND_BYPASS; ++ ++ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; ++ } else if ((!pcs_ib_caps || pcs_ib_caps & outband_ok) && ++ (!phy_ib_caps || phy_ib_caps & outband_ok)) { ++ /* Either in-band not supported at at least one end. ++ * In-band bypass at the other end is possible. ++ */ ++ if (phy_ib_caps & LINK_INBAND_DISABLE) ++ pl->phy_ib_mode = LINK_INBAND_DISABLE; ++ else if (phy_ib_caps & LINK_INBAND_BYPASS) ++ pl->phy_ib_mode = LINK_INBAND_BYPASS; ++ + neg_mode = PHYLINK_PCS_NEG_OUTBAND; ++ if (pl->phydev) ++ mode = MLO_AN_PHY; ++ } else { ++ /* invalid */ ++ phylink_warn(pl, "%s: incompatible in-band capabilities, trying in-band", ++ phy_modes(interface)); ++ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; ++ } ++ } else { ++ /* For Base-X without a PHY */ ++ if (pcs_ib_caps == LINK_INBAND_DISABLE) ++ /* If the PCS doesn't support inband, then inband must ++ * be disabled. ++ */ ++ neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED; ++ else if (pcs_ib_caps == LINK_INBAND_ENABLE) ++ /* If the PCS requires inband, then inband must always ++ * be enabled. ++ */ ++ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; + 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; + } + + pl->pcs_neg_mode = neg_mode; +@@ -1309,6 +1436,13 @@ static void phylink_major_config(struct + ERR_PTR(err)); + } + ++ if (pl->phydev && pl->phy_ib_mode) { ++ err = phy_config_inband(pl->phydev, pl->phy_ib_mode); ++ if (err < 0) ++ phylink_err(pl, "phy_config_inband: %pe\n", ++ ERR_PTR(err)); ++ } ++ + if (pl->sfp_bus) { + rate_kbd = phylink_interface_signal_rate(state->interface); + if (rate_kbd) diff --git a/lede/target/linux/generic/backport-6.12/601-13-v6.14-net-phylink-remove-phylink_phy_no_inband.patch b/lede/target/linux/generic/backport-6.12/601-13-v6.14-net-phylink-remove-phylink_phy_no_inband.patch new file mode 100644 index 0000000000..8be74a2ad6 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/601-13-v6.14-net-phylink-remove-phylink_phy_no_inband.patch @@ -0,0 +1,110 @@ +From 77ac9a8b2536e0eaca6c6f21070068458bf55981 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 3 Dec 2024 15:31:48 +0000 +Subject: [PATCH 13/13] net: phylink: remove phylink_phy_no_inband() + +Remove phylink_phy_no_inband() now that we are handling the lack of +inband negotiation by querying the capabilities of the PHY and PCS, +and the BCM84881 PHY driver provides us the information necessary to +make the decision. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUsO-006IUt-KN@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 27 ++++++--------------------- + 1 file changed, 6 insertions(+), 21 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -3394,10 +3394,11 @@ static phy_interface_t phylink_choose_sf + return interface; + } + +-static void phylink_sfp_set_config(struct phylink *pl, u8 mode, ++static void phylink_sfp_set_config(struct phylink *pl, + unsigned long *supported, + struct phylink_link_state *state) + { ++ u8 mode = MLO_AN_INBAND; + bool changed = false; + + phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n", +@@ -3431,8 +3432,7 @@ static void phylink_sfp_set_config(struc + phylink_mac_initial_config(pl, false); + } + +-static int phylink_sfp_config_phy(struct phylink *pl, u8 mode, +- struct phy_device *phy) ++static int phylink_sfp_config_phy(struct phylink *pl, struct phy_device *phy) + { + __ETHTOOL_DECLARE_LINK_MODE_MASK(support1); + __ETHTOOL_DECLARE_LINK_MODE_MASK(support); +@@ -3472,7 +3472,7 @@ static int phylink_sfp_config_phy(struct + if (ret) { + phylink_err(pl, + "validation of %s/%s with support %*pb failed: %pe\n", +- phylink_an_mode_str(mode), ++ phylink_an_mode_str(pl->req_link_an_mode), + phy_modes(config.interface), + __ETHTOOL_LINK_MODE_MASK_NBITS, support, + ERR_PTR(ret)); +@@ -3481,7 +3481,7 @@ static int phylink_sfp_config_phy(struct + + pl->link_port = pl->sfp_port; + +- phylink_sfp_set_config(pl, mode, support, &config); ++ phylink_sfp_set_config(pl, support, &config); + + return 0; + } +@@ -3556,7 +3556,7 @@ static int phylink_sfp_config_optical(st + + pl->link_port = pl->sfp_port; + +- phylink_sfp_set_config(pl, MLO_AN_INBAND, pl->sfp_support, &config); ++ phylink_sfp_set_config(pl, pl->sfp_support, &config); + + return 0; + } +@@ -3627,20 +3627,10 @@ static void phylink_sfp_link_up(void *up + phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_LINK); + } + +-/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII +- * or 802.3z control word, so inband will not work. +- */ +-static bool phylink_phy_no_inband(struct phy_device *phy) +-{ +- 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) + { + struct phylink *pl = upstream; + phy_interface_t interface; +- u8 mode; + int ret; + + /* +@@ -3652,17 +3642,12 @@ static int phylink_sfp_connect_phy(void + */ + phy_support_asym_pause(phy); + +- if (phylink_phy_no_inband(phy)) +- mode = MLO_AN_PHY; +- else +- mode = MLO_AN_INBAND; +- + /* Set the PHY's host supported interfaces */ + phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces, + pl->config->supported_interfaces); + + /* Do the initial configuration */ +- ret = phylink_sfp_config_phy(pl, mode, phy); ++ ret = phylink_sfp_config_phy(pl, phy); + if (ret < 0) + return ret; + diff --git a/lede/target/linux/generic/backport-6.12/602-01-v6.14-net-pcs-pcs-lynx-implement-pcs_inband_caps-method.patch b/lede/target/linux/generic/backport-6.12/602-01-v6.14-net-pcs-pcs-lynx-implement-pcs_inband_caps-method.patch new file mode 100644 index 0000000000..32ba605b1c --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/602-01-v6.14-net-pcs-pcs-lynx-implement-pcs_inband_caps-method.patch @@ -0,0 +1,53 @@ +From 6561f0e547be221f411fda5eddfcc5bd8bb058a5 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 5 Dec 2024 09:42:24 +0000 +Subject: [PATCH 1/3] net: pcs: pcs-lynx: implement pcs_inband_caps() method + +Report the PCS in-band capabilities to phylink for the Lynx PCS. + +Reviewed-by: Maxime Chevallier +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tJ8NM-006L5J-AH@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/pcs/pcs-lynx.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- a/drivers/net/pcs/pcs-lynx.c ++++ b/drivers/net/pcs/pcs-lynx.c +@@ -35,6 +35,27 @@ enum sgmii_speed { + #define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs) + #define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs) + ++static unsigned int lynx_pcs_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_QSGMII: ++ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; ++ ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ return LINK_INBAND_DISABLE; ++ ++ case PHY_INTERFACE_MODE_USXGMII: ++ return LINK_INBAND_ENABLE; ++ ++ default: ++ return 0; ++ } ++} ++ + static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs, + struct phylink_link_state *state) + { +@@ -306,6 +327,7 @@ static void lynx_pcs_link_up(struct phyl + } + + static const struct phylink_pcs_ops lynx_pcs_phylink_ops = { ++ .pcs_inband_caps = lynx_pcs_inband_caps, + .pcs_get_state = lynx_pcs_get_state, + .pcs_config = lynx_pcs_config, + .pcs_an_restart = lynx_pcs_an_restart, diff --git a/lede/target/linux/generic/backport-6.12/602-02-v6.14-net-pcs-pcs-mtk-lynxi-implement-pcs_inband_caps-meth.patch b/lede/target/linux/generic/backport-6.12/602-02-v6.14-net-pcs-pcs-mtk-lynxi-implement-pcs_inband_caps-meth.patch new file mode 100644 index 0000000000..1cfd3bab9b --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/602-02-v6.14-net-pcs-pcs-mtk-lynxi-implement-pcs_inband_caps-meth.patch @@ -0,0 +1,47 @@ +From 520d29bdda86915b3caf8c72825a574bff212553 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 5 Dec 2024 09:42:29 +0000 +Subject: [PATCH 2/3] net: pcs: pcs-mtk-lynxi: implement pcs_inband_caps() + method + +Report the PCS in-band capabilities to phylink for the LynxI PCS. + +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tJ8NR-006L5P-E3@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/pcs/pcs-mtk-lynxi.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/net/pcs/pcs-mtk-lynxi.c ++++ b/drivers/net/pcs/pcs-mtk-lynxi.c +@@ -88,6 +88,21 @@ static struct mtk_pcs_lynxi *pcs_to_mtk_ + return container_of(pcs, struct mtk_pcs_lynxi, pcs); + } + ++static unsigned int mtk_pcs_lynxi_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_QSGMII: ++ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; ++ ++ default: ++ return 0; ++ } ++} ++ + static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs, + struct phylink_link_state *state) + { +@@ -241,6 +256,7 @@ static void mtk_pcs_lynxi_disable(struct + } + + static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = { ++ .pcs_inband_caps = mtk_pcs_lynxi_inband_caps, + .pcs_get_state = mtk_pcs_lynxi_get_state, + .pcs_config = mtk_pcs_lynxi_config, + .pcs_an_restart = mtk_pcs_lynxi_restart_an, diff --git a/lede/target/linux/generic/backport-6.12/602-03-v6.14-net-pcs-xpcs-implement-pcs_inband_caps-method.patch b/lede/target/linux/generic/backport-6.12/602-03-v6.14-net-pcs-xpcs-implement-pcs_inband_caps-method.patch new file mode 100644 index 0000000000..8dc495bd0c --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/602-03-v6.14-net-pcs-xpcs-implement-pcs_inband_caps-method.patch @@ -0,0 +1,58 @@ +From 484d0170d6c6bbb5213d037664e9a551f793bacd Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 5 Dec 2024 09:42:34 +0000 +Subject: [PATCH 3/3] net: pcs: xpcs: implement pcs_inband_caps() method + +Report the PCS inband capabilities to phylink for XPCS. + +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tJ8NW-006L5V-I9@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/pcs/pcs-xpcs.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +--- a/drivers/net/pcs/pcs-xpcs.c ++++ b/drivers/net/pcs/pcs-xpcs.c +@@ -608,6 +608,33 @@ static int xpcs_validate(struct phylink_ + return 0; + } + ++static unsigned int xpcs_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface) ++{ ++ struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs); ++ const struct dw_xpcs_compat *compat; ++ ++ compat = xpcs_find_compat(xpcs->desc, interface); ++ if (!compat) ++ return 0; ++ ++ switch (compat->an_mode) { ++ case DW_AN_C73: ++ return LINK_INBAND_ENABLE; ++ ++ case DW_AN_C37_SGMII: ++ case DW_AN_C37_1000BASEX: ++ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; ++ ++ case DW_10GBASER: ++ case DW_2500BASEX: ++ return LINK_INBAND_DISABLE; ++ ++ default: ++ return 0; ++ } ++} ++ + void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces) + { + int i, j; +@@ -1365,6 +1392,7 @@ static const struct dw_xpcs_desc xpcs_de + + static const struct phylink_pcs_ops xpcs_phylink_ops = { + .pcs_validate = xpcs_validate, ++ .pcs_inband_caps = xpcs_inband_caps, + .pcs_config = xpcs_config, + .pcs_get_state = xpcs_get_state, + .pcs_an_restart = xpcs_an_restart, diff --git a/lede/target/linux/generic/backport-6.12/605-02-v6.17-net-phylink-provide-phylink_get_inband_type.patch b/lede/target/linux/generic/backport-6.12/605-02-v6.17-net-phylink-provide-phylink_get_inband_type.patch new file mode 100644 index 0000000000..e944f573e0 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/605-02-v6.17-net-phylink-provide-phylink_get_inband_type.patch @@ -0,0 +1,117 @@ +From 1bd905dfea9897eafef532000702e63a66849f54 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Sun, 31 Aug 2025 18:34:38 +0100 +Subject: net: phylink: provide phylink_get_inband_type() + +Provide a function to get the type of the inband signalling used for +a PHY interface type. This will be used in the subsequent patch to +address problems with 10G optical modules. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/E1uslws-00000001SP5-1R2R@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 79 ++++++++++++++++++++++----------------- + 1 file changed, 44 insertions(+), 35 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1147,6 +1147,42 @@ static void phylink_pcs_an_restart(struc + pl->pcs->ops->pcs_an_restart(pl->pcs); + } + ++enum inband_type { ++ INBAND_NONE, ++ INBAND_CISCO_SGMII, ++ INBAND_BASEX, ++}; ++ ++static enum inband_type phylink_get_inband_type(phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_QUSGMII: ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10G_QXGMII: ++ /* 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. ++ */ ++ return INBAND_CISCO_SGMII; ++ ++ 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. ++ */ ++ return INBAND_BASEX; ++ ++ default: ++ return INBAND_NONE; ++ } ++} ++ + /** + * phylink_pcs_neg_mode() - helper to determine PCS inband mode + * @pl: a pointer to a &struct phylink returned from phylink_create() +@@ -1174,46 +1210,19 @@ static void phylink_pcs_neg_mode(struct + unsigned int pcs_ib_caps = 0; + unsigned int phy_ib_caps = 0; + unsigned int neg_mode, mode; +- enum { +- INBAND_CISCO_SGMII, +- INBAND_BASEX, +- } type; +- +- mode = pl->req_link_an_mode; ++ enum inband_type type; + +- pl->phy_ib_mode = 0; +- +- switch (interface) { +- case PHY_INTERFACE_MODE_SGMII: +- case PHY_INTERFACE_MODE_QSGMII: +- case PHY_INTERFACE_MODE_QUSGMII: +- case PHY_INTERFACE_MODE_USXGMII: +- case PHY_INTERFACE_MODE_10G_QXGMII: +- /* 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. +- */ +- type = INBAND_CISCO_SGMII; +- 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. +- */ +- type = INBAND_BASEX; +- break; +- +- default: ++ type = phylink_get_inband_type(interface); ++ if (type == INBAND_NONE) { + pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE; +- pl->act_link_an_mode = mode; ++ pl->act_link_an_mode = pl->req_link_an_mode; + return; + } + ++ mode = pl->req_link_an_mode; ++ ++ pl->phy_ib_mode = 0; ++ + if (pcs) + pcs_ib_caps = phylink_pcs_inband_caps(pcs, interface); + diff --git a/lede/target/linux/generic/backport-6.12/605-03-v6.17-net-phylink-disable-autoneg-for-interfaces-that-have.patch b/lede/target/linux/generic/backport-6.12/605-03-v6.17-net-phylink-disable-autoneg-for-interfaces-that-have.patch new file mode 100644 index 0000000000..0861bb820d --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/605-03-v6.17-net-phylink-disable-autoneg-for-interfaces-that-have.patch @@ -0,0 +1,68 @@ +From a21202743f9ce4063e86b99cccaef48ef9813379 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Sun, 31 Aug 2025 18:34:43 +0100 +Subject: net: phylink: disable autoneg for interfaces that have no inband + +Mathew reports that as a result of commit 6561f0e547be ("net: pcs: +pcs-lynx: implement pcs_inband_caps() method"), 10G SFP modules no +longer work with the Lynx PCS. + +This problem is not specific to the Lynx PCS, but is caused by commit +df874f9e52c3 ("net: phylink: add pcs_inband_caps() method") which added +validation of the autoneg state to the optical SFP configuration path. + +Fix this by handling interface modes that fundamentally have no +inband negotiation more correctly - if we only have a single interface +mode, clear the Autoneg support bit and the advertising mask. If the +module can operate with several different interface modes, autoneg may +be supported for other modes, so leave the support mask alone and just +clear the Autoneg bit in the advertising mask. + +This restores 10G optical module functionality with PCS that supply +their inband support, and makes ethtool output look sane. + +Reported-by: Mathew McBride +Closes: https://lore.kernel.org/r/025c0ebe-5537-4fa3-b05a-8b835e5ad317@app.fastmail.com +Fixes: df874f9e52c3 ("net: phylink: add pcs_inband_caps() method") +Signed-off-by: Russell King (Oracle) +Tested-by: Vladimir Oltean +Link: https://patch.msgid.link/E1uslwx-00000001SPB-2kiM@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -3500,6 +3500,7 @@ static int phylink_sfp_config_optical(st + __ETHTOOL_DECLARE_LINK_MODE_MASK(support); + DECLARE_PHY_INTERFACE_MASK(interfaces); + struct phylink_link_state config; ++ enum inband_type inband_type; + phy_interface_t interface; + int ret; + +@@ -3546,6 +3547,23 @@ static int phylink_sfp_config_optical(st + phylink_dbg(pl, "optical SFP: chosen %s interface\n", + phy_modes(interface)); + ++ inband_type = phylink_get_inband_type(interface); ++ if (inband_type == INBAND_NONE) { ++ /* If this is the sole interface, and there is no inband ++ * support, clear the advertising mask and Autoneg bit in ++ * the support mask. Otherwise, just clear the Autoneg bit ++ * in the advertising mask. ++ */ ++ if (phy_interface_weight(pl->sfp_interfaces) == 1) { ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ pl->sfp_support); ++ linkmode_zero(config.advertising); ++ } else { ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ config.advertising); ++ } ++ } ++ + if (!phylink_validate_pcs_inband_autoneg(pl, interface, + config.advertising)) { + phylink_err(pl, "autoneg setting not compatible with PCS"); diff --git a/lede/target/linux/generic/backport-6.12/610-01-v6.13-net-dsa-use-ethtool-string-helpers.patch b/lede/target/linux/generic/backport-6.12/610-01-v6.13-net-dsa-use-ethtool-string-helpers.patch new file mode 100644 index 0000000000..a435e29144 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/610-01-v6.13-net-dsa-use-ethtool-string-helpers.patch @@ -0,0 +1,30 @@ +From f12b363887c706c40611fba645265527a8415832 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Sun, 27 Oct 2024 21:48:28 -0700 +Subject: [PATCH] net: dsa: use ethtool string helpers + +These are the preferred way to copy ethtool strings. + +Avoids incrementing pointers all over the place. + +Signed-off-by: Rosen Penev +(for hellcreek driver) +Reviewed-by: Kurt Kanzenbach +Link: https://patch.msgid.link/20241028044828.1639668-1-rosenp@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1086,8 +1086,7 @@ void b53_get_strings(struct dsa_switch * + + if (stringset == ETH_SS_STATS) { + for (i = 0; i < mib_size; i++) +- strscpy(data + i * ETH_GSTRING_LEN, +- mibs[i].name, ETH_GSTRING_LEN); ++ ethtool_puts(&data, mibs[i].name); + } else if (stringset == ETH_SS_PHY_STATS) { + phydev = b53_get_phy_device(ds, port); + if (!phydev) diff --git a/lede/target/linux/generic/backport-6.12/610-02-v6.15-net-dsa-b53-mdio-add-support-for-BCM53101.patch b/lede/target/linux/generic/backport-6.12/610-02-v6.15-net-dsa-b53-mdio-add-support-for-BCM53101.patch new file mode 100644 index 0000000000..6cbe547423 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/610-02-v6.15-net-dsa-b53-mdio-add-support-for-BCM53101.patch @@ -0,0 +1,76 @@ +From c4f873c2b65c839ff5e7c996bd9ef5a1e7eae11a Mon Sep 17 00:00:00 2001 +From: Torben Nielsen +Date: Mon, 17 Feb 2025 09:05:01 +0100 +Subject: [PATCH] net: dsa: b53: mdio: add support for BCM53101 + +BCM53101 is a ethernet switch, very similar to the BCM53115. +Enable support for it, in the existing b53 dsa driver. + +Signed-off-by: Torben Nielsen +Signed-off-by: Claus Stovgaard +Link: https://patch.msgid.link/20250217080503.1390282-1-claus.stovgaard@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 14 ++++++++++++++ + drivers/net/dsa/b53/b53_mdio.c | 1 + + drivers/net/dsa/b53/b53_priv.h | 2 ++ + 3 files changed, 17 insertions(+) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2606,6 +2606,19 @@ static const struct b53_chip_data b53_sw + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + }, + { ++ .chip_id = BCM53101_DEVICE_ID, ++ .dev_name = "BCM53101", ++ .vlans = 4096, ++ .enabled_ports = 0x11f, ++ .arl_bins = 4, ++ .arl_buckets = 512, ++ .vta_regs = B53_VTA_REGS, ++ .imp_port = 8, ++ .duplex_reg = B53_DUPLEX_STAT_GE, ++ .jumbo_pm_reg = B53_JUMBO_PORT_MASK, ++ .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ }, ++ { + .chip_id = BCM53115_DEVICE_ID, + .dev_name = "BCM53115", + .vlans = 4096, +@@ -2986,6 +2999,7 @@ int b53_switch_detect(struct b53_device + return ret; + + switch (id32) { ++ case BCM53101_DEVICE_ID: + case BCM53115_DEVICE_ID: + case BCM53125_DEVICE_ID: + case BCM53128_DEVICE_ID: +--- a/drivers/net/dsa/b53/b53_mdio.c ++++ b/drivers/net/dsa/b53/b53_mdio.c +@@ -374,6 +374,7 @@ static void b53_mdio_shutdown(struct mdi + + static const struct of_device_id b53_of_match[] = { + { .compatible = "brcm,bcm5325" }, ++ { .compatible = "brcm,bcm53101" }, + { .compatible = "brcm,bcm53115" }, + { .compatible = "brcm,bcm53125" }, + { .compatible = "brcm,bcm53128" }, +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -66,6 +66,7 @@ enum { + BCM5395_DEVICE_ID = 0x95, + BCM5397_DEVICE_ID = 0x97, + BCM5398_DEVICE_ID = 0x98, ++ BCM53101_DEVICE_ID = 0x53101, + BCM53115_DEVICE_ID = 0x53115, + BCM53125_DEVICE_ID = 0x53125, + BCM53128_DEVICE_ID = 0x53128, +@@ -190,6 +191,7 @@ static inline int is531x5(struct b53_dev + { + return dev->chip_id == BCM53115_DEVICE_ID || + dev->chip_id == BCM53125_DEVICE_ID || ++ dev->chip_id == BCM53101_DEVICE_ID || + dev->chip_id == BCM53128_DEVICE_ID || + dev->chip_id == BCM53134_DEVICE_ID; + } diff --git a/lede/target/linux/generic/backport-6.12/610-03-v6.16-net-dsa-b53-implement-setting-ageing-time.patch b/lede/target/linux/generic/backport-6.12/610-03-v6.16-net-dsa-b53-implement-setting-ageing-time.patch new file mode 100644 index 0000000000..196e70c42c --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/610-03-v6.16-net-dsa-b53-implement-setting-ageing-time.patch @@ -0,0 +1,105 @@ +From e39d14a760c039af0653e3df967e7525413924a0 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Sat, 10 May 2025 11:22:11 +0200 +Subject: [PATCH] net: dsa: b53: implement setting ageing time + +b53 supported switches support configuring ageing time between 1 and +1,048,575 seconds, so add an appropriate setter. + +This allows b53 to pass the FDB learning test for both vlan aware and +vlan unaware bridges. + +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250510092211.276541-1-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 28 ++++++++++++++++++++++++++++ + drivers/net/dsa/b53/b53_priv.h | 1 + + drivers/net/dsa/b53/b53_regs.h | 7 +++++++ + 3 files changed, 36 insertions(+) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1227,6 +1228,10 @@ static int b53_setup(struct dsa_switch * + */ + ds->untag_vlan_aware_bridge_pvid = true; + ++ /* Ageing time is set in seconds */ ++ ds->ageing_time_min = 1 * 1000; ++ ds->ageing_time_max = AGE_TIME_MAX * 1000; ++ + ret = b53_reset_switch(dev); + if (ret) { + dev_err(ds->dev, "failed to reset switch\n"); +@@ -2466,6 +2471,28 @@ static int b53_get_max_mtu(struct dsa_sw + return B53_MAX_MTU; + } + ++int b53_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) ++{ ++ struct b53_device *dev = ds->priv; ++ u32 atc; ++ int reg; ++ ++ if (is63xx(dev)) ++ reg = B53_AGING_TIME_CONTROL_63XX; ++ else ++ reg = B53_AGING_TIME_CONTROL; ++ ++ atc = DIV_ROUND_CLOSEST(msecs, 1000); ++ ++ if (!is5325(dev) && !is5365(dev)) ++ atc |= AGE_CHANGE; ++ ++ b53_write32(dev, B53_MGMT_PAGE, reg, atc); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(b53_set_ageing_time); ++ + static const struct phylink_mac_ops b53_phylink_mac_ops = { + .mac_select_pcs = b53_phylink_mac_select_pcs, + .mac_config = b53_phylink_mac_config, +@@ -2490,6 +2517,7 @@ static const struct dsa_switch_ops b53_s + .support_eee = b53_support_eee, + .get_mac_eee = b53_get_mac_eee, + .set_mac_eee = b53_set_mac_eee, ++ .set_ageing_time = b53_set_ageing_time, + .port_bridge_join = b53_br_join, + .port_bridge_leave = b53_br_leave, + .port_pre_bridge_flags = b53_br_flags_pre, +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -343,6 +343,7 @@ void b53_get_strings(struct dsa_switch * + void b53_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data); + int b53_get_sset_count(struct dsa_switch *ds, int port, int sset); + void b53_get_ethtool_phy_stats(struct dsa_switch *ds, int port, uint64_t *data); ++int b53_set_ageing_time(struct dsa_switch *ds, unsigned int msecs); + int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge, + bool *tx_fwd_offload, struct netlink_ext_ack *extack); + void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge); +--- a/drivers/net/dsa/b53/b53_regs.h ++++ b/drivers/net/dsa/b53/b53_regs.h +@@ -224,6 +224,13 @@ + #define BRCM_HDR_P5_EN BIT(1) /* Enable tagging on port 5 */ + #define BRCM_HDR_P7_EN BIT(2) /* Enable tagging on port 7 */ + ++/* Aging Time control register (32 bit) */ ++#define B53_AGING_TIME_CONTROL 0x06 ++#define B53_AGING_TIME_CONTROL_63XX 0x08 ++#define AGE_CHANGE BIT(20) ++#define AGE_TIME_MASK 0x7ffff ++#define AGE_TIME_MAX 1048575 ++ + /* Mirror capture control register (16 bit) */ + #define B53_MIR_CAP_CTL 0x10 + #define CAP_PORT_MASK 0xf diff --git a/lede/target/linux/generic/backport-6.12/610-04-v6.16-net-dsa-b53-do-not-configure-bcm63xx-s-IMP-port-inte.patch b/lede/target/linux/generic/backport-6.12/610-04-v6.16-net-dsa-b53-do-not-configure-bcm63xx-s-IMP-port-inte.patch new file mode 100644 index 0000000000..e70f09e050 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/610-04-v6.16-net-dsa-b53-do-not-configure-bcm63xx-s-IMP-port-inte.patch @@ -0,0 +1,70 @@ +From 75f4f7b2b13008803f84768ff90396f9d7553221 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Mon, 2 Jun 2025 21:39:51 +0200 +Subject: [PATCH] net: dsa: b53: do not configure bcm63xx's IMP port interface + +The IMP port is not a valid RGMII interface, but hard wired to internal, +so we shouldn't touch the undefined register B53_RGMII_CTRL_IMP. + +While this does not seem to have any side effects, let's not touch it at +all, so limit RGMII configuration on bcm63xx to the actual RGMII ports. + +Fixes: ce3bf94871f7 ("net: dsa: b53: add support for BCM63xx RGMIIs") +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250602193953.1010487-4-jonas.gorski@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/b53/b53_common.c | 22 ++++++++-------------- + 1 file changed, 8 insertions(+), 14 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1369,24 +1370,17 @@ static void b53_adjust_63xx_rgmii(struct + phy_interface_t interface) + { + struct b53_device *dev = ds->priv; +- u8 rgmii_ctrl = 0, off; +- +- if (port == dev->imp_port) +- off = B53_RGMII_CTRL_IMP; +- else +- off = B53_RGMII_CTRL_P(port); ++ u8 rgmii_ctrl = 0; + +- b53_read8(dev, B53_CTRL_PAGE, off, &rgmii_ctrl); ++ b53_read8(dev, B53_CTRL_PAGE, B53_RGMII_CTRL_P(port), &rgmii_ctrl); + rgmii_ctrl &= ~(RGMII_CTRL_DLL_RXC | RGMII_CTRL_DLL_TXC); + +- if (port != dev->imp_port) { +- if (is63268(dev)) +- rgmii_ctrl |= RGMII_CTRL_MII_OVERRIDE; ++ if (is63268(dev)) ++ rgmii_ctrl |= RGMII_CTRL_MII_OVERRIDE; + +- rgmii_ctrl |= RGMII_CTRL_ENABLE_GMII; +- } ++ rgmii_ctrl |= RGMII_CTRL_ENABLE_GMII; + +- b53_write8(dev, B53_CTRL_PAGE, off, rgmii_ctrl); ++ b53_write8(dev, B53_CTRL_PAGE, B53_RGMII_CTRL_P(port), rgmii_ctrl); + + dev_dbg(ds->dev, "Configured port %d for %s\n", port, + phy_modes(interface)); +@@ -1537,7 +1531,7 @@ static void b53_phylink_mac_config(struc + struct b53_device *dev = ds->priv; + int port = dp->index; + +- if (is63xx(dev) && port >= B53_63XX_RGMII0) ++ if (is63xx(dev) && in_range(port, B53_63XX_RGMII0, 4)) + b53_adjust_63xx_rgmii(ds, port, interface); + + if (mode == MLO_AN_FIXED) { diff --git a/lede/target/linux/generic/backport-6.12/611-01-v6.17-net-dsa-tag_brcm-add-support-for-legacy-FCS-tags.patch b/lede/target/linux/generic/backport-6.12/611-01-v6.17-net-dsa-tag_brcm-add-support-for-legacy-FCS-tags.patch new file mode 100644 index 0000000000..88f10be377 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-01-v6.17-net-dsa-tag_brcm-add-support-for-legacy-FCS-tags.patch @@ -0,0 +1,188 @@ +From ef07df397a621707903ef0d294a7df11f80cf206 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Sat, 14 Jun 2025 09:59:48 +0200 +Subject: [PATCH] net: dsa: tag_brcm: add support for legacy FCS tags +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for legacy Broadcom FCS tags, which are similar to +DSA_TAG_PROTO_BRCM_LEGACY. +BCM5325 and BCM5365 switches require including the original FCS value and +length, as opposed to BCM63xx switches. +Adding the original FCS value and length to DSA_TAG_PROTO_BRCM_LEGACY would +impact performance of BCM63xx switches, so it's better to create a new tag. + +Signed-off-by: Álvaro Fernández Rojas +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250614080000.1884236-3-noltari@gmail.com +Signed-off-by: Jakub Kicinski +--- + include/net/dsa.h | 2 ++ + net/dsa/Kconfig | 16 ++++++++-- + net/dsa/tag_brcm.c | 73 +++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 88 insertions(+), 3 deletions(-) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -54,11 +54,13 @@ struct tc_action; + #define DSA_TAG_PROTO_RZN1_A5PSW_VALUE 26 + #define DSA_TAG_PROTO_LAN937X_VALUE 27 + #define DSA_TAG_PROTO_VSC73XX_8021Q_VALUE 28 ++#define DSA_TAG_PROTO_BRCM_LEGACY_FCS_VALUE 29 + + enum dsa_tag_protocol { + DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, + DSA_TAG_PROTO_BRCM = DSA_TAG_PROTO_BRCM_VALUE, + DSA_TAG_PROTO_BRCM_LEGACY = DSA_TAG_PROTO_BRCM_LEGACY_VALUE, ++ DSA_TAG_PROTO_BRCM_LEGACY_FCS = DSA_TAG_PROTO_BRCM_LEGACY_FCS_VALUE, + DSA_TAG_PROTO_BRCM_PREPEND = DSA_TAG_PROTO_BRCM_PREPEND_VALUE, + DSA_TAG_PROTO_DSA = DSA_TAG_PROTO_DSA_VALUE, + DSA_TAG_PROTO_EDSA = DSA_TAG_PROTO_EDSA_VALUE, +--- a/net/dsa/Kconfig ++++ b/net/dsa/Kconfig +@@ -42,12 +42,24 @@ config NET_DSA_TAG_BRCM + Broadcom switches which place the tag after the MAC source address. + + config NET_DSA_TAG_BRCM_LEGACY +- tristate "Tag driver for Broadcom legacy switches using in-frame headers" ++ tristate "Tag driver for BCM63xx legacy switches using in-frame headers" + select NET_DSA_TAG_BRCM_COMMON + help + Say Y if you want to enable support for tagging frames for the +- Broadcom legacy switches which place the tag after the MAC source ++ BCM63xx legacy switches which place the tag after the MAC source + address. ++ This tag is used in BCM63xx legacy switches which work without the ++ original FCS and length before the tag insertion. ++ ++config NET_DSA_TAG_BRCM_LEGACY_FCS ++ tristate "Tag driver for BCM53xx legacy switches using in-frame headers" ++ select NET_DSA_TAG_BRCM_COMMON ++ help ++ Say Y if you want to enable support for tagging frames for the ++ BCM53xx legacy switches which place the tag after the MAC source ++ address. ++ This tag is used in BCM53xx legacy switches which expect original ++ FCS and length before the tag insertion to be present. + + config NET_DSA_TAG_BRCM_PREPEND + tristate "Tag driver for Broadcom switches using prepended headers" +--- a/net/dsa/tag_brcm.c ++++ b/net/dsa/tag_brcm.c +@@ -15,6 +15,7 @@ + + #define BRCM_NAME "brcm" + #define BRCM_LEGACY_NAME "brcm-legacy" ++#define BRCM_LEGACY_FCS_NAME "brcm-legacy-fcs" + #define BRCM_PREPEND_NAME "brcm-prepend" + + /* Legacy Broadcom tag (6 bytes) */ +@@ -32,6 +33,10 @@ + #define BRCM_LEG_MULTICAST (1 << 5) + #define BRCM_LEG_EGRESS (2 << 5) + #define BRCM_LEG_INGRESS (3 << 5) ++#define BRCM_LEG_LEN_HI(x) (((x) >> 8) & 0x7) ++ ++/* 4th byte in the tag */ ++#define BRCM_LEG_LEN_LO(x) ((x) & 0xff) + + /* 6th byte in the tag */ + #define BRCM_LEG_PORT_ID (0xf) +@@ -212,7 +217,8 @@ DSA_TAG_DRIVER(brcm_netdev_ops); + MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM, BRCM_NAME); + #endif + +-#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) ++#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) || \ ++ IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS) + static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb, + struct net_device *dev) + { +@@ -250,7 +256,9 @@ static struct sk_buff *brcm_leg_tag_rcv( + + return skb; + } ++#endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY || CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS */ + ++#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) + static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb, + struct net_device *dev) + { +@@ -300,6 +308,66 @@ DSA_TAG_DRIVER(brcm_legacy_netdev_ops); + MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM_LEGACY, BRCM_LEGACY_NAME); + #endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY */ + ++#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS) ++static struct sk_buff *brcm_leg_fcs_tag_xmit(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct dsa_port *dp = dsa_user_to_port(dev); ++ unsigned int fcs_len; ++ __le32 fcs_val; ++ u8 *brcm_tag; ++ ++ /* The Ethernet switch we are interfaced with needs packets to be at ++ * least 64 bytes (including FCS) otherwise they will be discarded when ++ * they enter the switch port logic. When Broadcom tags are enabled, we ++ * need to make sure that packets are at least 70 bytes (including FCS ++ * and tag) because the length verification is done after the Broadcom ++ * tag is stripped off the ingress packet. ++ * ++ * Let dsa_user_xmit() free the SKB. ++ */ ++ if (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false)) ++ return NULL; ++ ++ fcs_len = skb->len; ++ fcs_val = cpu_to_le32(crc32_le(~0, skb->data, fcs_len) ^ ~0); ++ ++ skb_push(skb, BRCM_LEG_TAG_LEN); ++ ++ dsa_alloc_etype_header(skb, BRCM_LEG_TAG_LEN); ++ ++ brcm_tag = skb->data + 2 * ETH_ALEN; ++ ++ /* Broadcom tag type */ ++ brcm_tag[0] = BRCM_LEG_TYPE_HI; ++ brcm_tag[1] = BRCM_LEG_TYPE_LO; ++ ++ /* Broadcom tag value */ ++ brcm_tag[2] = BRCM_LEG_EGRESS | BRCM_LEG_LEN_HI(fcs_len); ++ brcm_tag[3] = BRCM_LEG_LEN_LO(fcs_len); ++ brcm_tag[4] = 0; ++ brcm_tag[5] = dp->index & BRCM_LEG_PORT_ID; ++ ++ /* Original FCS value */ ++ if (__skb_pad(skb, ETH_FCS_LEN, false)) ++ return NULL; ++ skb_put_data(skb, &fcs_val, ETH_FCS_LEN); ++ ++ return skb; ++} ++ ++static const struct dsa_device_ops brcm_legacy_fcs_netdev_ops = { ++ .name = BRCM_LEGACY_FCS_NAME, ++ .proto = DSA_TAG_PROTO_BRCM_LEGACY_FCS, ++ .xmit = brcm_leg_fcs_tag_xmit, ++ .rcv = brcm_leg_tag_rcv, ++ .needed_headroom = BRCM_LEG_TAG_LEN, ++}; ++ ++DSA_TAG_DRIVER(brcm_legacy_fcs_netdev_ops); ++MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM_LEGACY_FCS, BRCM_LEGACY_FCS_NAME); ++#endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS */ ++ + #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) + static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb, + struct net_device *dev) +@@ -334,6 +402,9 @@ static struct dsa_tag_driver *dsa_tag_dr + #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) + &DSA_TAG_DRIVER_NAME(brcm_legacy_netdev_ops), + #endif ++#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS) ++ &DSA_TAG_DRIVER_NAME(brcm_legacy_fcs_netdev_ops), ++#endif + #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) + &DSA_TAG_DRIVER_NAME(brcm_prepend_netdev_ops), + #endif diff --git a/lede/target/linux/generic/backport-6.12/611-02-v6.17-net-dsa-b53-support-legacy-FCS-tags.patch b/lede/target/linux/generic/backport-6.12/611-02-v6.17-net-dsa-b53-support-legacy-FCS-tags.patch new file mode 100644 index 0000000000..b04c8ea27e --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-02-v6.17-net-dsa-b53-support-legacy-FCS-tags.patch @@ -0,0 +1,48 @@ +From c3cf059a4d419b9c888ce7e9952fa13ba7569b61 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Sat, 14 Jun 2025 09:59:49 +0200 +Subject: [PATCH] net: dsa: b53: support legacy FCS tags +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit 46c5176c586c ("net: dsa: b53: support legacy tags") introduced +support for legacy tags, but it turns out that BCM5325 and BCM5365 +switches require the original FCS value and length, so they have to be +treated differently. + +Reviewed-by: Florian Fainelli +Signed-off-by: Álvaro Fernández Rojas +Link: https://patch.msgid.link/20250614080000.1884236-4-noltari@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/Kconfig | 1 + + drivers/net/dsa/b53/b53_common.c | 7 +++++-- + 2 files changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/b53/Kconfig ++++ b/drivers/net/dsa/b53/Kconfig +@@ -5,6 +5,7 @@ menuconfig B53 + select NET_DSA_TAG_NONE + select NET_DSA_TAG_BRCM + select NET_DSA_TAG_BRCM_LEGACY ++ select NET_DSA_TAG_BRCM_LEGACY_FCS + select NET_DSA_TAG_BRCM_PREPEND + help + This driver adds support for Broadcom managed switch chips. It supports +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2307,8 +2307,11 @@ enum dsa_tag_protocol b53_get_tag_protoc + goto out; + } + +- /* Older models require a different 6 byte tag */ +- if (is5325(dev) || is5365(dev) || is63xx(dev)) { ++ /* Older models require different 6 byte tags */ ++ if (is5325(dev) || is5365(dev)) { ++ dev->tag_protocol = DSA_TAG_PROTO_BRCM_LEGACY_FCS; ++ goto out; ++ } else if (is63xx(dev)) { + dev->tag_protocol = DSA_TAG_PROTO_BRCM_LEGACY; + goto out; + } diff --git a/lede/target/linux/generic/backport-6.12/611-03-v6.17-net-dsa-b53-detect-BCM5325-variants.patch b/lede/target/linux/generic/backport-6.12/611-03-v6.17-net-dsa-b53-detect-BCM5325-variants.patch new file mode 100644 index 0000000000..3c2fa2d8c4 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-03-v6.17-net-dsa-b53-detect-BCM5325-variants.patch @@ -0,0 +1,112 @@ +From 0cbec9aef5a86194117a956546dc1aec95031f37 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Sat, 14 Jun 2025 09:59:50 +0200 +Subject: [PATCH] net: dsa: b53: detect BCM5325 variants +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We need to be able to differentiate the BCM5325 variants because: +- BCM5325M switches lack the ARLIO_PAGE->VLAN_ID_IDX register. +- BCM5325E have less 512 ARL buckets instead of 1024. + +Signed-off-by: Álvaro Fernández Rojas +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250614080000.1884236-5-noltari@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 24 +++++++++++++++++++++--- + drivers/net/dsa/b53/b53_priv.h | 19 +++++++++++++++++++ + 2 files changed, 40 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1835,7 +1835,8 @@ static int b53_arl_op(struct b53_device + + /* Perform a read for the given MAC and VID */ + b53_write48(dev, B53_ARLIO_PAGE, B53_MAC_ADDR_IDX, mac); +- b53_write16(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid); ++ if (!is5325m(dev)) ++ b53_write16(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid); + + /* Issue a read operation for this MAC */ + ret = b53_arl_rw_op(dev, 1); +@@ -2906,6 +2907,9 @@ static int b53_switch_init(struct b53_de + } + } + ++ if (is5325e(dev)) ++ dev->num_arl_buckets = 512; ++ + dev->num_ports = fls(dev->enabled_ports); + + dev->ds->num_ports = min_t(unsigned int, dev->num_ports, DSA_MAX_PORTS); +@@ -3007,10 +3011,24 @@ int b53_switch_detect(struct b53_device + b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_25, 0xf); + b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_25, &tmp); + +- if (tmp == 0xf) ++ if (tmp == 0xf) { ++ u32 phy_id; ++ int val; ++ + dev->chip_id = BCM5325_DEVICE_ID; +- else ++ ++ val = b53_phy_read16(dev->ds, 0, MII_PHYSID1); ++ phy_id = (val & 0xffff) << 16; ++ val = b53_phy_read16(dev->ds, 0, MII_PHYSID2); ++ phy_id |= (val & 0xfff0); ++ ++ if (phy_id == 0x00406330) ++ dev->variant_id = B53_VARIANT_5325M; ++ else if (phy_id == 0x0143bc30) ++ dev->variant_id = B53_VARIANT_5325E; ++ } else { + dev->chip_id = BCM5365_DEVICE_ID; ++ } + break; + case BCM5389_DEVICE_ID: + case BCM5395_DEVICE_ID: +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -84,6 +84,12 @@ enum { + BCM53134_DEVICE_ID = 0x5075, + }; + ++enum b53_variant_id { ++ B53_VARIANT_NONE = 0, ++ B53_VARIANT_5325E, ++ B53_VARIANT_5325M, ++}; ++ + struct b53_pcs { + struct phylink_pcs pcs; + struct b53_device *dev; +@@ -118,6 +124,7 @@ struct b53_device { + + /* chip specific data */ + u32 chip_id; ++ enum b53_variant_id variant_id; + u8 core_rev; + u8 vta_regs[3]; + u8 duplex_reg; +@@ -165,6 +172,18 @@ static inline int is5325(struct b53_devi + return dev->chip_id == BCM5325_DEVICE_ID; + } + ++static inline int is5325e(struct b53_device *dev) ++{ ++ return is5325(dev) && ++ dev->variant_id == B53_VARIANT_5325E; ++} ++ ++static inline int is5325m(struct b53_device *dev) ++{ ++ return is5325(dev) && ++ dev->variant_id == B53_VARIANT_5325M; ++} ++ + static inline int is5365(struct b53_device *dev) + { + #ifdef CONFIG_BCM47XX diff --git a/lede/target/linux/generic/backport-6.12/611-04-v6.17-net-dsa-b53-add-support-for-FDB-operations-on-5325-5365.patch b/lede/target/linux/generic/backport-6.12/611-04-v6.17-net-dsa-b53-add-support-for-FDB-operations-on-5325-5365.patch new file mode 100644 index 0000000000..9de73815da --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-04-v6.17-net-dsa-b53-add-support-for-FDB-operations-on-5325-5365.patch @@ -0,0 +1,250 @@ +From c45655386e532c85ff1d679fc2aa40b3aaff9916 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Sat, 14 Jun 2025 09:59:51 +0200 +Subject: [PATCH] net: dsa: b53: add support for FDB operations on 5325/5365 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BCM5325 and BCM5365 are part of a much older generation of switches which, +due to their limited number of ports and VLAN entries (up to 256) allowed +a single 64-bit register to hold a full ARL entry. +This requires a little bit of massaging when reading, writing and +converting ARL entries in both directions. + +Signed-off-by: Florian Fainelli +Signed-off-by: Álvaro Fernández Rojas +Link: https://patch.msgid.link/20250614080000.1884236-6-noltari@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 101 +++++++++++++++++++++++++------ + drivers/net/dsa/b53/b53_priv.h | 29 +++++++++ + drivers/net/dsa/b53/b53_regs.h | 7 ++- + 3 files changed, 115 insertions(+), 22 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1821,6 +1821,45 @@ static int b53_arl_read(struct b53_devic + return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT; + } + ++static int b53_arl_read_25(struct b53_device *dev, u64 mac, ++ u16 vid, struct b53_arl_entry *ent, u8 *idx) ++{ ++ DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES); ++ unsigned int i; ++ int ret; ++ ++ ret = b53_arl_op_wait(dev); ++ if (ret) ++ return ret; ++ ++ bitmap_zero(free_bins, dev->num_arl_bins); ++ ++ /* Read the bins */ ++ for (i = 0; i < dev->num_arl_bins; i++) { ++ u64 mac_vid; ++ ++ b53_read64(dev, B53_ARLIO_PAGE, ++ B53_ARLTBL_MAC_VID_ENTRY(i), &mac_vid); ++ ++ b53_arl_to_entry_25(ent, mac_vid); ++ ++ if (!(mac_vid & ARLTBL_VALID_25)) { ++ set_bit(i, free_bins); ++ continue; ++ } ++ if ((mac_vid & ARLTBL_MAC_MASK) != mac) ++ continue; ++ if (dev->vlan_enabled && ++ ((mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25) != vid) ++ continue; ++ *idx = i; ++ return 0; ++ } ++ ++ *idx = find_first_bit(free_bins, dev->num_arl_bins); ++ return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT; ++} ++ + static int b53_arl_op(struct b53_device *dev, int op, int port, + const unsigned char *addr, u16 vid, bool is_valid) + { +@@ -1843,7 +1882,10 @@ static int b53_arl_op(struct b53_device + if (ret) + return ret; + +- ret = b53_arl_read(dev, mac, vid, &ent, &idx); ++ if (is5325(dev) || is5365(dev)) ++ ret = b53_arl_read_25(dev, mac, vid, &ent, &idx); ++ else ++ ret = b53_arl_read(dev, mac, vid, &ent, &idx); + + /* If this is a read, just finish now */ + if (op) +@@ -1887,12 +1929,17 @@ static int b53_arl_op(struct b53_device + ent.is_static = true; + ent.is_age = false; + memcpy(ent.mac, addr, ETH_ALEN); +- b53_arl_from_entry(&mac_vid, &fwd_entry, &ent); ++ if (is5325(dev) || is5365(dev)) ++ b53_arl_from_entry_25(&mac_vid, &ent); ++ else ++ b53_arl_from_entry(&mac_vid, &fwd_entry, &ent); + + b53_write64(dev, B53_ARLIO_PAGE, + B53_ARLTBL_MAC_VID_ENTRY(idx), mac_vid); +- b53_write32(dev, B53_ARLIO_PAGE, +- B53_ARLTBL_DATA_ENTRY(idx), fwd_entry); ++ ++ if (!is5325(dev) && !is5365(dev)) ++ b53_write32(dev, B53_ARLIO_PAGE, ++ B53_ARLTBL_DATA_ENTRY(idx), fwd_entry); + + return b53_arl_rw_op(dev, 0); + } +@@ -1904,12 +1951,6 @@ int b53_fdb_add(struct dsa_switch *ds, i + struct b53_device *priv = ds->priv; + int ret; + +- /* 5325 and 5365 require some more massaging, but could +- * be supported eventually +- */ +- if (is5325(priv) || is5365(priv)) +- return -EOPNOTSUPP; +- + mutex_lock(&priv->arl_mutex); + ret = b53_arl_op(priv, 0, port, addr, vid, true); + mutex_unlock(&priv->arl_mutex); +@@ -1936,10 +1977,15 @@ EXPORT_SYMBOL(b53_fdb_del); + static int b53_arl_search_wait(struct b53_device *dev) + { + unsigned int timeout = 1000; +- u8 reg; ++ u8 reg, offset; ++ ++ if (is5325(dev) || is5365(dev)) ++ offset = B53_ARL_SRCH_CTL_25; ++ else ++ offset = B53_ARL_SRCH_CTL; + + do { +- b53_read8(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_CTL, ®); ++ b53_read8(dev, B53_ARLIO_PAGE, offset, ®); + if (!(reg & ARL_SRCH_STDN)) + return -ENOENT; + +@@ -1956,13 +2002,24 @@ static void b53_arl_search_rd(struct b53 + struct b53_arl_entry *ent) + { + u64 mac_vid; +- u32 fwd_entry; + +- b53_read64(dev, B53_ARLIO_PAGE, +- B53_ARL_SRCH_RSTL_MACVID(idx), &mac_vid); +- b53_read32(dev, B53_ARLIO_PAGE, +- B53_ARL_SRCH_RSTL(idx), &fwd_entry); +- b53_arl_to_entry(ent, mac_vid, fwd_entry); ++ if (is5325(dev)) { ++ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_25, ++ &mac_vid); ++ b53_arl_to_entry_25(ent, mac_vid); ++ } else if (is5365(dev)) { ++ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_65, ++ &mac_vid); ++ b53_arl_to_entry_25(ent, mac_vid); ++ } else { ++ u32 fwd_entry; ++ ++ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_MACVID(idx), ++ &mac_vid); ++ b53_read32(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL(idx), ++ &fwd_entry); ++ b53_arl_to_entry(ent, mac_vid, fwd_entry); ++ } + } + + static int b53_fdb_copy(int port, const struct b53_arl_entry *ent, +@@ -1986,14 +2043,20 @@ int b53_fdb_dump(struct dsa_switch *ds, + struct b53_device *priv = ds->priv; + struct b53_arl_entry results[2]; + unsigned int count = 0; ++ u8 offset; + int ret; + u8 reg; + + mutex_lock(&priv->arl_mutex); + ++ if (is5325(priv) || is5365(priv)) ++ offset = B53_ARL_SRCH_CTL_25; ++ else ++ offset = B53_ARL_SRCH_CTL; ++ + /* Start search operation */ + reg = ARL_SRCH_STDN; +- b53_write8(priv, B53_ARLIO_PAGE, B53_ARL_SRCH_CTL, reg); ++ b53_write8(priv, offset, B53_ARL_SRCH_CTL, reg); + + do { + ret = b53_arl_search_wait(priv); +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -317,6 +317,19 @@ static inline void b53_arl_to_entry(stru + ent->vid = mac_vid >> ARLTBL_VID_S; + } + ++static inline void b53_arl_to_entry_25(struct b53_arl_entry *ent, ++ u64 mac_vid) ++{ ++ memset(ent, 0, sizeof(*ent)); ++ ent->port = (mac_vid >> ARLTBL_DATA_PORT_ID_S_25) & ++ ARLTBL_DATA_PORT_ID_MASK_25; ++ ent->is_valid = !!(mac_vid & ARLTBL_VALID_25); ++ ent->is_age = !!(mac_vid & ARLTBL_AGE_25); ++ ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); ++ u64_to_ether_addr(mac_vid, ent->mac); ++ ent->vid = mac_vid >> ARLTBL_VID_S_65; ++} ++ + static inline void b53_arl_from_entry(u64 *mac_vid, u32 *fwd_entry, + const struct b53_arl_entry *ent) + { +@@ -331,6 +344,22 @@ static inline void b53_arl_from_entry(u6 + *fwd_entry |= ARLTBL_AGE; + } + ++static inline void b53_arl_from_entry_25(u64 *mac_vid, ++ const struct b53_arl_entry *ent) ++{ ++ *mac_vid = ether_addr_to_u64(ent->mac); ++ *mac_vid |= (u64)(ent->port & ARLTBL_DATA_PORT_ID_MASK_25) << ++ ARLTBL_DATA_PORT_ID_S_25; ++ *mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK_25) << ++ ARLTBL_VID_S_65; ++ if (ent->is_valid) ++ *mac_vid |= ARLTBL_VALID_25; ++ if (ent->is_static) ++ *mac_vid |= ARLTBL_STATIC_25; ++ if (ent->is_age) ++ *mac_vid |= ARLTBL_AGE_25; ++} ++ + #ifdef CONFIG_BCM47XX + + #include +--- a/drivers/net/dsa/b53/b53_regs.h ++++ b/drivers/net/dsa/b53/b53_regs.h +@@ -328,9 +328,10 @@ + #define ARLTBL_VID_MASK 0xfff + #define ARLTBL_DATA_PORT_ID_S_25 48 + #define ARLTBL_DATA_PORT_ID_MASK_25 0xf +-#define ARLTBL_AGE_25 BIT(61) +-#define ARLTBL_STATIC_25 BIT(62) +-#define ARLTBL_VALID_25 BIT(63) ++#define ARLTBL_VID_S_65 53 ++#define ARLTBL_AGE_25 BIT_ULL(61) ++#define ARLTBL_STATIC_25 BIT_ULL(62) ++#define ARLTBL_VALID_25 BIT_ULL(63) + + /* ARL Table Data Entry N Registers (32 bit) */ + #define B53_ARLTBL_DATA_ENTRY(n) ((0x10 * (n)) + 0x18) diff --git a/lede/target/linux/generic/backport-6.12/611-05-v6.17-net-dsa-b53-prevent-FAST_AGE-access-on-BCM5325.patch b/lede/target/linux/generic/backport-6.12/611-05-v6.17-net-dsa-b53-prevent-FAST_AGE-access-on-BCM5325.patch new file mode 100644 index 0000000000..7397e3323c --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-05-v6.17-net-dsa-b53-prevent-FAST_AGE-access-on-BCM5325.patch @@ -0,0 +1,51 @@ +From 9b6c767c312b4709e9aeb2314a6b47863e7fb72d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Sat, 14 Jun 2025 09:59:52 +0200 +Subject: [PATCH] net: dsa: b53: prevent FAST_AGE access on BCM5325 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BCM5325 doesn't implement FAST_AGE registers so we should avoid reading or +writing them. + +Signed-off-by: Álvaro Fernández Rojas +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250614080000.1884236-7-noltari@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -492,6 +492,9 @@ static int b53_flush_arl(struct b53_devi + { + unsigned int i; + ++ if (is5325(dev)) ++ return 0; ++ + b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL, + FAST_AGE_DONE | FAST_AGE_DYNAMIC | mask); + +@@ -516,6 +519,9 @@ out: + + static int b53_fast_age_port(struct b53_device *dev, int port) + { ++ if (is5325(dev)) ++ return 0; ++ + b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_PORT_CTRL, port); + + return b53_flush_arl(dev, FAST_AGE_PORT); +@@ -523,6 +529,9 @@ static int b53_fast_age_port(struct b53_ + + static int b53_fast_age_vlan(struct b53_device *dev, u16 vid) + { ++ if (is5325(dev)) ++ return 0; ++ + b53_write16(dev, B53_CTRL_PAGE, B53_FAST_AGE_VID_CTRL, vid); + + return b53_flush_arl(dev, FAST_AGE_VLAN); diff --git a/lede/target/linux/generic/backport-6.12/611-06-v6.17-net-dsa-b53-prevent-BRCM_HDR-access-on-older-devices.patch b/lede/target/linux/generic/backport-6.12/611-06-v6.17-net-dsa-b53-prevent-BRCM_HDR-access-on-older-devices.patch new file mode 100644 index 0000000000..6ea836734a --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-06-v6.17-net-dsa-b53-prevent-BRCM_HDR-access-on-older-devices.patch @@ -0,0 +1,33 @@ +From e17813968b08b1b09bf80699223dea48851cbd07 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Sat, 14 Jun 2025 09:59:56 +0200 +Subject: [PATCH] net: dsa: b53: prevent BRCM_HDR access on older devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Older switches don't implement BRCM_HDR register so we should avoid +reading or writing it. + +Reviewed-by: Florian Fainelli +Signed-off-by: Álvaro Fernández Rojas +Link: https://patch.msgid.link/20250614080000.1884236-11-noltari@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -747,6 +747,11 @@ void b53_brcm_hdr_setup(struct dsa_switc + hdr_ctl |= GC_FRM_MGMT_PORT_M; + b53_write8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, hdr_ctl); + ++ /* B53_BRCM_HDR not present on devices with legacy tags */ ++ if (dev->tag_protocol == DSA_TAG_PROTO_BRCM_LEGACY || ++ dev->tag_protocol == DSA_TAG_PROTO_BRCM_LEGACY_FCS) ++ return; ++ + /* Enable Broadcom tags for IMP port */ + b53_read8(dev, B53_MGMT_PAGE, B53_BRCM_HDR, &hdr_ctl); + if (tag_en) diff --git a/lede/target/linux/generic/backport-6.12/611-07-v6.17-net-dsa-b53-fix-unicast-multicast-flooding-on-BCM5325.patch b/lede/target/linux/generic/backport-6.12/611-07-v6.17-net-dsa-b53-fix-unicast-multicast-flooding-on-BCM5325.patch new file mode 100644 index 0000000000..6b9c86ed0c --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-07-v6.17-net-dsa-b53-fix-unicast-multicast-flooding-on-BCM5325.patch @@ -0,0 +1,128 @@ +From 651c9e71ffe44e99b5a9b011271c2117f0353b32 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Sat, 14 Jun 2025 09:59:58 +0200 +Subject: [PATCH] net: dsa: b53: fix unicast/multicast flooding on BCM5325 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BCM5325 doesn't implement UC_FLOOD_MASK, MC_FLOOD_MASK and IPMC_FLOOD_MASK +registers. +This has to be handled differently with other pages and registers. + +Signed-off-by: Álvaro Fernández Rojas +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250614080000.1884236-13-noltari@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 60 ++++++++++++++++++++++---------- + drivers/net/dsa/b53/b53_regs.h | 13 +++++++ + 2 files changed, 55 insertions(+), 18 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -564,12 +564,24 @@ static void b53_port_set_ucast_flood(str + { + u16 uc; + +- b53_read16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, &uc); +- if (unicast) +- uc |= BIT(port); +- else +- uc &= ~BIT(port); +- b53_write16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, uc); ++ if (is5325(dev)) { ++ if (port == B53_CPU_PORT_25) ++ port = B53_CPU_PORT; ++ ++ b53_read16(dev, B53_IEEE_PAGE, B53_IEEE_UCAST_DLF, &uc); ++ if (unicast) ++ uc |= BIT(port) | B53_IEEE_UCAST_DROP_EN; ++ else ++ uc &= ~BIT(port); ++ b53_write16(dev, B53_IEEE_PAGE, B53_IEEE_UCAST_DLF, uc); ++ } else { ++ b53_read16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, &uc); ++ if (unicast) ++ uc |= BIT(port); ++ else ++ uc &= ~BIT(port); ++ b53_write16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, uc); ++ } + } + + static void b53_port_set_mcast_flood(struct b53_device *dev, int port, +@@ -577,19 +589,31 @@ static void b53_port_set_mcast_flood(str + { + u16 mc; + +- b53_read16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, &mc); +- if (multicast) +- mc |= BIT(port); +- else +- mc &= ~BIT(port); +- b53_write16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, mc); +- +- b53_read16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, &mc); +- if (multicast) +- mc |= BIT(port); +- else +- mc &= ~BIT(port); +- b53_write16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, mc); ++ if (is5325(dev)) { ++ if (port == B53_CPU_PORT_25) ++ port = B53_CPU_PORT; ++ ++ b53_read16(dev, B53_IEEE_PAGE, B53_IEEE_MCAST_DLF, &mc); ++ if (multicast) ++ mc |= BIT(port) | B53_IEEE_MCAST_DROP_EN; ++ else ++ mc &= ~BIT(port); ++ b53_write16(dev, B53_IEEE_PAGE, B53_IEEE_MCAST_DLF, mc); ++ } else { ++ b53_read16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, &mc); ++ if (multicast) ++ mc |= BIT(port); ++ else ++ mc &= ~BIT(port); ++ b53_write16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, mc); ++ ++ b53_read16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, &mc); ++ if (multicast) ++ mc |= BIT(port); ++ else ++ mc &= ~BIT(port); ++ b53_write16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, mc); ++ } + } + + static void b53_port_set_learning(struct b53_device *dev, int port, +--- a/drivers/net/dsa/b53/b53_regs.h ++++ b/drivers/net/dsa/b53/b53_regs.h +@@ -29,6 +29,7 @@ + #define B53_ARLIO_PAGE 0x05 /* ARL Access */ + #define B53_FRAMEBUF_PAGE 0x06 /* Management frame access */ + #define B53_MEM_ACCESS_PAGE 0x08 /* Memory access */ ++#define B53_IEEE_PAGE 0x0a /* IEEE 802.1X */ + + /* PHY Registers */ + #define B53_PORT_MII_PAGE(i) (0x10 + (i)) /* Port i MII Registers */ +@@ -371,6 +372,18 @@ + #define B53_ARL_SRCH_RSTL(x) (B53_ARL_SRCH_RSTL_0 + ((x) * 0x10)) + + /************************************************************************* ++ * IEEE 802.1X Registers ++ *************************************************************************/ ++ ++/* Multicast DLF Drop Control register (16 bit) */ ++#define B53_IEEE_MCAST_DLF 0x94 ++#define B53_IEEE_MCAST_DROP_EN BIT(11) ++ ++/* Unicast DLF Drop Control register (16 bit) */ ++#define B53_IEEE_UCAST_DLF 0x96 ++#define B53_IEEE_UCAST_DROP_EN BIT(11) ++ ++/************************************************************************* + * Port VLAN Registers + *************************************************************************/ + diff --git a/lede/target/linux/generic/backport-6.12/611-08-v6.18-net-dsa-b53-Add-phy_enable-phy_disable-methods.patch b/lede/target/linux/generic/backport-6.12/611-08-v6.18-net-dsa-b53-Add-phy_enable-phy_disable-methods.patch new file mode 100644 index 0000000000..14106e3dd2 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-08-v6.18-net-dsa-b53-Add-phy_enable-phy_disable-methods.patch @@ -0,0 +1,50 @@ +From be7a79145d85af1a9d65a45560b9243b13a67782 Mon Sep 17 00:00:00 2001 +From: Kyle Hendry +Date: Wed, 23 Jul 2025 20:52:40 -0700 +Subject: [PATCH] net: dsa: b53: Add phy_enable(), phy_disable() methods + +Add phy enable/disable to b53 ops to be called when +enabling/disabling ports. + +Signed-off-by: Kyle Hendry +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250724035300.20497-2-kylehendrydev@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 6 ++++++ + drivers/net/dsa/b53/b53_priv.h | 2 ++ + 2 files changed, 8 insertions(+) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -689,6 +689,9 @@ int b53_enable_port(struct dsa_switch *d + + cpu_port = dsa_to_port(ds, port)->cpu_dp->index; + ++ if (dev->ops->phy_enable) ++ dev->ops->phy_enable(dev, port); ++ + if (dev->ops->irq_enable) + ret = dev->ops->irq_enable(dev, port); + if (ret) +@@ -727,6 +730,9 @@ void b53_disable_port(struct dsa_switch + reg |= PORT_CTRL_RX_DISABLE | PORT_CTRL_TX_DISABLE; + b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), reg); + ++ if (dev->ops->phy_disable) ++ dev->ops->phy_disable(dev, port); ++ + if (dev->ops->irq_disable) + dev->ops->irq_disable(dev, port); + } +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -45,6 +45,8 @@ struct b53_io_ops { + int (*phy_write16)(struct b53_device *dev, int addr, int reg, u16 value); + int (*irq_enable)(struct b53_device *dev, int port); + void (*irq_disable)(struct b53_device *dev, int port); ++ void (*phy_enable)(struct b53_device *dev, int port); ++ void (*phy_disable)(struct b53_device *dev, int port); + void (*phylink_get_caps)(struct b53_device *dev, int port, + struct phylink_config *config); + struct phylink_pcs *(*phylink_mac_select_pcs)(struct b53_device *dev, diff --git a/lede/target/linux/generic/backport-6.12/611-09-v6.18-net-dsa-b53-Define-chip-IDs-for-more-bcm63xx-SoCs.patch b/lede/target/linux/generic/backport-6.12/611-09-v6.18-net-dsa-b53-Define-chip-IDs-for-more-bcm63xx-SoCs.patch new file mode 100644 index 0000000000..0e039168ad --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-09-v6.18-net-dsa-b53-Define-chip-IDs-for-more-bcm63xx-SoCs.patch @@ -0,0 +1,124 @@ +From fcf02a462fab52fbfcb24e617dd940745afd0dff Mon Sep 17 00:00:00 2001 +From: Kyle Hendry +Date: Wed, 23 Jul 2025 20:52:42 -0700 +Subject: [PATCH] net: dsa: b53: Define chip IDs for more bcm63xx SoCs + +Add defines for bcm6318, bcm6328, bcm6362, bcm6368 chip IDs, +update tables and switch init. + +Signed-off-by: Kyle Hendry +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250724035300.20497-4-kylehendrydev@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 21 ++++++--------------- + drivers/net/dsa/b53/b53_mmap.c | 8 ++++---- + drivers/net/dsa/b53/b53_priv.h | 13 +++++++++++-- + 3 files changed, 21 insertions(+), 21 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1419,7 +1419,7 @@ static void b53_adjust_63xx_rgmii(struct + b53_read8(dev, B53_CTRL_PAGE, B53_RGMII_CTRL_P(port), &rgmii_ctrl); + rgmii_ctrl &= ~(RGMII_CTRL_DLL_RXC | RGMII_CTRL_DLL_TXC); + +- if (is63268(dev)) ++ if (is6318_268(dev)) + rgmii_ctrl |= RGMII_CTRL_MII_OVERRIDE; + + rgmii_ctrl |= RGMII_CTRL_ENABLE_GMII; +@@ -2804,19 +2804,6 @@ static const struct b53_chip_data b53_sw + .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, + }, + { +- .chip_id = BCM63268_DEVICE_ID, +- .dev_name = "BCM63268", +- .vlans = 4096, +- .enabled_ports = 0, /* pdata must provide them */ +- .arl_bins = 4, +- .arl_buckets = 1024, +- .imp_port = 8, +- .vta_regs = B53_VTA_REGS_63XX, +- .duplex_reg = B53_DUPLEX_STAT_63XX, +- .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, +- .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, +- }, +- { + .chip_id = BCM53010_DEVICE_ID, + .dev_name = "BCM53010", + .vlans = 4096, +@@ -2965,13 +2952,17 @@ static const struct b53_chip_data b53_sw + + static int b53_switch_init(struct b53_device *dev) + { ++ u32 chip_id = dev->chip_id; + unsigned int i; + int ret; + ++ if (is63xx(dev)) ++ chip_id = BCM63XX_DEVICE_ID; ++ + for (i = 0; i < ARRAY_SIZE(b53_switch_chips); i++) { + const struct b53_chip_data *chip = &b53_switch_chips[i]; + +- if (chip->chip_id == dev->chip_id) { ++ if (chip->chip_id == chip_id) { + if (!dev->enabled_ports) + dev->enabled_ports = chip->enabled_ports; + dev->name = chip->dev_name; +--- a/drivers/net/dsa/b53/b53_mmap.c ++++ b/drivers/net/dsa/b53/b53_mmap.c +@@ -348,16 +348,16 @@ static const struct of_device_id b53_mma + .data = (void *)BCM63XX_DEVICE_ID, + }, { + .compatible = "brcm,bcm6318-switch", +- .data = (void *)BCM63268_DEVICE_ID, ++ .data = (void *)BCM6318_DEVICE_ID, + }, { + .compatible = "brcm,bcm6328-switch", +- .data = (void *)BCM63XX_DEVICE_ID, ++ .data = (void *)BCM6328_DEVICE_ID, + }, { + .compatible = "brcm,bcm6362-switch", +- .data = (void *)BCM63XX_DEVICE_ID, ++ .data = (void *)BCM6362_DEVICE_ID, + }, { + .compatible = "brcm,bcm6368-switch", +- .data = (void *)BCM63XX_DEVICE_ID, ++ .data = (void *)BCM6368_DEVICE_ID, + }, { + .compatible = "brcm,bcm63268-switch", + .data = (void *)BCM63268_DEVICE_ID, +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -73,6 +73,10 @@ enum { + BCM53125_DEVICE_ID = 0x53125, + BCM53128_DEVICE_ID = 0x53128, + BCM63XX_DEVICE_ID = 0x6300, ++ BCM6318_DEVICE_ID = 0x6318, ++ BCM6328_DEVICE_ID = 0x6328, ++ BCM6362_DEVICE_ID = 0x6362, ++ BCM6368_DEVICE_ID = 0x6368, + BCM63268_DEVICE_ID = 0x63268, + BCM53010_DEVICE_ID = 0x53010, + BCM53011_DEVICE_ID = 0x53011, +@@ -220,12 +224,17 @@ static inline int is531x5(struct b53_dev + static inline int is63xx(struct b53_device *dev) + { + return dev->chip_id == BCM63XX_DEVICE_ID || ++ dev->chip_id == BCM6318_DEVICE_ID || ++ dev->chip_id == BCM6328_DEVICE_ID || ++ dev->chip_id == BCM6362_DEVICE_ID || ++ dev->chip_id == BCM6368_DEVICE_ID || + dev->chip_id == BCM63268_DEVICE_ID; + } + +-static inline int is63268(struct b53_device *dev) ++static inline int is6318_268(struct b53_device *dev) + { +- return dev->chip_id == BCM63268_DEVICE_ID; ++ return dev->chip_id == BCM6318_DEVICE_ID || ++ dev->chip_id == BCM63268_DEVICE_ID; + } + + static inline int is5301x(struct b53_device *dev) diff --git a/lede/target/linux/generic/backport-6.12/611-10-v6.18-net-dsa-b53-mmap-Add-syscon-reference-and-register-layout-for-bcm63268.patch b/lede/target/linux/generic/backport-6.12/611-10-v6.18-net-dsa-b53-mmap-Add-syscon-reference-and-register-layout-for-bcm63268.patch new file mode 100644 index 0000000000..92e540d384 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-10-v6.18-net-dsa-b53-mmap-Add-syscon-reference-and-register-layout-for-bcm63268.patch @@ -0,0 +1,69 @@ +From aed2aaa3c963f8aabbfa061a177022fee826ebfb Mon Sep 17 00:00:00 2001 +From: Kyle Hendry +Date: Wed, 23 Jul 2025 20:52:43 -0700 +Subject: [PATCH] net: dsa: b53: mmap: Add syscon reference and register layout + for bcm63268 + +On bcm63xx SoCs there are registers that control the PHYs in +the GPIO controller. Allow the b53 driver to access them +by passing in the syscon through the device tree. + +Add a structure to describe the ephy control register +and add register info for bcm63268. + +Signed-off-by: Kyle Hendry +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250724035300.20497-5-kylehendrydev@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_mmap.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +--- a/drivers/net/dsa/b53/b53_mmap.c ++++ b/drivers/net/dsa/b53/b53_mmap.c +@@ -21,13 +21,32 @@ + #include + #include + #include ++#include + #include + #include + + #include "b53_priv.h" + ++struct b53_phy_info { ++ u32 ephy_enable_mask; ++ u32 ephy_port_mask; ++ u32 ephy_bias_bit; ++ const u32 *ephy_offset; ++}; ++ + struct b53_mmap_priv { + void __iomem *regs; ++ struct regmap *gpio_ctrl; ++ const struct b53_phy_info *phy_info; ++}; ++ ++static const u32 bcm63268_ephy_offsets[] = {4, 9, 14}; ++ ++static const struct b53_phy_info bcm63268_ephy_info = { ++ .ephy_enable_mask = GENMASK(4, 0), ++ .ephy_port_mask = GENMASK((ARRAY_SIZE(bcm63268_ephy_offsets) - 1), 0), ++ .ephy_bias_bit = 24, ++ .ephy_offset = bcm63268_ephy_offsets, + }; + + static int b53_mmap_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val) +@@ -313,6 +332,12 @@ static int b53_mmap_probe(struct platfor + + priv->regs = pdata->regs; + ++ priv->gpio_ctrl = syscon_regmap_lookup_by_phandle(np, "brcm,gpio-ctrl"); ++ if (!IS_ERR(priv->gpio_ctrl)) { ++ if (pdata->chip_id == BCM63268_DEVICE_ID) ++ priv->phy_info = &bcm63268_ephy_info; ++ } ++ + dev = b53_switch_alloc(&pdev->dev, &b53_mmap_ops, priv); + if (!dev) + return -ENOMEM; diff --git a/lede/target/linux/generic/backport-6.12/611-11-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6318.patch b/lede/target/linux/generic/backport-6.12/611-11-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6318.patch new file mode 100644 index 0000000000..f6c1cbaf01 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-11-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6318.patch @@ -0,0 +1,47 @@ +From c251304ab021ff21c77e83e0babcb9eb76f8787a Mon Sep 17 00:00:00 2001 +From: Kyle Hendry +Date: Wed, 23 Jul 2025 20:52:44 -0700 +Subject: [PATCH] net: dsa: b53: mmap: Add register layout for bcm6318 + +Add ephy register info for bcm6318, which also applies to +bcm6328 and bcm6362. + +Signed-off-by: Kyle Hendry +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250724035300.20497-6-kylehendrydev@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_mmap.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +--- a/drivers/net/dsa/b53/b53_mmap.c ++++ b/drivers/net/dsa/b53/b53_mmap.c +@@ -40,6 +40,15 @@ struct b53_mmap_priv { + const struct b53_phy_info *phy_info; + }; + ++static const u32 bcm6318_ephy_offsets[] = {4, 5, 6, 7}; ++ ++static const struct b53_phy_info bcm6318_ephy_info = { ++ .ephy_enable_mask = BIT(0) | BIT(4) | BIT(8) | BIT(12) | BIT(16), ++ .ephy_port_mask = GENMASK((ARRAY_SIZE(bcm6318_ephy_offsets) - 1), 0), ++ .ephy_bias_bit = 24, ++ .ephy_offset = bcm6318_ephy_offsets, ++}; ++ + static const u32 bcm63268_ephy_offsets[] = {4, 9, 14}; + + static const struct b53_phy_info bcm63268_ephy_info = { +@@ -334,7 +343,11 @@ static int b53_mmap_probe(struct platfor + + priv->gpio_ctrl = syscon_regmap_lookup_by_phandle(np, "brcm,gpio-ctrl"); + if (!IS_ERR(priv->gpio_ctrl)) { +- if (pdata->chip_id == BCM63268_DEVICE_ID) ++ if (pdata->chip_id == BCM6318_DEVICE_ID || ++ pdata->chip_id == BCM6328_DEVICE_ID || ++ pdata->chip_id == BCM6362_DEVICE_ID) ++ priv->phy_info = &bcm6318_ephy_info; ++ else if (pdata->chip_id == BCM63268_DEVICE_ID) + priv->phy_info = &bcm63268_ephy_info; + } + diff --git a/lede/target/linux/generic/backport-6.12/611-12-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6368.patch b/lede/target/linux/generic/backport-6.12/611-12-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6368.patch new file mode 100644 index 0000000000..f703804a40 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-12-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6368.patch @@ -0,0 +1,42 @@ +From e8e13073dff7052b144d002bae2cfe9ddfa27e2a Mon Sep 17 00:00:00 2001 +From: Kyle Hendry +Date: Wed, 23 Jul 2025 20:52:45 -0700 +Subject: [PATCH] net: dsa: b53: mmap: Add register layout for bcm6368 + +Add ephy register info for bcm6368. + +Signed-off-by: Kyle Hendry +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250724035300.20497-7-kylehendrydev@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_mmap.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/net/dsa/b53/b53_mmap.c ++++ b/drivers/net/dsa/b53/b53_mmap.c +@@ -49,6 +49,15 @@ static const struct b53_phy_info bcm6318 + .ephy_offset = bcm6318_ephy_offsets, + }; + ++static const u32 bcm6368_ephy_offsets[] = {2, 3, 4, 5}; ++ ++static const struct b53_phy_info bcm6368_ephy_info = { ++ .ephy_enable_mask = BIT(0), ++ .ephy_port_mask = GENMASK((ARRAY_SIZE(bcm6368_ephy_offsets) - 1), 0), ++ .ephy_bias_bit = 0, ++ .ephy_offset = bcm6368_ephy_offsets, ++}; ++ + static const u32 bcm63268_ephy_offsets[] = {4, 9, 14}; + + static const struct b53_phy_info bcm63268_ephy_info = { +@@ -347,6 +356,8 @@ static int b53_mmap_probe(struct platfor + pdata->chip_id == BCM6328_DEVICE_ID || + pdata->chip_id == BCM6362_DEVICE_ID) + priv->phy_info = &bcm6318_ephy_info; ++ else if (pdata->chip_id == BCM6368_DEVICE_ID) ++ priv->phy_info = &bcm6368_ephy_info; + else if (pdata->chip_id == BCM63268_DEVICE_ID) + priv->phy_info = &bcm63268_ephy_info; + } diff --git a/lede/target/linux/generic/backport-6.12/611-13-v6.18-net-dsa-b53-mmap-Implement-bcm63xx-ephy-power-control.patch b/lede/target/linux/generic/backport-6.12/611-13-v6.18-net-dsa-b53-mmap-Implement-bcm63xx-ephy-power-control.patch new file mode 100644 index 0000000000..bf3aeb7047 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-13-v6.18-net-dsa-b53-mmap-Implement-bcm63xx-ephy-power-control.patch @@ -0,0 +1,100 @@ +From 5ac00023852d960528a0c1d10ae6c17893fc4113 Mon Sep 17 00:00:00 2001 +From: Kyle Hendry +Date: Wed, 23 Jul 2025 20:52:46 -0700 +Subject: [PATCH] net: dsa: b53: mmap: Implement bcm63xx ephy power control + +Implement the phy enable/disable calls for b53 mmap, and +set the power down registers in the ephy control register +appropriately. + +Signed-off-by: Kyle Hendry +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250724035300.20497-8-kylehendrydev@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_mmap.c | 50 ++++++++++++++++++++++++++++++++++ + 1 file changed, 50 insertions(+) + +--- a/drivers/net/dsa/b53/b53_mmap.c ++++ b/drivers/net/dsa/b53/b53_mmap.c +@@ -24,9 +24,12 @@ + #include + #include + #include ++#include + + #include "b53_priv.h" + ++#define BCM63XX_EPHY_REG 0x3C ++ + struct b53_phy_info { + u32 ephy_enable_mask; + u32 ephy_port_mask; +@@ -38,6 +41,7 @@ struct b53_mmap_priv { + void __iomem *regs; + struct regmap *gpio_ctrl; + const struct b53_phy_info *phy_info; ++ u32 phys_enabled; + }; + + static const u32 bcm6318_ephy_offsets[] = {4, 5, 6, 7}; +@@ -266,6 +270,50 @@ static int b53_mmap_phy_write16(struct b + return -EIO; + } + ++static int bcm63xx_ephy_set(struct b53_device *dev, int port, bool enable) ++{ ++ struct b53_mmap_priv *priv = dev->priv; ++ const struct b53_phy_info *info = priv->phy_info; ++ struct regmap *gpio_ctrl = priv->gpio_ctrl; ++ u32 mask, val; ++ ++ if (enable) { ++ mask = (info->ephy_enable_mask << info->ephy_offset[port]) ++ | BIT(info->ephy_bias_bit); ++ val = 0; ++ } else { ++ mask = (info->ephy_enable_mask << info->ephy_offset[port]); ++ if (!((priv->phys_enabled & ~BIT(port)) & info->ephy_port_mask)) ++ mask |= BIT(info->ephy_bias_bit); ++ val = mask; ++ } ++ return regmap_update_bits(gpio_ctrl, BCM63XX_EPHY_REG, mask, val); ++} ++ ++static void b53_mmap_phy_enable(struct b53_device *dev, int port) ++{ ++ struct b53_mmap_priv *priv = dev->priv; ++ int ret = 0; ++ ++ if (priv->phy_info && (BIT(port) & priv->phy_info->ephy_port_mask)) ++ ret = bcm63xx_ephy_set(dev, port, true); ++ ++ if (!ret) ++ priv->phys_enabled |= BIT(port); ++} ++ ++static void b53_mmap_phy_disable(struct b53_device *dev, int port) ++{ ++ struct b53_mmap_priv *priv = dev->priv; ++ int ret = 0; ++ ++ if (priv->phy_info && (BIT(port) & priv->phy_info->ephy_port_mask)) ++ ret = bcm63xx_ephy_set(dev, port, false); ++ ++ if (!ret) ++ priv->phys_enabled &= ~BIT(port); ++} ++ + static const struct b53_io_ops b53_mmap_ops = { + .read8 = b53_mmap_read8, + .read16 = b53_mmap_read16, +@@ -279,6 +327,8 @@ static const struct b53_io_ops b53_mmap_ + .write64 = b53_mmap_write64, + .phy_read16 = b53_mmap_phy_read16, + .phy_write16 = b53_mmap_phy_write16, ++ .phy_enable = b53_mmap_phy_enable, ++ .phy_disable = b53_mmap_phy_disable, + }; + + static int b53_mmap_probe_of(struct platform_device *pdev, diff --git a/lede/target/linux/generic/backport-6.12/611-14-v6.18-net-dsa-b53-mmap-Add-gphy-port-to-phy-info-for-bcm63268.patch b/lede/target/linux/generic/backport-6.12/611-14-v6.18-net-dsa-b53-mmap-Add-gphy-port-to-phy-info-for-bcm63268.patch new file mode 100644 index 0000000000..9aa99d234e --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-14-v6.18-net-dsa-b53-mmap-Add-gphy-port-to-phy-info-for-bcm63268.patch @@ -0,0 +1,33 @@ +From 7f95f04fe1903a31b61085e3ab1b4730f9d72941 Mon Sep 17 00:00:00 2001 +From: Kyle Hendry +Date: Wed, 13 Aug 2025 17:25:27 -0700 +Subject: [PATCH] net: dsa: b53: mmap: Add gphy port to phy info for bcm63268 + +Add gphy mask to bcm63xx phy info struct and add data for bcm63268 + +Signed-off-by: Kyle Hendry +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250814002530.5866-2-kylehendrydev@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_mmap.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/dsa/b53/b53_mmap.c ++++ b/drivers/net/dsa/b53/b53_mmap.c +@@ -31,6 +31,7 @@ + #define BCM63XX_EPHY_REG 0x3C + + struct b53_phy_info { ++ u32 gphy_port_mask; + u32 ephy_enable_mask; + u32 ephy_port_mask; + u32 ephy_bias_bit; +@@ -65,6 +66,7 @@ static const struct b53_phy_info bcm6368 + static const u32 bcm63268_ephy_offsets[] = {4, 9, 14}; + + static const struct b53_phy_info bcm63268_ephy_info = { ++ .gphy_port_mask = BIT(3), + .ephy_enable_mask = GENMASK(4, 0), + .ephy_port_mask = GENMASK((ARRAY_SIZE(bcm63268_ephy_offsets) - 1), 0), + .ephy_bias_bit = 24, diff --git a/lede/target/linux/generic/backport-6.12/611-15-v6.18-net-dsa-b53-mmap-Implement-bcm63268-gphy-power-control.patch b/lede/target/linux/generic/backport-6.12/611-15-v6.18-net-dsa-b53-mmap-Implement-bcm63268-gphy-power-control.patch new file mode 100644 index 0000000000..8dda51e19e --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-15-v6.18-net-dsa-b53-mmap-Implement-bcm63268-gphy-power-control.patch @@ -0,0 +1,77 @@ +From 61730ac10ba90c52563861a0119504f6a9be9868 Mon Sep 17 00:00:00 2001 +From: Kyle Hendry +Date: Wed, 13 Aug 2025 17:25:28 -0700 +Subject: [PATCH] net: dsa: b53: mmap: Implement bcm63268 gphy power control + +Add check for gphy in enable/disable phy calls and set power bits +in gphy control register. + +Signed-off-by: Kyle Hendry +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250814002530.5866-3-kylehendrydev@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_mmap.c | 33 +++++++++++++++++++++++++++++---- + 1 file changed, 29 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/b53/b53_mmap.c ++++ b/drivers/net/dsa/b53/b53_mmap.c +@@ -29,6 +29,10 @@ + #include "b53_priv.h" + + #define BCM63XX_EPHY_REG 0x3C ++#define BCM63268_GPHY_REG 0x54 ++ ++#define GPHY_CTRL_LOW_PWR BIT(3) ++#define GPHY_CTRL_IDDQ_BIAS BIT(0) + + struct b53_phy_info { + u32 gphy_port_mask; +@@ -292,13 +296,30 @@ static int bcm63xx_ephy_set(struct b53_d + return regmap_update_bits(gpio_ctrl, BCM63XX_EPHY_REG, mask, val); + } + ++static int bcm63268_gphy_set(struct b53_device *dev, bool enable) ++{ ++ struct b53_mmap_priv *priv = dev->priv; ++ struct regmap *gpio_ctrl = priv->gpio_ctrl; ++ u32 mask = GPHY_CTRL_IDDQ_BIAS | GPHY_CTRL_LOW_PWR; ++ u32 val = 0; ++ ++ if (!enable) ++ val = mask; ++ ++ return regmap_update_bits(gpio_ctrl, BCM63268_GPHY_REG, mask, val); ++} ++ + static void b53_mmap_phy_enable(struct b53_device *dev, int port) + { + struct b53_mmap_priv *priv = dev->priv; + int ret = 0; + +- if (priv->phy_info && (BIT(port) & priv->phy_info->ephy_port_mask)) +- ret = bcm63xx_ephy_set(dev, port, true); ++ if (priv->phy_info) { ++ if (BIT(port) & priv->phy_info->ephy_port_mask) ++ ret = bcm63xx_ephy_set(dev, port, true); ++ else if (BIT(port) & priv->phy_info->gphy_port_mask) ++ ret = bcm63268_gphy_set(dev, true); ++ } + + if (!ret) + priv->phys_enabled |= BIT(port); +@@ -309,8 +330,12 @@ static void b53_mmap_phy_disable(struct + struct b53_mmap_priv *priv = dev->priv; + int ret = 0; + +- if (priv->phy_info && (BIT(port) & priv->phy_info->ephy_port_mask)) +- ret = bcm63xx_ephy_set(dev, port, false); ++ if (priv->phy_info) { ++ if (BIT(port) & priv->phy_info->ephy_port_mask) ++ ret = bcm63xx_ephy_set(dev, port, false); ++ else if (BIT(port) & priv->phy_info->gphy_port_mask) ++ ret = bcm63268_gphy_set(dev, false); ++ } + + if (!ret) + priv->phys_enabled &= ~BIT(port); diff --git a/lede/target/linux/generic/backport-6.12/611-16-v6.18-net-dsa-b53-fix-reserved-register-access-in-b53_fdb_dump.patch b/lede/target/linux/generic/backport-6.12/611-16-v6.18-net-dsa-b53-fix-reserved-register-access-in-b53_fdb_dump.patch new file mode 100644 index 0000000000..5190cf908f --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-16-v6.18-net-dsa-b53-fix-reserved-register-access-in-b53_fdb_dump.patch @@ -0,0 +1,72 @@ +From 89eb9a62aed77b409663ba1eac152e8f758815b7 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 15 Aug 2025 22:18:09 +0200 +Subject: [PATCH] net: dsa: b53: fix reserved register access in b53_fdb_dump() + +When BCM5325 support was added in c45655386e53 ("net: dsa: b53: add +support for FDB operations on 5325/5365"), the register used for ARL access +was made conditional on the chip. + +But in b53_fdb_dump(), instead of the register argument the page +argument was replaced, causing it to write to a reserved page 0x50 on +!BCM5325*. Writing to this page seems to completely lock the switch up: + +[ 89.680000] b53-switch spi0.1 lan2: Link is Down +[ 89.680000] WARNING: CPU: 1 PID: 26 at drivers/net/phy/phy.c:1350 _phy_state_machine+0x1bc/0x454 +[ 89.720000] phy_check_link_status+0x0/0x114: returned: -5 +[ 89.730000] Modules linked in: nft_fib_inet nf_flow_table_inet nft_reject_ipv6 nft_reject_ipv4 nft_reject_inet nft_reject nft_redir nft_quota nft_numgen nft_nat nft_masq nft_log nft_limit nft_hash nft_flow_offload nft_fib_ipv6 nft_fib_ipv4 nft_fib nft_ct nft_chain_nat nf_tables nf_nat nf_flow_table nf_conntrack nfnetlink nf_reject_ipv6 nf_reject_ipv4 nf_log_syslog nf_defrag_ipv6 nf_defrag_ipv4 cls_flower sch_tbf sch_ingress sch_htb sch_hfsc em_u32 cls_u32 cls_route cls_matchall cls_fw cls_flow cls_basic act_skbedit act_mirred act_gact vrf md5 crc32c_cryptoapi +[ 89.780000] CPU: 1 UID: 0 PID: 26 Comm: kworker/u10:0 Tainted: G W 6.16.0-rc1+ #0 NONE +[ 89.780000] Tainted: [W]=WARN +[ 89.780000] Hardware name: Netgear DGND3700 v1 +[ 89.780000] Workqueue: events_power_efficient phy_state_machine +[ 89.780000] Stack : 809c762c 8006b050 00000001 820a9ce3 0000114c 000affff 805d22d0 8200ba00 +[ 89.780000] 82005000 6576656e 74735f70 6f776572 5f656666 10008b00 820a9cb8 82088700 +[ 89.780000] 00000000 00000000 809c762c 820a9a98 00000000 00000000 ffffefff 80a7a76c +[ 89.780000] 80a70000 820a9af8 80a70000 80a70000 80a70000 00000000 809c762c 820a9dd4 +[ 89.780000] 00000000 805d1494 80a029e4 80a70000 00000003 00000000 00000004 81a60004 +[ 89.780000] ... +[ 89.780000] Call Trace: +[ 89.780000] [<800228b8>] show_stack+0x38/0x118 +[ 89.780000] [<8001afc4>] dump_stack_lvl+0x6c/0xac +[ 89.780000] [<80046b90>] __warn+0x9c/0x114 +[ 89.780000] [<80046da8>] warn_slowpath_fmt+0x1a0/0x1b0 +[ 89.780000] [<805d1494>] _phy_state_machine+0x1bc/0x454 +[ 89.780000] [<805d22fc>] phy_state_machine+0x2c/0x70 +[ 89.780000] [<80066b08>] process_one_work+0x1e8/0x3e0 +[ 89.780000] [<80067a1c>] worker_thread+0x354/0x4e4 +[ 89.780000] [<800706cc>] kthread+0x130/0x274 +[ 89.780000] [<8001d808>] ret_from_kernel_thread+0x14/0x1c + +And any further accesses fail: + +[ 120.790000] b53-switch spi0.1: timeout waiting for ARL to finish: 0x81 +[ 120.800000] b53-switch spi0.1: port 2 failed to add 2c:b0:5d:27:9a:bd vid 3 to fdb: -145 +[ 121.010000] b53-switch spi0.1: timeout waiting for ARL to finish: 0xbf +[ 121.020000] b53-switch spi0.1: port 3 failed to add 2c:b0:5d:27:9a:bd vid 3 to fdb: -145 + +Restore the correct page B53_ARLIO_PAGE again, and move the offset +argument to the correct place. + +*On BCM5325, this became a write to the MIB page of Port 1. Still +a reserved offset, but likely less brokenness from that write. + +Fixes: c45655386e53 ("net: dsa: b53: add support for FDB operations on 5325/5365") +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250815201809.549195-1-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2100,7 +2100,7 @@ int b53_fdb_dump(struct dsa_switch *ds, + + /* Start search operation */ + reg = ARL_SRCH_STDN; +- b53_write8(priv, offset, B53_ARL_SRCH_CTL, reg); ++ b53_write8(priv, B53_ARLIO_PAGE, offset, reg); + + do { + ret = b53_arl_search_wait(priv); diff --git a/lede/target/linux/generic/backport-6.12/611-17-v6.18-net-dsa-b53-fix-ageing-time-for-BCM53101.patch b/lede/target/linux/generic/backport-6.12/611-17-v6.18-net-dsa-b53-fix-ageing-time-for-BCM53101.patch new file mode 100644 index 0000000000..0eb0870a4b --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-17-v6.18-net-dsa-b53-fix-ageing-time-for-BCM53101.patch @@ -0,0 +1,77 @@ +From 674b34c4c770551e916ae707829c7faea4782d3a Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 5 Sep 2025 14:45:07 +0200 +Subject: [PATCH] net: dsa: b53: fix ageing time for BCM53101 + +For some reason Broadcom decided that BCM53101 uses 0.5s increments for +the ageing time register, but kept the field width the same [1]. Due to +this, the actual ageing time was always half of what was configured. + +Fix this by adapting the limits and value calculation for BCM53101. + +So far it looks like this is the only chip with the increased tick +speed: + +$ grep -l -r "Specifies the aging time in 0.5 seconds" cdk/PKG/chip | sort +cdk/PKG/chip/bcm53101/bcm53101_a0_defs.h + +$ grep -l -r "Specifies the aging time in seconds" cdk/PKG/chip | sort +cdk/PKG/chip/bcm53010/bcm53010_a0_defs.h +cdk/PKG/chip/bcm53020/bcm53020_a0_defs.h +cdk/PKG/chip/bcm53084/bcm53084_a0_defs.h +cdk/PKG/chip/bcm53115/bcm53115_a0_defs.h +cdk/PKG/chip/bcm53118/bcm53118_a0_defs.h +cdk/PKG/chip/bcm53125/bcm53125_a0_defs.h +cdk/PKG/chip/bcm53128/bcm53128_a0_defs.h +cdk/PKG/chip/bcm53134/bcm53134_a0_defs.h +cdk/PKG/chip/bcm53242/bcm53242_a0_defs.h +cdk/PKG/chip/bcm53262/bcm53262_a0_defs.h +cdk/PKG/chip/bcm53280/bcm53280_a0_defs.h +cdk/PKG/chip/bcm53280/bcm53280_b0_defs.h +cdk/PKG/chip/bcm53600/bcm53600_a0_defs.h +cdk/PKG/chip/bcm89500/bcm89500_a0_defs.h + +[1] https://github.com/Broadcom/OpenMDK/blob/a5d3fc9b12af3eeb68f2ca0ce7ec4056cd14d6c2/cdk/PKG/chip/bcm53101/bcm53101_a0_defs.h#L28966 + +Fixes: e39d14a760c0 ("net: dsa: b53: implement setting ageing time") +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250905124507.59186-1-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1273,9 +1273,15 @@ static int b53_setup(struct dsa_switch * + */ + ds->untag_vlan_aware_bridge_pvid = true; + +- /* Ageing time is set in seconds */ +- ds->ageing_time_min = 1 * 1000; +- ds->ageing_time_max = AGE_TIME_MAX * 1000; ++ if (dev->chip_id == BCM53101_DEVICE_ID) { ++ /* BCM53101 uses 0.5 second increments */ ++ ds->ageing_time_min = 1 * 500; ++ ds->ageing_time_max = AGE_TIME_MAX * 500; ++ } else { ++ /* Everything else uses 1 second increments */ ++ ds->ageing_time_min = 1 * 1000; ++ ds->ageing_time_max = AGE_TIME_MAX * 1000; ++ } + + ret = b53_reset_switch(dev); + if (ret) { +@@ -2587,7 +2593,10 @@ int b53_set_ageing_time(struct dsa_switc + else + reg = B53_AGING_TIME_CONTROL; + +- atc = DIV_ROUND_CLOSEST(msecs, 1000); ++ if (dev->chip_id == BCM53101_DEVICE_ID) ++ atc = DIV_ROUND_CLOSEST(msecs, 500); ++ else ++ atc = DIV_ROUND_CLOSEST(msecs, 1000); + + if (!is5325(dev) && !is5365(dev)) + atc |= AGE_CHANGE; diff --git a/lede/target/linux/generic/backport-6.12/611-18-v6.18-net-dsa-b53-properly-bound-ARL-searches-for-4-ARL-bin-chips.patch b/lede/target/linux/generic/backport-6.12/611-18-v6.18-net-dsa-b53-properly-bound-ARL-searches-for-4-ARL-bin-chips.patch new file mode 100644 index 0000000000..50ddcf93ee --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-18-v6.18-net-dsa-b53-properly-bound-ARL-searches-for-4-ARL-bin-chips.patch @@ -0,0 +1,61 @@ +From e57723fe536f040cc2635ec1545dd0a7919a321e Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Sun, 2 Nov 2025 11:07:58 +0100 +Subject: [PATCH] net: dsa: b53: properly bound ARL searches for < 4 ARL bin + chips + +When iterating over the ARL table we stop at max ARL entries / 2, but +this is only valid if the chip actually returns 2 results at once. For +chips with only one result register we will stop before reaching the end +of the table if it is more than half full. + +Fix this by only dividing the maximum results by two if we have a chip +with more than one result register (i.e. those with 4 ARL bins). + +Fixes: cd169d799bee ("net: dsa: b53: Bound check ARL searches") +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20251102100758.28352-4-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2090,13 +2090,16 @@ static int b53_fdb_copy(int port, const + int b53_fdb_dump(struct dsa_switch *ds, int port, + dsa_fdb_dump_cb_t *cb, void *data) + { ++ unsigned int count = 0, results_per_hit = 1; + struct b53_device *priv = ds->priv; + struct b53_arl_entry results[2]; +- unsigned int count = 0; + u8 offset; + int ret; + u8 reg; + ++ if (priv->num_arl_bins > 2) ++ results_per_hit = 2; ++ + mutex_lock(&priv->arl_mutex); + + if (is5325(priv) || is5365(priv)) +@@ -2118,7 +2121,7 @@ int b53_fdb_dump(struct dsa_switch *ds, + if (ret) + break; + +- if (priv->num_arl_bins > 2) { ++ if (results_per_hit == 2) { + b53_arl_search_rd(priv, 1, &results[1]); + ret = b53_fdb_copy(port, &results[1], cb, data); + if (ret) +@@ -2128,7 +2131,7 @@ int b53_fdb_dump(struct dsa_switch *ds, + break; + } + +- } while (count++ < b53_max_arl_entries(priv) / 2); ++ } while (count++ < b53_max_arl_entries(priv) / results_per_hit); + + mutex_unlock(&priv->arl_mutex); + diff --git a/lede/target/linux/generic/backport-6.12/611-19-v6.18-net-dsa-tag_brcm-do-not-mark-link-local-traffic-as-offloaded.patch b/lede/target/linux/generic/backport-6.12/611-19-v6.18-net-dsa-tag_brcm-do-not-mark-link-local-traffic-as-offloaded.patch new file mode 100644 index 0000000000..7c3d06269a --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/611-19-v6.18-net-dsa-tag_brcm-do-not-mark-link-local-traffic-as-offloaded.patch @@ -0,0 +1,59 @@ +From 762e7e174da91cf4babfe77e45bc6b67334b1503 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Sun, 9 Nov 2025 14:46:35 +0100 +Subject: [PATCH] net: dsa: tag_brcm: do not mark link local traffic as + offloaded + +Broadcom switches locally terminate link local traffic and do not +forward it, so we should not mark it as offloaded. + +In some situations we still want/need to flood this traffic, e.g. if STP +is disabled, or it is explicitly enabled via the group_fwd_mask. But if +the skb is marked as offloaded, the kernel will assume this was already +done in hardware, and the packets never reach other bridge ports. + +So ensure that link local traffic is never marked as offloaded, so that +the kernel can forward/flood these packets in software if needed. + +Since the local termination in not configurable, check the destination +MAC, and never mark packets as offloaded if it is a link local ether +address. + +While modern switches set the tag reason code to BRCM_EG_RC_PROT_TERM +for trapped link local traffic, they also set it for link local traffic +that is flooded (01:80:c2:00:00:10 to 01:80:c2:00:00:2f), so we cannot +use it and need to look at the destination address for them as well. + +Fixes: 964dbf186eaa ("net: dsa: tag_brcm: add support for legacy tags") +Fixes: 0e62f543bed0 ("net: dsa: Fix duplicate frames flooded by learning") +Signed-off-by: Jonas Gorski +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20251109134635.243951-1-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + net/dsa/tag_brcm.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/net/dsa/tag_brcm.c ++++ b/net/dsa/tag_brcm.c +@@ -176,7 +176,8 @@ static struct sk_buff *brcm_tag_rcv_ll(s + /* Remove Broadcom tag and update checksum */ + skb_pull_rcsum(skb, BRCM_TAG_LEN); + +- dsa_default_offload_fwd_mark(skb); ++ if (likely(!is_link_local_ether_addr(eth_hdr(skb)->h_dest))) ++ dsa_default_offload_fwd_mark(skb); + + return skb; + } +@@ -250,7 +251,8 @@ static struct sk_buff *brcm_leg_tag_rcv( + /* Remove Broadcom tag and update checksum */ + skb_pull_rcsum(skb, len); + +- dsa_default_offload_fwd_mark(skb); ++ if (likely(!is_link_local_ether_addr(eth_hdr(skb)->h_dest))) ++ dsa_default_offload_fwd_mark(skb); + + dsa_strip_etype_header(skb, len); + diff --git a/lede/target/linux/generic/backport-6.12/612-01-v6.19-net-dsa-b53-b53_arl_read-25-use-the-entry-for-comparision.patch b/lede/target/linux/generic/backport-6.12/612-01-v6.19-net-dsa-b53-b53_arl_read-25-use-the-entry-for-comparision.patch new file mode 100644 index 0000000000..2b6cff796f --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/612-01-v6.19-net-dsa-b53-b53_arl_read-25-use-the-entry-for-comparision.patch @@ -0,0 +1,85 @@ +From a6e4fd38bf2f2e2363b61c27f4e6c49b14e4bb07 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 7 Nov 2025 09:07:42 +0100 +Subject: [PATCH] net: dsa: b53: b53_arl_read{,25}(): use the entry for + comparision + +Align the b53_arl_read{,25}() functions by consistently using the +parsed arl entry instead of parsing the raw registers again. + +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20251107080749.26936-2-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 22 ++++++++++------------ + 1 file changed, 10 insertions(+), 12 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1830,7 +1830,7 @@ static int b53_arl_rw_op(struct b53_devi + return b53_arl_op_wait(dev); + } + +-static int b53_arl_read(struct b53_device *dev, u64 mac, ++static int b53_arl_read(struct b53_device *dev, const u8 *mac, + u16 vid, struct b53_arl_entry *ent, u8 *idx) + { + DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES); +@@ -1854,14 +1854,13 @@ static int b53_arl_read(struct b53_devic + B53_ARLTBL_DATA_ENTRY(i), &fwd_entry); + b53_arl_to_entry(ent, mac_vid, fwd_entry); + +- if (!(fwd_entry & ARLTBL_VALID)) { ++ if (!ent->is_valid) { + set_bit(i, free_bins); + continue; + } +- if ((mac_vid & ARLTBL_MAC_MASK) != mac) ++ if (!ether_addr_equal(ent->mac, mac)) + continue; +- if (dev->vlan_enabled && +- ((mac_vid >> ARLTBL_VID_S) & ARLTBL_VID_MASK) != vid) ++ if (dev->vlan_enabled && ent->vid != vid) + continue; + *idx = i; + return 0; +@@ -1871,7 +1870,7 @@ static int b53_arl_read(struct b53_devic + return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT; + } + +-static int b53_arl_read_25(struct b53_device *dev, u64 mac, ++static int b53_arl_read_25(struct b53_device *dev, const u8 *mac, + u16 vid, struct b53_arl_entry *ent, u8 *idx) + { + DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES); +@@ -1893,14 +1892,13 @@ static int b53_arl_read_25(struct b53_de + + b53_arl_to_entry_25(ent, mac_vid); + +- if (!(mac_vid & ARLTBL_VALID_25)) { ++ if (!ent->is_valid) { + set_bit(i, free_bins); + continue; + } +- if ((mac_vid & ARLTBL_MAC_MASK) != mac) ++ if (!ether_addr_equal(ent->mac, mac)) + continue; +- if (dev->vlan_enabled && +- ((mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25) != vid) ++ if (dev->vlan_enabled && ent->vid != vid) + continue; + *idx = i; + return 0; +@@ -1933,9 +1931,9 @@ static int b53_arl_op(struct b53_device + return ret; + + if (is5325(dev) || is5365(dev)) +- ret = b53_arl_read_25(dev, mac, vid, &ent, &idx); ++ ret = b53_arl_read_25(dev, addr, vid, &ent, &idx); + else +- ret = b53_arl_read(dev, mac, vid, &ent, &idx); ++ ret = b53_arl_read(dev, addr, vid, &ent, &idx); + + /* If this is a read, just finish now */ + if (op) diff --git a/lede/target/linux/generic/backport-6.12/612-02-v6.19-net-dsa-b53-move-reading-ARL-entries-into-their-own-function.patch b/lede/target/linux/generic/backport-6.12/612-02-v6.19-net-dsa-b53-move-reading-ARL-entries-into-their-own-function.patch new file mode 100644 index 0000000000..8cf85ce7ad --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/612-02-v6.19-net-dsa-b53-move-reading-ARL-entries-into-their-own-function.patch @@ -0,0 +1,117 @@ +From 4a291fe7226736a465ddb3fa93c21fcef7162ec7 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 7 Nov 2025 09:07:43 +0100 +Subject: [PATCH] net: dsa: b53: move reading ARL entries into their own + function + +Instead of duplicating the whole code iterating over all bins for +BCM5325, factor out reading and parsing the entry into its own +functions, and name it the modern one after the first chip with that ARL +format, (BCM53)95. + +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20251107080749.26936-3-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 69 +++++++++++--------------------- + 1 file changed, 23 insertions(+), 46 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1830,48 +1830,30 @@ static int b53_arl_rw_op(struct b53_devi + return b53_arl_op_wait(dev); + } + +-static int b53_arl_read(struct b53_device *dev, const u8 *mac, +- u16 vid, struct b53_arl_entry *ent, u8 *idx) ++static void b53_arl_read_entry_25(struct b53_device *dev, ++ struct b53_arl_entry *ent, u8 idx) + { +- DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES); +- unsigned int i; +- int ret; +- +- ret = b53_arl_op_wait(dev); +- if (ret) +- return ret; ++ u64 mac_vid; + +- bitmap_zero(free_bins, dev->num_arl_bins); +- +- /* Read the bins */ +- for (i = 0; i < dev->num_arl_bins; i++) { +- u64 mac_vid; +- u32 fwd_entry; +- +- b53_read64(dev, B53_ARLIO_PAGE, +- B53_ARLTBL_MAC_VID_ENTRY(i), &mac_vid); +- b53_read32(dev, B53_ARLIO_PAGE, +- B53_ARLTBL_DATA_ENTRY(i), &fwd_entry); +- b53_arl_to_entry(ent, mac_vid, fwd_entry); ++ b53_read64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx), ++ &mac_vid); ++ b53_arl_to_entry_25(ent, mac_vid); ++} + +- if (!ent->is_valid) { +- set_bit(i, free_bins); +- continue; +- } +- if (!ether_addr_equal(ent->mac, mac)) +- continue; +- if (dev->vlan_enabled && ent->vid != vid) +- continue; +- *idx = i; +- return 0; +- } ++static void b53_arl_read_entry_95(struct b53_device *dev, ++ struct b53_arl_entry *ent, u8 idx) ++{ ++ u32 fwd_entry; ++ u64 mac_vid; + +- *idx = find_first_bit(free_bins, dev->num_arl_bins); +- return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT; ++ b53_read64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx), ++ &mac_vid); ++ b53_read32(dev, B53_ARLIO_PAGE, B53_ARLTBL_DATA_ENTRY(idx), &fwd_entry); ++ b53_arl_to_entry(ent, mac_vid, fwd_entry); + } + +-static int b53_arl_read_25(struct b53_device *dev, const u8 *mac, +- u16 vid, struct b53_arl_entry *ent, u8 *idx) ++static int b53_arl_read(struct b53_device *dev, const u8 *mac, ++ u16 vid, struct b53_arl_entry *ent, u8 *idx) + { + DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES); + unsigned int i; +@@ -1885,12 +1867,10 @@ static int b53_arl_read_25(struct b53_de + + /* Read the bins */ + for (i = 0; i < dev->num_arl_bins; i++) { +- u64 mac_vid; +- +- b53_read64(dev, B53_ARLIO_PAGE, +- B53_ARLTBL_MAC_VID_ENTRY(i), &mac_vid); +- +- b53_arl_to_entry_25(ent, mac_vid); ++ if (is5325(dev) || is5365(dev)) ++ b53_arl_read_entry_25(dev, ent, i); ++ else ++ b53_arl_read_entry_95(dev, ent, i); + + if (!ent->is_valid) { + set_bit(i, free_bins); +@@ -1930,10 +1910,7 @@ static int b53_arl_op(struct b53_device + if (ret) + return ret; + +- if (is5325(dev) || is5365(dev)) +- ret = b53_arl_read_25(dev, addr, vid, &ent, &idx); +- else +- ret = b53_arl_read(dev, addr, vid, &ent, &idx); ++ ret = b53_arl_read(dev, addr, vid, &ent, &idx); + + /* If this is a read, just finish now */ + if (op) diff --git a/lede/target/linux/generic/backport-6.12/612-03-v6.19-net-dsa-b53-move-writing-ARL-entries-into-their-own-functions.patch b/lede/target/linux/generic/backport-6.12/612-03-v6.19-net-dsa-b53-move-writing-ARL-entries-into-their-own-functions.patch new file mode 100644 index 0000000000..a171232d49 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/612-03-v6.19-net-dsa-b53-move-writing-ARL-entries-into-their-own-functions.patch @@ -0,0 +1,93 @@ +From bf6e9d2ae1dbafee53ec4ccd126595172e1e5278 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 7 Nov 2025 09:07:44 +0100 +Subject: [PATCH] net: dsa: b53: move writing ARL entries into their own + functions + +Move writing ARL entries into individual functions for each format. + +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20251107080749.26936-4-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 38 ++++++++++++++++++++++---------- + 1 file changed, 26 insertions(+), 12 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1840,6 +1840,16 @@ static void b53_arl_read_entry_25(struct + b53_arl_to_entry_25(ent, mac_vid); + } + ++static void b53_arl_write_entry_25(struct b53_device *dev, ++ const struct b53_arl_entry *ent, u8 idx) ++{ ++ u64 mac_vid; ++ ++ b53_arl_from_entry_25(&mac_vid, ent); ++ b53_write64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx), ++ mac_vid); ++} ++ + static void b53_arl_read_entry_95(struct b53_device *dev, + struct b53_arl_entry *ent, u8 idx) + { +@@ -1852,6 +1862,19 @@ static void b53_arl_read_entry_95(struct + b53_arl_to_entry(ent, mac_vid, fwd_entry); + } + ++static void b53_arl_write_entry_95(struct b53_device *dev, ++ const struct b53_arl_entry *ent, u8 idx) ++{ ++ u32 fwd_entry; ++ u64 mac_vid; ++ ++ b53_arl_from_entry(&mac_vid, &fwd_entry, ent); ++ b53_write64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx), ++ mac_vid); ++ b53_write32(dev, B53_ARLIO_PAGE, B53_ARLTBL_DATA_ENTRY(idx), ++ fwd_entry); ++} ++ + static int b53_arl_read(struct b53_device *dev, const u8 *mac, + u16 vid, struct b53_arl_entry *ent, u8 *idx) + { +@@ -1892,9 +1915,8 @@ static int b53_arl_op(struct b53_device + const unsigned char *addr, u16 vid, bool is_valid) + { + struct b53_arl_entry ent; +- u32 fwd_entry; +- u64 mac, mac_vid = 0; + u8 idx = 0; ++ u64 mac; + int ret; + + /* Convert the array into a 64-bit MAC */ +@@ -1927,7 +1949,6 @@ static int b53_arl_op(struct b53_device + /* We could not find a matching MAC, so reset to a new entry */ + dev_dbg(dev->dev, "{%pM,%.4d} not found, using idx: %d\n", + addr, vid, idx); +- fwd_entry = 0; + break; + default: + dev_dbg(dev->dev, "{%pM,%.4d} found, using idx: %d\n", +@@ -1955,16 +1976,9 @@ static int b53_arl_op(struct b53_device + ent.is_age = false; + memcpy(ent.mac, addr, ETH_ALEN); + if (is5325(dev) || is5365(dev)) +- b53_arl_from_entry_25(&mac_vid, &ent); ++ b53_arl_write_entry_25(dev, &ent, idx); + else +- b53_arl_from_entry(&mac_vid, &fwd_entry, &ent); +- +- b53_write64(dev, B53_ARLIO_PAGE, +- B53_ARLTBL_MAC_VID_ENTRY(idx), mac_vid); +- +- if (!is5325(dev) && !is5365(dev)) +- b53_write32(dev, B53_ARLIO_PAGE, +- B53_ARLTBL_DATA_ENTRY(idx), fwd_entry); ++ b53_arl_write_entry_95(dev, &ent, idx); + + return b53_arl_rw_op(dev, 0); + } diff --git a/lede/target/linux/generic/backport-6.12/612-04-v6.19-net-dsa-b53-provide-accessors-for-accessing-ARL_SRCH_CTL.patch b/lede/target/linux/generic/backport-6.12/612-04-v6.19-net-dsa-b53-provide-accessors-for-accessing-ARL_SRCH_CTL.patch new file mode 100644 index 0000000000..2922427c3c --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/612-04-v6.19-net-dsa-b53-provide-accessors-for-accessing-ARL_SRCH_CTL.patch @@ -0,0 +1,85 @@ +From 1716be6db04af53bac9b869f01156a460595cf41 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 7 Nov 2025 09:07:45 +0100 +Subject: [PATCH] net: dsa: b53: provide accessors for accessing ARL_SRCH_CTL + +In order to more easily support more formats, move accessing +ARL_SRCH_CTL into helper functions to contain the differences. + +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20251107080749.26936-5-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 37 +++++++++++++++++++++----------- + 1 file changed, 24 insertions(+), 13 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2013,18 +2013,37 @@ int b53_fdb_del(struct dsa_switch *ds, i + } + EXPORT_SYMBOL(b53_fdb_del); + +-static int b53_arl_search_wait(struct b53_device *dev) ++static void b53_read_arl_srch_ctl(struct b53_device *dev, u8 *val) + { +- unsigned int timeout = 1000; +- u8 reg, offset; ++ u8 offset; ++ ++ if (is5325(dev) || is5365(dev)) ++ offset = B53_ARL_SRCH_CTL_25; ++ else ++ offset = B53_ARL_SRCH_CTL; ++ ++ b53_read8(dev, B53_ARLIO_PAGE, offset, val); ++} ++ ++static void b53_write_arl_srch_ctl(struct b53_device *dev, u8 val) ++{ ++ u8 offset; + + if (is5325(dev) || is5365(dev)) + offset = B53_ARL_SRCH_CTL_25; + else + offset = B53_ARL_SRCH_CTL; + ++ b53_write8(dev, B53_ARLIO_PAGE, offset, val); ++} ++ ++static int b53_arl_search_wait(struct b53_device *dev) ++{ ++ unsigned int timeout = 1000; ++ u8 reg; ++ + do { +- b53_read8(dev, B53_ARLIO_PAGE, offset, ®); ++ b53_read_arl_srch_ctl(dev, ®); + if (!(reg & ARL_SRCH_STDN)) + return -ENOENT; + +@@ -2082,23 +2101,15 @@ int b53_fdb_dump(struct dsa_switch *ds, + unsigned int count = 0, results_per_hit = 1; + struct b53_device *priv = ds->priv; + struct b53_arl_entry results[2]; +- u8 offset; + int ret; +- u8 reg; + + if (priv->num_arl_bins > 2) + results_per_hit = 2; + + mutex_lock(&priv->arl_mutex); + +- if (is5325(priv) || is5365(priv)) +- offset = B53_ARL_SRCH_CTL_25; +- else +- offset = B53_ARL_SRCH_CTL; +- + /* Start search operation */ +- reg = ARL_SRCH_STDN; +- b53_write8(priv, B53_ARLIO_PAGE, offset, reg); ++ b53_write_arl_srch_ctl(priv, ARL_SRCH_STDN); + + do { + ret = b53_arl_search_wait(priv); diff --git a/lede/target/linux/generic/backport-6.12/612-05-v6.19-net-dsa-b53-split-reading-search-entry-into-their-own-functions.patch b/lede/target/linux/generic/backport-6.12/612-05-v6.19-net-dsa-b53-split-reading-search-entry-into-their-own-functions.patch new file mode 100644 index 0000000000..3e263f8cfb --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/612-05-v6.19-net-dsa-b53-split-reading-search-entry-into-their-own-functions.patch @@ -0,0 +1,86 @@ +From e0c476f325a8c9b961a3d446c24d3c8ecae7d186 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 7 Nov 2025 09:07:46 +0100 +Subject: [PATCH] net: dsa: b53: split reading search entry into their own + functions + +Split reading search entries into a function for each format. + +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20251107080749.26936-6-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 56 ++++++++++++++++++++++---------- + 1 file changed, 38 insertions(+), 18 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2056,28 +2056,48 @@ static int b53_arl_search_wait(struct b5 + return -ETIMEDOUT; + } + +-static void b53_arl_search_rd(struct b53_device *dev, u8 idx, +- struct b53_arl_entry *ent) ++static void b53_arl_search_read_25(struct b53_device *dev, u8 idx, ++ struct b53_arl_entry *ent) + { + u64 mac_vid; + +- if (is5325(dev)) { +- b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_25, +- &mac_vid); +- b53_arl_to_entry_25(ent, mac_vid); +- } else if (is5365(dev)) { +- b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_65, +- &mac_vid); +- b53_arl_to_entry_25(ent, mac_vid); +- } else { +- u32 fwd_entry; +- +- b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_MACVID(idx), +- &mac_vid); +- b53_read32(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL(idx), +- &fwd_entry); +- b53_arl_to_entry(ent, mac_vid, fwd_entry); +- } ++ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_25, ++ &mac_vid); ++ b53_arl_to_entry_25(ent, mac_vid); ++} ++ ++static void b53_arl_search_read_65(struct b53_device *dev, u8 idx, ++ struct b53_arl_entry *ent) ++{ ++ u64 mac_vid; ++ ++ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_65, ++ &mac_vid); ++ b53_arl_to_entry_25(ent, mac_vid); ++} ++ ++static void b53_arl_search_read_95(struct b53_device *dev, u8 idx, ++ struct b53_arl_entry *ent) ++{ ++ u32 fwd_entry; ++ u64 mac_vid; ++ ++ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_MACVID(idx), ++ &mac_vid); ++ b53_read32(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL(idx), ++ &fwd_entry); ++ b53_arl_to_entry(ent, mac_vid, fwd_entry); ++} ++ ++static void b53_arl_search_rd(struct b53_device *dev, u8 idx, ++ struct b53_arl_entry *ent) ++{ ++ if (is5325(dev)) ++ b53_arl_search_read_25(dev, idx, ent); ++ else if (is5365(dev)) ++ b53_arl_search_read_65(dev, idx, ent); ++ else ++ b53_arl_search_read_95(dev, idx, ent); + } + + static int b53_fdb_copy(int port, const struct b53_arl_entry *ent, diff --git a/lede/target/linux/generic/backport-6.12/612-06-v6.19-net-dsa-b53-move-ARL-entry-functions-into-ops-struct.patch b/lede/target/linux/generic/backport-6.12/612-06-v6.19-net-dsa-b53-move-ARL-entry-functions-into-ops-struct.patch new file mode 100644 index 0000000000..110e160fed --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/612-06-v6.19-net-dsa-b53-move-ARL-entry-functions-into-ops-struct.patch @@ -0,0 +1,348 @@ +From a7e73339ad46ade76d29fb6cc7d7854222608c26 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 7 Nov 2025 09:07:47 +0100 +Subject: [PATCH] net: dsa: b53: move ARL entry functions into ops struct + +Now that the differences in ARL entry formats are neatly contained into +functions per chip family, wrap them into an ops struct and add wrapper +functions to access them. + +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20251107080749.26936-7-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 67 ++++++++++++++++++++++---------- + drivers/net/dsa/b53/b53_priv.h | 30 ++++++++++++++ + 2 files changed, 76 insertions(+), 21 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1890,10 +1890,7 @@ static int b53_arl_read(struct b53_devic + + /* Read the bins */ + for (i = 0; i < dev->num_arl_bins; i++) { +- if (is5325(dev) || is5365(dev)) +- b53_arl_read_entry_25(dev, ent, i); +- else +- b53_arl_read_entry_95(dev, ent, i); ++ b53_arl_read_entry(dev, ent, i); + + if (!ent->is_valid) { + set_bit(i, free_bins); +@@ -1975,10 +1972,7 @@ static int b53_arl_op(struct b53_device + ent.is_static = true; + ent.is_age = false; + memcpy(ent.mac, addr, ETH_ALEN); +- if (is5325(dev) || is5365(dev)) +- b53_arl_write_entry_25(dev, &ent, idx); +- else +- b53_arl_write_entry_95(dev, &ent, idx); ++ b53_arl_write_entry(dev, &ent, idx); + + return b53_arl_rw_op(dev, 0); + } +@@ -2089,17 +2083,6 @@ static void b53_arl_search_read_95(struc + b53_arl_to_entry(ent, mac_vid, fwd_entry); + } + +-static void b53_arl_search_rd(struct b53_device *dev, u8 idx, +- struct b53_arl_entry *ent) +-{ +- if (is5325(dev)) +- b53_arl_search_read_25(dev, idx, ent); +- else if (is5365(dev)) +- b53_arl_search_read_65(dev, idx, ent); +- else +- b53_arl_search_read_95(dev, idx, ent); +-} +- + static int b53_fdb_copy(int port, const struct b53_arl_entry *ent, + dsa_fdb_dump_cb_t *cb, void *data) + { +@@ -2136,13 +2119,13 @@ int b53_fdb_dump(struct dsa_switch *ds, + if (ret) + break; + +- b53_arl_search_rd(priv, 0, &results[0]); ++ b53_arl_search_read(priv, 0, &results[0]); + ret = b53_fdb_copy(port, &results[0], cb, data); + if (ret) + break; + + if (results_per_hit == 2) { +- b53_arl_search_rd(priv, 1, &results[1]); ++ b53_arl_search_read(priv, 1, &results[1]); + ret = b53_fdb_copy(port, &results[1], cb, data); + if (ret) + break; +@@ -2675,6 +2658,24 @@ static const struct dsa_switch_ops b53_s + .port_change_mtu = b53_change_mtu, + }; + ++static const struct b53_arl_ops b53_arl_ops_25 = { ++ .arl_read_entry = b53_arl_read_entry_25, ++ .arl_write_entry = b53_arl_write_entry_25, ++ .arl_search_read = b53_arl_search_read_25, ++}; ++ ++static const struct b53_arl_ops b53_arl_ops_65 = { ++ .arl_read_entry = b53_arl_read_entry_25, ++ .arl_write_entry = b53_arl_write_entry_25, ++ .arl_search_read = b53_arl_search_read_65, ++}; ++ ++static const struct b53_arl_ops b53_arl_ops_95 = { ++ .arl_read_entry = b53_arl_read_entry_95, ++ .arl_write_entry = b53_arl_write_entry_95, ++ .arl_search_read = b53_arl_search_read_95, ++}; ++ + struct b53_chip_data { + u32 chip_id; + const char *dev_name; +@@ -2688,6 +2689,7 @@ struct b53_chip_data { + u8 duplex_reg; + u8 jumbo_pm_reg; + u8 jumbo_size_reg; ++ const struct b53_arl_ops *arl_ops; + }; + + #define B53_VTA_REGS \ +@@ -2707,6 +2709,7 @@ static const struct b53_chip_data b53_sw + .arl_buckets = 1024, + .imp_port = 5, + .duplex_reg = B53_DUPLEX_STAT_FE, ++ .arl_ops = &b53_arl_ops_25, + }, + { + .chip_id = BCM5365_DEVICE_ID, +@@ -2717,6 +2720,7 @@ static const struct b53_chip_data b53_sw + .arl_buckets = 1024, + .imp_port = 5, + .duplex_reg = B53_DUPLEX_STAT_FE, ++ .arl_ops = &b53_arl_ops_65, + }, + { + .chip_id = BCM5389_DEVICE_ID, +@@ -2730,6 +2734,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM5395_DEVICE_ID, +@@ -2743,6 +2748,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM5397_DEVICE_ID, +@@ -2756,6 +2762,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM5398_DEVICE_ID, +@@ -2769,6 +2776,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM53101_DEVICE_ID, +@@ -2782,6 +2790,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM53115_DEVICE_ID, +@@ -2795,6 +2804,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM53125_DEVICE_ID, +@@ -2808,6 +2818,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM53128_DEVICE_ID, +@@ -2821,6 +2832,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM63XX_DEVICE_ID, +@@ -2834,6 +2846,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_63XX, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM53010_DEVICE_ID, +@@ -2847,6 +2860,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM53011_DEVICE_ID, +@@ -2860,6 +2874,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM53012_DEVICE_ID, +@@ -2873,6 +2888,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM53018_DEVICE_ID, +@@ -2886,6 +2902,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM53019_DEVICE_ID, +@@ -2899,6 +2916,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM58XX_DEVICE_ID, +@@ -2912,6 +2930,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM583XX_DEVICE_ID, +@@ -2925,6 +2944,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + /* Starfighter 2 */ + { +@@ -2939,6 +2959,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM7445_DEVICE_ID, +@@ -2952,6 +2973,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM7278_DEVICE_ID, +@@ -2965,6 +2987,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + { + .chip_id = BCM53134_DEVICE_ID, +@@ -2979,6 +3002,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, ++ .arl_ops = &b53_arl_ops_95, + }, + }; + +@@ -3007,6 +3031,7 @@ static int b53_switch_init(struct b53_de + dev->num_vlans = chip->vlans; + dev->num_arl_bins = chip->arl_bins; + dev->num_arl_buckets = chip->arl_buckets; ++ dev->arl_ops = chip->arl_ops; + break; + } + } +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -58,6 +58,17 @@ struct b53_io_ops { + bool link_up); + }; + ++struct b53_arl_entry; ++ ++struct b53_arl_ops { ++ void (*arl_read_entry)(struct b53_device *dev, ++ struct b53_arl_entry *ent, u8 idx); ++ void (*arl_write_entry)(struct b53_device *dev, ++ const struct b53_arl_entry *ent, u8 idx); ++ void (*arl_search_read)(struct b53_device *dev, u8 idx, ++ struct b53_arl_entry *ent); ++}; ++ + #define B53_INVALID_LANE 0xff + + enum { +@@ -127,6 +138,7 @@ struct b53_device { + struct mutex stats_mutex; + struct mutex arl_mutex; + const struct b53_io_ops *ops; ++ const struct b53_arl_ops *arl_ops; + + /* chip specific data */ + u32 chip_id; +@@ -371,6 +383,24 @@ static inline void b53_arl_from_entry_25 + *mac_vid |= ARLTBL_AGE_25; + } + ++static inline void b53_arl_read_entry(struct b53_device *dev, ++ struct b53_arl_entry *ent, u8 idx) ++{ ++ dev->arl_ops->arl_read_entry(dev, ent, idx); ++} ++ ++static inline void b53_arl_write_entry(struct b53_device *dev, ++ const struct b53_arl_entry *ent, u8 idx) ++{ ++ dev->arl_ops->arl_write_entry(dev, ent, idx); ++} ++ ++static inline void b53_arl_search_read(struct b53_device *dev, u8 idx, ++ struct b53_arl_entry *ent) ++{ ++ dev->arl_ops->arl_search_read(dev, idx, ent); ++} ++ + #ifdef CONFIG_BCM47XX + + #include diff --git a/lede/target/linux/generic/backport-6.12/612-07-v6.19-net-dsa-b53-add-support-for-5389-5397-5398-ARL-entry-format.patch b/lede/target/linux/generic/backport-6.12/612-07-v6.19-net-dsa-b53-add-support-for-5389-5397-5398-ARL-entry-format.patch new file mode 100644 index 0000000000..948b4ab67b --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/612-07-v6.19-net-dsa-b53-add-support-for-5389-5397-5398-ARL-entry-format.patch @@ -0,0 +1,221 @@ +From 300f78e8b6b7be17c2c78afeded75be68acb1aa7 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 7 Nov 2025 09:07:48 +0100 +Subject: [PATCH] net: dsa: b53: add support for 5389/5397/5398 ARL entry + format + +BCM5389, BCM5397 and BCM5398 use a different ARL entry format with just +a 16 bit fwdentry register, as well as different search control and data +offsets. + +So add appropriate ops for them and switch those chips to use them. + +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20251107080749.26936-8-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 53 ++++++++++++++++++++++++++++++-- + drivers/net/dsa/b53/b53_priv.h | 26 ++++++++++++++++ + drivers/net/dsa/b53/b53_regs.h | 13 ++++++++ + 3 files changed, 89 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1850,6 +1850,31 @@ static void b53_arl_write_entry_25(struc + mac_vid); + } + ++static void b53_arl_read_entry_89(struct b53_device *dev, ++ struct b53_arl_entry *ent, u8 idx) ++{ ++ u64 mac_vid; ++ u16 fwd_entry; ++ ++ b53_read64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx), ++ &mac_vid); ++ b53_read16(dev, B53_ARLIO_PAGE, B53_ARLTBL_DATA_ENTRY(idx), &fwd_entry); ++ b53_arl_to_entry_89(ent, mac_vid, fwd_entry); ++} ++ ++static void b53_arl_write_entry_89(struct b53_device *dev, ++ const struct b53_arl_entry *ent, u8 idx) ++{ ++ u32 fwd_entry; ++ u64 mac_vid; ++ ++ b53_arl_from_entry_89(&mac_vid, &fwd_entry, ent); ++ b53_write64(dev, B53_ARLIO_PAGE, ++ B53_ARLTBL_MAC_VID_ENTRY(idx), mac_vid); ++ b53_write16(dev, B53_ARLIO_PAGE, ++ B53_ARLTBL_DATA_ENTRY(idx), fwd_entry); ++} ++ + static void b53_arl_read_entry_95(struct b53_device *dev, + struct b53_arl_entry *ent, u8 idx) + { +@@ -2013,6 +2038,8 @@ static void b53_read_arl_srch_ctl(struct + + if (is5325(dev) || is5365(dev)) + offset = B53_ARL_SRCH_CTL_25; ++ else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev)) ++ offset = B53_ARL_SRCH_CTL_89; + else + offset = B53_ARL_SRCH_CTL; + +@@ -2025,6 +2052,8 @@ static void b53_write_arl_srch_ctl(struc + + if (is5325(dev) || is5365(dev)) + offset = B53_ARL_SRCH_CTL_25; ++ else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev)) ++ offset = B53_ARL_SRCH_CTL_89; + else + offset = B53_ARL_SRCH_CTL; + +@@ -2070,6 +2099,18 @@ static void b53_arl_search_read_65(struc + b53_arl_to_entry_25(ent, mac_vid); + } + ++static void b53_arl_search_read_89(struct b53_device *dev, u8 idx, ++ struct b53_arl_entry *ent) ++{ ++ u16 fwd_entry; ++ u64 mac_vid; ++ ++ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_MACVID_89, ++ &mac_vid); ++ b53_read16(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_89, &fwd_entry); ++ b53_arl_to_entry_89(ent, mac_vid, fwd_entry); ++} ++ + static void b53_arl_search_read_95(struct b53_device *dev, u8 idx, + struct b53_arl_entry *ent) + { +@@ -2670,6 +2711,12 @@ static const struct b53_arl_ops b53_arl_ + .arl_search_read = b53_arl_search_read_65, + }; + ++static const struct b53_arl_ops b53_arl_ops_89 = { ++ .arl_read_entry = b53_arl_read_entry_89, ++ .arl_write_entry = b53_arl_write_entry_89, ++ .arl_search_read = b53_arl_search_read_89, ++}; ++ + static const struct b53_arl_ops b53_arl_ops_95 = { + .arl_read_entry = b53_arl_read_entry_95, + .arl_write_entry = b53_arl_write_entry_95, +@@ -2734,7 +2781,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, +- .arl_ops = &b53_arl_ops_95, ++ .arl_ops = &b53_arl_ops_89, + }, + { + .chip_id = BCM5395_DEVICE_ID, +@@ -2762,7 +2809,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, +- .arl_ops = &b53_arl_ops_95, ++ .arl_ops = &b53_arl_ops_89, + }, + { + .chip_id = BCM5398_DEVICE_ID, +@@ -2776,7 +2823,7 @@ static const struct b53_chip_data b53_sw + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, +- .arl_ops = &b53_arl_ops_95, ++ .arl_ops = &b53_arl_ops_89, + }, + { + .chip_id = BCM53101_DEVICE_ID, +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -353,6 +353,18 @@ static inline void b53_arl_to_entry_25(s + ent->vid = mac_vid >> ARLTBL_VID_S_65; + } + ++static inline void b53_arl_to_entry_89(struct b53_arl_entry *ent, ++ u64 mac_vid, u16 fwd_entry) ++{ ++ memset(ent, 0, sizeof(*ent)); ++ ent->port = fwd_entry & ARLTBL_DATA_PORT_ID_MASK_89; ++ ent->is_valid = !!(fwd_entry & ARLTBL_VALID_89); ++ ent->is_age = !!(fwd_entry & ARLTBL_AGE_89); ++ ent->is_static = !!(fwd_entry & ARLTBL_STATIC_89); ++ u64_to_ether_addr(mac_vid, ent->mac); ++ ent->vid = mac_vid >> ARLTBL_VID_S; ++} ++ + static inline void b53_arl_from_entry(u64 *mac_vid, u32 *fwd_entry, + const struct b53_arl_entry *ent) + { +@@ -383,6 +395,20 @@ static inline void b53_arl_from_entry_25 + *mac_vid |= ARLTBL_AGE_25; + } + ++static inline void b53_arl_from_entry_89(u64 *mac_vid, u32 *fwd_entry, ++ const struct b53_arl_entry *ent) ++{ ++ *mac_vid = ether_addr_to_u64(ent->mac); ++ *mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK) << ARLTBL_VID_S; ++ *fwd_entry = ent->port & ARLTBL_DATA_PORT_ID_MASK_89; ++ if (ent->is_valid) ++ *fwd_entry |= ARLTBL_VALID_89; ++ if (ent->is_static) ++ *fwd_entry |= ARLTBL_STATIC_89; ++ if (ent->is_age) ++ *fwd_entry |= ARLTBL_AGE_89; ++} ++ + static inline void b53_arl_read_entry(struct b53_device *dev, + struct b53_arl_entry *ent, u8 idx) + { +--- a/drivers/net/dsa/b53/b53_regs.h ++++ b/drivers/net/dsa/b53/b53_regs.h +@@ -342,12 +342,20 @@ + #define ARLTBL_STATIC BIT(15) + #define ARLTBL_VALID BIT(16) + ++/* BCM5389 ARL Table Data Entry N Register format (16 bit) */ ++#define ARLTBL_DATA_PORT_ID_MASK_89 GENMASK(8, 0) ++#define ARLTBL_TC_MASK_89 GENMASK(12, 10) ++#define ARLTBL_AGE_89 BIT(13) ++#define ARLTBL_STATIC_89 BIT(14) ++#define ARLTBL_VALID_89 BIT(15) ++ + /* Maximum number of bin entries in the ARL for all switches */ + #define B53_ARLTBL_MAX_BIN_ENTRIES 4 + + /* ARL Search Control Register (8 bit) */ + #define B53_ARL_SRCH_CTL 0x50 + #define B53_ARL_SRCH_CTL_25 0x20 ++#define B53_ARL_SRCH_CTL_89 0x30 + #define ARL_SRCH_VLID BIT(0) + #define ARL_SRCH_STDN BIT(7) + +@@ -355,10 +363,12 @@ + #define B53_ARL_SRCH_ADDR 0x51 + #define B53_ARL_SRCH_ADDR_25 0x22 + #define B53_ARL_SRCH_ADDR_65 0x24 ++#define B53_ARL_SRCH_ADDR_89 0x31 + #define ARL_ADDR_MASK GENMASK(14, 0) + + /* ARL Search MAC/VID Result (64 bit) */ + #define B53_ARL_SRCH_RSTL_0_MACVID 0x60 ++#define B53_ARL_SRCH_RSLT_MACVID_89 0x33 + + /* Single register search result on 5325 */ + #define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24 +@@ -368,6 +378,9 @@ + /* ARL Search Data Result (32 bit) */ + #define B53_ARL_SRCH_RSTL_0 0x68 + ++/* BCM5389 ARL Search Data Result (16 bit) */ ++#define B53_ARL_SRCH_RSLT_89 0x3b ++ + #define B53_ARL_SRCH_RSTL_MACVID(x) (B53_ARL_SRCH_RSTL_0_MACVID + ((x) * 0x10)) + #define B53_ARL_SRCH_RSTL(x) (B53_ARL_SRCH_RSTL_0 + ((x) * 0x10)) + diff --git a/lede/target/linux/generic/backport-6.12/612-08-v6.19-net-dsa-b53-add-support-for-bcm63xx-ARL-entry-format.patch b/lede/target/linux/generic/backport-6.12/612-08-v6.19-net-dsa-b53-add-support-for-bcm63xx-ARL-entry-format.patch new file mode 100644 index 0000000000..ec0e85e4cf --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/612-08-v6.19-net-dsa-b53-add-support-for-bcm63xx-ARL-entry-format.patch @@ -0,0 +1,177 @@ +From 2b3013ac03028a2364d8779719bb6bfbc0212435 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 7 Nov 2025 09:07:49 +0100 +Subject: [PATCH] net: dsa: b53: add support for bcm63xx ARL entry format + +The ARL registers of BCM63XX embedded switches are somewhat unique. The +normal ARL table access registers have the same format as BCM5389, but +the ARL search registers differ: + +* SRCH_CTL is at the same offset of BCM5389, but 16 bits wide. It does + not have more fields, just needs to be accessed by a 16 bit read. +* SRCH_RSLT_MACVID and SRCH_RSLT are aligned to 32 bit, and have shifted + offsets. +* SRCH_RSLT has a different format than the normal ARL data entry + register. +* There is only one set of ENTRY_N registers, implying a 1 bin layout. + +So add appropriate ops for bcm63xx and let it use it. + +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20251107080749.26936-9-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 44 +++++++++++++++++++++++++++----- + drivers/net/dsa/b53/b53_priv.h | 15 +++++++++++ + drivers/net/dsa/b53/b53_regs.h | 9 +++++++ + 3 files changed, 61 insertions(+), 7 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2038,12 +2038,20 @@ static void b53_read_arl_srch_ctl(struct + + if (is5325(dev) || is5365(dev)) + offset = B53_ARL_SRCH_CTL_25; +- else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev)) ++ else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev) || ++ is63xx(dev)) + offset = B53_ARL_SRCH_CTL_89; + else + offset = B53_ARL_SRCH_CTL; + +- b53_read8(dev, B53_ARLIO_PAGE, offset, val); ++ if (is63xx(dev)) { ++ u16 val16; ++ ++ b53_read16(dev, B53_ARLIO_PAGE, offset, &val16); ++ *val = val16 & 0xff; ++ } else { ++ b53_read8(dev, B53_ARLIO_PAGE, offset, val); ++ } + } + + static void b53_write_arl_srch_ctl(struct b53_device *dev, u8 val) +@@ -2052,12 +2060,16 @@ static void b53_write_arl_srch_ctl(struc + + if (is5325(dev) || is5365(dev)) + offset = B53_ARL_SRCH_CTL_25; +- else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev)) ++ else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev) || ++ is63xx(dev)) + offset = B53_ARL_SRCH_CTL_89; + else + offset = B53_ARL_SRCH_CTL; + +- b53_write8(dev, B53_ARLIO_PAGE, offset, val); ++ if (is63xx(dev)) ++ b53_write16(dev, B53_ARLIO_PAGE, offset, val); ++ else ++ b53_write8(dev, B53_ARLIO_PAGE, offset, val); + } + + static int b53_arl_search_wait(struct b53_device *dev) +@@ -2111,6 +2123,18 @@ static void b53_arl_search_read_89(struc + b53_arl_to_entry_89(ent, mac_vid, fwd_entry); + } + ++static void b53_arl_search_read_63xx(struct b53_device *dev, u8 idx, ++ struct b53_arl_entry *ent) ++{ ++ u16 fwd_entry; ++ u64 mac_vid; ++ ++ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_MACVID_63XX, ++ &mac_vid); ++ b53_read16(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_63XX, &fwd_entry); ++ b53_arl_search_to_entry_63xx(ent, mac_vid, fwd_entry); ++} ++ + static void b53_arl_search_read_95(struct b53_device *dev, u8 idx, + struct b53_arl_entry *ent) + { +@@ -2717,6 +2741,12 @@ static const struct b53_arl_ops b53_arl_ + .arl_search_read = b53_arl_search_read_89, + }; + ++static const struct b53_arl_ops b53_arl_ops_63xx = { ++ .arl_read_entry = b53_arl_read_entry_89, ++ .arl_write_entry = b53_arl_write_entry_89, ++ .arl_search_read = b53_arl_search_read_63xx, ++}; ++ + static const struct b53_arl_ops b53_arl_ops_95 = { + .arl_read_entry = b53_arl_read_entry_95, + .arl_write_entry = b53_arl_write_entry_95, +@@ -2886,14 +2916,14 @@ static const struct b53_chip_data b53_sw + .dev_name = "BCM63xx", + .vlans = 4096, + .enabled_ports = 0, /* pdata must provide them */ +- .arl_bins = 4, +- .arl_buckets = 1024, ++ .arl_bins = 1, ++ .arl_buckets = 4096, + .imp_port = 8, + .vta_regs = B53_VTA_REGS_63XX, + .duplex_reg = B53_DUPLEX_STAT_63XX, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, +- .arl_ops = &b53_arl_ops_95, ++ .arl_ops = &b53_arl_ops_63xx, + }, + { + .chip_id = BCM53010_DEVICE_ID, +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -409,6 +409,21 @@ static inline void b53_arl_from_entry_89 + *fwd_entry |= ARLTBL_AGE_89; + } + ++static inline void b53_arl_search_to_entry_63xx(struct b53_arl_entry *ent, ++ u64 mac_vid, u16 fwd_entry) ++{ ++ memset(ent, 0, sizeof(*ent)); ++ u64_to_ether_addr(mac_vid, ent->mac); ++ ent->vid = mac_vid >> ARLTBL_VID_S; ++ ++ ent->port = fwd_entry & ARL_SRST_PORT_ID_MASK_63XX; ++ ent->port >>= 1; ++ ++ ent->is_age = !!(fwd_entry & ARL_SRST_AGE_63XX); ++ ent->is_static = !!(fwd_entry & ARL_SRST_STATIC_63XX); ++ ent->is_valid = 1; ++} ++ + static inline void b53_arl_read_entry(struct b53_device *dev, + struct b53_arl_entry *ent, u8 idx) + { +--- a/drivers/net/dsa/b53/b53_regs.h ++++ b/drivers/net/dsa/b53/b53_regs.h +@@ -364,11 +364,13 @@ + #define B53_ARL_SRCH_ADDR_25 0x22 + #define B53_ARL_SRCH_ADDR_65 0x24 + #define B53_ARL_SRCH_ADDR_89 0x31 ++#define B53_ARL_SRCH_ADDR_63XX 0x32 + #define ARL_ADDR_MASK GENMASK(14, 0) + + /* ARL Search MAC/VID Result (64 bit) */ + #define B53_ARL_SRCH_RSTL_0_MACVID 0x60 + #define B53_ARL_SRCH_RSLT_MACVID_89 0x33 ++#define B53_ARL_SRCH_RSLT_MACVID_63XX 0x34 + + /* Single register search result on 5325 */ + #define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24 +@@ -384,6 +386,13 @@ + #define B53_ARL_SRCH_RSTL_MACVID(x) (B53_ARL_SRCH_RSTL_0_MACVID + ((x) * 0x10)) + #define B53_ARL_SRCH_RSTL(x) (B53_ARL_SRCH_RSTL_0 + ((x) * 0x10)) + ++/* 63XX ARL Search Data Result (16 bit) */ ++#define B53_ARL_SRCH_RSLT_63XX 0x3c ++#define ARL_SRST_PORT_ID_MASK_63XX GENMASK(9, 1) ++#define ARL_SRST_TC_MASK_63XX GENMASK(13, 11) ++#define ARL_SRST_AGE_63XX BIT(14) ++#define ARL_SRST_STATIC_63XX BIT(15) ++ + /************************************************************************* + * IEEE 802.1X Registers + *************************************************************************/ diff --git a/lede/target/linux/generic/backport-6.12/613-01-v6.19-net-dsa-b53-fix-VLAN_ID_IDX-write-size-for-BCM5325-65.patch b/lede/target/linux/generic/backport-6.12/613-01-v6.19-net-dsa-b53-fix-VLAN_ID_IDX-write-size-for-BCM5325-65.patch new file mode 100644 index 0000000000..d953ea7545 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/613-01-v6.19-net-dsa-b53-fix-VLAN_ID_IDX-write-size-for-BCM5325-65.patch @@ -0,0 +1,38 @@ +From 6f268e275c74dae0536e0b61982a8db25bcf4f16 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 28 Nov 2025 09:06:19 +0100 +Subject: [PATCH] net: dsa: b53: fix VLAN_ID_IDX write size for BCM5325/65 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since BCM5325 and BCM5365 only support up to 256 VLANs, the VLAN_ID_IDX +register is only 8 bit wide, not 16 bit, so use an appropriate accessor. + +Fixes: c45655386e53 ("net: dsa: b53: add support for FDB operations on 5325/5365") +Reviewed-by: Florian Fainelli +Tested-by: Álvaro Fernández Rojas +Signed-off-by: Jonas Gorski +Link: https://patch.msgid.link/20251128080625.27181-2-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1946,8 +1946,12 @@ static int b53_arl_op(struct b53_device + + /* Perform a read for the given MAC and VID */ + b53_write48(dev, B53_ARLIO_PAGE, B53_MAC_ADDR_IDX, mac); +- if (!is5325m(dev)) +- b53_write16(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid); ++ if (!is5325m(dev)) { ++ if (is5325(dev) || is5365(dev)) ++ b53_write8(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid); ++ else ++ b53_write16(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid); ++ } + + /* Issue a read operation for this MAC */ + ret = b53_arl_rw_op(dev, 1); diff --git a/lede/target/linux/generic/backport-6.12/613-02-v6.19-net-dsa-b53-fix-extracting-VID-from-entry-for-BCM5325-65.patch b/lede/target/linux/generic/backport-6.12/613-02-v6.19-net-dsa-b53-fix-extracting-VID-from-entry-for-BCM5325-65.patch new file mode 100644 index 0000000000..72f81d020f --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/613-02-v6.19-net-dsa-b53-fix-extracting-VID-from-entry-for-BCM5325-65.patch @@ -0,0 +1,35 @@ +From 9316012dd01952f75e37035360138ccc786ef727 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 28 Nov 2025 09:06:20 +0100 +Subject: [PATCH] net: dsa: b53: fix extracting VID from entry for BCM5325/65 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BCM5325/65's Entry register uses the highest three bits for +VALID/STATIC/AGE, so shifting by 53 only will add these to +b53_arl_entry::vid. + +So make sure to mask the vid value as well, to not get invalid VIDs. + +Fixes: c45655386e53 ("net: dsa: b53: add support for FDB operations on 5325/5365") +Reviewed-by: Florian Fainelli +Tested-by: Álvaro Fernández Rojas +Signed-off-by: Jonas Gorski +Link: https://patch.msgid.link/20251128080625.27181-3-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_priv.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -350,7 +350,7 @@ static inline void b53_arl_to_entry_25(s + ent->is_age = !!(mac_vid & ARLTBL_AGE_25); + ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); + u64_to_ether_addr(mac_vid, ent->mac); +- ent->vid = mac_vid >> ARLTBL_VID_S_65; ++ ent->vid = (mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25; + } + + static inline void b53_arl_to_entry_89(struct b53_arl_entry *ent, diff --git a/lede/target/linux/generic/backport-6.12/613-03-v6.19-net-dsa-b53-use-same-ARL-search-result-offset-for-BCM5325-65.patch b/lede/target/linux/generic/backport-6.12/613-03-v6.19-net-dsa-b53-use-same-ARL-search-result-offset-for-BCM5325-65.patch new file mode 100644 index 0000000000..ddb95dfcdc --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/613-03-v6.19-net-dsa-b53-use-same-ARL-search-result-offset-for-BCM5325-65.patch @@ -0,0 +1,78 @@ +From 8e46aacea4264bcb8d4265fb07577afff58ae78d Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 28 Nov 2025 09:06:21 +0100 +Subject: [PATCH] net: dsa: b53: use same ARL search result offset for BCM5325/65 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BCM5365's search result is at the same offset as BCM5325's search +result, and they (mostly) share the same format, so switch BCM5365 to +BCM5325's arl ops. + +Fixes: c45655386e53 ("net: dsa: b53: add support for FDB operations on 5325/5365") +Reviewed-by: Florian Fainelli +Tested-by: Álvaro Fernández Rojas +Signed-off-by: Jonas Gorski +Link: https://patch.msgid.link/20251128080625.27181-4-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 18 +----------------- + drivers/net/dsa/b53/b53_regs.h | 4 +--- + 2 files changed, 2 insertions(+), 20 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2105,16 +2105,6 @@ static void b53_arl_search_read_25(struc + b53_arl_to_entry_25(ent, mac_vid); + } + +-static void b53_arl_search_read_65(struct b53_device *dev, u8 idx, +- struct b53_arl_entry *ent) +-{ +- u64 mac_vid; +- +- b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_65, +- &mac_vid); +- b53_arl_to_entry_25(ent, mac_vid); +-} +- + static void b53_arl_search_read_89(struct b53_device *dev, u8 idx, + struct b53_arl_entry *ent) + { +@@ -2733,12 +2723,6 @@ static const struct b53_arl_ops b53_arl_ + .arl_search_read = b53_arl_search_read_25, + }; + +-static const struct b53_arl_ops b53_arl_ops_65 = { +- .arl_read_entry = b53_arl_read_entry_25, +- .arl_write_entry = b53_arl_write_entry_25, +- .arl_search_read = b53_arl_search_read_65, +-}; +- + static const struct b53_arl_ops b53_arl_ops_89 = { + .arl_read_entry = b53_arl_read_entry_89, + .arl_write_entry = b53_arl_write_entry_89, +@@ -2801,7 +2785,7 @@ static const struct b53_chip_data b53_sw + .arl_buckets = 1024, + .imp_port = 5, + .duplex_reg = B53_DUPLEX_STAT_FE, +- .arl_ops = &b53_arl_ops_65, ++ .arl_ops = &b53_arl_ops_25, + }, + { + .chip_id = BCM5389_DEVICE_ID, +--- a/drivers/net/dsa/b53/b53_regs.h ++++ b/drivers/net/dsa/b53/b53_regs.h +@@ -372,10 +372,8 @@ + #define B53_ARL_SRCH_RSLT_MACVID_89 0x33 + #define B53_ARL_SRCH_RSLT_MACVID_63XX 0x34 + +-/* Single register search result on 5325 */ ++/* Single register search result on 5325/5365 */ + #define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24 +-/* Single register search result on 5365 */ +-#define B53_ARL_SRCH_RSTL_0_MACVID_65 0x30 + + /* ARL Search Data Result (32 bit) */ + #define B53_ARL_SRCH_RSTL_0 0x68 diff --git a/lede/target/linux/generic/backport-6.12/613-04-v6.19-net-dsa-b53-fix-CPU-port-unicast-ARL-entries-for-BCM5325-65.patch b/lede/target/linux/generic/backport-6.12/613-04-v6.19-net-dsa-b53-fix-CPU-port-unicast-ARL-entries-for-BCM5325-65.patch new file mode 100644 index 0000000000..3748892ca8 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/613-04-v6.19-net-dsa-b53-fix-CPU-port-unicast-ARL-entries-for-BCM5325-65.patch @@ -0,0 +1,51 @@ +From 85132103f700b1340fc17df8a981509d17bf4872 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 28 Nov 2025 09:06:22 +0100 +Subject: [PATCH] net: dsa: b53: fix CPU port unicast ARL entries for BCM5325/65 + +On BCM5325 and BCM5365, unicast ARL entries use 8 as the value for the +CPU port, so we need to translate it to/from 5 as used for the CPU port +at most other places. + +Fixes: c45655386e53 ("net: dsa: b53: add support for FDB operations on 5325/5365") +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20251128080625.27181-5-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_priv.h | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -344,12 +344,14 @@ static inline void b53_arl_to_entry_25(s + u64 mac_vid) + { + memset(ent, 0, sizeof(*ent)); +- ent->port = (mac_vid >> ARLTBL_DATA_PORT_ID_S_25) & +- ARLTBL_DATA_PORT_ID_MASK_25; + ent->is_valid = !!(mac_vid & ARLTBL_VALID_25); + ent->is_age = !!(mac_vid & ARLTBL_AGE_25); + ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); + u64_to_ether_addr(mac_vid, ent->mac); ++ ent->port = (mac_vid >> ARLTBL_DATA_PORT_ID_S_25) & ++ ARLTBL_DATA_PORT_ID_MASK_25; ++ if (is_unicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT) ++ ent->port = B53_CPU_PORT_25; + ent->vid = (mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25; + } + +@@ -383,8 +385,11 @@ static inline void b53_arl_from_entry_25 + const struct b53_arl_entry *ent) + { + *mac_vid = ether_addr_to_u64(ent->mac); +- *mac_vid |= (u64)(ent->port & ARLTBL_DATA_PORT_ID_MASK_25) << +- ARLTBL_DATA_PORT_ID_S_25; ++ if (is_unicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT_25) ++ *mac_vid |= (u64)B53_CPU_PORT << ARLTBL_DATA_PORT_ID_S_25; ++ else ++ *mac_vid |= (u64)(ent->port & ARLTBL_DATA_PORT_ID_MASK_25) << ++ ARLTBL_DATA_PORT_ID_S_25; + *mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK_25) << + ARLTBL_VID_S_65; + if (ent->is_valid) diff --git a/lede/target/linux/generic/backport-6.12/613-05-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-multicast-port-masks.patch b/lede/target/linux/generic/backport-6.12/613-05-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-multicast-port-masks.patch new file mode 100644 index 0000000000..c0f5b5d600 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/613-05-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-multicast-port-masks.patch @@ -0,0 +1,120 @@ +From 3b08863469aa6028ac7c3120966f4e2f6051cf6b Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 28 Nov 2025 09:06:23 +0100 +Subject: [PATCH] net: dsa: b53: fix BCM5325/65 ARL entry multicast port masks + +We currently use the mask 0xf for writing and reading b53_entry::port, +but this is only correct for unicast ARL entries. Multicast ARL entries +use a bitmask, and 0xf is not enough space for ports > 3, which includes +the CPU port. + +So extend the mask accordingly to also fit port 4 (bit 4) and MII (bit +5). According to the datasheet the multicast port mask is [60:48], +making it 12 bit wide, but bits 60-55 are reserved anyway, and collide +with the priority field at [60:59], so I am not sure if this is valid. +Therefore leave it at the actual used range, [53:48]. + +The ARL search result register differs a bit, and there the mask is only +[52:48], so only spanning the user ports. The MII port bit is +contained in the Search Result Extension register. So create a separate +search result parse function that properly handles this. + +Fixes: c45655386e53 ("net: dsa: b53: add support for FDB operations on 5325/5365") +Reviewed-by: Florian Fainelli +Signed-off-by: Jonas Gorski +Link: https://patch.msgid.link/20251128080625.27181-6-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 4 +++- + drivers/net/dsa/b53/b53_priv.h | 25 +++++++++++++++++++++---- + drivers/net/dsa/b53/b53_regs.h | 8 +++++++- + 3 files changed, 31 insertions(+), 6 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2099,10 +2099,12 @@ static void b53_arl_search_read_25(struc + struct b53_arl_entry *ent) + { + u64 mac_vid; ++ u8 ext; + ++ b53_read8(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_EXT_25, &ext); + b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_25, + &mac_vid); +- b53_arl_to_entry_25(ent, mac_vid); ++ b53_arl_search_to_entry_25(ent, mac_vid, ext); + } + + static void b53_arl_search_read_89(struct b53_device *dev, u8 idx, +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -348,8 +348,8 @@ static inline void b53_arl_to_entry_25(s + ent->is_age = !!(mac_vid & ARLTBL_AGE_25); + ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); + u64_to_ether_addr(mac_vid, ent->mac); +- ent->port = (mac_vid >> ARLTBL_DATA_PORT_ID_S_25) & +- ARLTBL_DATA_PORT_ID_MASK_25; ++ ent->port = (mac_vid & ARLTBL_DATA_PORT_ID_MASK_25) >> ++ ARLTBL_DATA_PORT_ID_S_25; + if (is_unicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT) + ent->port = B53_CPU_PORT_25; + ent->vid = (mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25; +@@ -388,8 +388,8 @@ static inline void b53_arl_from_entry_25 + if (is_unicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT_25) + *mac_vid |= (u64)B53_CPU_PORT << ARLTBL_DATA_PORT_ID_S_25; + else +- *mac_vid |= (u64)(ent->port & ARLTBL_DATA_PORT_ID_MASK_25) << +- ARLTBL_DATA_PORT_ID_S_25; ++ *mac_vid |= ((u64)ent->port << ARLTBL_DATA_PORT_ID_S_25) & ++ ARLTBL_DATA_PORT_ID_MASK_25; + *mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK_25) << + ARLTBL_VID_S_65; + if (ent->is_valid) +@@ -414,6 +414,23 @@ static inline void b53_arl_from_entry_89 + *fwd_entry |= ARLTBL_AGE_89; + } + ++static inline void b53_arl_search_to_entry_25(struct b53_arl_entry *ent, ++ u64 mac_vid, u8 ext) ++{ ++ memset(ent, 0, sizeof(*ent)); ++ ent->is_valid = !!(mac_vid & ARLTBL_VALID_25); ++ ent->is_age = !!(mac_vid & ARLTBL_AGE_25); ++ ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); ++ u64_to_ether_addr(mac_vid, ent->mac); ++ ent->vid = (mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25; ++ ent->port = (mac_vid & ARL_SRCH_RSLT_PORT_ID_MASK_25) >> ++ ARL_SRCH_RSLT_PORT_ID_S_25; ++ if (is_multicast_ether_addr(ent->mac) && (ext & ARL_SRCH_RSLT_EXT_MC_MII)) ++ ent->port |= BIT(B53_CPU_PORT_25); ++ else if (!is_multicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT) ++ ent->port = B53_CPU_PORT_25; ++} ++ + static inline void b53_arl_search_to_entry_63xx(struct b53_arl_entry *ent, + u64 mac_vid, u16 fwd_entry) + { +--- a/drivers/net/dsa/b53/b53_regs.h ++++ b/drivers/net/dsa/b53/b53_regs.h +@@ -328,7 +328,7 @@ + #define ARLTBL_VID_MASK_25 0xff + #define ARLTBL_VID_MASK 0xfff + #define ARLTBL_DATA_PORT_ID_S_25 48 +-#define ARLTBL_DATA_PORT_ID_MASK_25 0xf ++#define ARLTBL_DATA_PORT_ID_MASK_25 GENMASK_ULL(53, 48) + #define ARLTBL_VID_S_65 53 + #define ARLTBL_AGE_25 BIT_ULL(61) + #define ARLTBL_STATIC_25 BIT_ULL(62) +@@ -374,6 +374,12 @@ + + /* Single register search result on 5325/5365 */ + #define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24 ++#define ARL_SRCH_RSLT_PORT_ID_S_25 48 ++#define ARL_SRCH_RSLT_PORT_ID_MASK_25 GENMASK_ULL(52, 48) ++ ++/* BCM5325/5365 Search result extend register (8 bit) */ ++#define B53_ARL_SRCH_RSLT_EXT_25 0x2c ++#define ARL_SRCH_RSLT_EXT_MC_MII BIT(2) + + /* ARL Search Data Result (32 bit) */ + #define B53_ARL_SRCH_RSTL_0 0x68 diff --git a/lede/target/linux/generic/backport-6.12/613-06-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-VIDs.patch b/lede/target/linux/generic/backport-6.12/613-06-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-VIDs.patch new file mode 100644 index 0000000000..a2025f980c --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/613-06-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-VIDs.patch @@ -0,0 +1,140 @@ +From d39514e6a2d14f57830d649e2bf03b49612c2f73 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 28 Nov 2025 09:06:24 +0100 +Subject: [PATCH] net: dsa: b53: fix BCM5325/65 ARL entry VIDs + +BCM5325/65's ARL entry registers do not contain the VID, only the search +result register does. ARL entries have a separate VID entry register for +the index into the VLAN table. + +So make ARL entry accessors use the VID entry registers instead, and +move the VLAN ID field definition to the search register definition. + +Fixes: c45655386e53 ("net: dsa: b53: add support for FDB operations on 5325/5365") +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20251128080625.27181-7-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 9 +++++++-- + drivers/net/dsa/b53/b53_priv.h | 12 ++++++------ + drivers/net/dsa/b53/b53_regs.h | 7 +++++-- + 3 files changed, 18 insertions(+), 10 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -1833,19 +1833,24 @@ static int b53_arl_rw_op(struct b53_devi + static void b53_arl_read_entry_25(struct b53_device *dev, + struct b53_arl_entry *ent, u8 idx) + { ++ u8 vid_entry; + u64 mac_vid; + ++ b53_read8(dev, B53_ARLIO_PAGE, B53_ARLTBL_VID_ENTRY_25(idx), ++ &vid_entry); + b53_read64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx), + &mac_vid); +- b53_arl_to_entry_25(ent, mac_vid); ++ b53_arl_to_entry_25(ent, mac_vid, vid_entry); + } + + static void b53_arl_write_entry_25(struct b53_device *dev, + const struct b53_arl_entry *ent, u8 idx) + { ++ u8 vid_entry; + u64 mac_vid; + +- b53_arl_from_entry_25(&mac_vid, ent); ++ b53_arl_from_entry_25(&mac_vid, &vid_entry, ent); ++ b53_write8(dev, B53_ARLIO_PAGE, B53_ARLTBL_VID_ENTRY_25(idx), vid_entry); + b53_write64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx), + mac_vid); + } +--- a/drivers/net/dsa/b53/b53_priv.h ++++ b/drivers/net/dsa/b53/b53_priv.h +@@ -341,7 +341,7 @@ static inline void b53_arl_to_entry(stru + } + + static inline void b53_arl_to_entry_25(struct b53_arl_entry *ent, +- u64 mac_vid) ++ u64 mac_vid, u8 vid_entry) + { + memset(ent, 0, sizeof(*ent)); + ent->is_valid = !!(mac_vid & ARLTBL_VALID_25); +@@ -352,7 +352,7 @@ static inline void b53_arl_to_entry_25(s + ARLTBL_DATA_PORT_ID_S_25; + if (is_unicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT) + ent->port = B53_CPU_PORT_25; +- ent->vid = (mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25; ++ ent->vid = vid_entry; + } + + static inline void b53_arl_to_entry_89(struct b53_arl_entry *ent, +@@ -381,7 +381,7 @@ static inline void b53_arl_from_entry(u6 + *fwd_entry |= ARLTBL_AGE; + } + +-static inline void b53_arl_from_entry_25(u64 *mac_vid, ++static inline void b53_arl_from_entry_25(u64 *mac_vid, u8 *vid_entry, + const struct b53_arl_entry *ent) + { + *mac_vid = ether_addr_to_u64(ent->mac); +@@ -390,14 +390,13 @@ static inline void b53_arl_from_entry_25 + else + *mac_vid |= ((u64)ent->port << ARLTBL_DATA_PORT_ID_S_25) & + ARLTBL_DATA_PORT_ID_MASK_25; +- *mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK_25) << +- ARLTBL_VID_S_65; + if (ent->is_valid) + *mac_vid |= ARLTBL_VALID_25; + if (ent->is_static) + *mac_vid |= ARLTBL_STATIC_25; + if (ent->is_age) + *mac_vid |= ARLTBL_AGE_25; ++ *vid_entry = ent->vid; + } + + static inline void b53_arl_from_entry_89(u64 *mac_vid, u32 *fwd_entry, +@@ -422,7 +421,8 @@ static inline void b53_arl_search_to_ent + ent->is_age = !!(mac_vid & ARLTBL_AGE_25); + ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); + u64_to_ether_addr(mac_vid, ent->mac); +- ent->vid = (mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25; ++ ent->vid = (mac_vid & ARL_SRCH_RSLT_VID_MASK_25) >> ++ ARL_SRCH_RSLT_VID_S_25; + ent->port = (mac_vid & ARL_SRCH_RSLT_PORT_ID_MASK_25) >> + ARL_SRCH_RSLT_PORT_ID_S_25; + if (is_multicast_ether_addr(ent->mac) && (ext & ARL_SRCH_RSLT_EXT_MC_MII)) +--- a/drivers/net/dsa/b53/b53_regs.h ++++ b/drivers/net/dsa/b53/b53_regs.h +@@ -325,11 +325,9 @@ + #define B53_ARLTBL_MAC_VID_ENTRY(n) ((0x10 * (n)) + 0x10) + #define ARLTBL_MAC_MASK 0xffffffffffffULL + #define ARLTBL_VID_S 48 +-#define ARLTBL_VID_MASK_25 0xff + #define ARLTBL_VID_MASK 0xfff + #define ARLTBL_DATA_PORT_ID_S_25 48 + #define ARLTBL_DATA_PORT_ID_MASK_25 GENMASK_ULL(53, 48) +-#define ARLTBL_VID_S_65 53 + #define ARLTBL_AGE_25 BIT_ULL(61) + #define ARLTBL_STATIC_25 BIT_ULL(62) + #define ARLTBL_VALID_25 BIT_ULL(63) +@@ -349,6 +347,9 @@ + #define ARLTBL_STATIC_89 BIT(14) + #define ARLTBL_VALID_89 BIT(15) + ++/* BCM5325/BCM565 ARL Table VID Entry N Registers (8 bit) */ ++#define B53_ARLTBL_VID_ENTRY_25(n) ((0x2 * (n)) + 0x30) ++ + /* Maximum number of bin entries in the ARL for all switches */ + #define B53_ARLTBL_MAX_BIN_ENTRIES 4 + +@@ -376,6 +377,8 @@ + #define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24 + #define ARL_SRCH_RSLT_PORT_ID_S_25 48 + #define ARL_SRCH_RSLT_PORT_ID_MASK_25 GENMASK_ULL(52, 48) ++#define ARL_SRCH_RSLT_VID_S_25 53 ++#define ARL_SRCH_RSLT_VID_MASK_25 GENMASK_ULL(60, 53) + + /* BCM5325/5365 Search result extend register (8 bit) */ + #define B53_ARL_SRCH_RSLT_EXT_25 0x2c diff --git a/lede/target/linux/generic/backport-6.12/613-07-v6.19-net-dsa-b53-allow-VID-0-for-BCM5325-65.patch b/lede/target/linux/generic/backport-6.12/613-07-v6.19-net-dsa-b53-allow-VID-0-for-BCM5325-65.patch new file mode 100644 index 0000000000..7c6a63fc91 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/613-07-v6.19-net-dsa-b53-allow-VID-0-for-BCM5325-65.patch @@ -0,0 +1,44 @@ +From 0b2b27058692d437b12d3f2a3bf0fa699af7376e Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Fri, 28 Nov 2025 09:06:25 +0100 +Subject: [PATCH] net: dsa: b53: allow VID 0 for BCM5325/65 + +Now that writing ARL entries works properly, we can actually use VID 0 +as the default untagged VLAN for BCM5325 and BCM5365 as well. + +So use 0 as default PVID for all chips and do not reject VLAN 0 anymore, +which we ignored since commit 45e9d59d3950 ("net: dsa: b53: do not allow +to configure VLAN 0") anyway. + +Signed-off-by: Jonas Gorski +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20251128080625.27181-8-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/b53/b53_common.c | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -852,10 +852,7 @@ static void b53_enable_stp(struct b53_de + + static u16 b53_default_pvid(struct b53_device *dev) + { +- if (is5325(dev) || is5365(dev)) +- return 1; +- else +- return 0; ++ return 0; + } + + static bool b53_vlan_port_needs_forced_tagged(struct dsa_switch *ds, int port) +@@ -1679,9 +1676,6 @@ static int b53_vlan_prepare(struct dsa_s + { + struct b53_device *dev = ds->priv; + +- if ((is5325(dev) || is5365(dev)) && vlan->vid == 0) +- return -EOPNOTSUPP; +- + /* Port 7 on 7278 connects to the ASP's UniMAC which is not capable of + * receiving VLAN tagged frames at all, we can still allow the port to + * be configured for egress untagged. diff --git a/lede/target/linux/generic/backport-6.12/626-v6.16-net-bridge-locally-receive-all-multicast-packets-if-.patch b/lede/target/linux/generic/backport-6.12/626-v6.16-net-bridge-locally-receive-all-multicast-packets-if-.patch new file mode 100644 index 0000000000..d9bd8c73a0 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/626-v6.16-net-bridge-locally-receive-all-multicast-packets-if-.patch @@ -0,0 +1,41 @@ +From a496d2f0fd612ab9e10700afe00dc9267bad788b Mon Sep 17 00:00:00 2001 +From: Shengyu Qu +Date: Mon, 14 Apr 2025 18:56:01 +0800 +Subject: net: bridge: locally receive all multicast packets if IFF_ALLMULTI is + set + +If multicast snooping is enabled, multicast packets may not always end up +on the local bridge interface, if the host is not a member of the multicast +group. Similar to how IFF_PROMISC allows all packets to be received +locally, let IFF_ALLMULTI allow all multicast packets to be received. + +OpenWrt uses a user space daemon for DHCPv6/RA/NDP handling, and in relay +mode it sets the ALLMULTI flag in order to receive all relevant queries on +the network. + +This works for normal network interfaces and non-snooping bridges, but not +snooping bridges (unless multicast routing is enabled). + +Reported-by: Felix Fietkau +Closes: https://github.com/openwrt/openwrt/issues/15857#issuecomment-2662851243 +Signed-off-by: Shengyu Qu +Reviewed-by: Ido Schimmel +Acked-by: Nikolay Aleksandrov +Link: https://patch.msgid.link/OSZPR01MB8434308370ACAFA90A22980798B32@OSZPR01MB8434.jpnprd01.prod.outlook.com +Signed-off-by: Jakub Kicinski +--- + net/bridge/br_input.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/bridge/br_input.c ++++ b/net/bridge/br_input.c +@@ -184,7 +184,8 @@ int br_handle_frame_finish(struct net *n + if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) && + br_multicast_querier_exists(brmctx, eth_hdr(skb), mdst)) { + if ((mdst && mdst->host_joined) || +- br_multicast_is_router(brmctx, skb)) { ++ br_multicast_is_router(brmctx, skb) || ++ br->dev->flags & IFF_ALLMULTI) { + local_rcv = true; + DEV_STATS_INC(br->dev, multicast); + } diff --git a/lede/target/linux/generic/backport-6.12/630-v6.13-net-usb-qmi_wwan-add-Quectel-RG255C.patch b/lede/target/linux/generic/backport-6.12/630-v6.13-net-usb-qmi_wwan-add-Quectel-RG255C.patch new file mode 100644 index 0000000000..a1eb835a55 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/630-v6.13-net-usb-qmi_wwan-add-Quectel-RG255C.patch @@ -0,0 +1,47 @@ +From 5c964c8a97c12145104f5d2782aa1ffccf3a93dd Mon Sep 17 00:00:00 2001 +From: Martin Hou +Date: Mon, 16 Dec 2024 11:06:18 +0800 +Subject: [PATCH] net: usb: qmi_wwan: add Quectel RG255C + +Add support for Quectel RG255C which is based on Qualcomm SDX35 chip. +The composition is DM / NMEA / AT / QMI. + +T: Bus=01 Lev=01 Prnt=01 Port=04 Cnt=01 Dev#= 2 Spd=480 MxCh= 0 +D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 +P: Vendor=2c7c ProdID=0316 Rev= 5.15 +S: Manufacturer=Quectel +S: Product=RG255C-CN +S: SerialNumber=c68192c1 +C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=500mA +I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option +E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms +E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms +I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms +E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms +I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option +E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms +E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms +E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms +I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan +E: Ad=86(I) Atr=03(Int.) MxPS= 8 Ivl=32ms +E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms +E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms + +Signed-off-by: Martin Hou +Link: https://patch.msgid.link/tencent_17DDD787B48E8A5AB8379ED69E23A0CD9309@qq.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/usb/qmi_wwan.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -1442,6 +1442,7 @@ static const struct usb_device_id produc + {QMI_QUIRK_SET_DTR(0x2c7c, 0x0195, 4)}, /* Quectel EG95 */ + {QMI_FIXED_INTF(0x2c7c, 0x0296, 4)}, /* Quectel BG96 */ + {QMI_QUIRK_SET_DTR(0x2c7c, 0x030e, 4)}, /* Quectel EM05GV2 */ ++ {QMI_QUIRK_SET_DTR(0x2c7c, 0x0316, 3)}, /* Quectel RG255C */ + {QMI_QUIRK_SET_DTR(0x2cb7, 0x0104, 4)}, /* Fibocom NL678 series */ + {QMI_QUIRK_SET_DTR(0x2cb7, 0x0112, 0)}, /* Fibocom FG132 */ + {QMI_FIXED_INTF(0x0489, 0xe0b4, 0)}, /* Foxconn T77W968 LTE */ diff --git a/lede/target/linux/generic/backport-6.12/630-v6.14-PM-sleep-wakeirq-Introduce-device-managed-variant-of.patch b/lede/target/linux/generic/backport-6.12/630-v6.14-PM-sleep-wakeirq-Introduce-device-managed-variant-of.patch new file mode 100644 index 0000000000..081bcda591 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/630-v6.14-PM-sleep-wakeirq-Introduce-device-managed-variant-of.patch @@ -0,0 +1,74 @@ +From fd8318a32573d73eb20637a0c80689de0dc98169 Mon Sep 17 00:00:00 2001 +From: Peng Fan +Date: Fri, 3 Jan 2025 16:41:13 +0800 +Subject: [PATCH] PM: sleep: wakeirq: Introduce device-managed variant of + dev_pm_set_wake_irq() + +Add device-managed variant of dev_pm_set_wake_irq which automatically +clear the wake irq on device destruction to simplify error handling +and resource management in drivers. + +Signed-off-by: Peng Fan +Link: https://patch.msgid.link/20250103-wake_irq-v2-1-e3aeff5e9966@nxp.com +Signed-off-by: Rafael J. Wysocki +--- + drivers/base/power/wakeirq.c | 26 ++++++++++++++++++++++++++ + include/linux/pm_wakeirq.h | 6 ++++++ + 2 files changed, 32 insertions(+) + +--- a/drivers/base/power/wakeirq.c ++++ b/drivers/base/power/wakeirq.c +@@ -103,6 +103,32 @@ void dev_pm_clear_wake_irq(struct device + } + EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq); + ++static void devm_pm_clear_wake_irq(void *dev) ++{ ++ dev_pm_clear_wake_irq(dev); ++} ++ ++/** ++ * devm_pm_set_wake_irq - device-managed variant of dev_pm_set_wake_irq ++ * @dev: Device entry ++ * @irq: Device IO interrupt ++ * ++ * ++ * Attach a device IO interrupt as a wake IRQ, same with dev_pm_set_wake_irq, ++ * but the device will be auto clear wake capability on driver detach. ++ */ ++int devm_pm_set_wake_irq(struct device *dev, int irq) ++{ ++ int ret; ++ ++ ret = dev_pm_set_wake_irq(dev, irq); ++ if (ret) ++ return ret; ++ ++ return devm_add_action_or_reset(dev, devm_pm_clear_wake_irq, dev); ++} ++EXPORT_SYMBOL_GPL(devm_pm_set_wake_irq); ++ + /** + * handle_threaded_wake_irq - Handler for dedicated wake-up interrupts + * @irq: Device specific dedicated wake-up interrupt +--- a/include/linux/pm_wakeirq.h ++++ b/include/linux/pm_wakeirq.h +@@ -10,6 +10,7 @@ extern int dev_pm_set_wake_irq(struct de + extern int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq); + extern int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq); + extern void dev_pm_clear_wake_irq(struct device *dev); ++extern int devm_pm_set_wake_irq(struct device *dev, int irq); + + #else /* !CONFIG_PM */ + +@@ -32,5 +33,10 @@ static inline void dev_pm_clear_wake_irq + { + } + ++static inline int devm_pm_set_wake_irq(struct device *dev, int irq) ++{ ++ return 0; ++} ++ + #endif /* CONFIG_PM */ + #endif /* _LINUX_PM_WAKEIRQ_H */ diff --git a/lede/target/linux/generic/backport-6.12/700-01-v7.0-net-sched-Export-mq-functions-for-reuse.patch b/lede/target/linux/generic/backport-6.12/700-01-v7.0-net-sched-Export-mq-functions-for-reuse.patch new file mode 100644 index 0000000000..01439cdbd7 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/700-01-v7.0-net-sched-Export-mq-functions-for-reuse.patch @@ -0,0 +1,255 @@ +From 8560edcc05114e42d4d580baaf124bce8c291d55 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= +Date: Fri, 9 Jan 2026 14:15:30 +0100 +Subject: [PATCH 1/7] net/sched: Export mq functions for reuse +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +To enable the cake_mq qdisc to reuse code from the mq qdisc, export a +bunch of functions from sch_mq. Split common functionality out from some +functions so it can be composed with other code, and export other +functions wholesale. To discourage wanton reuse, put the symbols into a +new NET_SCHED_INTERNAL namespace, and a sch_priv.h header file. + +No functional change intended. + +Reviewed-by: Willem de Bruijn +Signed-off-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260109-mq-cake-sub-qdisc-v8-1-8d613fece5d8@redhat.com +Signed-off-by: Paolo Abeni +--- + MAINTAINERS | 1 + + include/net/sch_priv.h | 27 ++++++++++++++++ + net/sched/sch_mq.c | 71 +++++++++++++++++++++++++++++------------- + 3 files changed, 77 insertions(+), 22 deletions(-) + create mode 100644 include/net/sch_priv.h + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -22541,6 +22541,7 @@ L: netdev@vger.kernel.org + S: Maintained + F: include/net/pkt_cls.h + F: include/net/pkt_sched.h ++F: include/net/sch_priv.h + F: include/net/tc_act/ + F: include/uapi/linux/pkt_cls.h + F: include/uapi/linux/pkt_sched.h +--- /dev/null ++++ b/include/net/sch_priv.h +@@ -0,0 +1,27 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __NET_SCHED_PRIV_H ++#define __NET_SCHED_PRIV_H ++ ++#include ++ ++struct mq_sched { ++ struct Qdisc **qdiscs; ++}; ++ ++int mq_init_common(struct Qdisc *sch, struct nlattr *opt, ++ struct netlink_ext_ack *extack, ++ const struct Qdisc_ops *qdisc_ops); ++void mq_destroy_common(struct Qdisc *sch); ++void mq_attach(struct Qdisc *sch); ++void mq_dump_common(struct Qdisc *sch, struct sk_buff *skb); ++struct netdev_queue *mq_select_queue(struct Qdisc *sch, ++ struct tcmsg *tcm); ++struct Qdisc *mq_leaf(struct Qdisc *sch, unsigned long cl); ++unsigned long mq_find(struct Qdisc *sch, u32 classid); ++int mq_dump_class(struct Qdisc *sch, unsigned long cl, ++ struct sk_buff *skb, struct tcmsg *tcm); ++int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl, ++ struct gnet_dump *d); ++void mq_walk(struct Qdisc *sch, struct qdisc_walker *arg); ++ ++#endif +--- a/net/sched/sch_mq.c ++++ b/net/sched/sch_mq.c +@@ -15,11 +15,7 @@ + #include + #include + #include +-#include +- +-struct mq_sched { +- struct Qdisc **qdiscs; +-}; ++#include + + static int mq_offload(struct Qdisc *sch, enum tc_mq_command cmd) + { +@@ -49,23 +45,29 @@ static int mq_offload_stats(struct Qdisc + return qdisc_offload_dump_helper(sch, TC_SETUP_QDISC_MQ, &opt); + } + +-static void mq_destroy(struct Qdisc *sch) ++void mq_destroy_common(struct Qdisc *sch) + { + struct net_device *dev = qdisc_dev(sch); + struct mq_sched *priv = qdisc_priv(sch); + unsigned int ntx; + +- mq_offload(sch, TC_MQ_DESTROY); +- + if (!priv->qdiscs) + return; + for (ntx = 0; ntx < dev->num_tx_queues && priv->qdiscs[ntx]; ntx++) + qdisc_put(priv->qdiscs[ntx]); + kfree(priv->qdiscs); + } ++EXPORT_SYMBOL_NS_GPL(mq_destroy_common, NET_SCHED_INTERNAL); + +-static int mq_init(struct Qdisc *sch, struct nlattr *opt, +- struct netlink_ext_ack *extack) ++static void mq_destroy(struct Qdisc *sch) ++{ ++ mq_offload(sch, TC_MQ_DESTROY); ++ mq_destroy_common(sch); ++} ++ ++int mq_init_common(struct Qdisc *sch, struct nlattr *opt, ++ struct netlink_ext_ack *extack, ++ const struct Qdisc_ops *qdisc_ops) + { + struct net_device *dev = qdisc_dev(sch); + struct mq_sched *priv = qdisc_priv(sch); +@@ -87,7 +89,8 @@ static int mq_init(struct Qdisc *sch, st + + for (ntx = 0; ntx < dev->num_tx_queues; ntx++) { + dev_queue = netdev_get_tx_queue(dev, ntx); +- qdisc = qdisc_create_dflt(dev_queue, get_default_qdisc_ops(dev, ntx), ++ qdisc = qdisc_create_dflt(dev_queue, ++ qdisc_ops ?: get_default_qdisc_ops(dev, ntx), + TC_H_MAKE(TC_H_MAJ(sch->handle), + TC_H_MIN(ntx + 1)), + extack); +@@ -98,12 +101,24 @@ static int mq_init(struct Qdisc *sch, st + } + + sch->flags |= TCQ_F_MQROOT; ++ return 0; ++} ++EXPORT_SYMBOL_NS_GPL(mq_init_common, NET_SCHED_INTERNAL); ++ ++static int mq_init(struct Qdisc *sch, struct nlattr *opt, ++ struct netlink_ext_ack *extack) ++{ ++ int ret; ++ ++ ret = mq_init_common(sch, opt, extack, NULL); ++ if (ret) ++ return ret; + + mq_offload(sch, TC_MQ_CREATE); + return 0; + } + +-static void mq_attach(struct Qdisc *sch) ++void mq_attach(struct Qdisc *sch) + { + struct net_device *dev = qdisc_dev(sch); + struct mq_sched *priv = qdisc_priv(sch); +@@ -124,8 +139,9 @@ static void mq_attach(struct Qdisc *sch) + kfree(priv->qdiscs); + priv->qdiscs = NULL; + } ++EXPORT_SYMBOL_NS_GPL(mq_attach, NET_SCHED_INTERNAL); + +-static int mq_dump(struct Qdisc *sch, struct sk_buff *skb) ++void mq_dump_common(struct Qdisc *sch, struct sk_buff *skb) + { + struct net_device *dev = qdisc_dev(sch); + struct Qdisc *qdisc; +@@ -152,7 +168,12 @@ static int mq_dump(struct Qdisc *sch, st + + spin_unlock_bh(qdisc_lock(qdisc)); + } ++} ++EXPORT_SYMBOL_NS_GPL(mq_dump_common, NET_SCHED_INTERNAL); + ++static int mq_dump(struct Qdisc *sch, struct sk_buff *skb) ++{ ++ mq_dump_common(sch, skb); + return mq_offload_stats(sch); + } + +@@ -166,11 +187,12 @@ static struct netdev_queue *mq_queue_get + return netdev_get_tx_queue(dev, ntx); + } + +-static struct netdev_queue *mq_select_queue(struct Qdisc *sch, +- struct tcmsg *tcm) ++struct netdev_queue *mq_select_queue(struct Qdisc *sch, ++ struct tcmsg *tcm) + { + return mq_queue_get(sch, TC_H_MIN(tcm->tcm_parent)); + } ++EXPORT_SYMBOL_NS_GPL(mq_select_queue, NET_SCHED_INTERNAL); + + static int mq_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new, + struct Qdisc **old, struct netlink_ext_ack *extack) +@@ -198,14 +220,15 @@ static int mq_graft(struct Qdisc *sch, u + return 0; + } + +-static struct Qdisc *mq_leaf(struct Qdisc *sch, unsigned long cl) ++struct Qdisc *mq_leaf(struct Qdisc *sch, unsigned long cl) + { + struct netdev_queue *dev_queue = mq_queue_get(sch, cl); + + return rtnl_dereference(dev_queue->qdisc_sleeping); + } ++EXPORT_SYMBOL_NS_GPL(mq_leaf, NET_SCHED_INTERNAL); + +-static unsigned long mq_find(struct Qdisc *sch, u32 classid) ++unsigned long mq_find(struct Qdisc *sch, u32 classid) + { + unsigned int ntx = TC_H_MIN(classid); + +@@ -213,9 +236,10 @@ static unsigned long mq_find(struct Qdis + return 0; + return ntx; + } ++EXPORT_SYMBOL_NS_GPL(mq_find, NET_SCHED_INTERNAL); + +-static int mq_dump_class(struct Qdisc *sch, unsigned long cl, +- struct sk_buff *skb, struct tcmsg *tcm) ++int mq_dump_class(struct Qdisc *sch, unsigned long cl, ++ struct sk_buff *skb, struct tcmsg *tcm) + { + struct netdev_queue *dev_queue = mq_queue_get(sch, cl); + +@@ -224,9 +248,10 @@ static int mq_dump_class(struct Qdisc *s + tcm->tcm_info = rtnl_dereference(dev_queue->qdisc_sleeping)->handle; + return 0; + } ++EXPORT_SYMBOL_NS_GPL(mq_dump_class, NET_SCHED_INTERNAL); + +-static int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl, +- struct gnet_dump *d) ++int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl, ++ struct gnet_dump *d) + { + struct netdev_queue *dev_queue = mq_queue_get(sch, cl); + +@@ -236,8 +261,9 @@ static int mq_dump_class_stats(struct Qd + return -1; + return 0; + } ++EXPORT_SYMBOL_NS_GPL(mq_dump_class_stats, NET_SCHED_INTERNAL); + +-static void mq_walk(struct Qdisc *sch, struct qdisc_walker *arg) ++void mq_walk(struct Qdisc *sch, struct qdisc_walker *arg) + { + struct net_device *dev = qdisc_dev(sch); + unsigned int ntx; +@@ -251,6 +277,7 @@ static void mq_walk(struct Qdisc *sch, s + break; + } + } ++EXPORT_SYMBOL_NS_GPL(mq_walk, NET_SCHED_INTERNAL); + + static const struct Qdisc_class_ops mq_class_ops = { + .select_queue = mq_select_queue, diff --git a/lede/target/linux/generic/backport-6.12/700-02-v7.0-net-sched-sch_cake-Factor-out-config-variables-into-.patch b/lede/target/linux/generic/backport-6.12/700-02-v7.0-net-sched-sch_cake-Factor-out-config-variables-into-.patch new file mode 100644 index 0000000000..8df110b556 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/700-02-v7.0-net-sched-sch_cake-Factor-out-config-variables-into-.patch @@ -0,0 +1,636 @@ +From 23090d3e9db80c2a374df1e636247eff9b6dd972 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= +Date: Fri, 9 Jan 2026 14:15:31 +0100 +Subject: [PATCH 2/7] net/sched: sch_cake: Factor out config variables into + separate struct +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Factor out all the user-configurable variables into a separate struct +and embed it into struct cake_sched_data. This is done in preparation +for sharing the configuration across multiple instances of cake in an mq +setup. + +No functional change is intended with this patch. + +Reviewed-by: Jamal Hadi Salim +Reviewed-by: Willem de Bruijn +Signed-off-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260109-mq-cake-sub-qdisc-v8-2-8d613fece5d8@redhat.com +Signed-off-by: Paolo Abeni +--- + net/sched/sch_cake.c | 245 +++++++++++++++++++++++-------------------- + 1 file changed, 133 insertions(+), 112 deletions(-) + +--- a/net/sched/sch_cake.c ++++ b/net/sched/sch_cake.c +@@ -197,40 +197,42 @@ struct cake_tin_data { + u32 way_collisions; + }; /* number of tins is small, so size of this struct doesn't matter much */ + ++struct cake_sched_config { ++ u64 rate_bps; ++ u64 interval; ++ u64 target; ++ u32 buffer_config_limit; ++ u32 fwmark_mask; ++ u16 fwmark_shft; ++ s16 rate_overhead; ++ u16 rate_mpu; ++ u16 rate_flags; ++ u8 tin_mode; ++ u8 flow_mode; ++ u8 atm_mode; ++ u8 ack_filter; ++}; ++ + struct cake_sched_data { + struct tcf_proto __rcu *filter_list; /* optional external classifier */ + struct tcf_block *block; + struct cake_tin_data *tins; ++ struct cake_sched_config *config; + + struct cake_heap_entry overflow_heap[CAKE_QUEUES * CAKE_MAX_TINS]; +- u16 overflow_timeout; +- +- u16 tin_cnt; +- u8 tin_mode; +- u8 flow_mode; +- u8 ack_filter; +- u8 atm_mode; +- +- u32 fwmark_mask; +- u16 fwmark_shft; + + /* time_next = time_this + ((len * rate_ns) >> rate_shft) */ +- u16 rate_shft; + ktime_t time_next_packet; + ktime_t failsafe_next_packet; + u64 rate_ns; +- u64 rate_bps; +- u16 rate_flags; +- s16 rate_overhead; +- u16 rate_mpu; +- u64 interval; +- u64 target; ++ u16 rate_shft; ++ u16 overflow_timeout; ++ u16 tin_cnt; + + /* resource tracking */ + u32 buffer_used; + u32 buffer_max_used; + u32 buffer_limit; +- u32 buffer_config_limit; + + /* indices for dequeue */ + u16 cur_tin; +@@ -1195,7 +1197,7 @@ static bool cake_tcph_may_drop(const str + static struct sk_buff *cake_ack_filter(struct cake_sched_data *q, + struct cake_flow *flow) + { +- bool aggressive = q->ack_filter == CAKE_ACK_AGGRESSIVE; ++ bool aggressive = q->config->ack_filter == CAKE_ACK_AGGRESSIVE; + struct sk_buff *elig_ack = NULL, *elig_ack_prev = NULL; + struct sk_buff *skb_check, *skb_prev = NULL; + const struct ipv6hdr *ipv6h, *ipv6h_check; +@@ -1355,15 +1357,17 @@ static u64 cake_ewma(u64 avg, u64 sample + return avg; + } + +-static u32 cake_calc_overhead(struct cake_sched_data *q, u32 len, u32 off) ++static u32 cake_calc_overhead(struct cake_sched_data *qd, u32 len, u32 off) + { ++ struct cake_sched_config *q = qd->config; ++ + if (q->rate_flags & CAKE_FLAG_OVERHEAD) + len -= off; + +- if (q->max_netlen < len) +- q->max_netlen = len; +- if (q->min_netlen > len) +- q->min_netlen = len; ++ if (qd->max_netlen < len) ++ qd->max_netlen = len; ++ if (qd->min_netlen > len) ++ qd->min_netlen = len; + + len += q->rate_overhead; + +@@ -1382,10 +1386,10 @@ static u32 cake_calc_overhead(struct cak + len += (len + 63) / 64; + } + +- if (q->max_adjlen < len) +- q->max_adjlen = len; +- if (q->min_adjlen > len) +- q->min_adjlen = len; ++ if (qd->max_adjlen < len) ++ qd->max_adjlen = len; ++ if (qd->min_adjlen > len) ++ qd->min_adjlen = len; + + return len; + } +@@ -1587,7 +1591,7 @@ static unsigned int cake_drop(struct Qdi + b->tin_dropped++; + sch->qstats.drops++; + +- if (q->rate_flags & CAKE_FLAG_INGRESS) ++ if (q->config->rate_flags & CAKE_FLAG_INGRESS) + cake_advance_shaper(q, b, skb, now, true); + + __qdisc_drop(skb, to_free); +@@ -1657,7 +1661,8 @@ static u8 cake_handle_diffserv(struct sk + static struct cake_tin_data *cake_select_tin(struct Qdisc *sch, + struct sk_buff *skb) + { +- struct cake_sched_data *q = qdisc_priv(sch); ++ struct cake_sched_data *qd = qdisc_priv(sch); ++ struct cake_sched_config *q = qd->config; + u32 tin, mark; + bool wash; + u8 dscp; +@@ -1674,24 +1679,24 @@ static struct cake_tin_data *cake_select + if (q->tin_mode == CAKE_DIFFSERV_BESTEFFORT) + tin = 0; + +- else if (mark && mark <= q->tin_cnt) +- tin = q->tin_order[mark - 1]; ++ else if (mark && mark <= qd->tin_cnt) ++ tin = qd->tin_order[mark - 1]; + + else if (TC_H_MAJ(skb->priority) == sch->handle && + TC_H_MIN(skb->priority) > 0 && +- TC_H_MIN(skb->priority) <= q->tin_cnt) +- tin = q->tin_order[TC_H_MIN(skb->priority) - 1]; ++ TC_H_MIN(skb->priority) <= qd->tin_cnt) ++ tin = qd->tin_order[TC_H_MIN(skb->priority) - 1]; + + else { + if (!wash) + dscp = cake_handle_diffserv(skb, wash); +- tin = q->tin_index[dscp]; ++ tin = qd->tin_index[dscp]; + +- if (unlikely(tin >= q->tin_cnt)) ++ if (unlikely(tin >= qd->tin_cnt)) + tin = 0; + } + +- return &q->tins[tin]; ++ return &qd->tins[tin]; + } + + static u32 cake_classify(struct Qdisc *sch, struct cake_tin_data **t, +@@ -1747,7 +1752,7 @@ static s32 cake_enqueue(struct sk_buff * + bool same_flow = false; + + /* choose flow to insert into */ +- idx = cake_classify(sch, &b, skb, q->flow_mode, &ret); ++ idx = cake_classify(sch, &b, skb, q->config->flow_mode, &ret); + if (idx == 0) { + if (ret & __NET_XMIT_BYPASS) + qdisc_qstats_drop(sch); +@@ -1782,7 +1787,7 @@ static s32 cake_enqueue(struct sk_buff * + if (unlikely(len > b->max_skblen)) + b->max_skblen = len; + +- if (skb_is_gso(skb) && q->rate_flags & CAKE_FLAG_SPLIT_GSO) { ++ if (skb_is_gso(skb) && q->config->rate_flags & CAKE_FLAG_SPLIT_GSO) { + struct sk_buff *segs, *nskb; + netdev_features_t features = netif_skb_features(skb); + unsigned int slen = 0, numsegs = 0; +@@ -1823,7 +1828,7 @@ static s32 cake_enqueue(struct sk_buff * + get_cobalt_cb(skb)->adjusted_len = cake_overhead(q, skb); + flow_queue_add(flow, skb); + +- if (q->ack_filter) ++ if (q->config->ack_filter) + ack = cake_ack_filter(q, flow); + + if (ack) { +@@ -1832,7 +1837,7 @@ static s32 cake_enqueue(struct sk_buff * + ack_pkt_len = qdisc_pkt_len(ack); + b->bytes += ack_pkt_len; + q->buffer_used += skb->truesize - ack->truesize; +- if (q->rate_flags & CAKE_FLAG_INGRESS) ++ if (q->config->rate_flags & CAKE_FLAG_INGRESS) + cake_advance_shaper(q, b, ack, now, true); + + qdisc_tree_reduce_backlog(sch, 1, ack_pkt_len); +@@ -1855,7 +1860,7 @@ static s32 cake_enqueue(struct sk_buff * + cake_heapify_up(q, b->overflow_idx[idx]); + + /* incoming bandwidth capacity estimate */ +- if (q->rate_flags & CAKE_FLAG_AUTORATE_INGRESS) { ++ if (q->config->rate_flags & CAKE_FLAG_AUTORATE_INGRESS) { + u64 packet_interval = \ + ktime_to_ns(ktime_sub(now, q->last_packet_time)); + +@@ -1887,7 +1892,7 @@ static s32 cake_enqueue(struct sk_buff * + if (ktime_after(now, + ktime_add_ms(q->last_reconfig_time, + 250))) { +- q->rate_bps = (q->avg_peak_bandwidth * 15) >> 4; ++ q->config->rate_bps = (q->avg_peak_bandwidth * 15) >> 4; + cake_reconfigure(sch); + } + } +@@ -1907,7 +1912,7 @@ static s32 cake_enqueue(struct sk_buff * + flow->set = CAKE_SET_SPARSE; + b->sparse_flow_count++; + +- flow->deficit = cake_get_flow_quantum(b, flow, q->flow_mode); ++ flow->deficit = cake_get_flow_quantum(b, flow, q->config->flow_mode); + } else if (flow->set == CAKE_SET_SPARSE_WAIT) { + /* this flow was empty, accounted as a sparse flow, but actually + * in the bulk rotation. +@@ -1916,8 +1921,8 @@ static s32 cake_enqueue(struct sk_buff * + b->sparse_flow_count--; + b->bulk_flow_count++; + +- cake_inc_srchost_bulk_flow_count(b, flow, q->flow_mode); +- cake_inc_dsthost_bulk_flow_count(b, flow, q->flow_mode); ++ cake_inc_srchost_bulk_flow_count(b, flow, q->config->flow_mode); ++ cake_inc_dsthost_bulk_flow_count(b, flow, q->config->flow_mode); + } + + if (q->buffer_used > q->buffer_max_used) +@@ -2103,8 +2108,8 @@ retry: + b->sparse_flow_count--; + b->bulk_flow_count++; + +- cake_inc_srchost_bulk_flow_count(b, flow, q->flow_mode); +- cake_inc_dsthost_bulk_flow_count(b, flow, q->flow_mode); ++ cake_inc_srchost_bulk_flow_count(b, flow, q->config->flow_mode); ++ cake_inc_dsthost_bulk_flow_count(b, flow, q->config->flow_mode); + + flow->set = CAKE_SET_BULK; + } else { +@@ -2116,7 +2121,7 @@ retry: + } + } + +- flow->deficit += cake_get_flow_quantum(b, flow, q->flow_mode); ++ flow->deficit += cake_get_flow_quantum(b, flow, q->config->flow_mode); + list_move_tail(&flow->flowchain, &b->old_flows); + + goto retry; +@@ -2140,8 +2145,8 @@ retry: + if (flow->set == CAKE_SET_BULK) { + b->bulk_flow_count--; + +- cake_dec_srchost_bulk_flow_count(b, flow, q->flow_mode); +- cake_dec_dsthost_bulk_flow_count(b, flow, q->flow_mode); ++ cake_dec_srchost_bulk_flow_count(b, flow, q->config->flow_mode); ++ cake_dec_dsthost_bulk_flow_count(b, flow, q->config->flow_mode); + + b->decaying_flow_count++; + } else if (flow->set == CAKE_SET_SPARSE || +@@ -2159,8 +2164,8 @@ retry: + else if (flow->set == CAKE_SET_BULK) { + b->bulk_flow_count--; + +- cake_dec_srchost_bulk_flow_count(b, flow, q->flow_mode); +- cake_dec_dsthost_bulk_flow_count(b, flow, q->flow_mode); ++ cake_dec_srchost_bulk_flow_count(b, flow, q->config->flow_mode); ++ cake_dec_dsthost_bulk_flow_count(b, flow, q->config->flow_mode); + } else + b->decaying_flow_count--; + +@@ -2172,13 +2177,13 @@ retry: + /* Last packet in queue may be marked, shouldn't be dropped */ + if (!cobalt_should_drop(&flow->cvars, &b->cparams, now, skb, + (b->bulk_flow_count * +- !!(q->rate_flags & ++ !!(q->config->rate_flags & + CAKE_FLAG_INGRESS))) || + !flow->head) + break; + + /* drop this packet, get another one */ +- if (q->rate_flags & CAKE_FLAG_INGRESS) { ++ if (q->config->rate_flags & CAKE_FLAG_INGRESS) { + len = cake_advance_shaper(q, b, skb, + now, true); + flow->deficit -= len; +@@ -2189,7 +2194,7 @@ retry: + qdisc_tree_reduce_backlog(sch, 1, qdisc_pkt_len(skb)); + qdisc_qstats_drop(sch); + kfree_skb(skb); +- if (q->rate_flags & CAKE_FLAG_INGRESS) ++ if (q->config->rate_flags & CAKE_FLAG_INGRESS) + goto retry; + } + +@@ -2311,7 +2316,7 @@ static int cake_config_besteffort(struct + struct cake_sched_data *q = qdisc_priv(sch); + struct cake_tin_data *b = &q->tins[0]; + u32 mtu = psched_mtu(qdisc_dev(sch)); +- u64 rate = q->rate_bps; ++ u64 rate = q->config->rate_bps; + + q->tin_cnt = 1; + +@@ -2319,7 +2324,7 @@ static int cake_config_besteffort(struct + q->tin_order = normal_order; + + cake_set_rate(b, rate, mtu, +- us_to_ns(q->target), us_to_ns(q->interval)); ++ us_to_ns(q->config->target), us_to_ns(q->config->interval)); + b->tin_quantum = 65535; + + return 0; +@@ -2330,7 +2335,7 @@ static int cake_config_precedence(struct + /* convert high-level (user visible) parameters into internal format */ + struct cake_sched_data *q = qdisc_priv(sch); + u32 mtu = psched_mtu(qdisc_dev(sch)); +- u64 rate = q->rate_bps; ++ u64 rate = q->config->rate_bps; + u32 quantum = 256; + u32 i; + +@@ -2341,8 +2346,8 @@ static int cake_config_precedence(struct + for (i = 0; i < q->tin_cnt; i++) { + struct cake_tin_data *b = &q->tins[i]; + +- cake_set_rate(b, rate, mtu, us_to_ns(q->target), +- us_to_ns(q->interval)); ++ cake_set_rate(b, rate, mtu, us_to_ns(q->config->target), ++ us_to_ns(q->config->interval)); + + b->tin_quantum = max_t(u16, 1U, quantum); + +@@ -2419,7 +2424,7 @@ static int cake_config_diffserv8(struct + + struct cake_sched_data *q = qdisc_priv(sch); + u32 mtu = psched_mtu(qdisc_dev(sch)); +- u64 rate = q->rate_bps; ++ u64 rate = q->config->rate_bps; + u32 quantum = 256; + u32 i; + +@@ -2433,8 +2438,8 @@ static int cake_config_diffserv8(struct + for (i = 0; i < q->tin_cnt; i++) { + struct cake_tin_data *b = &q->tins[i]; + +- cake_set_rate(b, rate, mtu, us_to_ns(q->target), +- us_to_ns(q->interval)); ++ cake_set_rate(b, rate, mtu, us_to_ns(q->config->target), ++ us_to_ns(q->config->interval)); + + b->tin_quantum = max_t(u16, 1U, quantum); + +@@ -2463,7 +2468,7 @@ static int cake_config_diffserv4(struct + + struct cake_sched_data *q = qdisc_priv(sch); + u32 mtu = psched_mtu(qdisc_dev(sch)); +- u64 rate = q->rate_bps; ++ u64 rate = q->config->rate_bps; + u32 quantum = 1024; + + q->tin_cnt = 4; +@@ -2474,13 +2479,13 @@ static int cake_config_diffserv4(struct + + /* class characteristics */ + cake_set_rate(&q->tins[0], rate, mtu, +- us_to_ns(q->target), us_to_ns(q->interval)); ++ us_to_ns(q->config->target), us_to_ns(q->config->interval)); + cake_set_rate(&q->tins[1], rate >> 4, mtu, +- us_to_ns(q->target), us_to_ns(q->interval)); ++ us_to_ns(q->config->target), us_to_ns(q->config->interval)); + cake_set_rate(&q->tins[2], rate >> 1, mtu, +- us_to_ns(q->target), us_to_ns(q->interval)); ++ us_to_ns(q->config->target), us_to_ns(q->config->interval)); + cake_set_rate(&q->tins[3], rate >> 2, mtu, +- us_to_ns(q->target), us_to_ns(q->interval)); ++ us_to_ns(q->config->target), us_to_ns(q->config->interval)); + + /* bandwidth-sharing weights */ + q->tins[0].tin_quantum = quantum; +@@ -2500,7 +2505,7 @@ static int cake_config_diffserv3(struct + */ + struct cake_sched_data *q = qdisc_priv(sch); + u32 mtu = psched_mtu(qdisc_dev(sch)); +- u64 rate = q->rate_bps; ++ u64 rate = q->config->rate_bps; + u32 quantum = 1024; + + q->tin_cnt = 3; +@@ -2511,11 +2516,11 @@ static int cake_config_diffserv3(struct + + /* class characteristics */ + cake_set_rate(&q->tins[0], rate, mtu, +- us_to_ns(q->target), us_to_ns(q->interval)); ++ us_to_ns(q->config->target), us_to_ns(q->config->interval)); + cake_set_rate(&q->tins[1], rate >> 4, mtu, +- us_to_ns(q->target), us_to_ns(q->interval)); ++ us_to_ns(q->config->target), us_to_ns(q->config->interval)); + cake_set_rate(&q->tins[2], rate >> 2, mtu, +- us_to_ns(q->target), us_to_ns(q->interval)); ++ us_to_ns(q->config->target), us_to_ns(q->config->interval)); + + /* bandwidth-sharing weights */ + q->tins[0].tin_quantum = quantum; +@@ -2527,7 +2532,8 @@ static int cake_config_diffserv3(struct + + static void cake_reconfigure(struct Qdisc *sch) + { +- struct cake_sched_data *q = qdisc_priv(sch); ++ struct cake_sched_data *qd = qdisc_priv(sch); ++ struct cake_sched_config *q = qd->config; + int c, ft; + + switch (q->tin_mode) { +@@ -2553,36 +2559,37 @@ static void cake_reconfigure(struct Qdis + break; + } + +- for (c = q->tin_cnt; c < CAKE_MAX_TINS; c++) { ++ for (c = qd->tin_cnt; c < CAKE_MAX_TINS; c++) { + cake_clear_tin(sch, c); +- q->tins[c].cparams.mtu_time = q->tins[ft].cparams.mtu_time; ++ qd->tins[c].cparams.mtu_time = qd->tins[ft].cparams.mtu_time; + } + +- q->rate_ns = q->tins[ft].tin_rate_ns; +- q->rate_shft = q->tins[ft].tin_rate_shft; ++ qd->rate_ns = qd->tins[ft].tin_rate_ns; ++ qd->rate_shft = qd->tins[ft].tin_rate_shft; + + if (q->buffer_config_limit) { +- q->buffer_limit = q->buffer_config_limit; ++ qd->buffer_limit = q->buffer_config_limit; + } else if (q->rate_bps) { + u64 t = q->rate_bps * q->interval; + + do_div(t, USEC_PER_SEC / 4); +- q->buffer_limit = max_t(u32, t, 4U << 20); ++ qd->buffer_limit = max_t(u32, t, 4U << 20); + } else { +- q->buffer_limit = ~0; ++ qd->buffer_limit = ~0; + } + + sch->flags &= ~TCQ_F_CAN_BYPASS; + +- q->buffer_limit = min(q->buffer_limit, +- max(sch->limit * psched_mtu(qdisc_dev(sch)), +- q->buffer_config_limit)); ++ qd->buffer_limit = min(qd->buffer_limit, ++ max(sch->limit * psched_mtu(qdisc_dev(sch)), ++ q->buffer_config_limit)); + } + + static int cake_change(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) + { +- struct cake_sched_data *q = qdisc_priv(sch); ++ struct cake_sched_data *qd = qdisc_priv(sch); ++ struct cake_sched_config *q = qd->config; + struct nlattr *tb[TCA_CAKE_MAX + 1]; + u16 rate_flags; + u8 flow_mode; +@@ -2636,19 +2643,19 @@ static int cake_change(struct Qdisc *sch + nla_get_s32(tb[TCA_CAKE_OVERHEAD])); + rate_flags |= CAKE_FLAG_OVERHEAD; + +- q->max_netlen = 0; +- q->max_adjlen = 0; +- q->min_netlen = ~0; +- q->min_adjlen = ~0; ++ qd->max_netlen = 0; ++ qd->max_adjlen = 0; ++ qd->min_netlen = ~0; ++ qd->min_adjlen = ~0; + } + + if (tb[TCA_CAKE_RAW]) { + rate_flags &= ~CAKE_FLAG_OVERHEAD; + +- q->max_netlen = 0; +- q->max_adjlen = 0; +- q->min_netlen = ~0; +- q->min_adjlen = ~0; ++ qd->max_netlen = 0; ++ qd->max_adjlen = 0; ++ qd->min_netlen = ~0; ++ qd->min_adjlen = ~0; + } + + if (tb[TCA_CAKE_MPU]) +@@ -2704,7 +2711,7 @@ static int cake_change(struct Qdisc *sch + + WRITE_ONCE(q->rate_flags, rate_flags); + WRITE_ONCE(q->flow_mode, flow_mode); +- if (q->tins) { ++ if (qd->tins) { + sch_tree_lock(sch); + cake_reconfigure(sch); + sch_tree_unlock(sch); +@@ -2720,14 +2727,20 @@ static void cake_destroy(struct Qdisc *s + qdisc_watchdog_cancel(&q->watchdog); + tcf_block_put(q->block); + kvfree(q->tins); ++ kvfree(q->config); + } + + static int cake_init(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) + { +- struct cake_sched_data *q = qdisc_priv(sch); ++ struct cake_sched_data *qd = qdisc_priv(sch); ++ struct cake_sched_config *q; + int i, j, err; + ++ q = kzalloc(sizeof(*q), GFP_KERNEL); ++ if (!q) ++ return -ENOMEM; ++ + sch->limit = 10240; + q->tin_mode = CAKE_DIFFSERV_DIFFSERV3; + q->flow_mode = CAKE_FLOW_TRIPLE; +@@ -2739,33 +2752,36 @@ static int cake_init(struct Qdisc *sch, + * for 5 to 10% of interval + */ + q->rate_flags |= CAKE_FLAG_SPLIT_GSO; +- q->cur_tin = 0; +- q->cur_flow = 0; ++ qd->cur_tin = 0; ++ qd->cur_flow = 0; ++ qd->config = q; + +- qdisc_watchdog_init(&q->watchdog, sch); ++ qdisc_watchdog_init(&qd->watchdog, sch); + + if (opt) { + err = cake_change(sch, opt, extack); + + if (err) +- return err; ++ goto err; + } + +- err = tcf_block_get(&q->block, &q->filter_list, sch, extack); ++ err = tcf_block_get(&qd->block, &qd->filter_list, sch, extack); + if (err) +- return err; ++ goto err; + + quantum_div[0] = ~0; + for (i = 1; i <= CAKE_QUEUES; i++) + quantum_div[i] = 65535 / i; + +- q->tins = kvcalloc(CAKE_MAX_TINS, sizeof(struct cake_tin_data), +- GFP_KERNEL); +- if (!q->tins) +- return -ENOMEM; ++ qd->tins = kvcalloc(CAKE_MAX_TINS, sizeof(struct cake_tin_data), ++ GFP_KERNEL); ++ if (!qd->tins) { ++ err = -ENOMEM; ++ goto err; ++ } + + for (i = 0; i < CAKE_MAX_TINS; i++) { +- struct cake_tin_data *b = q->tins + i; ++ struct cake_tin_data *b = qd->tins + i; + + INIT_LIST_HEAD(&b->new_flows); + INIT_LIST_HEAD(&b->old_flows); +@@ -2781,22 +2797,27 @@ static int cake_init(struct Qdisc *sch, + INIT_LIST_HEAD(&flow->flowchain); + cobalt_vars_init(&flow->cvars); + +- q->overflow_heap[k].t = i; +- q->overflow_heap[k].b = j; ++ qd->overflow_heap[k].t = i; ++ qd->overflow_heap[k].b = j; + b->overflow_idx[j] = k; + } + } + + cake_reconfigure(sch); +- q->avg_peak_bandwidth = q->rate_bps; +- q->min_netlen = ~0; +- q->min_adjlen = ~0; ++ qd->avg_peak_bandwidth = q->rate_bps; ++ qd->min_netlen = ~0; ++ qd->min_adjlen = ~0; + return 0; ++err: ++ kvfree(qd->config); ++ qd->config = NULL; ++ return err; + } + + static int cake_dump(struct Qdisc *sch, struct sk_buff *skb) + { +- struct cake_sched_data *q = qdisc_priv(sch); ++ struct cake_sched_data *qd = qdisc_priv(sch); ++ struct cake_sched_config *q = qd->config; + struct nlattr *opts; + u16 rate_flags; + u8 flow_mode; diff --git a/lede/target/linux/generic/backport-6.12/700-03-v7.0-net-sched-sch_cake-Add-cake_mq-qdisc-for-using-cake-.patch b/lede/target/linux/generic/backport-6.12/700-03-v7.0-net-sched-sch_cake-Add-cake_mq-qdisc-for-using-cake-.patch new file mode 100644 index 0000000000..645b27f874 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/700-03-v7.0-net-sched-sch_cake-Add-cake_mq-qdisc-for-using-cake-.patch @@ -0,0 +1,130 @@ +From c076e98c66afe06e41e118eb96d6b15019b822f2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= +Date: Fri, 9 Jan 2026 14:15:32 +0100 +Subject: [PATCH 3/7] net/sched: sch_cake: Add cake_mq qdisc for using cake on + mq devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add a cake_mq qdisc which installs cake instances on each hardware +queue on a multi-queue device. + +This is just a copy of sch_mq that installs cake instead of the default +qdisc on each queue. Subsequent commits will add sharing of the config +between cake instances, as well as a multi-queue aware shaper algorithm. + +Reviewed-by: Willem de Bruijn +Signed-off-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260109-mq-cake-sub-qdisc-v8-3-8d613fece5d8@redhat.com +Signed-off-by: Paolo Abeni +--- + net/sched/sch_cake.c | 79 +++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 78 insertions(+), 1 deletion(-) + +--- a/net/sched/sch_cake.c ++++ b/net/sched/sch_cake.c +@@ -67,6 +67,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -3154,14 +3155,89 @@ static struct Qdisc_ops cake_qdisc_ops _ + }; + MODULE_ALIAS_NET_SCH("cake"); + ++struct cake_mq_sched { ++ struct mq_sched mq_priv; /* must be first */ ++}; ++ ++static void cake_mq_destroy(struct Qdisc *sch) ++{ ++ mq_destroy_common(sch); ++} ++ ++static int cake_mq_init(struct Qdisc *sch, struct nlattr *opt, ++ struct netlink_ext_ack *extack) ++{ ++ int ret; ++ ++ ret = mq_init_common(sch, opt, extack, &cake_qdisc_ops); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int cake_mq_dump(struct Qdisc *sch, struct sk_buff *skb) ++{ ++ mq_dump_common(sch, skb); ++ return 0; ++} ++ ++static int cake_mq_change(struct Qdisc *sch, struct nlattr *opt, ++ struct netlink_ext_ack *extack) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int cake_mq_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new, ++ struct Qdisc **old, struct netlink_ext_ack *extack) ++{ ++ NL_SET_ERR_MSG(extack, "can't replace cake_mq sub-qdiscs"); ++ return -EOPNOTSUPP; ++} ++ ++static const struct Qdisc_class_ops cake_mq_class_ops = { ++ .select_queue = mq_select_queue, ++ .graft = cake_mq_graft, ++ .leaf = mq_leaf, ++ .find = mq_find, ++ .walk = mq_walk, ++ .dump = mq_dump_class, ++ .dump_stats = mq_dump_class_stats, ++}; ++ ++static struct Qdisc_ops cake_mq_qdisc_ops __read_mostly = { ++ .cl_ops = &cake_mq_class_ops, ++ .id = "cake_mq", ++ .priv_size = sizeof(struct cake_mq_sched), ++ .init = cake_mq_init, ++ .destroy = cake_mq_destroy, ++ .attach = mq_attach, ++ .change = cake_mq_change, ++ .change_real_num_tx = mq_change_real_num_tx, ++ .dump = cake_mq_dump, ++ .owner = THIS_MODULE, ++}; ++MODULE_ALIAS_NET_SCH("cake_mq"); ++ + static int __init cake_module_init(void) + { +- return register_qdisc(&cake_qdisc_ops); ++ int ret; ++ ++ ret = register_qdisc(&cake_qdisc_ops); ++ if (ret) ++ return ret; ++ ++ ret = register_qdisc(&cake_mq_qdisc_ops); ++ if (ret) ++ unregister_qdisc(&cake_qdisc_ops); ++ ++ return ret; + } + + static void __exit cake_module_exit(void) + { + unregister_qdisc(&cake_qdisc_ops); ++ unregister_qdisc(&cake_mq_qdisc_ops); + } + + module_init(cake_module_init) +@@ -3169,3 +3245,4 @@ module_exit(cake_module_exit) + MODULE_AUTHOR("Jonathan Morton"); + MODULE_LICENSE("Dual BSD/GPL"); + MODULE_DESCRIPTION("The CAKE shaper."); ++MODULE_IMPORT_NS(NET_SCHED_INTERNAL); diff --git a/lede/target/linux/generic/backport-6.12/700-04-v7.0-net-sched-sch_cake-Share-config-across-cake_mq-sub-q.patch b/lede/target/linux/generic/backport-6.12/700-04-v7.0-net-sched-sch_cake-Share-config-across-cake_mq-sub-q.patch new file mode 100644 index 0000000000..e481ef9c0e --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/700-04-v7.0-net-sched-sch_cake-Share-config-across-cake_mq-sub-q.patch @@ -0,0 +1,318 @@ +From 68e71714d1e02ca388ea99defbe76061b7dd09a3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= +Date: Fri, 9 Jan 2026 14:15:33 +0100 +Subject: [PATCH 4/7] net/sched: sch_cake: Share config across cake_mq + sub-qdiscs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This adds support for configuring the cake_mq instance directly, sharing +the config across the cake sub-qdiscs. + +Signed-off-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260109-mq-cake-sub-qdisc-v8-4-8d613fece5d8@redhat.com +Signed-off-by: Paolo Abeni +--- + net/sched/sch_cake.c | 173 +++++++++++++++++++++++++++++++++---------- + 1 file changed, 133 insertions(+), 40 deletions(-) + +--- a/net/sched/sch_cake.c ++++ b/net/sched/sch_cake.c +@@ -212,6 +212,7 @@ struct cake_sched_config { + u8 flow_mode; + u8 atm_mode; + u8 ack_filter; ++ u8 is_shared; + }; + + struct cake_sched_data { +@@ -2586,14 +2587,12 @@ static void cake_reconfigure(struct Qdis + q->buffer_config_limit)); + } + +-static int cake_change(struct Qdisc *sch, struct nlattr *opt, +- struct netlink_ext_ack *extack) ++static int cake_config_change(struct cake_sched_config *q, struct nlattr *opt, ++ struct netlink_ext_ack *extack, bool *overhead_changed) + { +- struct cake_sched_data *qd = qdisc_priv(sch); +- struct cake_sched_config *q = qd->config; + struct nlattr *tb[TCA_CAKE_MAX + 1]; +- u16 rate_flags; +- u8 flow_mode; ++ u16 rate_flags = q->rate_flags; ++ u8 flow_mode = q->flow_mode; + int err; + + err = nla_parse_nested_deprecated(tb, TCA_CAKE_MAX, opt, cake_policy, +@@ -2601,7 +2600,6 @@ static int cake_change(struct Qdisc *sch + if (err < 0) + return err; + +- flow_mode = q->flow_mode; + if (tb[TCA_CAKE_NAT]) { + #if IS_ENABLED(CONFIG_NF_CONNTRACK) + flow_mode &= ~CAKE_FLOW_NAT_FLAG; +@@ -2614,6 +2612,19 @@ static int cake_change(struct Qdisc *sch + #endif + } + ++ if (tb[TCA_CAKE_AUTORATE]) { ++ if (!!nla_get_u32(tb[TCA_CAKE_AUTORATE])) { ++ if (q->is_shared) { ++ NL_SET_ERR_MSG_ATTR(extack, tb[TCA_CAKE_AUTORATE], ++ "Can't use autorate-ingress with cake_mq"); ++ return -EOPNOTSUPP; ++ } ++ rate_flags |= CAKE_FLAG_AUTORATE_INGRESS; ++ } else { ++ rate_flags &= ~CAKE_FLAG_AUTORATE_INGRESS; ++ } ++ } ++ + if (tb[TCA_CAKE_BASE_RATE64]) + WRITE_ONCE(q->rate_bps, + nla_get_u64(tb[TCA_CAKE_BASE_RATE64])); +@@ -2622,7 +2633,6 @@ static int cake_change(struct Qdisc *sch + WRITE_ONCE(q->tin_mode, + nla_get_u32(tb[TCA_CAKE_DIFFSERV_MODE])); + +- rate_flags = q->rate_flags; + if (tb[TCA_CAKE_WASH]) { + if (!!nla_get_u32(tb[TCA_CAKE_WASH])) + rate_flags |= CAKE_FLAG_WASH; +@@ -2643,20 +2653,12 @@ static int cake_change(struct Qdisc *sch + WRITE_ONCE(q->rate_overhead, + nla_get_s32(tb[TCA_CAKE_OVERHEAD])); + rate_flags |= CAKE_FLAG_OVERHEAD; +- +- qd->max_netlen = 0; +- qd->max_adjlen = 0; +- qd->min_netlen = ~0; +- qd->min_adjlen = ~0; ++ *overhead_changed = true; + } + + if (tb[TCA_CAKE_RAW]) { + rate_flags &= ~CAKE_FLAG_OVERHEAD; +- +- qd->max_netlen = 0; +- qd->max_adjlen = 0; +- qd->min_netlen = ~0; +- qd->min_adjlen = ~0; ++ *overhead_changed = true; + } + + if (tb[TCA_CAKE_MPU]) +@@ -2675,13 +2677,6 @@ static int cake_change(struct Qdisc *sch + WRITE_ONCE(q->target, max(target, 1U)); + } + +- if (tb[TCA_CAKE_AUTORATE]) { +- if (!!nla_get_u32(tb[TCA_CAKE_AUTORATE])) +- rate_flags |= CAKE_FLAG_AUTORATE_INGRESS; +- else +- rate_flags &= ~CAKE_FLAG_AUTORATE_INGRESS; +- } +- + if (tb[TCA_CAKE_INGRESS]) { + if (!!nla_get_u32(tb[TCA_CAKE_INGRESS])) + rate_flags |= CAKE_FLAG_INGRESS; +@@ -2712,6 +2707,34 @@ static int cake_change(struct Qdisc *sch + + WRITE_ONCE(q->rate_flags, rate_flags); + WRITE_ONCE(q->flow_mode, flow_mode); ++ ++ return 0; ++} ++ ++static int cake_change(struct Qdisc *sch, struct nlattr *opt, ++ struct netlink_ext_ack *extack) ++{ ++ struct cake_sched_data *qd = qdisc_priv(sch); ++ struct cake_sched_config *q = qd->config; ++ bool overhead_changed = false; ++ int ret; ++ ++ if (q->is_shared) { ++ NL_SET_ERR_MSG(extack, "can't reconfigure cake_mq sub-qdiscs"); ++ return -EOPNOTSUPP; ++ } ++ ++ ret = cake_config_change(q, opt, extack, &overhead_changed); ++ if (ret) ++ return ret; ++ ++ if (overhead_changed) { ++ qd->max_netlen = 0; ++ qd->max_adjlen = 0; ++ qd->min_netlen = ~0; ++ qd->min_adjlen = ~0; ++ } ++ + if (qd->tins) { + sch_tree_lock(sch); + cake_reconfigure(sch); +@@ -2728,7 +2751,23 @@ static void cake_destroy(struct Qdisc *s + qdisc_watchdog_cancel(&q->watchdog); + tcf_block_put(q->block); + kvfree(q->tins); +- kvfree(q->config); ++ if (q->config && !q->config->is_shared) ++ kvfree(q->config); ++} ++ ++static void cake_config_init(struct cake_sched_config *q, bool is_shared) ++{ ++ q->tin_mode = CAKE_DIFFSERV_DIFFSERV3; ++ q->flow_mode = CAKE_FLOW_TRIPLE; ++ ++ q->rate_bps = 0; /* unlimited by default */ ++ ++ q->interval = 100000; /* 100ms default */ ++ q->target = 5000; /* 5ms: codel RFC argues ++ * for 5 to 10% of interval ++ */ ++ q->rate_flags |= CAKE_FLAG_SPLIT_GSO; ++ q->is_shared = is_shared; + } + + static int cake_init(struct Qdisc *sch, struct nlattr *opt, +@@ -2742,17 +2781,9 @@ static int cake_init(struct Qdisc *sch, + if (!q) + return -ENOMEM; + +- sch->limit = 10240; +- q->tin_mode = CAKE_DIFFSERV_DIFFSERV3; +- q->flow_mode = CAKE_FLOW_TRIPLE; ++ cake_config_init(q, false); + +- q->rate_bps = 0; /* unlimited by default */ +- +- q->interval = 100000; /* 100ms default */ +- q->target = 5000; /* 5ms: codel RFC argues +- * for 5 to 10% of interval +- */ +- q->rate_flags |= CAKE_FLAG_SPLIT_GSO; ++ sch->limit = 10240; + qd->cur_tin = 0; + qd->cur_flow = 0; + qd->config = q; +@@ -2815,10 +2846,21 @@ err: + return err; + } + +-static int cake_dump(struct Qdisc *sch, struct sk_buff *skb) ++static void cake_config_replace(struct Qdisc *sch, struct cake_sched_config *cfg) + { + struct cake_sched_data *qd = qdisc_priv(sch); + struct cake_sched_config *q = qd->config; ++ ++ qd->config = cfg; ++ ++ if (!q->is_shared) ++ kvfree(q); ++ ++ cake_reconfigure(sch); ++} ++ ++static int cake_config_dump(struct cake_sched_config *q, struct sk_buff *skb) ++{ + struct nlattr *opts; + u16 rate_flags; + u8 flow_mode; +@@ -2894,6 +2936,13 @@ nla_put_failure: + return -1; + } + ++static int cake_dump(struct Qdisc *sch, struct sk_buff *skb) ++{ ++ struct cake_sched_data *qd = qdisc_priv(sch); ++ ++ return cake_config_dump(qd->config, skb); ++} ++ + static int cake_dump_stats(struct Qdisc *sch, struct gnet_dump *d) + { + struct nlattr *stats = nla_nest_start_noflag(d->skb, TCA_STATS_APP); +@@ -3157,6 +3206,7 @@ MODULE_ALIAS_NET_SCH("cake"); + + struct cake_mq_sched { + struct mq_sched mq_priv; /* must be first */ ++ struct cake_sched_config cake_config; + }; + + static void cake_mq_destroy(struct Qdisc *sch) +@@ -3167,25 +3217,68 @@ static void cake_mq_destroy(struct Qdisc + static int cake_mq_init(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) + { +- int ret; ++ struct cake_mq_sched *priv = qdisc_priv(sch); ++ struct net_device *dev = qdisc_dev(sch); ++ int ret, ntx; ++ bool _unused; ++ ++ cake_config_init(&priv->cake_config, true); ++ if (opt) { ++ ret = cake_config_change(&priv->cake_config, opt, extack, &_unused); ++ if (ret) ++ return ret; ++ } + + ret = mq_init_common(sch, opt, extack, &cake_qdisc_ops); + if (ret) + return ret; + ++ for (ntx = 0; ntx < dev->num_tx_queues; ntx++) ++ cake_config_replace(priv->mq_priv.qdiscs[ntx], &priv->cake_config); ++ + return 0; + } + + static int cake_mq_dump(struct Qdisc *sch, struct sk_buff *skb) + { ++ struct cake_mq_sched *priv = qdisc_priv(sch); ++ + mq_dump_common(sch, skb); +- return 0; ++ return cake_config_dump(&priv->cake_config, skb); + } + + static int cake_mq_change(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) + { +- return -EOPNOTSUPP; ++ struct cake_mq_sched *priv = qdisc_priv(sch); ++ struct net_device *dev = qdisc_dev(sch); ++ bool overhead_changed = false; ++ unsigned int ntx; ++ int ret; ++ ++ ret = cake_config_change(&priv->cake_config, opt, extack, &overhead_changed); ++ if (ret) ++ return ret; ++ ++ for (ntx = 0; ntx < dev->num_tx_queues; ntx++) { ++ struct Qdisc *chld = rtnl_dereference(netdev_get_tx_queue(dev, ntx)->qdisc_sleeping); ++ struct cake_sched_data *qd = qdisc_priv(chld); ++ ++ if (overhead_changed) { ++ qd->max_netlen = 0; ++ qd->max_adjlen = 0; ++ qd->min_netlen = ~0; ++ qd->min_adjlen = ~0; ++ } ++ ++ if (qd->tins) { ++ sch_tree_lock(chld); ++ cake_reconfigure(chld); ++ sch_tree_unlock(chld); ++ } ++ } ++ ++ return 0; + } + + static int cake_mq_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new, diff --git a/lede/target/linux/generic/backport-6.12/700-05-v7.0-net-sched-sch_cake-share-shaper-state-across-sub-ins.patch b/lede/target/linux/generic/backport-6.12/700-05-v7.0-net-sched-sch_cake-share-shaper-state-across-sub-ins.patch new file mode 100644 index 0000000000..62bf38d35d --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/700-05-v7.0-net-sched-sch_cake-share-shaper-state-across-sub-ins.patch @@ -0,0 +1,175 @@ +From 090dde0780266eb80126fa970870bafdb4e937c3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20K=C3=B6ppeler?= +Date: Fri, 9 Jan 2026 14:15:34 +0100 +Subject: [PATCH 5/7] net/sched: sch_cake: share shaper state across + sub-instances of cake_mq +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit adds shared shaper state across the cake instances beneath a +cake_mq qdisc. It works by periodically tracking the number of active +instances, and scaling the configured rate by the number of active +queues. + +The scan is lockless and simply reads the qlen and the last_active state +variable of each of the instances configured beneath the parent cake_mq +instance. Locking is not required since the values are only updated by +the owning instance, and eventual consistency is sufficient for the +purpose of estimating the number of active queues. + +The interval for scanning the number of active queues is set to 200 us. +We found this to be a good tradeoff between overhead and response time. +For a detailed analysis of this aspect see the Netdevconf talk: + +https://netdevconf.info/0x19/docs/netdev-0x19-paper16-talk-paper.pdf + +Reviewed-by: Jamal Hadi Salim +Signed-off-by: Jonas Köppeler +Signed-off-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260109-mq-cake-sub-qdisc-v8-5-8d613fece5d8@redhat.com +Signed-off-by: Paolo Abeni +--- + Documentation/netlink/specs/tc.yaml | 3 ++ + include/uapi/linux/pkt_sched.h | 1 + + net/sched/sch_cake.c | 51 +++++++++++++++++++++++++++++ + 3 files changed, 55 insertions(+) + +--- a/Documentation/netlink/specs/tc.yaml ++++ b/Documentation/netlink/specs/tc.yaml +@@ -2161,6 +2161,9 @@ attribute-sets: + - + name: blue-timer-us + type: s32 ++ - ++ name: active-queues ++ type: u32 + - + name: tc-cake-tin-stats-attrs + attributes: +--- a/include/uapi/linux/pkt_sched.h ++++ b/include/uapi/linux/pkt_sched.h +@@ -1034,6 +1034,7 @@ enum { + TCA_CAKE_STATS_DROP_NEXT_US, + TCA_CAKE_STATS_P_DROP, + TCA_CAKE_STATS_BLUE_TIMER_US, ++ TCA_CAKE_STATS_ACTIVE_QUEUES, + __TCA_CAKE_STATS_MAX + }; + #define TCA_CAKE_STATS_MAX (__TCA_CAKE_STATS_MAX - 1) +--- a/net/sched/sch_cake.c ++++ b/net/sched/sch_cake.c +@@ -202,6 +202,7 @@ struct cake_sched_config { + u64 rate_bps; + u64 interval; + u64 target; ++ u64 sync_time; + u32 buffer_config_limit; + u32 fwmark_mask; + u16 fwmark_shft; +@@ -258,6 +259,11 @@ struct cake_sched_data { + u16 max_adjlen; + u16 min_netlen; + u16 min_adjlen; ++ ++ /* mq sync state */ ++ u64 last_checked_active; ++ u64 last_active; ++ u32 active_queues; + }; + + enum { +@@ -384,6 +390,8 @@ static const u32 inv_sqrt_cache[REC_INV_ + 1239850263, 1191209601, 1147878294, 1108955788 + }; + ++static void cake_set_rate(struct cake_tin_data *b, u64 rate, u32 mtu, ++ u64 target_ns, u64 rtt_est_ns); + /* http://en.wikipedia.org/wiki/Methods_of_computing_square_roots + * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2) + * +@@ -2003,6 +2011,40 @@ static struct sk_buff *cake_dequeue(stru + u64 delay; + u32 len; + ++ if (q->config->is_shared && now - q->last_checked_active >= q->config->sync_time) { ++ struct net_device *dev = qdisc_dev(sch); ++ struct cake_sched_data *other_priv; ++ u64 new_rate = q->config->rate_bps; ++ u64 other_qlen, other_last_active; ++ struct Qdisc *other_sch; ++ u32 num_active_qs = 1; ++ unsigned int ntx; ++ ++ for (ntx = 0; ntx < dev->num_tx_queues; ntx++) { ++ other_sch = rcu_dereference(netdev_get_tx_queue(dev, ntx)->qdisc_sleeping); ++ other_priv = qdisc_priv(other_sch); ++ ++ if (other_priv == q) ++ continue; ++ ++ other_qlen = READ_ONCE(other_sch->q.qlen); ++ other_last_active = READ_ONCE(other_priv->last_active); ++ ++ if (other_qlen || other_last_active > q->last_checked_active) ++ num_active_qs++; ++ } ++ ++ if (num_active_qs > 1) ++ new_rate = div64_u64(q->config->rate_bps, num_active_qs); ++ ++ /* mtu = 0 is used to only update the rate and not mess with cobalt params */ ++ cake_set_rate(b, new_rate, 0, 0, 0); ++ q->last_checked_active = now; ++ q->active_queues = num_active_qs; ++ q->rate_ns = b->tin_rate_ns; ++ q->rate_shft = b->tin_rate_shft; ++ } ++ + begin: + if (!sch->q.qlen) + return NULL; +@@ -2202,6 +2244,7 @@ retry: + + b->tin_ecn_mark += !!flow->cvars.ecn_marked; + qdisc_bstats_update(sch, skb); ++ WRITE_ONCE(q->last_active, now); + + /* collect delay stats */ + delay = ktime_to_ns(ktime_sub(now, cobalt_get_enqueue_time(skb))); +@@ -2302,6 +2345,9 @@ static void cake_set_rate(struct cake_ti + b->tin_rate_ns = rate_ns; + b->tin_rate_shft = rate_shft; + ++ if (mtu == 0) ++ return; ++ + byte_target_ns = (byte_target * rate_ns) >> rate_shft; + + b->cparams.target = max((byte_target_ns * 3) / 2, target_ns); +@@ -2768,6 +2814,7 @@ static void cake_config_init(struct cake + */ + q->rate_flags |= CAKE_FLAG_SPLIT_GSO; + q->is_shared = is_shared; ++ q->sync_time = 200 * NSEC_PER_USEC; + } + + static int cake_init(struct Qdisc *sch, struct nlattr *opt, +@@ -2839,6 +2886,9 @@ static int cake_init(struct Qdisc *sch, + qd->avg_peak_bandwidth = q->rate_bps; + qd->min_netlen = ~0; + qd->min_adjlen = ~0; ++ qd->active_queues = 0; ++ qd->last_checked_active = 0; ++ + return 0; + err: + kvfree(qd->config); +@@ -2971,6 +3021,7 @@ static int cake_dump_stats(struct Qdisc + PUT_STAT_U32(MAX_ADJLEN, q->max_adjlen); + PUT_STAT_U32(MIN_NETLEN, q->min_netlen); + PUT_STAT_U32(MIN_ADJLEN, q->min_adjlen); ++ PUT_STAT_U32(ACTIVE_QUEUES, q->active_queues); + + #undef PUT_STAT_U32 + #undef PUT_STAT_U64 diff --git a/lede/target/linux/generic/backport-6.12/700-06-v7.0-selftests-tc-testing-add-selftests-for-cake_mq-qdisc.patch b/lede/target/linux/generic/backport-6.12/700-06-v7.0-selftests-tc-testing-add-selftests-for-cake_mq-qdisc.patch new file mode 100644 index 0000000000..c012a15884 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/700-06-v7.0-selftests-tc-testing-add-selftests-for-cake_mq-qdisc.patch @@ -0,0 +1,606 @@ +From e5e7c7c6a027ce2f001fc60dc388a560c01427fd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20K=C3=B6ppeler?= +Date: Fri, 9 Jan 2026 14:15:35 +0100 +Subject: [PATCH 6/7] selftests/tc-testing: add selftests for cake_mq qdisc +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Test 684b: Create CAKE_MQ with default setting (4 queues) +Test 7ee8: Create CAKE_MQ with bandwidth limit (4 queues) +Test 1f87: Create CAKE_MQ with rtt time (4 queues) +Test e9cf: Create CAKE_MQ with besteffort flag (4 queues) +Test 7c05: Create CAKE_MQ with diffserv8 flag (4 queues) +Test 5a77: Create CAKE_MQ with diffserv4 flag (4 queues) +Test 8f7a: Create CAKE_MQ with flowblind flag (4 queues) +Test 7ef7: Create CAKE_MQ with dsthost and nat flag (4 queues) +Test 2e4d: Create CAKE_MQ with wash flag (4 queues) +Test b3e6: Create CAKE_MQ with flowblind and no-split-gso flag (4 queues) +Test 62cd: Create CAKE_MQ with dual-srchost and ack-filter flag (4 queues) +Test 0df3: Create CAKE_MQ with dual-dsthost and ack-filter-aggressive flag (4 queues) +Test 9a75: Create CAKE_MQ with memlimit and ptm flag (4 queues) +Test cdef: Create CAKE_MQ with fwmark and atm flag (4 queues) +Test 93dd: Create CAKE_MQ with overhead 0 and mpu (4 queues) +Test 1475: Create CAKE_MQ with conservative and ingress flag (4 queues) +Test 7bf1: Delete CAKE_MQ with conservative and ingress flag (4 queues) +Test ee55: Replace CAKE_MQ with mpu (4 queues) +Test 6df9: Change CAKE_MQ with mpu (4 queues) +Test 67e2: Show CAKE_MQ class (4 queues) +Test 2de4: Change bandwidth of CAKE_MQ (4 queues) +Test 5f62: Fail to create CAKE_MQ with autorate-ingress flag (4 queues) +Test 038e: Fail to change setting of sub-qdisc under CAKE_MQ +Test 7bdc: Fail to replace sub-qdisc under CAKE_MQ +Test 18e0: Fail to install CAKE_MQ on single queue device + +Reviewed-by: Victor Nogueira +Signed-off-by: Jonas Köppeler +Signed-off-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260109-mq-cake-sub-qdisc-v8-6-8d613fece5d8@redhat.com +Signed-off-by: Paolo Abeni +--- + .../tc-testing/tc-tests/qdiscs/cake_mq.json | 559 ++++++++++++++++++ + 1 file changed, 559 insertions(+) + create mode 100644 tools/testing/selftests/tc-testing/tc-tests/qdiscs/cake_mq.json + +--- /dev/null ++++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/cake_mq.json +@@ -0,0 +1,559 @@ ++[ ++ { ++ "id": "684b", ++ "name": "Create CAKE_MQ with default setting (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device || true", ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "7ee8", ++ "name": "Create CAKE_MQ with bandwidth limit (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq bandwidth 1000", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth 1Kbit diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "1f87", ++ "name": "Create CAKE_MQ with rtt time (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq rtt 200", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 200us raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "e9cf", ++ "name": "Create CAKE_MQ with besteffort flag (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq besteffort", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited besteffort triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "7c05", ++ "name": "Create CAKE_MQ with diffserv8 flag (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq diffserv8", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv8 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "5a77", ++ "name": "Create CAKE_MQ with diffserv4 flag (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq diffserv4", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv4 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "8f7a", ++ "name": "Create CAKE_MQ with flowblind flag (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq flowblind", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 flowblind nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "7ef7", ++ "name": "Create CAKE_MQ with dsthost and nat flag (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq dsthost nat", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 dsthost nat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "2e4d", ++ "name": "Create CAKE_MQ with wash flag (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq hosts wash", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 hosts nonat wash no-ack-filter split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "b3e6", ++ "name": "Create CAKE_MQ with flowblind and no-split-gso flag (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq flowblind no-split-gso", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 flowblind nonat nowash no-ack-filter no-split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "62cd", ++ "name": "Create CAKE_MQ with dual-srchost and ack-filter flag (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq dual-srchost ack-filter", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 dual-srchost nonat nowash ack-filter split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "0df3", ++ "name": "Create CAKE_MQ with dual-dsthost and ack-filter-aggressive flag (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq dual-dsthost ack-filter-aggressive", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 dual-dsthost nonat nowash ack-filter-aggressive split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "9a75", ++ "name": "Create CAKE_MQ with memlimit and ptm flag (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq memlimit 10000 ptm", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw ptm overhead 0 memlimit 10000b ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "cdef", ++ "name": "Create CAKE_MQ with fwmark and atm flag (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq fwmark 8 atm", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw atm overhead 0 fwmark 0x8 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "93dd", ++ "name": "Create CAKE_MQ with overhead 0 and mpu (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq overhead 128 mpu 256", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms noatm overhead 128 mpu 256 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "1475", ++ "name": "Create CAKE_MQ with conservative and ingress flag (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq conservative ingress", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash ingress no-ack-filter split-gso rtt 100ms atm overhead 48 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "7bf1", ++ "name": "Delete CAKE_MQ with conservative and ingress flag (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device", ++ "$TC qdisc add dev $ETH handle 1: root cake_mq conservative ingress" ++ ], ++ "cmdUnderTest": "$TC qdisc del dev $ETH handle 1: root", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash ingress no-ack-filter split-gso rtt 100ms atm overhead 48 ", ++ "matchCount": "0", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "ee55", ++ "name": "Replace CAKE_MQ with mpu (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device", ++ "$TC qdisc add dev $ETH handle 1: root cake_mq overhead 128 mpu 256" ++ ], ++ "cmdUnderTest": "$TC qdisc replace dev $ETH handle 1: root cake_mq mpu 128", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms noatm overhead 128 mpu 128 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "6df9", ++ "name": "Change CAKE_MQ with mpu (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device", ++ "$TC qdisc add dev $ETH handle 1: root cake_mq overhead 128 mpu 256" ++ ], ++ "cmdUnderTest": "$TC qdisc change dev $ETH handle 1: root cake_mq mpu 128", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms noatm overhead 128 mpu 128 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "67e2", ++ "name": "Show CAKE_MQ class (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq", ++ "expExitCode": "0", ++ "verifyCmd": "$TC class show dev $ETH", ++ "matchPattern": "class cake_mq", ++ "matchCount": "4", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "2de4", ++ "name": "Change bandwidth of CAKE_MQ (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device", ++ "$TC qdisc add dev $ETH handle 1: root cake_mq" ++ ], ++ "cmdUnderTest": "$TC qdisc replace dev $ETH handle 1: root cake_mq bandwidth 1000", ++ "expExitCode": "0", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth 1Kbit diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "5f62", ++ "name": "Fail to create CAKE_MQ with autorate-ingress flag (4 queues)", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq autorate-ingress", ++ "expExitCode": "2", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited autorate-ingress diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "0", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "038e", ++ "name": "Fail to change setting of sub-qdisc under CAKE_MQ", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device", ++ "$TC qdisc add dev $ETH handle 1: root cake_mq" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH parent 1:1 cake besteffort flows", ++ "expExitCode": "2", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "7bdc", ++ "name": "Fail to replace sub-qdisc under CAKE_MQ", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 4\" > /sys/bus/netdevsim/new_device", ++ "$TC qdisc add dev $ETH handle 1: root cake_mq" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH parent 1:1 fq", ++ "expExitCode": "2", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "5", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "18e0", ++ "name": "Fail to install CAKE_MQ on single queue device", ++ "category": [ ++ "qdisc", ++ "cake_mq" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 1\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH handle 1: root cake_mq", ++ "expExitCode": "2", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc (cake_mq 1: root|cake 0: parent 1:[1-4]) bandwidth unlimited diffserv3 triple-isolate nonat nowash no-ack-filter split-gso rtt 100ms raw overhead 0 ", ++ "matchCount": "0", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ } ++] diff --git a/lede/target/linux/generic/backport-6.12/700-07-v7.0-net-sched-cake-avoid-separate-allocation-of-struct-c.patch b/lede/target/linux/generic/backport-6.12/700-07-v7.0-net-sched-cake-avoid-separate-allocation-of-struct-c.patch new file mode 100644 index 0000000000..1ba4cd3bc4 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/700-07-v7.0-net-sched-cake-avoid-separate-allocation-of-struct-c.patch @@ -0,0 +1,112 @@ +From 060969bc048d2f85149b7f1a8bbb56e6b1434cae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= +Date: Tue, 13 Jan 2026 15:31:56 +0100 +Subject: [PATCH 7/7] net/sched: cake: avoid separate allocation of struct + cake_sched_config +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Paolo pointed out that we can avoid separately allocating struct +cake_sched_config even in the non-mq case, by embedding it into struct +cake_sched_data. This reduces the complexity of the logic that swaps the +pointers and frees the old value, at the cost of adding 56 bytes to the +latter. Since cake_sched_data is already almost 17k bytes, this seems +like a reasonable tradeoff. + +Suggested-by: Paolo Abeni +Signed-off-by: Toke Høiland-Jørgensen +Fixes: bc0ce2bad36c ("net/sched: sch_cake: Factor out config variables into separate struct") +Link: https://patch.msgid.link/20260113143157.2581680-1-toke@redhat.com +Signed-off-by: Jakub Kicinski +--- + net/sched/sch_cake.c | 29 ++++++----------------------- + 1 file changed, 6 insertions(+), 23 deletions(-) + +--- a/net/sched/sch_cake.c ++++ b/net/sched/sch_cake.c +@@ -221,6 +221,7 @@ struct cake_sched_data { + struct tcf_block *block; + struct cake_tin_data *tins; + struct cake_sched_config *config; ++ struct cake_sched_config initial_config; + + struct cake_heap_entry overflow_heap[CAKE_QUEUES * CAKE_MAX_TINS]; + +@@ -2797,8 +2798,6 @@ static void cake_destroy(struct Qdisc *s + qdisc_watchdog_cancel(&q->watchdog); + tcf_block_put(q->block); + kvfree(q->tins); +- if (q->config && !q->config->is_shared) +- kvfree(q->config); + } + + static void cake_config_init(struct cake_sched_config *q, bool is_shared) +@@ -2821,13 +2820,9 @@ static int cake_init(struct Qdisc *sch, + struct netlink_ext_ack *extack) + { + struct cake_sched_data *qd = qdisc_priv(sch); +- struct cake_sched_config *q; ++ struct cake_sched_config *q = &qd->initial_config; + int i, j, err; + +- q = kzalloc(sizeof(*q), GFP_KERNEL); +- if (!q) +- return -ENOMEM; +- + cake_config_init(q, false); + + sch->limit = 10240; +@@ -2839,14 +2834,13 @@ static int cake_init(struct Qdisc *sch, + + if (opt) { + err = cake_change(sch, opt, extack); +- + if (err) +- goto err; ++ return err; + } + + err = tcf_block_get(&qd->block, &qd->filter_list, sch, extack); + if (err) +- goto err; ++ return err; + + quantum_div[0] = ~0; + for (i = 1; i <= CAKE_QUEUES; i++) +@@ -2854,10 +2848,8 @@ static int cake_init(struct Qdisc *sch, + + qd->tins = kvcalloc(CAKE_MAX_TINS, sizeof(struct cake_tin_data), + GFP_KERNEL); +- if (!qd->tins) { +- err = -ENOMEM; +- goto err; +- } ++ if (!qd->tins) ++ return -ENOMEM; + + for (i = 0; i < CAKE_MAX_TINS; i++) { + struct cake_tin_data *b = qd->tins + i; +@@ -2890,22 +2882,13 @@ static int cake_init(struct Qdisc *sch, + qd->last_checked_active = 0; + + return 0; +-err: +- kvfree(qd->config); +- qd->config = NULL; +- return err; + } + + static void cake_config_replace(struct Qdisc *sch, struct cake_sched_config *cfg) + { + struct cake_sched_data *qd = qdisc_priv(sch); +- struct cake_sched_config *q = qd->config; + + qd->config = cfg; +- +- if (!q->is_shared) +- kvfree(q); +- + cake_reconfigure(sch); + } + diff --git a/lede/target/linux/generic/backport-6.12/701-01-v7.0-net-sched-sch_cake-avoid-sync-overhead-when-unlimite.patch b/lede/target/linux/generic/backport-6.12/701-01-v7.0-net-sched-sch_cake-avoid-sync-overhead-when-unlimite.patch new file mode 100644 index 0000000000..60a003c1de --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/701-01-v7.0-net-sched-sch_cake-avoid-sync-overhead-when-unlimite.patch @@ -0,0 +1,32 @@ +From 0b3cd139be565b85f4a3579e376152b9def6256a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20K=C3=B6ppeler?= +Date: Thu, 26 Feb 2026 12:40:15 +0100 +Subject: [PATCH] net/sched: sch_cake: avoid sync overhead when unlimited +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Skip inter-instance sync when no rate limit is configured, as it serves +no purpose and only adds overhead. + +Fixes: 1bddd758bac2 ("net/sched: sch_cake: share shaper state across sub-instances of cake_mq") +Signed-off-by: Jonas Köppeler +Acked-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260226-cake-mq-skip-sync-bandwidth-unlimited-v1-1-01830bb4db87@tu-berlin.de +Signed-off-by: Jakub Kicinski +--- + net/sched/sch_cake.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/sched/sch_cake.c ++++ b/net/sched/sch_cake.c +@@ -2012,7 +2012,8 @@ static struct sk_buff *cake_dequeue(stru + u64 delay; + u32 len; + +- if (q->config->is_shared && now - q->last_checked_active >= q->config->sync_time) { ++ if (q->config->is_shared && q->rate_ns && ++ now - q->last_checked_active >= q->config->sync_time) { + struct net_device *dev = qdisc_dev(sch); + struct cake_sched_data *other_priv; + u64 new_rate = q->config->rate_bps; diff --git a/lede/target/linux/generic/backport-6.12/701-02-v7.0-net-sched-sch_cake-fixup-cake_mq-rate-adjustment-for.patch b/lede/target/linux/generic/backport-6.12/701-02-v7.0-net-sched-sch_cake-fixup-cake_mq-rate-adjustment-for.patch new file mode 100644 index 0000000000..357f6b6736 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/701-02-v7.0-net-sched-sch_cake-fixup-cake_mq-rate-adjustment-for.patch @@ -0,0 +1,187 @@ +From 15c2715a52645fd8e6e18b7abc3449292d118c7c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20K=C3=B6ppeler?= +Date: Thu, 26 Feb 2026 12:40:16 +0100 +Subject: [PATCH] net/sched: sch_cake: fixup cake_mq rate adjustment for + diffserv config +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cake_mq's rate adjustment during the sync periods did not adjust the +rates for every tin in a diffserv config. This lead to inconsistencies +of rates between the tins. Fix this by setting the rates for all tins +during synchronization. + +Fixes: 1bddd758bac2 ("net/sched: sch_cake: share shaper state across sub-instances of cake_mq") +Signed-off-by: Jonas Köppeler +Acked-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260226-cake-mq-skip-sync-bandwidth-unlimited-v1-2-01830bb4db87@tu-berlin.de +Signed-off-by: Jakub Kicinski +--- + net/sched/sch_cake.c | 50 ++++++++++++++++++++------------------------ + 1 file changed, 23 insertions(+), 27 deletions(-) + +--- a/net/sched/sch_cake.c ++++ b/net/sched/sch_cake.c +@@ -391,8 +391,8 @@ static const u32 inv_sqrt_cache[REC_INV_ + 1239850263, 1191209601, 1147878294, 1108955788 + }; + +-static void cake_set_rate(struct cake_tin_data *b, u64 rate, u32 mtu, +- u64 target_ns, u64 rtt_est_ns); ++static void cake_configure_rates(struct Qdisc *sch, u64 rate, bool rate_adjust); ++ + /* http://en.wikipedia.org/wiki/Methods_of_computing_square_roots + * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2) + * +@@ -2039,12 +2039,9 @@ static struct sk_buff *cake_dequeue(stru + if (num_active_qs > 1) + new_rate = div64_u64(q->config->rate_bps, num_active_qs); + +- /* mtu = 0 is used to only update the rate and not mess with cobalt params */ +- cake_set_rate(b, new_rate, 0, 0, 0); ++ cake_configure_rates(sch, new_rate, true); + q->last_checked_active = now; + q->active_queues = num_active_qs; +- q->rate_ns = b->tin_rate_ns; +- q->rate_shft = b->tin_rate_shft; + } + + begin: +@@ -2361,12 +2358,10 @@ static void cake_set_rate(struct cake_ti + b->cparams.p_dec = 1 << 20; /* 1/4096 */ + } + +-static int cake_config_besteffort(struct Qdisc *sch) ++static int cake_config_besteffort(struct Qdisc *sch, u64 rate, u32 mtu) + { + struct cake_sched_data *q = qdisc_priv(sch); + struct cake_tin_data *b = &q->tins[0]; +- u32 mtu = psched_mtu(qdisc_dev(sch)); +- u64 rate = q->config->rate_bps; + + q->tin_cnt = 1; + +@@ -2380,12 +2375,10 @@ static int cake_config_besteffort(struct + return 0; + } + +-static int cake_config_precedence(struct Qdisc *sch) ++static int cake_config_precedence(struct Qdisc *sch, u64 rate, u32 mtu) + { + /* convert high-level (user visible) parameters into internal format */ + struct cake_sched_data *q = qdisc_priv(sch); +- u32 mtu = psched_mtu(qdisc_dev(sch)); +- u64 rate = q->config->rate_bps; + u32 quantum = 256; + u32 i; + +@@ -2456,7 +2449,7 @@ static int cake_config_precedence(struct + * Total 12 traffic classes. + */ + +-static int cake_config_diffserv8(struct Qdisc *sch) ++static int cake_config_diffserv8(struct Qdisc *sch, u64 rate, u32 mtu) + { + /* Pruned list of traffic classes for typical applications: + * +@@ -2473,8 +2466,6 @@ static int cake_config_diffserv8(struct + */ + + struct cake_sched_data *q = qdisc_priv(sch); +- u32 mtu = psched_mtu(qdisc_dev(sch)); +- u64 rate = q->config->rate_bps; + u32 quantum = 256; + u32 i; + +@@ -2504,7 +2495,7 @@ static int cake_config_diffserv8(struct + return 0; + } + +-static int cake_config_diffserv4(struct Qdisc *sch) ++static int cake_config_diffserv4(struct Qdisc *sch, u64 rate, u32 mtu) + { + /* Further pruned list of traffic classes for four-class system: + * +@@ -2517,8 +2508,6 @@ static int cake_config_diffserv4(struct + */ + + struct cake_sched_data *q = qdisc_priv(sch); +- u32 mtu = psched_mtu(qdisc_dev(sch)); +- u64 rate = q->config->rate_bps; + u32 quantum = 1024; + + q->tin_cnt = 4; +@@ -2546,7 +2535,7 @@ static int cake_config_diffserv4(struct + return 0; + } + +-static int cake_config_diffserv3(struct Qdisc *sch) ++static int cake_config_diffserv3(struct Qdisc *sch, u64 rate, u32 mtu) + { + /* Simplified Diffserv structure with 3 tins. + * Latency Sensitive (CS7, CS6, EF, VA, TOS4) +@@ -2554,8 +2543,6 @@ static int cake_config_diffserv3(struct + * Low Priority (LE, CS1) + */ + struct cake_sched_data *q = qdisc_priv(sch); +- u32 mtu = psched_mtu(qdisc_dev(sch)); +- u64 rate = q->config->rate_bps; + u32 quantum = 1024; + + q->tin_cnt = 3; +@@ -2580,32 +2567,33 @@ static int cake_config_diffserv3(struct + return 0; + } + +-static void cake_reconfigure(struct Qdisc *sch) ++static void cake_configure_rates(struct Qdisc *sch, u64 rate, bool rate_adjust) + { ++ u32 mtu = likely(rate_adjust) ? 0 : psched_mtu(qdisc_dev(sch)); + struct cake_sched_data *qd = qdisc_priv(sch); + struct cake_sched_config *q = qd->config; + int c, ft; + + switch (q->tin_mode) { + case CAKE_DIFFSERV_BESTEFFORT: +- ft = cake_config_besteffort(sch); ++ ft = cake_config_besteffort(sch, rate, mtu); + break; + + case CAKE_DIFFSERV_PRECEDENCE: +- ft = cake_config_precedence(sch); ++ ft = cake_config_precedence(sch, rate, mtu); + break; + + case CAKE_DIFFSERV_DIFFSERV8: +- ft = cake_config_diffserv8(sch); ++ ft = cake_config_diffserv8(sch, rate, mtu); + break; + + case CAKE_DIFFSERV_DIFFSERV4: +- ft = cake_config_diffserv4(sch); ++ ft = cake_config_diffserv4(sch, rate, mtu); + break; + + case CAKE_DIFFSERV_DIFFSERV3: + default: +- ft = cake_config_diffserv3(sch); ++ ft = cake_config_diffserv3(sch, rate, mtu); + break; + } + +@@ -2616,6 +2604,14 @@ static void cake_reconfigure(struct Qdis + + qd->rate_ns = qd->tins[ft].tin_rate_ns; + qd->rate_shft = qd->tins[ft].tin_rate_shft; ++} ++ ++static void cake_reconfigure(struct Qdisc *sch) ++{ ++ struct cake_sched_data *qd = qdisc_priv(sch); ++ struct cake_sched_config *q = qd->config; ++ ++ cake_configure_rates(sch, qd->config->rate_bps, false); + + if (q->buffer_config_limit) { + qd->buffer_limit = q->buffer_config_limit; diff --git a/lede/target/linux/generic/backport-6.12/792-v6.16-igc-enable-HW-vlan-tag-insertion-stripping-by-defaul.patch b/lede/target/linux/generic/backport-6.12/710-v6.16-igc-enable-HW-vlan-tag-insertion-stripping-by-defaul.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/792-v6.16-igc-enable-HW-vlan-tag-insertion-stripping-by-defaul.patch rename to lede/target/linux/generic/backport-6.12/710-v6.16-igc-enable-HW-vlan-tag-insertion-stripping-by-defaul.patch diff --git a/lede/target/linux/generic/backport-6.12/720-v6.13-net-phy-mediatek-ge-soc-Fix-coding-style.patch b/lede/target/linux/generic/backport-6.12/720-01-v6.13-net-phy-mediatek-ge-soc-Fix-coding-style.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/720-v6.13-net-phy-mediatek-ge-soc-Fix-coding-style.patch rename to lede/target/linux/generic/backport-6.12/720-01-v6.13-net-phy-mediatek-ge-soc-Fix-coding-style.patch diff --git a/lede/target/linux/generic/backport-6.12/721-v6.13-net-phy-mediatek-ge-soc-Shrink-line-wrapping-to-80-c.patch b/lede/target/linux/generic/backport-6.12/720-02-v6.13-net-phy-mediatek-ge-soc-Shrink-line-wrapping-to-80-c.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/721-v6.13-net-phy-mediatek-ge-soc-Shrink-line-wrapping-to-80-c.patch rename to lede/target/linux/generic/backport-6.12/720-02-v6.13-net-phy-mediatek-ge-soc-Shrink-line-wrapping-to-80-c.patch diff --git a/lede/target/linux/generic/backport-6.12/722-v6.13-net-phy-mediatek-ge-soc-Propagate-error-code-correct.patch b/lede/target/linux/generic/backport-6.12/720-03-v6.13-net-phy-mediatek-ge-soc-Propagate-error-code-correct.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/722-v6.13-net-phy-mediatek-ge-soc-Propagate-error-code-correct.patch rename to lede/target/linux/generic/backport-6.12/720-03-v6.13-net-phy-mediatek-ge-soc-Propagate-error-code-correct.patch diff --git a/lede/target/linux/generic/backport-6.12/723-v6.13-net-phy-mediatek-Re-organize-MediaTek-ethernet-phy-d.patch b/lede/target/linux/generic/backport-6.12/720-04-v6.13-net-phy-mediatek-Re-organize-MediaTek-ethernet-phy-d.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/723-v6.13-net-phy-mediatek-Re-organize-MediaTek-ethernet-phy-d.patch rename to lede/target/linux/generic/backport-6.12/720-04-v6.13-net-phy-mediatek-Re-organize-MediaTek-ethernet-phy-d.patch diff --git a/lede/target/linux/generic/backport-6.12/724-v6.13-net-phy-mediatek-Move-LED-helper-functions-into-mtk-.patch b/lede/target/linux/generic/backport-6.12/720-05-v6.13-net-phy-mediatek-Move-LED-helper-functions-into-mtk-.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/724-v6.13-net-phy-mediatek-Move-LED-helper-functions-into-mtk-.patch rename to lede/target/linux/generic/backport-6.12/720-05-v6.13-net-phy-mediatek-Move-LED-helper-functions-into-mtk-.patch diff --git a/lede/target/linux/generic/backport-6.12/725-v6.13-net-phy-mediatek-Improve-readability-of-mtk-phy-lib..patch b/lede/target/linux/generic/backport-6.12/720-06-v6.13-net-phy-mediatek-Improve-readability-of-mtk-phy-lib..patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/725-v6.13-net-phy-mediatek-Improve-readability-of-mtk-phy-lib..patch rename to lede/target/linux/generic/backport-6.12/720-06-v6.13-net-phy-mediatek-Improve-readability-of-mtk-phy-lib..patch diff --git a/lede/target/linux/generic/backport-6.12/726-v6.13-net-phy-mediatek-Integrate-read-write-page-helper-fu.patch b/lede/target/linux/generic/backport-6.12/720-07-v6.13-net-phy-mediatek-Integrate-read-write-page-helper-fu.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/726-v6.13-net-phy-mediatek-Integrate-read-write-page-helper-fu.patch rename to lede/target/linux/generic/backport-6.12/720-07-v6.13-net-phy-mediatek-Integrate-read-write-page-helper-fu.patch diff --git a/lede/target/linux/generic/backport-6.12/727-v6.13-net-phy-mediatek-add-MT7530-MT7531-s-PHY-ID-macros.patch b/lede/target/linux/generic/backport-6.12/720-08-v6.13-net-phy-mediatek-add-MT7530-MT7531-s-PHY-ID-macros.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/727-v6.13-net-phy-mediatek-add-MT7530-MT7531-s-PHY-ID-macros.patch rename to lede/target/linux/generic/backport-6.12/720-08-v6.13-net-phy-mediatek-add-MT7530-MT7531-s-PHY-ID-macros.patch diff --git a/lede/target/linux/generic/backport-6.12/728-v6.14-net-phy-Constify-struct-mdio_device_id.patch b/lede/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch similarity index 99% rename from lede/target/linux/generic/backport-6.12/728-v6.14-net-phy-Constify-struct-mdio_device_id.patch rename to lede/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch index 6b85e59577..c0c840d3af 100644 --- a/lede/target/linux/generic/backport-6.12/728-v6.14-net-phy-Constify-struct-mdio_device_id.patch +++ b/lede/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch @@ -194,7 +194,7 @@ Signed-off-by: Jakub Kicinski { PHY_ID_BCM72165, 0xfffffff0, }, --- a/drivers/net/phy/bcm84881.c +++ b/drivers/net/phy/bcm84881.c -@@ -252,7 +252,7 @@ static struct phy_driver bcm84881_driver +@@ -262,7 +262,7 @@ static struct phy_driver bcm84881_driver module_phy_driver(bcm84881_drivers); /* FIXME: module auto-loading for Clause 45 PHYs seems non-functional */ @@ -403,7 +403,7 @@ Signed-off-by: Jakub Kicinski }; --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c -@@ -4133,7 +4133,7 @@ static struct phy_driver marvell_drivers +@@ -4218,7 +4218,7 @@ static struct phy_driver marvell_drivers module_phy_driver(marvell_drivers); @@ -458,7 +458,7 @@ Signed-off-by: Jakub Kicinski { } --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c -@@ -5701,7 +5701,7 @@ MODULE_DESCRIPTION("Micrel PHY driver"); +@@ -5835,7 +5835,7 @@ MODULE_DESCRIPTION("Micrel PHY driver"); MODULE_AUTHOR("David J. Choi"); MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/generic/backport-6.12/729-v6.15-net-phy-mediatek-Change-to-more-meaningful-macros.patch b/lede/target/linux/generic/backport-6.12/720-10-v6.15-net-phy-mediatek-Change-to-more-meaningful-macros.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/729-v6.15-net-phy-mediatek-Change-to-more-meaningful-macros.patch rename to lede/target/linux/generic/backport-6.12/720-10-v6.15-net-phy-mediatek-Change-to-more-meaningful-macros.patch diff --git a/lede/target/linux/generic/backport-6.12/730-v6.15-net-phy-mediatek-Add-token-ring-access-helper-functi.patch b/lede/target/linux/generic/backport-6.12/720-11-v6.15-net-phy-mediatek-Add-token-ring-access-helper-functi.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/730-v6.15-net-phy-mediatek-Add-token-ring-access-helper-functi.patch rename to lede/target/linux/generic/backport-6.12/720-11-v6.15-net-phy-mediatek-Add-token-ring-access-helper-functi.patch diff --git a/lede/target/linux/generic/backport-6.12/731-v6.15-net-phy-mediatek-Add-token-ring-set-bit-operation-su.patch b/lede/target/linux/generic/backport-6.12/720-12-v6.15-net-phy-mediatek-Add-token-ring-set-bit-operation-su.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/731-v6.15-net-phy-mediatek-Add-token-ring-set-bit-operation-su.patch rename to lede/target/linux/generic/backport-6.12/720-12-v6.15-net-phy-mediatek-Add-token-ring-set-bit-operation-su.patch diff --git a/lede/target/linux/generic/backport-6.12/732-v6.15-net-phy-mediatek-Add-token-ring-clear-bit-operation-.patch b/lede/target/linux/generic/backport-6.12/720-13-v6.15-net-phy-mediatek-Add-token-ring-clear-bit-operation-.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/732-v6.15-net-phy-mediatek-Add-token-ring-clear-bit-operation-.patch rename to lede/target/linux/generic/backport-6.12/720-13-v6.15-net-phy-mediatek-Add-token-ring-clear-bit-operation-.patch diff --git a/lede/target/linux/generic/backport-6.12/733-v6.15-net-phy-mediatek-Move-some-macros-to-phy-lib-for-lat.patch b/lede/target/linux/generic/backport-6.12/720-14-v6.15-net-phy-mediatek-Move-some-macros-to-phy-lib-for-lat.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/733-v6.15-net-phy-mediatek-Move-some-macros-to-phy-lib-for-lat.patch rename to lede/target/linux/generic/backport-6.12/720-14-v6.15-net-phy-mediatek-Move-some-macros-to-phy-lib-for-lat.patch diff --git a/lede/target/linux/generic/backport-6.12/735-v6.16-net-phy-mediatek-permit-to-compile-test-GE-SOC-PHY-d.patch b/lede/target/linux/generic/backport-6.12/720-15-v6.16-net-phy-mediatek-permit-to-compile-test-GE-SOC-PHY-d.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/735-v6.16-net-phy-mediatek-permit-to-compile-test-GE-SOC-PHY-d.patch rename to lede/target/linux/generic/backport-6.12/720-15-v6.16-net-phy-mediatek-permit-to-compile-test-GE-SOC-PHY-d.patch diff --git a/lede/target/linux/generic/backport-6.12/736-v6.16-net-phy-mediatek-add-Airoha-PHY-ID-to-SoC-driver.patch b/lede/target/linux/generic/backport-6.12/720-16-v6.16-net-phy-mediatek-add-Airoha-PHY-ID-to-SoC-driver.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/736-v6.16-net-phy-mediatek-add-Airoha-PHY-ID-to-SoC-driver.patch rename to lede/target/linux/generic/backport-6.12/720-16-v6.16-net-phy-mediatek-add-Airoha-PHY-ID-to-SoC-driver.patch diff --git a/lede/target/linux/generic/backport-6.12/737-v6.16-net-phy-mediatek-init-val-in-.phy_led_polarity_set-f.patch b/lede/target/linux/generic/backport-6.12/720-17-v6.16-net-phy-mediatek-init-val-in-.phy_led_polarity_set-f.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/737-v6.16-net-phy-mediatek-init-val-in-.phy_led_polarity_set-f.patch rename to lede/target/linux/generic/backport-6.12/720-17-v6.16-net-phy-mediatek-init-val-in-.phy_led_polarity_set-f.patch diff --git a/lede/target/linux/generic/backport-6.12/753-v6.15-net-ethernet-mediatek-add-EEE-support.patch b/lede/target/linux/generic/backport-6.12/721-01-v6.15-net-ethernet-mediatek-add-EEE-support.patch similarity index 96% rename from lede/target/linux/generic/backport-6.12/753-v6.15-net-ethernet-mediatek-add-EEE-support.patch rename to lede/target/linux/generic/backport-6.12/721-01-v6.15-net-ethernet-mediatek-add-EEE-support.patch index 2ca3f2ef00..c58635a284 100644 --- a/lede/target/linux/generic/backport-6.12/753-v6.15-net-ethernet-mediatek-add-EEE-support.patch +++ b/lede/target/linux/generic/backport-6.12/721-01-v6.15-net-ethernet-mediatek-add-EEE-support.patch @@ -39,7 +39,7 @@ Signed-off-by: Qingfang Deng mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK; mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); } -@@ -4506,6 +4516,61 @@ static int mtk_set_pauseparam(struct net +@@ -4514,6 +4524,61 @@ static int mtk_set_pauseparam(struct net return phylink_ethtool_set_pauseparam(mac->phylink, pause); } @@ -101,7 +101,7 @@ Signed-off-by: Qingfang Deng static u16 mtk_select_queue(struct net_device *dev, struct sk_buff *skb, struct net_device *sb_dev) { -@@ -4538,6 +4603,8 @@ static const struct ethtool_ops mtk_etht +@@ -4546,6 +4611,8 @@ static const struct ethtool_ops mtk_etht .set_pauseparam = mtk_set_pauseparam, .get_rxnfc = mtk_get_rxnfc, .set_rxnfc = mtk_set_rxnfc, @@ -110,7 +110,7 @@ Signed-off-by: Qingfang Deng }; static const struct net_device_ops mtk_netdev_ops = { -@@ -4598,6 +4665,8 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4606,6 +4673,8 @@ static int mtk_add_mac(struct mtk_eth *e } mac = netdev_priv(eth->netdev[id]); eth->mac[id] = mac; diff --git a/lede/target/linux/generic/backport-6.12/839-v6.13-net-phy-aquantia-allow-forcing-order-of-MDI-pairs.patch b/lede/target/linux/generic/backport-6.12/730-01-v6.13-net-phy-aquantia-allow-forcing-order-of-MDI-pairs.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/839-v6.13-net-phy-aquantia-allow-forcing-order-of-MDI-pairs.patch rename to lede/target/linux/generic/backport-6.12/730-01-v6.13-net-phy-aquantia-allow-forcing-order-of-MDI-pairs.patch diff --git a/lede/target/linux/generic/backport-6.12/840-v6.13-net-phy-aquantia-fix-return-value-check-in-aqr107_co.patch b/lede/target/linux/generic/backport-6.12/730-02-v6.13-net-phy-aquantia-fix-return-value-check-in-aqr107_co.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/840-v6.13-net-phy-aquantia-fix-return-value-check-in-aqr107_co.patch rename to lede/target/linux/generic/backport-6.12/730-02-v6.13-net-phy-aquantia-fix-return-value-check-in-aqr107_co.patch diff --git a/lede/target/linux/generic/backport-6.12/841-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch b/lede/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch similarity index 97% rename from lede/target/linux/generic/backport-6.12/841-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch rename to lede/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch index 9c317606e1..6822dc0f22 100644 --- a/lede/target/linux/generic/backport-6.12/841-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch +++ b/lede/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch @@ -39,7 +39,7 @@ Signed-off-by: Paolo Abeni if (!phydev->drv->led_polarity_set) --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -874,8 +874,9 @@ struct phy_plca_status { +@@ -902,8 +902,9 @@ struct phy_plca_status { /* Modes for PHY LED configuration */ enum phy_led_modes { diff --git a/lede/target/linux/generic/backport-6.12/842-v6.13-net-phy-aquantia-correctly-describe-LED-polarity-ove.patch b/lede/target/linux/generic/backport-6.12/730-04-v6.13-net-phy-aquantia-correctly-describe-LED-polarity-ove.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/842-v6.13-net-phy-aquantia-correctly-describe-LED-polarity-ove.patch rename to lede/target/linux/generic/backport-6.12/730-04-v6.13-net-phy-aquantia-correctly-describe-LED-polarity-ove.patch diff --git a/lede/target/linux/generic/backport-6.12/843-v6.13-net-phy-mxl-gpy-add-basic-LED-support.patch b/lede/target/linux/generic/backport-6.12/730-05-v6.13-net-phy-mxl-gpy-add-basic-LED-support.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/843-v6.13-net-phy-mxl-gpy-add-basic-LED-support.patch rename to lede/target/linux/generic/backport-6.12/730-05-v6.13-net-phy-mxl-gpy-add-basic-LED-support.patch diff --git a/lede/target/linux/generic/backport-6.12/844-v6.13-net-phy-mxl-gpy-add-missing-support-for-TRIGGER_NETD.patch b/lede/target/linux/generic/backport-6.12/730-06-v6.13-net-phy-mxl-gpy-add-missing-support-for-TRIGGER_NETD.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/844-v6.13-net-phy-mxl-gpy-add-missing-support-for-TRIGGER_NETD.patch rename to lede/target/linux/generic/backport-6.12/730-06-v6.13-net-phy-mxl-gpy-add-missing-support-for-TRIGGER_NETD.patch diff --git a/lede/target/linux/generic/backport-6.12/845-v6.13-net-phy-mxl-gpy-correctly-describe-LED-polarity.patch b/lede/target/linux/generic/backport-6.12/730-07-v6.13-net-phy-mxl-gpy-correctly-describe-LED-polarity.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/845-v6.13-net-phy-mxl-gpy-correctly-describe-LED-polarity.patch rename to lede/target/linux/generic/backport-6.12/730-07-v6.13-net-phy-mxl-gpy-correctly-describe-LED-polarity.patch diff --git a/lede/target/linux/generic/backport-6.12/846-v6.13-net-phy-intel-xway-add-support-for-PHY-LEDs.patch b/lede/target/linux/generic/backport-6.12/730-08-v6.13-net-phy-intel-xway-add-support-for-PHY-LEDs.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/846-v6.13-net-phy-intel-xway-add-support-for-PHY-LEDs.patch rename to lede/target/linux/generic/backport-6.12/730-08-v6.13-net-phy-intel-xway-add-support-for-PHY-LEDs.patch diff --git a/lede/target/linux/generic/backport-6.12/735-v6.13-net-phy-avoid-undefined-behavior-in-_led_polarity_se.patch b/lede/target/linux/generic/backport-6.12/735-v6.13-net-phy-avoid-undefined-behavior-in-_led_polarity_se.patch new file mode 100644 index 0000000000..7a1553ae28 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/735-v6.13-net-phy-avoid-undefined-behavior-in-_led_polarity_se.patch @@ -0,0 +1,64 @@ +From cff865c700711ecc3824b2dfe181637f3ed23c80 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Tue, 17 Dec 2024 09:10:34 +0100 +Subject: net: phy: avoid undefined behavior in *_led_polarity_set() + +gcc runs into undefined behavior at the end of the three led_polarity_set() +callback functions if it were called with a zero 'modes' argument and it +just ends the function there without returning from it. + +This gets flagged by 'objtool' as a function that continues on +to the next one: + +drivers/net/phy/aquantia/aquantia_leds.o: warning: objtool: aqr_phy_led_polarity_set+0xf: can't find jump dest instruction at .text+0x5d9 +drivers/net/phy/intel-xway.o: warning: objtool: xway_gphy_led_polarity_set() falls through to next function xway_gphy_config_init() +drivers/net/phy/mxl-gpy.o: warning: objtool: gpy_led_polarity_set() falls through to next function gpy_led_hw_control_get() + +There is no point to micro-optimize the behavior here to save a single-digit +number of bytes in the kernel, so just change this to a "return -EINVAL" +as we do when any unexpected bits are set. + +Fixes: 1758af47b98c ("net: phy: intel-xway: add support for PHY LEDs") +Fixes: 9d55e68b19f2 ("net: phy: aquantia: correctly describe LED polarity override") +Fixes: eb89c79c1b8f ("net: phy: mxl-gpy: correctly describe LED polarity") +Signed-off-by: Arnd Bergmann +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20241217081056.238792-1-arnd@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/aquantia/aquantia_leds.c | 2 +- + drivers/net/phy/intel-xway.c | 2 +- + drivers/net/phy/mxl-gpy.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/aquantia/aquantia_leds.c ++++ b/drivers/net/phy/aquantia/aquantia_leds.c +@@ -156,5 +156,5 @@ int aqr_phy_led_polarity_set(struct phy_ + if (force_active_high || force_active_low) + return aqr_phy_led_active_low_set(phydev, index, force_active_low); + +- unreachable(); ++ return -EINVAL; + } +--- a/drivers/net/phy/intel-xway.c ++++ b/drivers/net/phy/intel-xway.c +@@ -529,7 +529,7 @@ static int xway_gphy_led_polarity_set(st + if (force_active_high) + return phy_clear_bits(phydev, XWAY_MDIO_LED, XWAY_GPHY_LED_INV(index)); + +- unreachable(); ++ return -EINVAL; + } + + static struct phy_driver xway_gphy[] = { +--- a/drivers/net/phy/mxl-gpy.c ++++ b/drivers/net/phy/mxl-gpy.c +@@ -1014,7 +1014,7 @@ static int gpy_led_polarity_set(struct p + if (force_active_high) + return phy_clear_bits(phydev, PHY_LED, PHY_LED_POLARITY(index)); + +- unreachable(); ++ return -EINVAL; + } + + static struct phy_driver gpy_drivers[] = { diff --git a/lede/target/linux/generic/backport-6.12/901-v6.13-net-dsa-mv88e6xxx-Support-LED-control.patch b/lede/target/linux/generic/backport-6.12/740-v6.13-net-dsa-mv88e6xxx-Support-LED-control.patch similarity index 100% rename from lede/target/linux/generic/backport-6.12/901-v6.13-net-dsa-mv88e6xxx-Support-LED-control.patch rename to lede/target/linux/generic/backport-6.12/740-v6.13-net-dsa-mv88e6xxx-Support-LED-control.patch diff --git a/lede/target/linux/generic/backport-6.12/741-v6.13-net-dsa-mv88e6xxx-fix-unreleased-fwnode_handle-in-se.patch b/lede/target/linux/generic/backport-6.12/741-v6.13-net-dsa-mv88e6xxx-fix-unreleased-fwnode_handle-in-se.patch new file mode 100644 index 0000000000..2c81983a20 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/741-v6.13-net-dsa-mv88e6xxx-fix-unreleased-fwnode_handle-in-se.patch @@ -0,0 +1,31 @@ +From b8ee7a11c75436b85fa1641aa5f970de0f8a575c Mon Sep 17 00:00:00 2001 +From: Javier Carrasco +Date: Sat, 19 Oct 2024 22:16:49 +0200 +Subject: net: dsa: mv88e6xxx: fix unreleased fwnode_handle in setup_port() + +'ports_fwnode' is initialized via device_get_named_child_node(), which +requires a call to fwnode_handle_put() when the variable is no longer +required to avoid leaking memory. + +Add the missing fwnode_handle_put() after 'ports_fwnode' has been used +and is no longer required. + +Fixes: 94a2a84f5e9e ("net: dsa: mv88e6xxx: Support LED control") +Signed-off-by: Javier Carrasco +Reviewed-by: Andrew Lunn +Reviewed-by: Linus Walleij +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mv88e6xxx/chip.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -3441,6 +3441,7 @@ static int mv88e6xxx_setup_port(struct m + break; + } + } ++ fwnode_handle_put(ports_fwnode); + } else { + dev_dbg(chip->dev, "no ethernet ports node defined for the device\n"); + } diff --git a/lede/target/linux/generic/backport-6.12/742-v6.17-net-dsa-mv88e6xxx-Fix-fwnode-reference-leaks-in-mv88.patch b/lede/target/linux/generic/backport-6.12/742-v6.17-net-dsa-mv88e6xxx-Fix-fwnode-reference-leaks-in-mv88.patch new file mode 100644 index 0000000000..6e0fbb82af --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/742-v6.17-net-dsa-mv88e6xxx-Fix-fwnode-reference-leaks-in-mv88.patch @@ -0,0 +1,68 @@ +From f63e7c8a83892781f6ceb55566f9497639c44555 Mon Sep 17 00:00:00 2001 +From: Miaoqian Lin +Date: Mon, 1 Sep 2025 15:32:23 +0800 +Subject: net: dsa: mv88e6xxx: Fix fwnode reference leaks in + mv88e6xxx_port_setup_leds + +Fix multiple fwnode reference leaks: + +1. The function calls fwnode_get_named_child_node() to get the "leds" node, + but never calls fwnode_handle_put(leds) to release this reference. + +2. Within the fwnode_for_each_child_node() loop, the early return + paths that don't properly release the "led" fwnode reference. + +This fix follows the same pattern as commit d029edefed39 +("net dsa: qca8k: fix usages of device_get_named_child_node()") + +Fixes: 94a2a84f5e9e ("net: dsa: mv88e6xxx: Support LED control") +Cc: stable@vger.kernel.org +Signed-off-by: Miaoqian Lin +Reviewed-by: Linus Walleij +Link: https://patch.msgid.link/20250901073224.2273103-1-linmq006@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/leds.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/leds.c ++++ b/drivers/net/dsa/mv88e6xxx/leds.c +@@ -779,7 +779,8 @@ int mv88e6xxx_port_setup_leds(struct mv8 + continue; + if (led_num > 1) { + dev_err(dev, "invalid LED specified port %d\n", port); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_put_led; + } + + if (led_num == 0) +@@ -823,17 +824,25 @@ int mv88e6xxx_port_setup_leds(struct mv8 + init_data.devname_mandatory = true; + init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d:0%d", chip->info->name, + port, led_num); +- if (!init_data.devicename) +- return -ENOMEM; ++ if (!init_data.devicename) { ++ ret = -ENOMEM; ++ goto err_put_led; ++ } + + ret = devm_led_classdev_register_ext(dev, l, &init_data); + kfree(init_data.devicename); + + if (ret) { + dev_err(dev, "Failed to init LED %d for port %d", led_num, port); +- return ret; ++ goto err_put_led; + } + } + ++ fwnode_handle_put(leds); + return 0; ++ ++err_put_led: ++ fwnode_handle_put(led); ++ fwnode_handle_put(leds); ++ return ret; + } diff --git a/lede/target/linux/generic/backport-6.12/780-01-v6.13-r8169-remove-original-workaround-for-RTL8125-broken-.patch b/lede/target/linux/generic/backport-6.12/780-01-v6.13-r8169-remove-original-workaround-for-RTL8125-broken-.patch index ed79d3914e..bd10a96772 100644 --- a/lede/target/linux/generic/backport-6.12/780-01-v6.13-r8169-remove-original-workaround-for-RTL8125-broken-.patch +++ b/lede/target/linux/generic/backport-6.12/780-01-v6.13-r8169-remove-original-workaround-for-RTL8125-broken-.patch @@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -4813,11 +4813,7 @@ static void r8169_phylink_handler(struct +@@ -4810,11 +4810,7 @@ static void r8169_phylink_handler(struct if (netif_carrier_ok(ndev)) { rtl_link_chg_patch(tp); pm_request_resume(d); diff --git a/lede/target/linux/generic/backport-6.12/780-02-v6.13-r8169-enable-SG-TSO-on-selected-chip-versions-per-de.patch b/lede/target/linux/generic/backport-6.12/780-02-v6.13-r8169-enable-SG-TSO-on-selected-chip-versions-per-de.patch index 67823d4363..7ea1a11ee3 100644 --- a/lede/target/linux/generic/backport-6.12/780-02-v6.13-r8169-enable-SG-TSO-on-selected-chip-versions-per-de.patch +++ b/lede/target/linux/generic/backport-6.12/780-02-v6.13-r8169-enable-SG-TSO-on-selected-chip-versions-per-de.patch @@ -20,7 +20,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -5526,11 +5526,6 @@ static int rtl_init_one(struct pci_dev * +@@ -5524,11 +5524,6 @@ static int rtl_init_one(struct pci_dev * dev->features |= dev->hw_features; @@ -32,7 +32,7 @@ Signed-off-by: David S. Miller if (rtl_chip_supports_csum_v2(tp)) { dev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6; netif_set_tso_max_size(dev, RTL_GSO_MAX_SIZE_V2); -@@ -5541,6 +5536,17 @@ static int rtl_init_one(struct pci_dev * +@@ -5539,6 +5534,17 @@ static int rtl_init_one(struct pci_dev * netif_set_tso_max_segs(dev, RTL_GSO_MAX_SEGS_V1); } diff --git a/lede/target/linux/generic/backport-6.12/780-03-v6.13-r8169-implement-additional-ethtool-stats-ops.patch b/lede/target/linux/generic/backport-6.12/780-03-v6.13-r8169-implement-additional-ethtool-stats-ops.patch index 8ecb5c794c..594a8fae1a 100644 --- a/lede/target/linux/generic/backport-6.12/780-03-v6.13-r8169-implement-additional-ethtool-stats-ops.patch +++ b/lede/target/linux/generic/backport-6.12/780-03-v6.13-r8169-implement-additional-ethtool-stats-ops.patch @@ -118,7 +118,7 @@ Signed-off-by: Jakub Kicinski }; static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii) -@@ -3929,6 +4008,9 @@ static void rtl_hw_start_8125(struct rtl +@@ -3926,6 +4005,9 @@ static void rtl_hw_start_8125(struct rtl break; } diff --git a/lede/target/linux/generic/backport-6.12/780-04-v6.13-r8169-don-t-take-RTNL-lock-in-rtl_task.patch b/lede/target/linux/generic/backport-6.12/780-04-v6.13-r8169-don-t-take-RTNL-lock-in-rtl_task.patch index dd42817b99..a125ebb6cd 100644 --- a/lede/target/linux/generic/backport-6.12/780-04-v6.13-r8169-don-t-take-RTNL-lock-in-rtl_task.patch +++ b/lede/target/linux/generic/backport-6.12/780-04-v6.13-r8169-don-t-take-RTNL-lock-in-rtl_task.patch @@ -18,7 +18,7 @@ Signed-off-by: Andrew Lunn --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -4836,10 +4836,8 @@ static void rtl_task(struct work_struct +@@ -4833,10 +4833,8 @@ static void rtl_task(struct work_struct container_of(work, struct rtl8169_private, wk.work); int ret; @@ -30,7 +30,7 @@ Signed-off-by: Andrew Lunn if (test_and_clear_bit(RTL_FLAG_TASK_TX_TIMEOUT, tp->wk.flags)) { /* if chip isn't accessible, reset bus to revive it */ -@@ -4848,7 +4846,7 @@ static void rtl_task(struct work_struct +@@ -4845,7 +4843,7 @@ static void rtl_task(struct work_struct if (ret < 0) { netdev_err(tp->dev, "Can't reset secondary PCI bus, detach NIC\n"); netif_device_detach(tp->dev); @@ -39,7 +39,7 @@ Signed-off-by: Andrew Lunn } } -@@ -4867,8 +4865,6 @@ reset: +@@ -4864,8 +4862,6 @@ reset: } else if (test_and_clear_bit(RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE, tp->wk.flags)) { rtl_reset_work(tp); } diff --git a/lede/target/linux/generic/backport-6.12/780-05-v6.13-replace-custom-flag-with-disable_work-et-al.patch b/lede/target/linux/generic/backport-6.12/780-05-v6.13-replace-custom-flag-with-disable_work-et-al.patch index ae4bc15e30..49e274a5e2 100644 --- a/lede/target/linux/generic/backport-6.12/780-05-v6.13-replace-custom-flag-with-disable_work-et-al.patch +++ b/lede/target/linux/generic/backport-6.12/780-05-v6.13-replace-custom-flag-with-disable_work-et-al.patch @@ -39,7 +39,7 @@ Signed-off-by: Andrew Lunn } static void rtl8169_init_phy(struct rtl8169_private *tp) -@@ -4836,9 +4833,6 @@ static void rtl_task(struct work_struct +@@ -4833,9 +4830,6 @@ static void rtl_task(struct work_struct container_of(work, struct rtl8169_private, wk.work); int ret; @@ -49,7 +49,7 @@ Signed-off-by: Andrew Lunn if (test_and_clear_bit(RTL_FLAG_TASK_TX_TIMEOUT, tp->wk.flags)) { /* if chip isn't accessible, reset bus to revive it */ if (RTL_R32(tp, TxConfig) == ~0) { -@@ -4922,6 +4916,7 @@ static int r8169_phy_connect(struct rtl8 +@@ -4919,6 +4913,7 @@ static int r8169_phy_connect(struct rtl8 static void rtl8169_down(struct rtl8169_private *tp) { @@ -57,7 +57,7 @@ Signed-off-by: Andrew Lunn /* Clear all task flags */ bitmap_zero(tp->wk.flags, RTL_FLAG_MAX); -@@ -4950,7 +4945,7 @@ static void rtl8169_up(struct rtl8169_pr +@@ -4947,7 +4942,7 @@ static void rtl8169_up(struct rtl8169_pr phy_resume(tp->phydev); rtl8169_init_phy(tp); napi_enable(&tp->napi); @@ -66,7 +66,7 @@ Signed-off-by: Andrew Lunn rtl_reset_work(tp); phy_start(tp->phydev); -@@ -4967,8 +4962,6 @@ static int rtl8169_close(struct net_devi +@@ -4964,8 +4959,6 @@ static int rtl8169_close(struct net_devi rtl8169_down(tp); rtl8169_rx_clear(tp); @@ -75,7 +75,7 @@ Signed-off-by: Andrew Lunn free_irq(tp->irq, tp); phy_disconnect(tp->phydev); -@@ -5201,7 +5194,7 @@ static void rtl_remove_one(struct pci_de +@@ -5199,7 +5192,7 @@ static void rtl_remove_one(struct pci_de if (pci_dev_run_wake(pdev)) pm_runtime_get_noresume(&pdev->dev); @@ -84,7 +84,7 @@ Signed-off-by: Andrew Lunn if (IS_ENABLED(CONFIG_R8169_LEDS)) r8169_remove_leds(tp->leds); -@@ -5579,6 +5572,7 @@ static int rtl_init_one(struct pci_dev * +@@ -5577,6 +5570,7 @@ static int rtl_init_one(struct pci_dev * tp->irq = pci_irq_vector(pdev, 0); INIT_WORK(&tp->wk.work, rtl_task); diff --git a/lede/target/linux/generic/backport-6.12/780-14-v6.13-r8169-improve-initialization-of-RSS-registers-on-RTL.patch b/lede/target/linux/generic/backport-6.12/780-14-v6.13-r8169-improve-initialization-of-RSS-registers-on-RTL.patch index f8777b897a..d00b08e0fa 100644 --- a/lede/target/linux/generic/backport-6.12/780-14-v6.13-r8169-improve-initialization-of-RSS-registers-on-RTL.patch +++ b/lede/target/linux/generic/backport-6.12/780-14-v6.13-r8169-improve-initialization-of-RSS-registers-on-RTL.patch @@ -25,7 +25,7 @@ Signed-off-by: Jakub Kicinski EEE_TXIDLE_TIMER_8125 = 0x6048, }; -@@ -3791,8 +3793,8 @@ static void rtl_hw_start_8125_common(str +@@ -3788,8 +3790,8 @@ static void rtl_hw_start_8125_common(str rtl_pcie_state_l2l3_disable(tp); RTL_W16(tp, 0x382, 0x221b); diff --git a/lede/target/linux/generic/backport-6.12/780-15-v6.13-r8169-remove-leftover-locks-after-reverted-change.patch b/lede/target/linux/generic/backport-6.12/780-15-v6.13-r8169-remove-leftover-locks-after-reverted-change.patch index 7af3abacfb..19bcf08d55 100644 --- a/lede/target/linux/generic/backport-6.12/780-15-v6.13-r8169-remove-leftover-locks-after-reverted-change.patch +++ b/lede/target/linux/generic/backport-6.12/780-15-v6.13-r8169-remove-leftover-locks-after-reverted-change.patch @@ -102,7 +102,7 @@ Signed-off-by: Jakub Kicinski switch (tp->mac_version) { case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06: -@@ -5479,8 +5456,6 @@ static int rtl_init_one(struct pci_dev * +@@ -5477,8 +5454,6 @@ static int rtl_init_one(struct pci_dev * tp->supports_gmii = ent->driver_data == RTL_CFG_NO_GBIT ? 0 : 1; tp->ocp_base = OCP_STD_PHY_BASE; diff --git a/lede/target/linux/generic/backport-6.12/780-20-v6.13-r8169-copy-vendor-driver-2.5G-5G-EEE-advertisement-c.patch b/lede/target/linux/generic/backport-6.12/780-20-v6.13-r8169-copy-vendor-driver-2.5G-5G-EEE-advertisement-c.patch index a88283903a..fee9d95368 100644 --- a/lede/target/linux/generic/backport-6.12/780-20-v6.13-r8169-copy-vendor-driver-2.5G-5G-EEE-advertisement-c.patch +++ b/lede/target/linux/generic/backport-6.12/780-20-v6.13-r8169-copy-vendor-driver-2.5G-5G-EEE-advertisement-c.patch @@ -22,7 +22,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -5255,6 +5255,11 @@ static int r8169_mdio_register(struct rt +@@ -5253,6 +5253,11 @@ static int r8169_mdio_register(struct rt phy_support_eee(tp->phydev); phy_support_asym_pause(tp->phydev); diff --git a/lede/target/linux/generic/backport-6.12/780-21-v6.14-r8169-remove-unused-flag-RTL_FLAG_TASK_RESET_NO_QUEU.patch b/lede/target/linux/generic/backport-6.12/780-21-v6.14-r8169-remove-unused-flag-RTL_FLAG_TASK_RESET_NO_QUEU.patch index ad938baec0..182858ac02 100644 --- a/lede/target/linux/generic/backport-6.12/780-21-v6.14-r8169-remove-unused-flag-RTL_FLAG_TASK_RESET_NO_QUEU.patch +++ b/lede/target/linux/generic/backport-6.12/780-21-v6.14-r8169-remove-unused-flag-RTL_FLAG_TASK_RESET_NO_QUEU.patch @@ -24,7 +24,7 @@ Signed-off-by: Jakub Kicinski RTL_FLAG_TASK_TX_TIMEOUT, RTL_FLAG_MAX }; -@@ -4749,8 +4748,6 @@ static void rtl_task(struct work_struct +@@ -4746,8 +4745,6 @@ static void rtl_task(struct work_struct reset: rtl_reset_work(tp); netif_wake_queue(tp->dev); diff --git a/lede/target/linux/generic/backport-6.12/780-22-v6.14-r8169-remove-support-for-chip-version-11.patch b/lede/target/linux/generic/backport-6.12/780-22-v6.14-r8169-remove-support-for-chip-version-11.patch index 6753d70ab8..055e0f0155 100644 --- a/lede/target/linux/generic/backport-6.12/780-22-v6.14-r8169-remove-support-for-chip-version-11.patch +++ b/lede/target/linux/generic/backport-6.12/780-22-v6.14-r8169-remove-support-for-chip-version-11.patch @@ -47,7 +47,7 @@ Signed-off-by: Jakub Kicinski * { 0x7c8, 0x300, RTL_GIGA_MAC_VER_11 }, */ -@@ -3829,7 +3828,6 @@ static void rtl_hw_config(struct rtl8169 +@@ -3826,7 +3825,6 @@ static void rtl_hw_config(struct rtl8169 [RTL_GIGA_MAC_VER_08] = rtl_hw_start_8102e_3, [RTL_GIGA_MAC_VER_09] = rtl_hw_start_8102e_2, [RTL_GIGA_MAC_VER_10] = NULL, @@ -55,7 +55,7 @@ Signed-off-by: Jakub Kicinski [RTL_GIGA_MAC_VER_14] = rtl_hw_start_8401, [RTL_GIGA_MAC_VER_17] = rtl_hw_start_8168b, [RTL_GIGA_MAC_VER_18] = rtl_hw_start_8168cp_1, -@@ -4705,12 +4703,6 @@ static irqreturn_t rtl8169_interrupt(int +@@ -4702,12 +4700,6 @@ static irqreturn_t rtl8169_interrupt(int if (status & LinkChg) phy_mac_interrupt(tp->phydev); @@ -68,7 +68,7 @@ Signed-off-by: Jakub Kicinski rtl_irq_disable(tp); napi_schedule(&tp->napi); out: -@@ -5126,9 +5118,6 @@ static void rtl_set_irq_mask(struct rtl8 +@@ -5124,9 +5116,6 @@ static void rtl_set_irq_mask(struct rtl8 if (tp->mac_version <= RTL_GIGA_MAC_VER_06) tp->irq_mask |= SYSErr | RxFIFOOver; @@ -78,7 +78,7 @@ Signed-off-by: Jakub Kicinski } static int rtl_alloc_irq(struct rtl8169_private *tp) -@@ -5323,7 +5312,6 @@ static int rtl_jumbo_max(struct rtl8169_ +@@ -5321,7 +5310,6 @@ static int rtl_jumbo_max(struct rtl8169_ case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06: return JUMBO_7K; /* RTL8168b */ diff --git a/lede/target/linux/generic/backport-6.12/780-23-v6.14-r8169-adjust-version-numbering-for-RTL8126.patch b/lede/target/linux/generic/backport-6.12/780-23-v6.14-r8169-adjust-version-numbering-for-RTL8126.patch index 9e3fd0a66e..7ea47bd2ed 100644 --- a/lede/target/linux/generic/backport-6.12/780-23-v6.14-r8169-adjust-version-numbering-for-RTL8126.patch +++ b/lede/target/linux/generic/backport-6.12/780-23-v6.14-r8169-adjust-version-numbering-for-RTL8126.patch @@ -107,7 +107,7 @@ Signed-off-by: Jakub Kicinski RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq); rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42); rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond_2, 100, 42); -@@ -2926,7 +2926,7 @@ static void rtl_enable_exit_l1(struct rt +@@ -2923,7 +2923,7 @@ static void rtl_enable_exit_l1(struct rt case RTL_GIGA_MAC_VER_37 ... RTL_GIGA_MAC_VER_38: rtl_eri_set_bits(tp, 0xd4, 0x0c00); break; @@ -116,7 +116,7 @@ Signed-off-by: Jakub Kicinski r8168_mac_ocp_modify(tp, 0xc0ac, 0, 0x1f80); break; default: -@@ -2940,7 +2940,7 @@ static void rtl_disable_exit_l1(struct r +@@ -2937,7 +2937,7 @@ static void rtl_disable_exit_l1(struct r case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38: rtl_eri_clear_bits(tp, 0xd4, 0x1f00); break; @@ -125,7 +125,7 @@ Signed-off-by: Jakub Kicinski r8168_mac_ocp_modify(tp, 0xc0ac, 0x1f80, 0); break; default: -@@ -2966,8 +2966,8 @@ static void rtl_hw_aspm_clkreq_enable(st +@@ -2963,8 +2963,8 @@ static void rtl_hw_aspm_clkreq_enable(st rtl_mod_config5(tp, 0, ASPM_en); switch (tp->mac_version) { @@ -136,7 +136,7 @@ Signed-off-by: Jakub Kicinski val8 = RTL_R8(tp, INT_CFG0_8125) | INT_CFG0_CLKREQEN; RTL_W8(tp, INT_CFG0_8125, val8); break; -@@ -2978,7 +2978,7 @@ static void rtl_hw_aspm_clkreq_enable(st +@@ -2975,7 +2975,7 @@ static void rtl_hw_aspm_clkreq_enable(st switch (tp->mac_version) { case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48: @@ -145,7 +145,7 @@ Signed-off-by: Jakub Kicinski /* reset ephy tx/rx disable timer */ r8168_mac_ocp_modify(tp, 0xe094, 0xff00, 0); /* chip can trigger L1.2 */ -@@ -2990,7 +2990,7 @@ static void rtl_hw_aspm_clkreq_enable(st +@@ -2987,7 +2987,7 @@ static void rtl_hw_aspm_clkreq_enable(st } else { switch (tp->mac_version) { case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48: @@ -154,7 +154,7 @@ Signed-off-by: Jakub Kicinski r8168_mac_ocp_modify(tp, 0xe092, 0x00ff, 0); break; default: -@@ -2998,8 +2998,8 @@ static void rtl_hw_aspm_clkreq_enable(st +@@ -2995,8 +2995,8 @@ static void rtl_hw_aspm_clkreq_enable(st } switch (tp->mac_version) { @@ -165,7 +165,7 @@ Signed-off-by: Jakub Kicinski val8 = RTL_R8(tp, INT_CFG0_8125) & ~INT_CFG0_CLKREQEN; RTL_W8(tp, INT_CFG0_8125, val8); break; -@@ -3719,12 +3719,12 @@ static void rtl_hw_start_8125_common(str +@@ -3716,12 +3716,12 @@ static void rtl_hw_start_8125_common(str /* disable new tx descriptor format */ r8168_mac_ocp_modify(tp, 0xeb58, 0x0001, 0x0000); @@ -182,7 +182,7 @@ Signed-off-by: Jakub Kicinski r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400); else if (tp->mac_version == RTL_GIGA_MAC_VER_63) r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0200); -@@ -3742,8 +3742,8 @@ static void rtl_hw_start_8125_common(str +@@ -3739,8 +3739,8 @@ static void rtl_hw_start_8125_common(str r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0000); r8168_mac_ocp_modify(tp, 0xe040, 0x1000, 0x0000); r8168_mac_ocp_modify(tp, 0xea1c, 0x0003, 0x0001); @@ -193,7 +193,7 @@ Signed-off-by: Jakub Kicinski r8168_mac_ocp_modify(tp, 0xea1c, 0x0300, 0x0000); else r8168_mac_ocp_modify(tp, 0xea1c, 0x0004, 0x0000); -@@ -3863,8 +3863,8 @@ static void rtl_hw_config(struct rtl8169 +@@ -3860,8 +3860,8 @@ static void rtl_hw_config(struct rtl8169 [RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2, [RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b, [RTL_GIGA_MAC_VER_64] = rtl_hw_start_8125d, @@ -204,7 +204,7 @@ Signed-off-by: Jakub Kicinski }; if (hw_configs[tp->mac_version]) -@@ -3885,8 +3885,8 @@ static void rtl_hw_start_8125(struct rtl +@@ -3882,8 +3882,8 @@ static void rtl_hw_start_8125(struct rtl RTL_W32(tp, i, 0); break; case RTL_GIGA_MAC_VER_63: @@ -215,7 +215,7 @@ Signed-off-by: Jakub Kicinski for (i = 0xa00; i < 0xa80; i += 4) RTL_W32(tp, i, 0); RTL_W16(tp, INT_CFG1_8125, 0x0000); -@@ -4118,7 +4118,7 @@ static void rtl8169_cleanup(struct rtl81 +@@ -4115,7 +4115,7 @@ static void rtl8169_cleanup(struct rtl81 RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq); rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666); break; @@ -224,7 +224,7 @@ Signed-off-by: Jakub Kicinski rtl_enable_rxdvgate(tp); fsleep(2000); break; -@@ -4275,7 +4275,7 @@ static unsigned int rtl_quirk_packet_pad +@@ -4272,7 +4272,7 @@ static unsigned int rtl_quirk_packet_pad switch (tp->mac_version) { case RTL_GIGA_MAC_VER_34: @@ -233,7 +233,7 @@ Signed-off-by: Jakub Kicinski padto = max_t(unsigned int, padto, ETH_ZLEN); break; default: -@@ -5294,7 +5294,7 @@ static void rtl_hw_initialize(struct rtl +@@ -5291,7 +5291,7 @@ static void rtl_hw_initialize(struct rtl case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48: rtl_hw_init_8168g(tp); break; diff --git a/lede/target/linux/generic/backport-6.12/780-24-v6.14-r8169-add-support-for-RTL8125D-rev.b.patch b/lede/target/linux/generic/backport-6.12/780-24-v6.14-r8169-add-support-for-RTL8125D-rev.b.patch index e53d93f213..bbc447f4de 100644 --- a/lede/target/linux/generic/backport-6.12/780-24-v6.14-r8169-add-support-for-RTL8125D-rev.b.patch +++ b/lede/target/linux/generic/backport-6.12/780-24-v6.14-r8169-add-support-for-RTL8125D-rev.b.patch @@ -62,7 +62,7 @@ Signed-off-by: Jakub Kicinski { 0x7cf, 0x688, RTL_GIGA_MAC_VER_64 }, /* 8125B family. */ -@@ -3863,6 +3867,7 @@ static void rtl_hw_config(struct rtl8169 +@@ -3860,6 +3864,7 @@ static void rtl_hw_config(struct rtl8169 [RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2, [RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b, [RTL_GIGA_MAC_VER_64] = rtl_hw_start_8125d, @@ -70,7 +70,7 @@ Signed-off-by: Jakub Kicinski [RTL_GIGA_MAC_VER_70] = rtl_hw_start_8126a, [RTL_GIGA_MAC_VER_71] = rtl_hw_start_8126a, }; -@@ -3881,6 +3886,7 @@ static void rtl_hw_start_8125(struct rtl +@@ -3878,6 +3883,7 @@ static void rtl_hw_start_8125(struct rtl switch (tp->mac_version) { case RTL_GIGA_MAC_VER_61: case RTL_GIGA_MAC_VER_64: diff --git a/lede/target/linux/generic/backport-6.12/780-25-v6.14-r8169-add-support-for-RTL8125BP-rev.b.patch b/lede/target/linux/generic/backport-6.12/780-25-v6.14-r8169-add-support-for-RTL8125BP-rev.b.patch index e358951f9d..7b4f474bee 100644 --- a/lede/target/linux/generic/backport-6.12/780-25-v6.14-r8169-add-support-for-RTL8125BP-rev.b.patch +++ b/lede/target/linux/generic/backport-6.12/780-25-v6.14-r8169-add-support-for-RTL8125BP-rev.b.patch @@ -127,7 +127,7 @@ Signed-off-by: Paolo Abeni /* 8125D family. */ { 0x7cf, 0x689, RTL_GIGA_MAC_VER_65 }, { 0x7cf, 0x688, RTL_GIGA_MAC_VER_64 }, -@@ -3868,6 +3896,7 @@ static void rtl_hw_config(struct rtl8169 +@@ -3865,6 +3893,7 @@ static void rtl_hw_config(struct rtl8169 [RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b, [RTL_GIGA_MAC_VER_64] = rtl_hw_start_8125d, [RTL_GIGA_MAC_VER_65] = rtl_hw_start_8125d, @@ -135,7 +135,7 @@ Signed-off-by: Paolo Abeni [RTL_GIGA_MAC_VER_70] = rtl_hw_start_8126a, [RTL_GIGA_MAC_VER_71] = rtl_hw_start_8126a, }; -@@ -3887,6 +3916,7 @@ static void rtl_hw_start_8125(struct rtl +@@ -3884,6 +3913,7 @@ static void rtl_hw_start_8125(struct rtl case RTL_GIGA_MAC_VER_61: case RTL_GIGA_MAC_VER_64: case RTL_GIGA_MAC_VER_65: diff --git a/lede/target/linux/generic/backport-6.12/780-29-v6.15-r8169-add-PHY-c45-ops-for-MDIO_MMD_VENDOR2-registers.patch b/lede/target/linux/generic/backport-6.12/780-29-v6.15-r8169-add-PHY-c45-ops-for-MDIO_MMD_VENDOR2-registers.patch index 1fe7f8c2be..1336ec6f91 100644 --- a/lede/target/linux/generic/backport-6.12/780-29-v6.15-r8169-add-PHY-c45-ops-for-MDIO_MMD_VENDOR2-registers.patch +++ b/lede/target/linux/generic/backport-6.12/780-29-v6.15-r8169-add-PHY-c45-ops-for-MDIO_MMD_VENDOR2-registers.patch @@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -5227,6 +5227,33 @@ static int r8169_mdio_write_reg(struct m +@@ -5225,6 +5225,33 @@ static int r8169_mdio_write_reg(struct m return 0; } @@ -53,7 +53,7 @@ Signed-off-by: Jakub Kicinski static int r8169_mdio_register(struct rtl8169_private *tp) { struct pci_dev *pdev = tp->pci_dev; -@@ -5257,6 +5284,11 @@ static int r8169_mdio_register(struct rt +@@ -5255,6 +5282,11 @@ static int r8169_mdio_register(struct rt new_bus->read = r8169_mdio_read_reg; new_bus->write = r8169_mdio_write_reg; diff --git a/lede/target/linux/generic/backport-6.12/780-30-v6.15-r8169-increase-max-jumbo-packet-size-on-RTL8125-RTL8.patch b/lede/target/linux/generic/backport-6.12/780-30-v6.15-r8169-increase-max-jumbo-packet-size-on-RTL8125-RTL8.patch index 571022051b..852c9a3da7 100644 --- a/lede/target/linux/generic/backport-6.12/780-30-v6.15-r8169-increase-max-jumbo-packet-size-on-RTL8125-RTL8.patch +++ b/lede/target/linux/generic/backport-6.12/780-30-v6.15-r8169-increase-max-jumbo-packet-size-on-RTL8125-RTL8.patch @@ -28,7 +28,7 @@ Signed-off-by: Jakub Kicinski static const struct { const char *name; -@@ -5386,6 +5387,9 @@ static int rtl_jumbo_max(struct rtl8169_ +@@ -5384,6 +5385,9 @@ static int rtl_jumbo_max(struct rtl8169_ /* RTL8168c */ case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_24: return JUMBO_6K; diff --git a/lede/target/linux/generic/backport-6.12/780-31-v6.15-r8169-switch-away-from-deprecated-pcim_iomap_table.patch b/lede/target/linux/generic/backport-6.12/780-31-v6.15-r8169-switch-away-from-deprecated-pcim_iomap_table.patch index 039e6596ac..0721247508 100644 --- a/lede/target/linux/generic/backport-6.12/780-31-v6.15-r8169-switch-away-from-deprecated-pcim_iomap_table.patch +++ b/lede/target/linux/generic/backport-6.12/780-31-v6.15-r8169-switch-away-from-deprecated-pcim_iomap_table.patch @@ -17,7 +17,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -5473,11 +5473,10 @@ static int rtl_init_one(struct pci_dev * +@@ -5471,11 +5471,10 @@ static int rtl_init_one(struct pci_dev * if (region < 0) return dev_err_probe(&pdev->dev, -ENODEV, "no MMIO resource found\n"); diff --git a/lede/target/linux/generic/backport-6.12/780-32-v6.15-r8169-enable-RTL8168H-RTL8168EP-RTL8168FP-ASPM-suppo.patch b/lede/target/linux/generic/backport-6.12/780-32-v6.15-r8169-enable-RTL8168H-RTL8168EP-RTL8168FP-ASPM-suppo.patch index 7cc6556dd7..331d296355 100644 --- a/lede/target/linux/generic/backport-6.12/780-32-v6.15-r8169-enable-RTL8168H-RTL8168EP-RTL8168FP-ASPM-suppo.patch +++ b/lede/target/linux/generic/backport-6.12/780-32-v6.15-r8169-enable-RTL8168H-RTL8168EP-RTL8168FP-ASPM-suppo.patch @@ -16,7 +16,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -5424,7 +5424,7 @@ done: +@@ -5422,7 +5422,7 @@ done: /* register is set if system vendor successfully tested ASPM 1.2 */ static bool rtl_aspm_is_safe(struct rtl8169_private *tp) { diff --git a/lede/target/linux/generic/backport-6.12/780-34-v6.16-r8169-add-helper-rtl_csi_mod-for-accessing-extended.patch b/lede/target/linux/generic/backport-6.12/780-34-v6.16-r8169-add-helper-rtl_csi_mod-for-accessing-extended.patch index a24485d1d6..383f9eb5f7 100644 --- a/lede/target/linux/generic/backport-6.12/780-34-v6.16-r8169-add-helper-rtl_csi_mod-for-accessing-extended.patch +++ b/lede/target/linux/generic/backport-6.12/780-34-v6.16-r8169-add-helper-rtl_csi_mod-for-accessing-extended.patch @@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -2852,10 +2852,23 @@ static u32 rtl_csi_read(struct rtl8169_p +@@ -2849,10 +2849,23 @@ static u32 rtl_csi_read(struct rtl8169_p RTL_R32(tp, CSIDR) : ~0; } @@ -42,7 +42,7 @@ Signed-off-by: Jakub Kicinski int rc; u8 val; -@@ -2872,16 +2885,12 @@ static void rtl_disable_zrxdc_timeout(st +@@ -2869,16 +2882,12 @@ static void rtl_disable_zrxdc_timeout(st } } @@ -60,7 +60,7 @@ Signed-off-by: Jakub Kicinski /* According to Realtek the value at config space address 0x070f * controls the L0s/L1 entrance latency. We try standard ECAM access -@@ -2893,10 +2902,7 @@ static void rtl_set_aspm_entry_latency(s +@@ -2890,10 +2899,7 @@ static void rtl_set_aspm_entry_latency(s pci_write_config_byte(pdev, 0x070f, val) == PCIBIOS_SUCCESSFUL) return; diff --git a/lede/target/linux/generic/backport-6.12/780-36-v6.16-r8169-refactor-chip-version-detection.patch b/lede/target/linux/generic/backport-6.12/780-36-v6.16-r8169-refactor-chip-version-detection.patch index e0682bea86..ae9cfb8a66 100644 --- a/lede/target/linux/generic/backport-6.12/780-36-v6.16-r8169-refactor-chip-version-detection.patch +++ b/lede/target/linux/generic/backport-6.12/780-36-v6.16-r8169-refactor-chip-version-detection.patch @@ -353,7 +353,7 @@ Signed-off-by: Jakub Kicinski } static void rtl_release_firmware(struct rtl8169_private *tp) -@@ -5439,9 +5371,9 @@ static bool rtl_aspm_is_safe(struct rtl8 +@@ -5437,9 +5369,9 @@ static bool rtl_aspm_is_safe(struct rtl8 static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -364,7 +364,7 @@ Signed-off-by: Jakub Kicinski struct net_device *dev; u32 txconfig; u16 xid; -@@ -5491,12 +5423,13 @@ static int rtl_init_one(struct pci_dev * +@@ -5489,12 +5421,13 @@ static int rtl_init_one(struct pci_dev * xid = (txconfig >> 20) & 0xfcf; /* Identify chip attached to board */ @@ -381,7 +381,7 @@ Signed-off-by: Jakub Kicinski /* Disable ASPM L1 as that cause random device stop working * problems as well as full system hangs for some PCIe devices users. -@@ -5601,8 +5534,6 @@ static int rtl_init_one(struct pci_dev * +@@ -5599,8 +5532,6 @@ static int rtl_init_one(struct pci_dev * rtl_set_irq_mask(tp); @@ -390,7 +390,7 @@ Signed-off-by: Jakub Kicinski tp->counters = dmam_alloc_coherent (&pdev->dev, sizeof(*tp->counters), &tp->counters_phys_addr, GFP_KERNEL); -@@ -5627,7 +5558,7 @@ static int rtl_init_one(struct pci_dev * +@@ -5625,7 +5556,7 @@ static int rtl_init_one(struct pci_dev * } netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n", diff --git a/lede/target/linux/generic/backport-6.12/780-37-v6.16-r8169-add-RTL_GIGA_MAC_VER_LAST-to-facilitate-adding.patch b/lede/target/linux/generic/backport-6.12/780-37-v6.16-r8169-add-RTL_GIGA_MAC_VER_LAST-to-facilitate-adding.patch index 8948a296ca..6dad3f38e1 100644 --- a/lede/target/linux/generic/backport-6.12/780-37-v6.16-r8169-add-RTL_GIGA_MAC_VER_LAST-to-facilitate-adding.patch +++ b/lede/target/linux/generic/backport-6.12/780-37-v6.16-r8169-add-RTL_GIGA_MAC_VER_LAST-to-facilitate-adding.patch @@ -85,7 +85,7 @@ Signed-off-by: Jakub Kicinski RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq); rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42); rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond_2, 100, 42); -@@ -2898,7 +2898,7 @@ static void rtl_enable_exit_l1(struct rt +@@ -2895,7 +2895,7 @@ static void rtl_enable_exit_l1(struct rt case RTL_GIGA_MAC_VER_37 ... RTL_GIGA_MAC_VER_38: rtl_eri_set_bits(tp, 0xd4, 0x0c00); break; @@ -94,7 +94,7 @@ Signed-off-by: Jakub Kicinski r8168_mac_ocp_modify(tp, 0xc0ac, 0, 0x1f80); break; default: -@@ -2912,7 +2912,7 @@ static void rtl_disable_exit_l1(struct r +@@ -2909,7 +2909,7 @@ static void rtl_disable_exit_l1(struct r case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38: rtl_eri_clear_bits(tp, 0xd4, 0x1f00); break; @@ -103,7 +103,7 @@ Signed-off-by: Jakub Kicinski r8168_mac_ocp_modify(tp, 0xc0ac, 0x1f80, 0); break; default: -@@ -2950,7 +2950,7 @@ static void rtl_hw_aspm_clkreq_enable(st +@@ -2947,7 +2947,7 @@ static void rtl_hw_aspm_clkreq_enable(st switch (tp->mac_version) { case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48: @@ -112,7 +112,7 @@ Signed-off-by: Jakub Kicinski /* reset ephy tx/rx disable timer */ r8168_mac_ocp_modify(tp, 0xe094, 0xff00, 0); /* chip can trigger L1.2 */ -@@ -2962,7 +2962,7 @@ static void rtl_hw_aspm_clkreq_enable(st +@@ -2959,7 +2959,7 @@ static void rtl_hw_aspm_clkreq_enable(st } else { switch (tp->mac_version) { case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48: @@ -121,7 +121,7 @@ Signed-off-by: Jakub Kicinski r8168_mac_ocp_modify(tp, 0xe092, 0x00ff, 0); break; default: -@@ -4094,7 +4094,7 @@ static void rtl8169_cleanup(struct rtl81 +@@ -4091,7 +4091,7 @@ static void rtl8169_cleanup(struct rtl81 RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq); rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666); break; @@ -130,7 +130,7 @@ Signed-off-by: Jakub Kicinski rtl_enable_rxdvgate(tp); fsleep(2000); break; -@@ -4251,7 +4251,7 @@ static unsigned int rtl_quirk_packet_pad +@@ -4248,7 +4248,7 @@ static unsigned int rtl_quirk_packet_pad switch (tp->mac_version) { case RTL_GIGA_MAC_VER_34: @@ -139,7 +139,7 @@ Signed-off-by: Jakub Kicinski padto = max_t(unsigned int, padto, ETH_ZLEN); break; default: -@@ -5301,7 +5301,7 @@ static void rtl_hw_initialize(struct rtl +@@ -5299,7 +5299,7 @@ static void rtl_hw_initialize(struct rtl case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48: rtl_hw_init_8168g(tp); break; @@ -148,7 +148,7 @@ Signed-off-by: Jakub Kicinski rtl_hw_init_8125(tp); break; default: -@@ -5326,7 +5326,7 @@ static int rtl_jumbo_max(struct rtl8169_ +@@ -5324,7 +5324,7 @@ static int rtl_jumbo_max(struct rtl8169_ case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_24: return JUMBO_6K; /* RTL8125/8126 */ diff --git a/lede/target/linux/generic/backport-6.12/780-38-v6.16-r8169-use-pci_prepare_to_sleep-in-rtl_shutdown.patch b/lede/target/linux/generic/backport-6.12/780-38-v6.16-r8169-use-pci_prepare_to_sleep-in-rtl_shutdown.patch index 784dc69953..0f085f08e0 100644 --- a/lede/target/linux/generic/backport-6.12/780-38-v6.16-r8169-use-pci_prepare_to_sleep-in-rtl_shutdown.patch +++ b/lede/target/linux/generic/backport-6.12/780-38-v6.16-r8169-use-pci_prepare_to_sleep-in-rtl_shutdown.patch @@ -22,7 +22,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -5039,10 +5039,8 @@ static void rtl_shutdown(struct pci_dev +@@ -5037,10 +5037,8 @@ static void rtl_shutdown(struct pci_dev /* Restore original MAC address */ rtl_rar_set(tp, tp->dev->perm_addr); diff --git a/lede/target/linux/generic/backport-6.12/780-39-v6.16-r8169-merge-chip-versions-70-and-71-RTL8126A.patch b/lede/target/linux/generic/backport-6.12/780-39-v6.16-r8169-merge-chip-versions-70-and-71-RTL8126A.patch index ecc04ef6ae..caab6c69f1 100644 --- a/lede/target/linux/generic/backport-6.12/780-39-v6.16-r8169-merge-chip-versions-70-and-71-RTL8126A.patch +++ b/lede/target/linux/generic/backport-6.12/780-39-v6.16-r8169-merge-chip-versions-70-and-71-RTL8126A.patch @@ -37,7 +37,7 @@ Signed-off-by: Jakub Kicinski { 0x7cf, 0x649, RTL_GIGA_MAC_VER_70, "RTL8126A", FIRMWARE_8126A_2 }, /* 8125BP family. */ -@@ -2939,7 +2939,6 @@ static void rtl_hw_aspm_clkreq_enable(st +@@ -2936,7 +2936,6 @@ static void rtl_hw_aspm_clkreq_enable(st rtl_mod_config5(tp, 0, ASPM_en); switch (tp->mac_version) { case RTL_GIGA_MAC_VER_70: @@ -45,7 +45,7 @@ Signed-off-by: Jakub Kicinski val8 = RTL_R8(tp, INT_CFG0_8125) | INT_CFG0_CLKREQEN; RTL_W8(tp, INT_CFG0_8125, val8); break; -@@ -2971,7 +2970,6 @@ static void rtl_hw_aspm_clkreq_enable(st +@@ -2968,7 +2967,6 @@ static void rtl_hw_aspm_clkreq_enable(st switch (tp->mac_version) { case RTL_GIGA_MAC_VER_70: @@ -53,7 +53,7 @@ Signed-off-by: Jakub Kicinski val8 = RTL_R8(tp, INT_CFG0_8125) & ~INT_CFG0_CLKREQEN; RTL_W8(tp, INT_CFG0_8125, val8); break; -@@ -3691,12 +3689,10 @@ static void rtl_hw_start_8125_common(str +@@ -3688,12 +3686,10 @@ static void rtl_hw_start_8125_common(str /* disable new tx descriptor format */ r8168_mac_ocp_modify(tp, 0xeb58, 0x0001, 0x0000); @@ -68,7 +68,7 @@ Signed-off-by: Jakub Kicinski r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400); else if (tp->mac_version == RTL_GIGA_MAC_VER_63) r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0200); -@@ -3714,8 +3710,7 @@ static void rtl_hw_start_8125_common(str +@@ -3711,8 +3707,7 @@ static void rtl_hw_start_8125_common(str r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0000); r8168_mac_ocp_modify(tp, 0xe040, 0x1000, 0x0000); r8168_mac_ocp_modify(tp, 0xea1c, 0x0003, 0x0001); @@ -78,7 +78,7 @@ Signed-off-by: Jakub Kicinski r8168_mac_ocp_modify(tp, 0xea1c, 0x0300, 0x0000); else r8168_mac_ocp_modify(tp, 0xea1c, 0x0004, 0x0000); -@@ -3838,7 +3833,6 @@ static void rtl_hw_config(struct rtl8169 +@@ -3835,7 +3830,6 @@ static void rtl_hw_config(struct rtl8169 [RTL_GIGA_MAC_VER_65] = rtl_hw_start_8125d, [RTL_GIGA_MAC_VER_66] = rtl_hw_start_8125d, [RTL_GIGA_MAC_VER_70] = rtl_hw_start_8126a, @@ -86,7 +86,7 @@ Signed-off-by: Jakub Kicinski }; if (hw_configs[tp->mac_version]) -@@ -3862,7 +3856,6 @@ static void rtl_hw_start_8125(struct rtl +@@ -3859,7 +3853,6 @@ static void rtl_hw_start_8125(struct rtl break; case RTL_GIGA_MAC_VER_63: case RTL_GIGA_MAC_VER_70: diff --git a/lede/target/linux/generic/backport-6.12/780-40-v6.16-r8169-merge-chip-versions-64-and-65-RTL8125D.patch b/lede/target/linux/generic/backport-6.12/780-40-v6.16-r8169-merge-chip-versions-64-and-65-RTL8125D.patch index a5e4c123a2..5110c2776e 100644 --- a/lede/target/linux/generic/backport-6.12/780-40-v6.16-r8169-merge-chip-versions-64-and-65-RTL8125D.patch +++ b/lede/target/linux/generic/backport-6.12/780-40-v6.16-r8169-merge-chip-versions-64-and-65-RTL8125D.patch @@ -37,7 +37,7 @@ Signed-off-by: Jakub Kicinski { 0x7cf, 0x688, RTL_GIGA_MAC_VER_64, "RTL8125D", FIRMWARE_8125D_1 }, /* 8125B family. */ -@@ -3830,7 +3830,6 @@ static void rtl_hw_config(struct rtl8169 +@@ -3827,7 +3827,6 @@ static void rtl_hw_config(struct rtl8169 [RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2, [RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b, [RTL_GIGA_MAC_VER_64] = rtl_hw_start_8125d, @@ -45,7 +45,7 @@ Signed-off-by: Jakub Kicinski [RTL_GIGA_MAC_VER_66] = rtl_hw_start_8125d, [RTL_GIGA_MAC_VER_70] = rtl_hw_start_8126a, }; -@@ -3849,7 +3848,6 @@ static void rtl_hw_start_8125(struct rtl +@@ -3846,7 +3845,6 @@ static void rtl_hw_start_8125(struct rtl switch (tp->mac_version) { case RTL_GIGA_MAC_VER_61: case RTL_GIGA_MAC_VER_64: diff --git a/lede/target/linux/generic/backport-6.12/780-41-v6.16-r8169-merge-chip-versions-52-and-53-RTL8117.patch b/lede/target/linux/generic/backport-6.12/780-41-v6.16-r8169-merge-chip-versions-52-and-53-RTL8117.patch index 7ed72a9897..b28c28f4e2 100644 --- a/lede/target/linux/generic/backport-6.12/780-41-v6.16-r8169-merge-chip-versions-52-and-53-RTL8117.patch +++ b/lede/target/linux/generic/backport-6.12/780-41-v6.16-r8169-merge-chip-versions-52-and-53-RTL8117.patch @@ -84,7 +84,7 @@ Signed-off-by: Jakub Kicinski rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42); rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42); break; -@@ -3826,7 +3824,6 @@ static void rtl_hw_config(struct rtl8169 +@@ -3823,7 +3821,6 @@ static void rtl_hw_config(struct rtl8169 [RTL_GIGA_MAC_VER_48] = rtl_hw_start_8168h_1, [RTL_GIGA_MAC_VER_51] = rtl_hw_start_8168ep_3, [RTL_GIGA_MAC_VER_52] = rtl_hw_start_8117, @@ -92,7 +92,7 @@ Signed-off-by: Jakub Kicinski [RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2, [RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b, [RTL_GIGA_MAC_VER_64] = rtl_hw_start_8125d, -@@ -5284,7 +5281,7 @@ static void rtl_hw_init_8125(struct rtl8 +@@ -5282,7 +5279,7 @@ static void rtl_hw_init_8125(struct rtl8 static void rtl_hw_initialize(struct rtl8169_private *tp) { switch (tp->mac_version) { diff --git a/lede/target/linux/generic/backport-6.12/780-42-v6.16-r8169-add-support-for-RTL8127A.patch b/lede/target/linux/generic/backport-6.12/780-42-v6.16-r8169-add-support-for-RTL8127A.patch index 5ed1f341ec..45587a39b7 100644 --- a/lede/target/linux/generic/backport-6.12/780-42-v6.16-r8169-add-support-for-RTL8127A.patch +++ b/lede/target/linux/generic/backport-6.12/780-42-v6.16-r8169-add-support-for-RTL8127A.patch @@ -64,7 +64,7 @@ Signed-off-by: Jakub Kicinski static inline struct device *tp_to_dev(struct rtl8169_private *tp) { -@@ -2937,6 +2944,7 @@ static void rtl_hw_aspm_clkreq_enable(st +@@ -2934,6 +2941,7 @@ static void rtl_hw_aspm_clkreq_enable(st rtl_mod_config5(tp, 0, ASPM_en); switch (tp->mac_version) { case RTL_GIGA_MAC_VER_70: @@ -72,7 +72,7 @@ Signed-off-by: Jakub Kicinski val8 = RTL_R8(tp, INT_CFG0_8125) | INT_CFG0_CLKREQEN; RTL_W8(tp, INT_CFG0_8125, val8); break; -@@ -2968,6 +2976,7 @@ static void rtl_hw_aspm_clkreq_enable(st +@@ -2965,6 +2973,7 @@ static void rtl_hw_aspm_clkreq_enable(st switch (tp->mac_version) { case RTL_GIGA_MAC_VER_70: @@ -80,7 +80,7 @@ Signed-off-by: Jakub Kicinski val8 = RTL_R8(tp, INT_CFG0_8125) & ~INT_CFG0_CLKREQEN; RTL_W8(tp, INT_CFG0_8125, val8); break; -@@ -3687,10 +3696,13 @@ static void rtl_hw_start_8125_common(str +@@ -3684,10 +3693,13 @@ static void rtl_hw_start_8125_common(str /* disable new tx descriptor format */ r8168_mac_ocp_modify(tp, 0xeb58, 0x0001, 0x0000); @@ -96,7 +96,7 @@ Signed-off-by: Jakub Kicinski r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400); else if (tp->mac_version == RTL_GIGA_MAC_VER_63) r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0200); -@@ -3708,7 +3720,8 @@ static void rtl_hw_start_8125_common(str +@@ -3705,7 +3717,8 @@ static void rtl_hw_start_8125_common(str r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0000); r8168_mac_ocp_modify(tp, 0xe040, 0x1000, 0x0000); r8168_mac_ocp_modify(tp, 0xea1c, 0x0003, 0x0001); @@ -106,7 +106,7 @@ Signed-off-by: Jakub Kicinski r8168_mac_ocp_modify(tp, 0xea1c, 0x0300, 0x0000); else r8168_mac_ocp_modify(tp, 0xea1c, 0x0004, 0x0000); -@@ -3786,6 +3799,12 @@ static void rtl_hw_start_8126a(struct rt +@@ -3783,6 +3796,12 @@ static void rtl_hw_start_8126a(struct rt rtl_hw_start_8125_common(tp); } @@ -119,7 +119,7 @@ Signed-off-by: Jakub Kicinski static void rtl_hw_config(struct rtl8169_private *tp) { static const rtl_generic_fct hw_configs[] = { -@@ -3829,6 +3848,7 @@ static void rtl_hw_config(struct rtl8169 +@@ -3826,6 +3845,7 @@ static void rtl_hw_config(struct rtl8169 [RTL_GIGA_MAC_VER_64] = rtl_hw_start_8125d, [RTL_GIGA_MAC_VER_66] = rtl_hw_start_8125d, [RTL_GIGA_MAC_VER_70] = rtl_hw_start_8126a, @@ -127,7 +127,7 @@ Signed-off-by: Jakub Kicinski }; if (hw_configs[tp->mac_version]) -@@ -3846,8 +3866,11 @@ static void rtl_hw_start_8125(struct rtl +@@ -3843,8 +3863,11 @@ static void rtl_hw_start_8125(struct rtl case RTL_GIGA_MAC_VER_61: case RTL_GIGA_MAC_VER_64: case RTL_GIGA_MAC_VER_66: diff --git a/lede/target/linux/generic/backport-6.12/781-28-v6.18-net-phy-realtek-convert-RTL8226-CG-to-c45-only.patch b/lede/target/linux/generic/backport-6.12/781-28-v6.18-net-phy-realtek-convert-RTL8226-CG-to-c45-only.patch new file mode 100644 index 0000000000..43f2c7b82c --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/781-28-v6.18-net-phy-realtek-convert-RTL8226-CG-to-c45-only.patch @@ -0,0 +1,169 @@ +From 34167f1a024d2c5abae0b0325a6d0b8257160f86 Mon Sep 17 00:00:00 2001 +From: Markus Stockhausen +Date: Wed, 13 Aug 2025 01:44:07 -0400 +Subject: net: phy: realtek: convert RTL8226-CG to c45 only + +Short: Convert the RTL8226-CG to c45 so it can be used in its +Realtek based ecosystems. + +Long: The RTL8226-CG can be mainly found on devices of the +Realtek Otto switch platform. Devices like the Zyxel XGS1210-12 +are based on it. These implement a hardware based phy polling +in the background to update SoC status registers. + +The hardware provides 4 smi busses where phys are attached to. +For each bus one can decide if it is polled in c45 or c22 mode. +See https://svanheule.net/realtek/longan/register/smi_glb_ctrl +With this setting the register access will be limited by the +hardware. This is very complex (including caching and special +c45-over-c22 handling). But basically it boils down to "enable +protocol x and SoC will disable register access via protocol y". + +Mainline already gained support for the rtl9300 mdio driver +in commit 24e31e474769 ("net: mdio: Add RTL9300 MDIO driver"). + +It covers the basic features, but a lot effort is still needed +to understand hardware properly. So it runs a simple setup by +selecting the proper bus mode during startup. + + /* Put the interfaces into C45 mode if required */ + glb_ctrl_mask = GENMASK(19, 16); + for (i = 0; i < MAX_SMI_BUSSES; i++) + if (priv->smi_bus_is_c45[i]) + glb_ctrl_val |= GLB_CTRL_INTF_SEL(i); + ... + err = regmap_update_bits(regmap, SMI_GLB_CTRL, + glb_ctrl_mask, glb_ctrl_val); + +To avoid complex coding later on, it limits access by only +providing either c22 or c45: + + bus->name = "Realtek Switch MDIO Bus"; + if (priv->smi_bus_is_c45[mdio_bus]) { + bus->read_c45 = rtl9300_mdio_read_c45; + bus->write_c45 = rtl9300_mdio_write_c45; + } else { + bus->read = rtl9300_mdio_read_c22; + bus->write = rtl9300_mdio_write_c22; + } + +Because of these limitations the existing RTL8226 phy driver +is not working at all on Realtek switches. Convert the driver +to c45-only. + +Luckily the RTL8226 seems to support proper MDIO_PMA_EXTABLE +flags. So standard function genphy_c45_pma_read_abilities() can +call genphy_c45_pma_read_ext_abilities() and 10/100/1000 is +populated right. Thus conversion is straight forward. + +Outputs before - REMARK: For this a "hacked" bus was used that +toggles the mode for each c22/c45 access. But that is slow and +produces unstable data in the SoC status registers). + +Settings for lan9: + Supported ports: [ TP MII ] + Supported link modes: 10baseT/Half 10baseT/Full + 100baseT/Half 100baseT/Full + 1000baseT/Full + 2500baseT/Full + Supported pause frame use: Symmetric Receive-only + Supports auto-negotiation: Yes + Supported FEC modes: Not reported + Advertised link modes: 10baseT/Half 10baseT/Full + 100baseT/Half 100baseT/Full + 1000baseT/Full + 2500baseT/Full + Advertised pause frame use: Symmetric Receive-only + Advertised auto-negotiation: Yes + Advertised FEC modes: Not reported + Speed: Unknown! + Duplex: Unknown! (255) + Port: Twisted Pair + PHYAD: 24 + Transceiver: external + Auto-negotiation: on + MDI-X: Unknown + Supports Wake-on: d + Wake-on: d + Link detected: no + +Outputs with this commit: + +Settings for lan9: + Supported ports: [ TP ] + Supported link modes: 10baseT/Half 10baseT/Full + 100baseT/Half 100baseT/Full + 1000baseT/Full + 2500baseT/Full + Supported pause frame use: Symmetric Receive-only + Supports auto-negotiation: Yes + Supported FEC modes: Not reported + Advertised link modes: 10baseT/Half 10baseT/Full + 100baseT/Half 100baseT/Full + 1000baseT/Full + 2500baseT/Full + Advertised pause frame use: Symmetric Receive-only + Advertised auto-negotiation: Yes + Advertised FEC modes: Not reported + Speed: Unknown! + Duplex: Unknown! (255) + Port: Twisted Pair + PHYAD: 24 + Transceiver: external + Auto-negotiation: on + MDI-X: Unknown + Supports Wake-on: d + Wake-on: d + Link detected: no + +Signed-off-by: Markus Stockhausen +Link: https://patch.msgid.link/20250813054407.1108285-1-markus.stockhausen@gmx.de +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 28 +++++++++++++++++++++------- + 1 file changed, 21 insertions(+), 7 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -1274,6 +1274,21 @@ static int rtl822x_c45_read_status(struc + return 0; + } + ++static int rtl822x_c45_soft_reset(struct phy_device *phydev) ++{ ++ int ret, val; ++ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, ++ MDIO_CTRL1_RESET, MDIO_CTRL1_RESET); ++ if (ret < 0) ++ return ret; ++ ++ return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PMAPMD, ++ MDIO_CTRL1, val, ++ !(val & MDIO_CTRL1_RESET), ++ 5000, 100000, true); ++} ++ + static int rtl822xb_c45_read_status(struct phy_device *phydev) + { + int ret; +@@ -1660,13 +1675,12 @@ static struct phy_driver realtek_drvs[] + }, { + PHY_ID_MATCH_EXACT(0x001cc838), + .name = "RTL8226-CG 2.5Gbps PHY", +- .get_features = rtl822x_get_features, +- .config_aneg = rtl822x_config_aneg, +- .read_status = rtl822x_read_status, +- .suspend = genphy_suspend, +- .resume = rtlgen_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, ++ .soft_reset = rtl822x_c45_soft_reset, ++ .get_features = rtl822x_c45_get_features, ++ .config_aneg = rtl822x_c45_config_aneg, ++ .read_status = rtl822x_c45_read_status, ++ .suspend = genphy_c45_pma_suspend, ++ .resume = rtlgen_c45_resume, + }, { + PHY_ID_MATCH_EXACT(0x001cc848), + .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", diff --git a/lede/target/linux/generic/backport-6.12/781-29-v6.18-net-phy-realtek-enable-serdes-option-mode-for-RTL8226-CG.patch b/lede/target/linux/generic/backport-6.12/781-29-v6.18-net-phy-realtek-enable-serdes-option-mode-for-RTL8226-CG.patch new file mode 100644 index 0000000000..9ffb260df1 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/781-29-v6.18-net-phy-realtek-enable-serdes-option-mode-for-RTL8226-CG.patch @@ -0,0 +1,92 @@ +From 3a752e67800106a5c42d802d67e06c60aa71d07b Mon Sep 17 00:00:00 2001 +From: Markus Stockhausen +Date: Fri, 15 Aug 2025 04:20:09 -0400 +Subject: net: phy: realtek: enable serdes option mode for RTL8226-CG + +The RTL8226-CG can make use of the serdes option mode feature to +dynamically switch between SGMII and 2500base-X. From what is +known the setup sequence is much simpler with no magic values. + +Convert the exiting config_init() into a helper that configures +the PHY depending on generation 1 or 2. Call the helper from two +separated new config_init() functions. + +Finally convert the phy_driver specs of the RTL8226-CG to make +use of the new configuration and switch over to the extended +read_status() function to dynamically change the interface +according to the serdes mode. + +Remark! The logic could be simpler if the serdes mode could be +set before all other generation 2 magic values. Due to missing +RTL8221B test hardware the mmd command order was kept. + +Tested on Zyxel XGS1210-12. + +Signed-off-by: Markus Stockhausen +Link: https://patch.msgid.link/20250815082009.3678865-1-markus.stockhausen@gmx.de +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 26 ++++++++++++++++++++------ + 1 file changed, 20 insertions(+), 6 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -1032,7 +1032,7 @@ static int rtl822x_probe(struct phy_devi + return 0; + } + +-static int rtl822xb_config_init(struct phy_device *phydev) ++static int rtl822x_set_serdes_option_mode(struct phy_device *phydev, bool gen1) + { + bool has_2500, has_sgmii; + u16 mode; +@@ -1067,15 +1067,18 @@ static int rtl822xb_config_init(struct p + /* the following sequence with magic numbers sets up the SerDes + * option mode + */ +- ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x75f3, 0); +- if (ret < 0) +- return ret; ++ ++ if (!gen1) { ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x75f3, 0); ++ if (ret < 0) ++ return ret; ++ } + + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND1, + RTL822X_VND1_SERDES_OPTION, + RTL822X_VND1_SERDES_OPTION_MODE_MASK, + mode); +- if (ret < 0) ++ if (gen1 || ret < 0) + return ret; + + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6a04, 0x0503); +@@ -1089,6 +1092,16 @@ static int rtl822xb_config_init(struct p + return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020); + } + ++static int rtl822x_config_init(struct phy_device *phydev) ++{ ++ return rtl822x_set_serdes_option_mode(phydev, true); ++} ++ ++static int rtl822xb_config_init(struct phy_device *phydev) ++{ ++ return rtl822x_set_serdes_option_mode(phydev, false); ++} ++ + static int rtl822xb_get_rate_matching(struct phy_device *phydev, + phy_interface_t iface) + { +@@ -1678,7 +1691,8 @@ static struct phy_driver realtek_drvs[] + .soft_reset = rtl822x_c45_soft_reset, + .get_features = rtl822x_c45_get_features, + .config_aneg = rtl822x_c45_config_aneg, +- .read_status = rtl822x_c45_read_status, ++ .config_init = rtl822x_config_init, ++ .read_status = rtl822xb_c45_read_status, + .suspend = genphy_c45_pma_suspend, + .resume = rtlgen_c45_resume, + }, { diff --git a/lede/target/linux/generic/backport-6.12/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch b/lede/target/linux/generic/backport-6.12/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch index cda5226904..c22231ea66 100644 --- a/lede/target/linux/generic/backport-6.12/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch +++ b/lede/target/linux/generic/backport-6.12/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch @@ -281,7 +281,7 @@ Signed-off-by: Jakub Kicinski } --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -1004,7 +1004,8 @@ struct phy_driver { +@@ -1045,7 +1045,8 @@ struct phy_driver { * driver for the given phydev. If NULL, matching is based on * phy_id and phy_id_mask. */ diff --git a/lede/target/linux/generic/backport-6.12/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch b/lede/target/linux/generic/backport-6.12/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch index 9e28011b0c..1ac3b2333f 100644 --- a/lede/target/linux/generic/backport-6.12/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch +++ b/lede/target/linux/generic/backport-6.12/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch @@ -97,7 +97,7 @@ Signed-off-by: Jakub Kicinski static ssize_t --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -1906,6 +1906,9 @@ char *phy_attached_info_irq(struct phy_d +@@ -1950,6 +1950,9 @@ char *phy_attached_info_irq(struct phy_d __malloc; void phy_attached_info(struct phy_device *phydev); diff --git a/lede/target/linux/generic/backport-6.12/782-05-v6.16-net-phy-Add-support-for-Aeonsemi-AS21xxx-PHYs.patch b/lede/target/linux/generic/backport-6.12/782-05-v6.16-net-phy-Add-support-for-Aeonsemi-AS21xxx-PHYs.patch index bcf9b1a6e5..f1bcb35e66 100644 --- a/lede/target/linux/generic/backport-6.12/782-05-v6.16-net-phy-Add-support-for-Aeonsemi-AS21xxx-PHYs.patch +++ b/lede/target/linux/generic/backport-6.12/782-05-v6.16-net-phy-Add-support-for-Aeonsemi-AS21xxx-PHYs.patch @@ -42,6 +42,21 @@ Signed-off-by: Jakub Kicinski 4 files changed, 1106 insertions(+) create mode 100644 drivers/net/phy/as21xxx.c +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -637,6 +637,12 @@ F: drivers/iio/accel/adxl380.h + F: drivers/iio/accel/adxl380_i2c.c + F: drivers/iio/accel/adxl380_spi.c + ++AEONSEMI PHY DRIVER ++M: Christian Marangi ++L: netdev@vger.kernel.org ++S: Maintained ++F: drivers/net/phy/as21xxx.c ++ + AF8133J THREE-AXIS MAGNETOMETER DRIVER + M: Ondřej Jirman + S: Maintained --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -79,6 +79,18 @@ config SFP @@ -964,7 +979,7 @@ Signed-off-by: Jakub Kicinski + + /* Skip PHY that are not AS21xxx or already have firmware loaded */ + if (phydev->c45_ids.device_ids[MDIO_MMD_PCS] != PHY_ID_AS21XXX) -+ return genphy_match_phy_device(phydev, (struct phy_driver *)phydrv); ++ return genphy_match_phy_device(phydev, phydrv); + + /* Read PHY ID to handle firmware just loaded */ + ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID1); diff --git a/lede/target/linux/generic/backport-6.12/783-01-v6.18-net-dsa-Move-KS8995-to-the-DSA-subsystem.patch b/lede/target/linux/generic/backport-6.12/783-01-v6.18-net-dsa-Move-KS8995-to-the-DSA-subsystem.patch new file mode 100644 index 0000000000..204595693f --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/783-01-v6.18-net-dsa-Move-KS8995-to-the-DSA-subsystem.patch @@ -0,0 +1,1092 @@ +From 9c370f7f92b0232fe925ca2caefb5e3126a0357d Mon Sep 17 00:00:00 2001 +From: Linus Walleij +Date: Wed, 13 Aug 2025 23:43:03 +0200 +Subject: [PATCH 1/4] net: dsa: Move KS8995 to the DSA subsystem + +By reading the datasheets for the KS8995 it is obvious that this +is a 100 Mbit DSA switch. + +Let us start the refactoring by moving it to the DSA subsystem to +preserve development history. + +Verified that the chip still probes the same after this patch +provided CONFIG_HAVE_NET_DSA, CONFIG_NET_DSA and CONFIG_DSA_KS8995 +are selected. + +Signed-off-by: Linus Walleij +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250813-ks8995-to-dsa-v1-1-75c359ede3a5@linaro.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/Kconfig | 7 +++++++ + drivers/net/dsa/Makefile | 1 + + drivers/net/{phy/spi_ks8995.c => dsa/ks8995.c} | 0 + drivers/net/phy/Kconfig | 4 ---- + drivers/net/phy/Makefile | 1 - + 5 files changed, 8 insertions(+), 5 deletions(-) + rename drivers/net/{phy/spi_ks8995.c => dsa/ks8995.c} (100%) + +--- a/drivers/net/dsa/Kconfig ++++ b/drivers/net/dsa/Kconfig +@@ -98,6 +98,13 @@ config NET_DSA_RZN1_A5PSW + This driver supports the A5PSW switch, which is embedded in Renesas + RZ/N1 SoC. + ++config NET_DSA_KS8995 ++ tristate "Micrel KS8995 family 5-ports 10/100 Ethernet switches" ++ depends on SPI ++ help ++ This driver supports the Micrel KS8995 family of 10/100 Mbit ethernet ++ switches, managed over SPI. ++ + config NET_DSA_SMSC_LAN9303 + tristate + select NET_DSA_TAG_LAN9303 +--- a/drivers/net/dsa/Makefile ++++ b/drivers/net/dsa/Makefile +@@ -5,6 +5,7 @@ obj-$(CONFIG_NET_DSA_LOOP) += dsa_loop.o + ifdef CONFIG_NET_DSA_LOOP + obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdinfo.o + endif ++obj-$(CONFIG_NET_DSA_KS8995) += ks8995.o + obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o + obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o + obj-$(CONFIG_NET_DSA_MT7530_MDIO) += mt7530-mdio.o +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -443,7 +443,3 @@ config XILINX_GMII2RGMII + Ethernet physical media devices and the Gigabit Ethernet controller. + + endif # PHYLIB +- +-config MICREL_KS8995MA +- tristate "Micrel KS8995MA 5-ports 10/100 managed Ethernet switch" +- depends on SPI +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -77,7 +77,6 @@ obj-$(CONFIG_MARVELL_88X2222_PHY) += mar + obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o + obj-y += mediatek/ + obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o +-obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o + obj-$(CONFIG_MICREL_PHY) += micrel.o + obj-$(CONFIG_MICROCHIP_PHY) += microchip.o + obj-$(CONFIG_MICROCHIP_T1_PHY) += microchip_t1.o +--- /dev/null ++++ b/drivers/net/dsa/ks8995.c +@@ -0,0 +1,506 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * SPI driver for Micrel/Kendin KS8995M and KSZ8864RMN ethernet switches ++ * ++ * Copyright (C) 2008 Gabor Juhos ++ * ++ * This file was based on: drivers/spi/at25.c ++ * Copyright (C) 2006 David Brownell ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define DRV_VERSION "0.1.1" ++#define DRV_DESC "Micrel KS8995 Ethernet switch SPI driver" ++ ++/* ------------------------------------------------------------------------ */ ++ ++#define KS8995_REG_ID0 0x00 /* Chip ID0 */ ++#define KS8995_REG_ID1 0x01 /* Chip ID1 */ ++ ++#define KS8995_REG_GC0 0x02 /* Global Control 0 */ ++#define KS8995_REG_GC1 0x03 /* Global Control 1 */ ++#define KS8995_REG_GC2 0x04 /* Global Control 2 */ ++#define KS8995_REG_GC3 0x05 /* Global Control 3 */ ++#define KS8995_REG_GC4 0x06 /* Global Control 4 */ ++#define KS8995_REG_GC5 0x07 /* Global Control 5 */ ++#define KS8995_REG_GC6 0x08 /* Global Control 6 */ ++#define KS8995_REG_GC7 0x09 /* Global Control 7 */ ++#define KS8995_REG_GC8 0x0a /* Global Control 8 */ ++#define KS8995_REG_GC9 0x0b /* Global Control 9 */ ++ ++#define KS8995_REG_PC(p, r) ((0x10 * p) + r) /* Port Control */ ++#define KS8995_REG_PS(p, r) ((0x10 * p) + r + 0xe) /* Port Status */ ++ ++#define KS8995_REG_TPC0 0x60 /* TOS Priority Control 0 */ ++#define KS8995_REG_TPC1 0x61 /* TOS Priority Control 1 */ ++#define KS8995_REG_TPC2 0x62 /* TOS Priority Control 2 */ ++#define KS8995_REG_TPC3 0x63 /* TOS Priority Control 3 */ ++#define KS8995_REG_TPC4 0x64 /* TOS Priority Control 4 */ ++#define KS8995_REG_TPC5 0x65 /* TOS Priority Control 5 */ ++#define KS8995_REG_TPC6 0x66 /* TOS Priority Control 6 */ ++#define KS8995_REG_TPC7 0x67 /* TOS Priority Control 7 */ ++ ++#define KS8995_REG_MAC0 0x68 /* MAC address 0 */ ++#define KS8995_REG_MAC1 0x69 /* MAC address 1 */ ++#define KS8995_REG_MAC2 0x6a /* MAC address 2 */ ++#define KS8995_REG_MAC3 0x6b /* MAC address 3 */ ++#define KS8995_REG_MAC4 0x6c /* MAC address 4 */ ++#define KS8995_REG_MAC5 0x6d /* MAC address 5 */ ++ ++#define KS8995_REG_IAC0 0x6e /* Indirect Access Control 0 */ ++#define KS8995_REG_IAC1 0x6f /* Indirect Access Control 0 */ ++#define KS8995_REG_IAD7 0x70 /* Indirect Access Data 7 */ ++#define KS8995_REG_IAD6 0x71 /* Indirect Access Data 6 */ ++#define KS8995_REG_IAD5 0x72 /* Indirect Access Data 5 */ ++#define KS8995_REG_IAD4 0x73 /* Indirect Access Data 4 */ ++#define KS8995_REG_IAD3 0x74 /* Indirect Access Data 3 */ ++#define KS8995_REG_IAD2 0x75 /* Indirect Access Data 2 */ ++#define KS8995_REG_IAD1 0x76 /* Indirect Access Data 1 */ ++#define KS8995_REG_IAD0 0x77 /* Indirect Access Data 0 */ ++ ++#define KSZ8864_REG_ID1 0xfe /* Chip ID in bit 7 */ ++ ++#define KS8995_REGS_SIZE 0x80 ++#define KSZ8864_REGS_SIZE 0x100 ++#define KSZ8795_REGS_SIZE 0x100 ++ ++#define ID1_CHIPID_M 0xf ++#define ID1_CHIPID_S 4 ++#define ID1_REVISION_M 0x7 ++#define ID1_REVISION_S 1 ++#define ID1_START_SW 1 /* start the switch */ ++ ++#define FAMILY_KS8995 0x95 ++#define FAMILY_KSZ8795 0x87 ++#define CHIPID_M 0 ++#define KS8995_CHIP_ID 0x00 ++#define KSZ8864_CHIP_ID 0x01 ++#define KSZ8795_CHIP_ID 0x09 ++ ++#define KS8995_CMD_WRITE 0x02U ++#define KS8995_CMD_READ 0x03U ++ ++#define KS8995_RESET_DELAY 10 /* usec */ ++ ++enum ks8995_chip_variant { ++ ks8995, ++ ksz8864, ++ ksz8795, ++ max_variant ++}; ++ ++struct ks8995_chip_params { ++ char *name; ++ int family_id; ++ int chip_id; ++ int regs_size; ++ int addr_width; ++ int addr_shift; ++}; ++ ++static const struct ks8995_chip_params ks8995_chip[] = { ++ [ks8995] = { ++ .name = "KS8995MA", ++ .family_id = FAMILY_KS8995, ++ .chip_id = KS8995_CHIP_ID, ++ .regs_size = KS8995_REGS_SIZE, ++ .addr_width = 8, ++ .addr_shift = 0, ++ }, ++ [ksz8864] = { ++ .name = "KSZ8864RMN", ++ .family_id = FAMILY_KS8995, ++ .chip_id = KSZ8864_CHIP_ID, ++ .regs_size = KSZ8864_REGS_SIZE, ++ .addr_width = 8, ++ .addr_shift = 0, ++ }, ++ [ksz8795] = { ++ .name = "KSZ8795CLX", ++ .family_id = FAMILY_KSZ8795, ++ .chip_id = KSZ8795_CHIP_ID, ++ .regs_size = KSZ8795_REGS_SIZE, ++ .addr_width = 12, ++ .addr_shift = 1, ++ }, ++}; ++ ++struct ks8995_switch { ++ struct spi_device *spi; ++ struct mutex lock; ++ struct gpio_desc *reset_gpio; ++ struct bin_attribute regs_attr; ++ const struct ks8995_chip_params *chip; ++ int revision_id; ++}; ++ ++static const struct spi_device_id ks8995_id[] = { ++ {"ks8995", ks8995}, ++ {"ksz8864", ksz8864}, ++ {"ksz8795", ksz8795}, ++ { } ++}; ++MODULE_DEVICE_TABLE(spi, ks8995_id); ++ ++static const struct of_device_id ks8895_spi_of_match[] = { ++ { .compatible = "micrel,ks8995" }, ++ { .compatible = "micrel,ksz8864" }, ++ { .compatible = "micrel,ksz8795" }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, ks8895_spi_of_match); ++ ++static inline u8 get_chip_id(u8 val) ++{ ++ return (val >> ID1_CHIPID_S) & ID1_CHIPID_M; ++} ++ ++static inline u8 get_chip_rev(u8 val) ++{ ++ return (val >> ID1_REVISION_S) & ID1_REVISION_M; ++} ++ ++/* create_spi_cmd - create a chip specific SPI command header ++ * @ks: pointer to switch instance ++ * @cmd: SPI command for switch ++ * @address: register address for command ++ * ++ * Different chip families use different bit pattern to address the switches ++ * registers: ++ * ++ * KS8995: 8bit command + 8bit address ++ * KSZ8795: 3bit command + 12bit address + 1bit TR (?) ++ */ ++static inline __be16 create_spi_cmd(struct ks8995_switch *ks, int cmd, ++ unsigned address) ++{ ++ u16 result = cmd; ++ ++ /* make room for address (incl. address shift) */ ++ result <<= ks->chip->addr_width + ks->chip->addr_shift; ++ /* add address */ ++ result |= address << ks->chip->addr_shift; ++ /* SPI protocol needs big endian */ ++ return cpu_to_be16(result); ++} ++/* ------------------------------------------------------------------------ */ ++static int ks8995_read(struct ks8995_switch *ks, char *buf, ++ unsigned offset, size_t count) ++{ ++ __be16 cmd; ++ struct spi_transfer t[2]; ++ struct spi_message m; ++ int err; ++ ++ cmd = create_spi_cmd(ks, KS8995_CMD_READ, offset); ++ spi_message_init(&m); ++ ++ memset(&t, 0, sizeof(t)); ++ ++ t[0].tx_buf = &cmd; ++ t[0].len = sizeof(cmd); ++ spi_message_add_tail(&t[0], &m); ++ ++ t[1].rx_buf = buf; ++ t[1].len = count; ++ spi_message_add_tail(&t[1], &m); ++ ++ mutex_lock(&ks->lock); ++ err = spi_sync(ks->spi, &m); ++ mutex_unlock(&ks->lock); ++ ++ return err ? err : count; ++} ++ ++static int ks8995_write(struct ks8995_switch *ks, char *buf, ++ unsigned offset, size_t count) ++{ ++ __be16 cmd; ++ struct spi_transfer t[2]; ++ struct spi_message m; ++ int err; ++ ++ cmd = create_spi_cmd(ks, KS8995_CMD_WRITE, offset); ++ spi_message_init(&m); ++ ++ memset(&t, 0, sizeof(t)); ++ ++ t[0].tx_buf = &cmd; ++ t[0].len = sizeof(cmd); ++ spi_message_add_tail(&t[0], &m); ++ ++ t[1].tx_buf = buf; ++ t[1].len = count; ++ spi_message_add_tail(&t[1], &m); ++ ++ mutex_lock(&ks->lock); ++ err = spi_sync(ks->spi, &m); ++ mutex_unlock(&ks->lock); ++ ++ return err ? err : count; ++} ++ ++static inline int ks8995_read_reg(struct ks8995_switch *ks, u8 addr, u8 *buf) ++{ ++ return ks8995_read(ks, buf, addr, 1) != 1; ++} ++ ++static inline int ks8995_write_reg(struct ks8995_switch *ks, u8 addr, u8 val) ++{ ++ char buf = val; ++ ++ return ks8995_write(ks, &buf, addr, 1) != 1; ++} ++ ++/* ------------------------------------------------------------------------ */ ++ ++static int ks8995_stop(struct ks8995_switch *ks) ++{ ++ return ks8995_write_reg(ks, KS8995_REG_ID1, 0); ++} ++ ++static int ks8995_start(struct ks8995_switch *ks) ++{ ++ return ks8995_write_reg(ks, KS8995_REG_ID1, 1); ++} ++ ++static int ks8995_reset(struct ks8995_switch *ks) ++{ ++ int err; ++ ++ err = ks8995_stop(ks); ++ if (err) ++ return err; ++ ++ udelay(KS8995_RESET_DELAY); ++ ++ return ks8995_start(ks); ++} ++ ++static ssize_t ks8995_registers_read(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) ++{ ++ struct device *dev; ++ struct ks8995_switch *ks8995; ++ ++ dev = kobj_to_dev(kobj); ++ ks8995 = dev_get_drvdata(dev); ++ ++ return ks8995_read(ks8995, buf, off, count); ++} ++ ++static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) ++{ ++ struct device *dev; ++ struct ks8995_switch *ks8995; ++ ++ dev = kobj_to_dev(kobj); ++ ks8995 = dev_get_drvdata(dev); ++ ++ return ks8995_write(ks8995, buf, off, count); ++} ++ ++/* ks8995_get_revision - get chip revision ++ * @ks: pointer to switch instance ++ * ++ * Verify chip family and id and get chip revision. ++ */ ++static int ks8995_get_revision(struct ks8995_switch *ks) ++{ ++ int err; ++ u8 id0, id1, ksz8864_id; ++ ++ /* read family id */ ++ err = ks8995_read_reg(ks, KS8995_REG_ID0, &id0); ++ if (err) { ++ err = -EIO; ++ goto err_out; ++ } ++ ++ /* verify family id */ ++ if (id0 != ks->chip->family_id) { ++ dev_err(&ks->spi->dev, "chip family id mismatch: expected 0x%02x but 0x%02x read\n", ++ ks->chip->family_id, id0); ++ err = -ENODEV; ++ goto err_out; ++ } ++ ++ switch (ks->chip->family_id) { ++ case FAMILY_KS8995: ++ /* try reading chip id at CHIP ID1 */ ++ err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1); ++ if (err) { ++ err = -EIO; ++ goto err_out; ++ } ++ ++ /* verify chip id */ ++ if ((get_chip_id(id1) == CHIPID_M) && ++ (get_chip_id(id1) == ks->chip->chip_id)) { ++ /* KS8995MA */ ++ ks->revision_id = get_chip_rev(id1); ++ } else if (get_chip_id(id1) != CHIPID_M) { ++ /* KSZ8864RMN */ ++ err = ks8995_read_reg(ks, KS8995_REG_ID1, &ksz8864_id); ++ if (err) { ++ err = -EIO; ++ goto err_out; ++ } ++ ++ if ((ksz8864_id & 0x80) && ++ (ks->chip->chip_id == KSZ8864_CHIP_ID)) { ++ ks->revision_id = get_chip_rev(id1); ++ } ++ ++ } else { ++ dev_err(&ks->spi->dev, "unsupported chip id for KS8995 family: 0x%02x\n", ++ id1); ++ err = -ENODEV; ++ } ++ break; ++ case FAMILY_KSZ8795: ++ /* try reading chip id at CHIP ID1 */ ++ err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1); ++ if (err) { ++ err = -EIO; ++ goto err_out; ++ } ++ ++ if (get_chip_id(id1) == ks->chip->chip_id) { ++ ks->revision_id = get_chip_rev(id1); ++ } else { ++ dev_err(&ks->spi->dev, "unsupported chip id for KSZ8795 family: 0x%02x\n", ++ id1); ++ err = -ENODEV; ++ } ++ break; ++ default: ++ dev_err(&ks->spi->dev, "unsupported family id: 0x%02x\n", id0); ++ err = -ENODEV; ++ break; ++ } ++err_out: ++ return err; ++} ++ ++static const struct bin_attribute ks8995_registers_attr = { ++ .attr = { ++ .name = "registers", ++ .mode = 0600, ++ }, ++ .size = KS8995_REGS_SIZE, ++ .read = ks8995_registers_read, ++ .write = ks8995_registers_write, ++}; ++ ++/* ------------------------------------------------------------------------ */ ++static int ks8995_probe(struct spi_device *spi) ++{ ++ struct ks8995_switch *ks; ++ int err; ++ int variant = spi_get_device_id(spi)->driver_data; ++ ++ if (variant >= max_variant) { ++ dev_err(&spi->dev, "bad chip variant %d\n", variant); ++ return -ENODEV; ++ } ++ ++ ks = devm_kzalloc(&spi->dev, sizeof(*ks), GFP_KERNEL); ++ if (!ks) ++ return -ENOMEM; ++ ++ mutex_init(&ks->lock); ++ ks->spi = spi; ++ ks->chip = &ks8995_chip[variant]; ++ ++ ks->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", ++ GPIOD_OUT_HIGH); ++ err = PTR_ERR_OR_ZERO(ks->reset_gpio); ++ if (err) { ++ dev_err(&spi->dev, ++ "failed to get reset gpio: %d\n", err); ++ return err; ++ } ++ ++ err = gpiod_set_consumer_name(ks->reset_gpio, "switch-reset"); ++ if (err) ++ return err; ++ ++ /* de-assert switch reset */ ++ /* FIXME: this likely requires a delay */ ++ gpiod_set_value_cansleep(ks->reset_gpio, 0); ++ ++ spi_set_drvdata(spi, ks); ++ ++ spi->mode = SPI_MODE_0; ++ spi->bits_per_word = 8; ++ err = spi_setup(spi); ++ if (err) { ++ dev_err(&spi->dev, "spi_setup failed, err=%d\n", err); ++ return err; ++ } ++ ++ err = ks8995_get_revision(ks); ++ if (err) ++ return err; ++ ++ memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr)); ++ ks->regs_attr.size = ks->chip->regs_size; ++ ++ err = ks8995_reset(ks); ++ if (err) ++ return err; ++ ++ sysfs_attr_init(&ks->regs_attr.attr); ++ err = sysfs_create_bin_file(&spi->dev.kobj, &ks->regs_attr); ++ if (err) { ++ dev_err(&spi->dev, "unable to create sysfs file, err=%d\n", ++ err); ++ return err; ++ } ++ ++ dev_info(&spi->dev, "%s device found, Chip ID:%x, Revision:%x\n", ++ ks->chip->name, ks->chip->chip_id, ks->revision_id); ++ ++ return 0; ++} ++ ++static void ks8995_remove(struct spi_device *spi) ++{ ++ struct ks8995_switch *ks = spi_get_drvdata(spi); ++ ++ sysfs_remove_bin_file(&spi->dev.kobj, &ks->regs_attr); ++ ++ /* assert reset */ ++ gpiod_set_value_cansleep(ks->reset_gpio, 1); ++} ++ ++/* ------------------------------------------------------------------------ */ ++static struct spi_driver ks8995_driver = { ++ .driver = { ++ .name = "spi-ks8995", ++ .of_match_table = ks8895_spi_of_match, ++ }, ++ .probe = ks8995_probe, ++ .remove = ks8995_remove, ++ .id_table = ks8995_id, ++}; ++ ++module_spi_driver(ks8995_driver); ++ ++MODULE_DESCRIPTION(DRV_DESC); ++MODULE_VERSION(DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_LICENSE("GPL v2"); +--- a/drivers/net/phy/spi_ks8995.c ++++ /dev/null +@@ -1,506 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * SPI driver for Micrel/Kendin KS8995M and KSZ8864RMN ethernet switches +- * +- * Copyright (C) 2008 Gabor Juhos +- * +- * This file was based on: drivers/spi/at25.c +- * Copyright (C) 2006 David Brownell +- */ +- +-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#define DRV_VERSION "0.1.1" +-#define DRV_DESC "Micrel KS8995 Ethernet switch SPI driver" +- +-/* ------------------------------------------------------------------------ */ +- +-#define KS8995_REG_ID0 0x00 /* Chip ID0 */ +-#define KS8995_REG_ID1 0x01 /* Chip ID1 */ +- +-#define KS8995_REG_GC0 0x02 /* Global Control 0 */ +-#define KS8995_REG_GC1 0x03 /* Global Control 1 */ +-#define KS8995_REG_GC2 0x04 /* Global Control 2 */ +-#define KS8995_REG_GC3 0x05 /* Global Control 3 */ +-#define KS8995_REG_GC4 0x06 /* Global Control 4 */ +-#define KS8995_REG_GC5 0x07 /* Global Control 5 */ +-#define KS8995_REG_GC6 0x08 /* Global Control 6 */ +-#define KS8995_REG_GC7 0x09 /* Global Control 7 */ +-#define KS8995_REG_GC8 0x0a /* Global Control 8 */ +-#define KS8995_REG_GC9 0x0b /* Global Control 9 */ +- +-#define KS8995_REG_PC(p, r) ((0x10 * p) + r) /* Port Control */ +-#define KS8995_REG_PS(p, r) ((0x10 * p) + r + 0xe) /* Port Status */ +- +-#define KS8995_REG_TPC0 0x60 /* TOS Priority Control 0 */ +-#define KS8995_REG_TPC1 0x61 /* TOS Priority Control 1 */ +-#define KS8995_REG_TPC2 0x62 /* TOS Priority Control 2 */ +-#define KS8995_REG_TPC3 0x63 /* TOS Priority Control 3 */ +-#define KS8995_REG_TPC4 0x64 /* TOS Priority Control 4 */ +-#define KS8995_REG_TPC5 0x65 /* TOS Priority Control 5 */ +-#define KS8995_REG_TPC6 0x66 /* TOS Priority Control 6 */ +-#define KS8995_REG_TPC7 0x67 /* TOS Priority Control 7 */ +- +-#define KS8995_REG_MAC0 0x68 /* MAC address 0 */ +-#define KS8995_REG_MAC1 0x69 /* MAC address 1 */ +-#define KS8995_REG_MAC2 0x6a /* MAC address 2 */ +-#define KS8995_REG_MAC3 0x6b /* MAC address 3 */ +-#define KS8995_REG_MAC4 0x6c /* MAC address 4 */ +-#define KS8995_REG_MAC5 0x6d /* MAC address 5 */ +- +-#define KS8995_REG_IAC0 0x6e /* Indirect Access Control 0 */ +-#define KS8995_REG_IAC1 0x6f /* Indirect Access Control 0 */ +-#define KS8995_REG_IAD7 0x70 /* Indirect Access Data 7 */ +-#define KS8995_REG_IAD6 0x71 /* Indirect Access Data 6 */ +-#define KS8995_REG_IAD5 0x72 /* Indirect Access Data 5 */ +-#define KS8995_REG_IAD4 0x73 /* Indirect Access Data 4 */ +-#define KS8995_REG_IAD3 0x74 /* Indirect Access Data 3 */ +-#define KS8995_REG_IAD2 0x75 /* Indirect Access Data 2 */ +-#define KS8995_REG_IAD1 0x76 /* Indirect Access Data 1 */ +-#define KS8995_REG_IAD0 0x77 /* Indirect Access Data 0 */ +- +-#define KSZ8864_REG_ID1 0xfe /* Chip ID in bit 7 */ +- +-#define KS8995_REGS_SIZE 0x80 +-#define KSZ8864_REGS_SIZE 0x100 +-#define KSZ8795_REGS_SIZE 0x100 +- +-#define ID1_CHIPID_M 0xf +-#define ID1_CHIPID_S 4 +-#define ID1_REVISION_M 0x7 +-#define ID1_REVISION_S 1 +-#define ID1_START_SW 1 /* start the switch */ +- +-#define FAMILY_KS8995 0x95 +-#define FAMILY_KSZ8795 0x87 +-#define CHIPID_M 0 +-#define KS8995_CHIP_ID 0x00 +-#define KSZ8864_CHIP_ID 0x01 +-#define KSZ8795_CHIP_ID 0x09 +- +-#define KS8995_CMD_WRITE 0x02U +-#define KS8995_CMD_READ 0x03U +- +-#define KS8995_RESET_DELAY 10 /* usec */ +- +-enum ks8995_chip_variant { +- ks8995, +- ksz8864, +- ksz8795, +- max_variant +-}; +- +-struct ks8995_chip_params { +- char *name; +- int family_id; +- int chip_id; +- int regs_size; +- int addr_width; +- int addr_shift; +-}; +- +-static const struct ks8995_chip_params ks8995_chip[] = { +- [ks8995] = { +- .name = "KS8995MA", +- .family_id = FAMILY_KS8995, +- .chip_id = KS8995_CHIP_ID, +- .regs_size = KS8995_REGS_SIZE, +- .addr_width = 8, +- .addr_shift = 0, +- }, +- [ksz8864] = { +- .name = "KSZ8864RMN", +- .family_id = FAMILY_KS8995, +- .chip_id = KSZ8864_CHIP_ID, +- .regs_size = KSZ8864_REGS_SIZE, +- .addr_width = 8, +- .addr_shift = 0, +- }, +- [ksz8795] = { +- .name = "KSZ8795CLX", +- .family_id = FAMILY_KSZ8795, +- .chip_id = KSZ8795_CHIP_ID, +- .regs_size = KSZ8795_REGS_SIZE, +- .addr_width = 12, +- .addr_shift = 1, +- }, +-}; +- +-struct ks8995_switch { +- struct spi_device *spi; +- struct mutex lock; +- struct gpio_desc *reset_gpio; +- struct bin_attribute regs_attr; +- const struct ks8995_chip_params *chip; +- int revision_id; +-}; +- +-static const struct spi_device_id ks8995_id[] = { +- {"ks8995", ks8995}, +- {"ksz8864", ksz8864}, +- {"ksz8795", ksz8795}, +- { } +-}; +-MODULE_DEVICE_TABLE(spi, ks8995_id); +- +-static const struct of_device_id ks8895_spi_of_match[] = { +- { .compatible = "micrel,ks8995" }, +- { .compatible = "micrel,ksz8864" }, +- { .compatible = "micrel,ksz8795" }, +- { }, +-}; +-MODULE_DEVICE_TABLE(of, ks8895_spi_of_match); +- +-static inline u8 get_chip_id(u8 val) +-{ +- return (val >> ID1_CHIPID_S) & ID1_CHIPID_M; +-} +- +-static inline u8 get_chip_rev(u8 val) +-{ +- return (val >> ID1_REVISION_S) & ID1_REVISION_M; +-} +- +-/* create_spi_cmd - create a chip specific SPI command header +- * @ks: pointer to switch instance +- * @cmd: SPI command for switch +- * @address: register address for command +- * +- * Different chip families use different bit pattern to address the switches +- * registers: +- * +- * KS8995: 8bit command + 8bit address +- * KSZ8795: 3bit command + 12bit address + 1bit TR (?) +- */ +-static inline __be16 create_spi_cmd(struct ks8995_switch *ks, int cmd, +- unsigned address) +-{ +- u16 result = cmd; +- +- /* make room for address (incl. address shift) */ +- result <<= ks->chip->addr_width + ks->chip->addr_shift; +- /* add address */ +- result |= address << ks->chip->addr_shift; +- /* SPI protocol needs big endian */ +- return cpu_to_be16(result); +-} +-/* ------------------------------------------------------------------------ */ +-static int ks8995_read(struct ks8995_switch *ks, char *buf, +- unsigned offset, size_t count) +-{ +- __be16 cmd; +- struct spi_transfer t[2]; +- struct spi_message m; +- int err; +- +- cmd = create_spi_cmd(ks, KS8995_CMD_READ, offset); +- spi_message_init(&m); +- +- memset(&t, 0, sizeof(t)); +- +- t[0].tx_buf = &cmd; +- t[0].len = sizeof(cmd); +- spi_message_add_tail(&t[0], &m); +- +- t[1].rx_buf = buf; +- t[1].len = count; +- spi_message_add_tail(&t[1], &m); +- +- mutex_lock(&ks->lock); +- err = spi_sync(ks->spi, &m); +- mutex_unlock(&ks->lock); +- +- return err ? err : count; +-} +- +-static int ks8995_write(struct ks8995_switch *ks, char *buf, +- unsigned offset, size_t count) +-{ +- __be16 cmd; +- struct spi_transfer t[2]; +- struct spi_message m; +- int err; +- +- cmd = create_spi_cmd(ks, KS8995_CMD_WRITE, offset); +- spi_message_init(&m); +- +- memset(&t, 0, sizeof(t)); +- +- t[0].tx_buf = &cmd; +- t[0].len = sizeof(cmd); +- spi_message_add_tail(&t[0], &m); +- +- t[1].tx_buf = buf; +- t[1].len = count; +- spi_message_add_tail(&t[1], &m); +- +- mutex_lock(&ks->lock); +- err = spi_sync(ks->spi, &m); +- mutex_unlock(&ks->lock); +- +- return err ? err : count; +-} +- +-static inline int ks8995_read_reg(struct ks8995_switch *ks, u8 addr, u8 *buf) +-{ +- return ks8995_read(ks, buf, addr, 1) != 1; +-} +- +-static inline int ks8995_write_reg(struct ks8995_switch *ks, u8 addr, u8 val) +-{ +- char buf = val; +- +- return ks8995_write(ks, &buf, addr, 1) != 1; +-} +- +-/* ------------------------------------------------------------------------ */ +- +-static int ks8995_stop(struct ks8995_switch *ks) +-{ +- return ks8995_write_reg(ks, KS8995_REG_ID1, 0); +-} +- +-static int ks8995_start(struct ks8995_switch *ks) +-{ +- return ks8995_write_reg(ks, KS8995_REG_ID1, 1); +-} +- +-static int ks8995_reset(struct ks8995_switch *ks) +-{ +- int err; +- +- err = ks8995_stop(ks); +- if (err) +- return err; +- +- udelay(KS8995_RESET_DELAY); +- +- return ks8995_start(ks); +-} +- +-static ssize_t ks8995_registers_read(struct file *filp, struct kobject *kobj, +- struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) +-{ +- struct device *dev; +- struct ks8995_switch *ks8995; +- +- dev = kobj_to_dev(kobj); +- ks8995 = dev_get_drvdata(dev); +- +- return ks8995_read(ks8995, buf, off, count); +-} +- +-static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj, +- struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) +-{ +- struct device *dev; +- struct ks8995_switch *ks8995; +- +- dev = kobj_to_dev(kobj); +- ks8995 = dev_get_drvdata(dev); +- +- return ks8995_write(ks8995, buf, off, count); +-} +- +-/* ks8995_get_revision - get chip revision +- * @ks: pointer to switch instance +- * +- * Verify chip family and id and get chip revision. +- */ +-static int ks8995_get_revision(struct ks8995_switch *ks) +-{ +- int err; +- u8 id0, id1, ksz8864_id; +- +- /* read family id */ +- err = ks8995_read_reg(ks, KS8995_REG_ID0, &id0); +- if (err) { +- err = -EIO; +- goto err_out; +- } +- +- /* verify family id */ +- if (id0 != ks->chip->family_id) { +- dev_err(&ks->spi->dev, "chip family id mismatch: expected 0x%02x but 0x%02x read\n", +- ks->chip->family_id, id0); +- err = -ENODEV; +- goto err_out; +- } +- +- switch (ks->chip->family_id) { +- case FAMILY_KS8995: +- /* try reading chip id at CHIP ID1 */ +- err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1); +- if (err) { +- err = -EIO; +- goto err_out; +- } +- +- /* verify chip id */ +- if ((get_chip_id(id1) == CHIPID_M) && +- (get_chip_id(id1) == ks->chip->chip_id)) { +- /* KS8995MA */ +- ks->revision_id = get_chip_rev(id1); +- } else if (get_chip_id(id1) != CHIPID_M) { +- /* KSZ8864RMN */ +- err = ks8995_read_reg(ks, KS8995_REG_ID1, &ksz8864_id); +- if (err) { +- err = -EIO; +- goto err_out; +- } +- +- if ((ksz8864_id & 0x80) && +- (ks->chip->chip_id == KSZ8864_CHIP_ID)) { +- ks->revision_id = get_chip_rev(id1); +- } +- +- } else { +- dev_err(&ks->spi->dev, "unsupported chip id for KS8995 family: 0x%02x\n", +- id1); +- err = -ENODEV; +- } +- break; +- case FAMILY_KSZ8795: +- /* try reading chip id at CHIP ID1 */ +- err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1); +- if (err) { +- err = -EIO; +- goto err_out; +- } +- +- if (get_chip_id(id1) == ks->chip->chip_id) { +- ks->revision_id = get_chip_rev(id1); +- } else { +- dev_err(&ks->spi->dev, "unsupported chip id for KSZ8795 family: 0x%02x\n", +- id1); +- err = -ENODEV; +- } +- break; +- default: +- dev_err(&ks->spi->dev, "unsupported family id: 0x%02x\n", id0); +- err = -ENODEV; +- break; +- } +-err_out: +- return err; +-} +- +-static const struct bin_attribute ks8995_registers_attr = { +- .attr = { +- .name = "registers", +- .mode = 0600, +- }, +- .size = KS8995_REGS_SIZE, +- .read = ks8995_registers_read, +- .write = ks8995_registers_write, +-}; +- +-/* ------------------------------------------------------------------------ */ +-static int ks8995_probe(struct spi_device *spi) +-{ +- struct ks8995_switch *ks; +- int err; +- int variant = spi_get_device_id(spi)->driver_data; +- +- if (variant >= max_variant) { +- dev_err(&spi->dev, "bad chip variant %d\n", variant); +- return -ENODEV; +- } +- +- ks = devm_kzalloc(&spi->dev, sizeof(*ks), GFP_KERNEL); +- if (!ks) +- return -ENOMEM; +- +- mutex_init(&ks->lock); +- ks->spi = spi; +- ks->chip = &ks8995_chip[variant]; +- +- ks->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", +- GPIOD_OUT_HIGH); +- err = PTR_ERR_OR_ZERO(ks->reset_gpio); +- if (err) { +- dev_err(&spi->dev, +- "failed to get reset gpio: %d\n", err); +- return err; +- } +- +- err = gpiod_set_consumer_name(ks->reset_gpio, "switch-reset"); +- if (err) +- return err; +- +- /* de-assert switch reset */ +- /* FIXME: this likely requires a delay */ +- gpiod_set_value_cansleep(ks->reset_gpio, 0); +- +- spi_set_drvdata(spi, ks); +- +- spi->mode = SPI_MODE_0; +- spi->bits_per_word = 8; +- err = spi_setup(spi); +- if (err) { +- dev_err(&spi->dev, "spi_setup failed, err=%d\n", err); +- return err; +- } +- +- err = ks8995_get_revision(ks); +- if (err) +- return err; +- +- memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr)); +- ks->regs_attr.size = ks->chip->regs_size; +- +- err = ks8995_reset(ks); +- if (err) +- return err; +- +- sysfs_attr_init(&ks->regs_attr.attr); +- err = sysfs_create_bin_file(&spi->dev.kobj, &ks->regs_attr); +- if (err) { +- dev_err(&spi->dev, "unable to create sysfs file, err=%d\n", +- err); +- return err; +- } +- +- dev_info(&spi->dev, "%s device found, Chip ID:%x, Revision:%x\n", +- ks->chip->name, ks->chip->chip_id, ks->revision_id); +- +- return 0; +-} +- +-static void ks8995_remove(struct spi_device *spi) +-{ +- struct ks8995_switch *ks = spi_get_drvdata(spi); +- +- sysfs_remove_bin_file(&spi->dev.kobj, &ks->regs_attr); +- +- /* assert reset */ +- gpiod_set_value_cansleep(ks->reset_gpio, 1); +-} +- +-/* ------------------------------------------------------------------------ */ +-static struct spi_driver ks8995_driver = { +- .driver = { +- .name = "spi-ks8995", +- .of_match_table = ks8895_spi_of_match, +- }, +- .probe = ks8995_probe, +- .remove = ks8995_remove, +- .id_table = ks8995_id, +-}; +- +-module_spi_driver(ks8995_driver); +- +-MODULE_DESCRIPTION(DRV_DESC); +-MODULE_VERSION(DRV_VERSION); +-MODULE_AUTHOR("Gabor Juhos "); +-MODULE_LICENSE("GPL v2"); diff --git a/lede/target/linux/generic/backport-6.12/783-02-v6.18-net-dsa-ks8995-Add-proper-RESET-delay.patch b/lede/target/linux/generic/backport-6.12/783-02-v6.18-net-dsa-ks8995-Add-proper-RESET-delay.patch new file mode 100644 index 0000000000..3b0b731d4b --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/783-02-v6.18-net-dsa-ks8995-Add-proper-RESET-delay.patch @@ -0,0 +1,40 @@ +From 7367bfc8b34d7ad5b0c06e19fe24533db22ed8ea Mon Sep 17 00:00:00 2001 +From: Linus Walleij +Date: Wed, 13 Aug 2025 23:43:04 +0200 +Subject: [PATCH 2/4] net: dsa: ks8995: Add proper RESET delay + +According to the datasheet we need to wait 100us before accessing +any registers in the KS8995 after a reset de-assertion. + +Add this delay, if and only if we obtained a GPIO descriptor, +otherwise it is just a pointless delay. + +Signed-off-by: Linus Walleij +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250813-ks8995-to-dsa-v1-2-75c359ede3a5@linaro.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/ks8995.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/ks8995.c ++++ b/drivers/net/dsa/ks8995.c +@@ -438,9 +438,15 @@ static int ks8995_probe(struct spi_devic + if (err) + return err; + +- /* de-assert switch reset */ +- /* FIXME: this likely requires a delay */ +- gpiod_set_value_cansleep(ks->reset_gpio, 0); ++ if (ks->reset_gpio) { ++ /* ++ * If a reset line was obtained, wait for 100us after ++ * de-asserting RESET before accessing any registers, see ++ * the KS8995MA datasheet, page 44. ++ */ ++ gpiod_set_value_cansleep(ks->reset_gpio, 0); ++ udelay(100); ++ } + + spi_set_drvdata(spi, ks); + diff --git a/lede/target/linux/generic/backport-6.12/783-03-v6.18-net-dsa-ks8995-Delete-sysfs-register-access.patch b/lede/target/linux/generic/backport-6.12/783-03-v6.18-net-dsa-ks8995-Delete-sysfs-register-access.patch new file mode 100644 index 0000000000..78b9141ed7 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/783-03-v6.18-net-dsa-ks8995-Delete-sysfs-register-access.patch @@ -0,0 +1,109 @@ +From 0e8d3f3623a45f69b6641ff9921ecd0c5afaa4ca Mon Sep 17 00:00:00 2001 +From: Linus Walleij +Date: Wed, 13 Aug 2025 23:43:05 +0200 +Subject: [PATCH 3/4] net: dsa: ks8995: Delete sysfs register access + +There is some sysfs file to read and write registers randomly +in the ks8995 driver. + +The contemporary way to achieve the same thing is to implement +regmap abstractions, if needed. Delete this and implement +regmap later if we want to be able to inspect individual registers. + +Signed-off-by: Linus Walleij +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250813-ks8995-to-dsa-v1-3-75c359ede3a5@linaro.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/ks8995.c | 48 ---------------------------------------- + 1 file changed, 48 deletions(-) + +--- a/drivers/net/dsa/ks8995.c ++++ b/drivers/net/dsa/ks8995.c +@@ -140,7 +140,6 @@ struct ks8995_switch { + struct spi_device *spi; + struct mutex lock; + struct gpio_desc *reset_gpio; +- struct bin_attribute regs_attr; + const struct ks8995_chip_params *chip; + int revision_id; + }; +@@ -288,30 +287,6 @@ static int ks8995_reset(struct ks8995_sw + return ks8995_start(ks); + } + +-static ssize_t ks8995_registers_read(struct file *filp, struct kobject *kobj, +- struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) +-{ +- struct device *dev; +- struct ks8995_switch *ks8995; +- +- dev = kobj_to_dev(kobj); +- ks8995 = dev_get_drvdata(dev); +- +- return ks8995_read(ks8995, buf, off, count); +-} +- +-static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj, +- struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) +-{ +- struct device *dev; +- struct ks8995_switch *ks8995; +- +- dev = kobj_to_dev(kobj); +- ks8995 = dev_get_drvdata(dev); +- +- return ks8995_write(ks8995, buf, off, count); +-} +- + /* ks8995_get_revision - get chip revision + * @ks: pointer to switch instance + * +@@ -395,16 +370,6 @@ err_out: + return err; + } + +-static const struct bin_attribute ks8995_registers_attr = { +- .attr = { +- .name = "registers", +- .mode = 0600, +- }, +- .size = KS8995_REGS_SIZE, +- .read = ks8995_registers_read, +- .write = ks8995_registers_write, +-}; +- + /* ------------------------------------------------------------------------ */ + static int ks8995_probe(struct spi_device *spi) + { +@@ -462,21 +427,10 @@ static int ks8995_probe(struct spi_devic + if (err) + return err; + +- memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr)); +- ks->regs_attr.size = ks->chip->regs_size; +- + err = ks8995_reset(ks); + if (err) + return err; + +- sysfs_attr_init(&ks->regs_attr.attr); +- err = sysfs_create_bin_file(&spi->dev.kobj, &ks->regs_attr); +- if (err) { +- dev_err(&spi->dev, "unable to create sysfs file, err=%d\n", +- err); +- return err; +- } +- + dev_info(&spi->dev, "%s device found, Chip ID:%x, Revision:%x\n", + ks->chip->name, ks->chip->chip_id, ks->revision_id); + +@@ -487,8 +441,6 @@ static void ks8995_remove(struct spi_dev + { + struct ks8995_switch *ks = spi_get_drvdata(spi); + +- sysfs_remove_bin_file(&spi->dev.kobj, &ks->regs_attr); +- + /* assert reset */ + gpiod_set_value_cansleep(ks->reset_gpio, 1); + } diff --git a/lede/target/linux/generic/backport-6.12/783-04-v6.18-net-dsa-ks8995-Add-basic-switch-set-up.patch b/lede/target/linux/generic/backport-6.12/783-04-v6.18-net-dsa-ks8995-Add-basic-switch-set-up.patch new file mode 100644 index 0000000000..670fe61252 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/783-04-v6.18-net-dsa-ks8995-Add-basic-switch-set-up.patch @@ -0,0 +1,546 @@ +From 4b486b63e07313e1e3807f9d5e6636aa564e0fbc Mon Sep 17 00:00:00 2001 +From: Linus Walleij +Date: Wed, 13 Aug 2025 23:43:06 +0200 +Subject: [PATCH 4/4] net: dsa: ks8995: Add basic switch set-up + +We start to extend the KS8995 driver by simply registering it +as a DSA device and implementing a few switch callbacks for +STP set-up and such to begin with. + +No special tags or other advanced stuff: we use DSA_TAG_NONE +and rely on the default set-up in the switch with the special +DSA tags turned off. This makes the switch wire up properly +to all its PHY's and simple bridge traffic works properly. + +After this the bridge DT bindings are respected, ports and their +PHYs get connected to the switch and react appropriately through +the phylib when cables are plugged in etc. + +Tested like this in a hacky OpenWrt image: + +Bring up conduit interface manually: +ixp4xx_eth c8009000.ethernet eth0: eth0: link up, + speed 100 Mb/s, full duplex + +spi-ks8995 spi0.0: enable port 0 +spi-ks8995 spi0.0: set KS8995_REG_PC2 for port 0 to 06 +spi-ks8995 spi0.0 lan1: configuring for phy/mii link mode +spi-ks8995 spi0.0 lan1: Link is Up - 100Mbps/Full - flow control rx/tx + +PING 169.254.1.1 (169.254.1.1): 56 data bytes +64 bytes from 169.254.1.1: seq=0 ttl=64 time=1.629 ms +64 bytes from 169.254.1.1: seq=1 ttl=64 time=0.951 ms + +I also tested SSH from the device to the host and it works fine. + +It also works fine to ping the device from the host and to SSH +into the device from the host. + +This brings the ks8995 driver to a reasonable state where it can +be used from the current device tree bindings and the existing +device trees in the kernel. + +Signed-off-by: Linus Walleij +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250813-ks8995-to-dsa-v1-4-75c359ede3a5@linaro.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/Kconfig | 1 + + drivers/net/dsa/ks8995.c | 398 ++++++++++++++++++++++++++++++++++++++- + 2 files changed, 396 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/Kconfig ++++ b/drivers/net/dsa/Kconfig +@@ -101,6 +101,7 @@ config NET_DSA_RZN1_A5PSW + config NET_DSA_KS8995 + tristate "Micrel KS8995 family 5-ports 10/100 Ethernet switches" + depends on SPI ++ select NET_DSA_TAG_NONE + help + This driver supports the Micrel KS8995 family of 10/100 Mbit ethernet + switches, managed over SPI. +--- a/drivers/net/dsa/ks8995.c ++++ b/drivers/net/dsa/ks8995.c +@@ -3,6 +3,7 @@ + * SPI driver for Micrel/Kendin KS8995M and KSZ8864RMN ethernet switches + * + * Copyright (C) 2008 Gabor Juhos ++ * Copyright (C) 2025 Linus Walleij + * + * This file was based on: drivers/spi/at25.c + * Copyright (C) 2006 David Brownell +@@ -10,6 +11,9 @@ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + ++#include ++#include ++#include + #include + #include + #include +@@ -17,8 +21,8 @@ + #include + #include + #include +- + #include ++#include + + #define DRV_VERSION "0.1.1" + #define DRV_DESC "Micrel KS8995 Ethernet switch SPI driver" +@@ -29,18 +33,59 @@ + #define KS8995_REG_ID1 0x01 /* Chip ID1 */ + + #define KS8995_REG_GC0 0x02 /* Global Control 0 */ ++ ++#define KS8995_GC0_P5_PHY BIT(3) /* Port 5 PHY enabled */ ++ + #define KS8995_REG_GC1 0x03 /* Global Control 1 */ + #define KS8995_REG_GC2 0x04 /* Global Control 2 */ ++ ++#define KS8995_GC2_HUGE BIT(2) /* Huge packet support */ ++#define KS8995_GC2_LEGAL BIT(1) /* Legal size override */ ++ + #define KS8995_REG_GC3 0x05 /* Global Control 3 */ + #define KS8995_REG_GC4 0x06 /* Global Control 4 */ ++ ++#define KS8995_GC4_10BT BIT(4) /* Force switch to 10Mbit */ ++#define KS8995_GC4_MII_FLOW BIT(5) /* MII full-duplex flow control enable */ ++#define KS8995_GC4_MII_HD BIT(6) /* MII half-duplex mode enable */ ++ + #define KS8995_REG_GC5 0x07 /* Global Control 5 */ + #define KS8995_REG_GC6 0x08 /* Global Control 6 */ + #define KS8995_REG_GC7 0x09 /* Global Control 7 */ + #define KS8995_REG_GC8 0x0a /* Global Control 8 */ + #define KS8995_REG_GC9 0x0b /* Global Control 9 */ + +-#define KS8995_REG_PC(p, r) ((0x10 * p) + r) /* Port Control */ +-#define KS8995_REG_PS(p, r) ((0x10 * p) + r + 0xe) /* Port Status */ ++#define KS8995_GC9_SPECIAL BIT(0) /* Special tagging mode (DSA) */ ++ ++/* In DSA the ports 1-4 are numbered 0-3 and the CPU port is port 4 */ ++#define KS8995_REG_PC(p, r) (0x10 + (0x10 * (p)) + (r)) /* Port Control */ ++#define KS8995_REG_PS(p, r) (0x1e + (0x10 * (p)) + (r)) /* Port Status */ ++ ++#define KS8995_REG_PC0 0x00 /* Port Control 0 */ ++#define KS8995_REG_PC1 0x01 /* Port Control 1 */ ++#define KS8995_REG_PC2 0x02 /* Port Control 2 */ ++#define KS8995_REG_PC3 0x03 /* Port Control 3 */ ++#define KS8995_REG_PC4 0x04 /* Port Control 4 */ ++#define KS8995_REG_PC5 0x05 /* Port Control 5 */ ++#define KS8995_REG_PC6 0x06 /* Port Control 6 */ ++#define KS8995_REG_PC7 0x07 /* Port Control 7 */ ++#define KS8995_REG_PC8 0x08 /* Port Control 8 */ ++#define KS8995_REG_PC9 0x09 /* Port Control 9 */ ++#define KS8995_REG_PC10 0x0a /* Port Control 10 */ ++#define KS8995_REG_PC11 0x0b /* Port Control 11 */ ++#define KS8995_REG_PC12 0x0c /* Port Control 12 */ ++#define KS8995_REG_PC13 0x0d /* Port Control 13 */ ++ ++#define KS8995_PC0_TAG_INS BIT(2) /* Enable tag insertion on port */ ++#define KS8995_PC0_TAG_REM BIT(1) /* Enable tag removal on port */ ++#define KS8995_PC0_PRIO_EN BIT(0) /* Enable priority handling */ ++ ++#define KS8995_PC2_TXEN BIT(2) /* Enable TX on port */ ++#define KS8995_PC2_RXEN BIT(1) /* Enable RX on port */ ++#define KS8995_PC2_LEARN_DIS BIT(0) /* Disable learning on port */ ++ ++#define KS8995_PC13_TXDIS BIT(6) /* Disable transmitter */ ++#define KS8995_PC13_PWDN BIT(3) /* Power down */ + + #define KS8995_REG_TPC0 0x60 /* TOS Priority Control 0 */ + #define KS8995_REG_TPC1 0x61 /* TOS Priority Control 1 */ +@@ -91,6 +136,8 @@ + #define KS8995_CMD_WRITE 0x02U + #define KS8995_CMD_READ 0x03U + ++#define KS8995_CPU_PORT 4 ++#define KS8995_NUM_PORTS 5 /* 5 ports including the CPU port */ + #define KS8995_RESET_DELAY 10 /* usec */ + + enum ks8995_chip_variant { +@@ -138,10 +185,13 @@ static const struct ks8995_chip_params k + + struct ks8995_switch { + struct spi_device *spi; ++ struct device *dev; ++ struct dsa_switch *ds; + struct mutex lock; + struct gpio_desc *reset_gpio; + const struct ks8995_chip_params *chip; + int revision_id; ++ unsigned int max_mtu[KS8995_NUM_PORTS]; + }; + + static const struct spi_device_id ks8995_id[] = { +@@ -370,6 +420,327 @@ err_out: + return err; + } + ++static int ks8995_check_config(struct ks8995_switch *ks) ++{ ++ int ret; ++ u8 val; ++ ++ ret = ks8995_read_reg(ks, KS8995_REG_GC0, &val); ++ if (ret) { ++ dev_err(ks->dev, "failed to read KS8995_REG_GC0\n"); ++ return ret; ++ } ++ ++ dev_dbg(ks->dev, "port 5 PHY %senabled\n", ++ (val & KS8995_GC0_P5_PHY) ? "" : "not "); ++ ++ val |= KS8995_GC0_P5_PHY; ++ ret = ks8995_write_reg(ks, KS8995_REG_GC0, val); ++ if (ret) ++ dev_err(ks->dev, "failed to set KS8995_REG_GC0\n"); ++ ++ dev_dbg(ks->dev, "set KS8995_REG_GC0 to 0x%02x\n", val); ++ ++ return 0; ++} ++ ++static void ++ks8995_mac_config(struct phylink_config *config, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++} ++ ++static void ++ks8995_mac_link_up(struct phylink_config *config, struct phy_device *phydev, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, bool tx_pause, bool rx_pause) ++{ ++ struct dsa_port *dp = dsa_phylink_to_port(config); ++ struct ks8995_switch *ks = dp->ds->priv; ++ int port = dp->index; ++ int ret; ++ u8 val; ++ ++ /* Allow forcing the mode on the fixed CPU port, no autonegotiation. ++ * We assume autonegotiation works on the PHY-facing ports. ++ */ ++ if (port != KS8995_CPU_PORT) ++ return; ++ ++ dev_dbg(ks->dev, "MAC link up on CPU port (%d)\n", port); ++ ++ ret = ks8995_read_reg(ks, KS8995_REG_GC4, &val); ++ if (ret) { ++ dev_err(ks->dev, "failed to read KS8995_REG_GC4\n"); ++ return; ++ } ++ ++ /* Conjure port config */ ++ switch (speed) { ++ case SPEED_10: ++ dev_dbg(ks->dev, "set switch MII to 100Mbit mode\n"); ++ val |= KS8995_GC4_10BT; ++ break; ++ case SPEED_100: ++ default: ++ dev_dbg(ks->dev, "set switch MII to 100Mbit mode\n"); ++ val &= ~KS8995_GC4_10BT; ++ break; ++ } ++ ++ if (duplex == DUPLEX_HALF) { ++ dev_dbg(ks->dev, "set switch MII to half duplex\n"); ++ val |= KS8995_GC4_MII_HD; ++ } else { ++ dev_dbg(ks->dev, "set switch MII to full duplex\n"); ++ val &= ~KS8995_GC4_MII_HD; ++ } ++ ++ dev_dbg(ks->dev, "set KS8995_REG_GC4 to %02x\n", val); ++ ++ /* Enable the CPU port */ ++ ret = ks8995_write_reg(ks, KS8995_REG_GC4, val); ++ if (ret) ++ dev_err(ks->dev, "failed to set KS8995_REG_GC4\n"); ++} ++ ++static void ++ks8995_mac_link_down(struct phylink_config *config, unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct dsa_port *dp = dsa_phylink_to_port(config); ++ struct ks8995_switch *ks = dp->ds->priv; ++ int port = dp->index; ++ ++ if (port != KS8995_CPU_PORT) ++ return; ++ ++ dev_dbg(ks->dev, "MAC link down on CPU port (%d)\n", port); ++ ++ /* Disable the CPU port */ ++} ++ ++static const struct phylink_mac_ops ks8995_phylink_mac_ops = { ++ .mac_config = ks8995_mac_config, ++ .mac_link_up = ks8995_mac_link_up, ++ .mac_link_down = ks8995_mac_link_down, ++}; ++ ++static enum ++dsa_tag_protocol ks8995_get_tag_protocol(struct dsa_switch *ds, ++ int port, ++ enum dsa_tag_protocol mp) ++{ ++ /* This switch actually uses the 6 byte KS8995 protocol */ ++ return DSA_TAG_PROTO_NONE; ++} ++ ++static int ks8995_setup(struct dsa_switch *ds) ++{ ++ return 0; ++} ++ ++static int ks8995_port_enable(struct dsa_switch *ds, int port, ++ struct phy_device *phy) ++{ ++ struct ks8995_switch *ks = ds->priv; ++ ++ dev_dbg(ks->dev, "enable port %d\n", port); ++ ++ return 0; ++} ++ ++static void ks8995_port_disable(struct dsa_switch *ds, int port) ++{ ++ struct ks8995_switch *ks = ds->priv; ++ ++ dev_dbg(ks->dev, "disable port %d\n", port); ++} ++ ++static int ks8995_port_pre_bridge_flags(struct dsa_switch *ds, int port, ++ struct switchdev_brport_flags flags, ++ struct netlink_ext_ack *extack) ++{ ++ /* We support enabling/disabling learning */ ++ if (flags.mask & ~(BR_LEARNING)) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int ks8995_port_bridge_flags(struct dsa_switch *ds, int port, ++ struct switchdev_brport_flags flags, ++ struct netlink_ext_ack *extack) ++{ ++ struct ks8995_switch *ks = ds->priv; ++ int ret; ++ u8 val; ++ ++ if (flags.mask & BR_LEARNING) { ++ ret = ks8995_read_reg(ks, KS8995_REG_PC(port, KS8995_REG_PC2), &val); ++ if (ret) { ++ dev_err(ks->dev, "failed to read KS8995_REG_PC2 on port %d\n", port); ++ return ret; ++ } ++ ++ if (flags.val & BR_LEARNING) ++ val &= ~KS8995_PC2_LEARN_DIS; ++ else ++ val |= KS8995_PC2_LEARN_DIS; ++ ++ ret = ks8995_write_reg(ks, KS8995_REG_PC(port, KS8995_REG_PC2), val); ++ if (ret) { ++ dev_err(ks->dev, "failed to write KS8995_REG_PC2 on port %d\n", port); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static void ks8995_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) ++{ ++ struct ks8995_switch *ks = ds->priv; ++ int ret; ++ u8 val; ++ ++ ret = ks8995_read_reg(ks, KS8995_REG_PC(port, KS8995_REG_PC2), &val); ++ if (ret) { ++ dev_err(ks->dev, "failed to read KS8995_REG_PC2 on port %d\n", port); ++ return; ++ } ++ ++ /* Set the bits for the different STP states in accordance with ++ * the datasheet, pages 36-37 "Spanning tree support". ++ */ ++ switch (state) { ++ case BR_STATE_DISABLED: ++ case BR_STATE_BLOCKING: ++ case BR_STATE_LISTENING: ++ val &= ~KS8995_PC2_TXEN; ++ val &= ~KS8995_PC2_RXEN; ++ val |= KS8995_PC2_LEARN_DIS; ++ break; ++ case BR_STATE_LEARNING: ++ val &= ~KS8995_PC2_TXEN; ++ val &= ~KS8995_PC2_RXEN; ++ val &= ~KS8995_PC2_LEARN_DIS; ++ break; ++ case BR_STATE_FORWARDING: ++ val |= KS8995_PC2_TXEN; ++ val |= KS8995_PC2_RXEN; ++ val &= ~KS8995_PC2_LEARN_DIS; ++ break; ++ default: ++ dev_err(ks->dev, "unknown bridge state requested\n"); ++ return; ++ } ++ ++ ret = ks8995_write_reg(ks, KS8995_REG_PC(port, KS8995_REG_PC2), val); ++ if (ret) { ++ dev_err(ks->dev, "failed to write KS8995_REG_PC2 on port %d\n", port); ++ return; ++ } ++ ++ dev_dbg(ks->dev, "set KS8995_REG_PC2 for port %d to %02x\n", port, val); ++} ++ ++static void ks8995_phylink_get_caps(struct dsa_switch *dsa, int port, ++ struct phylink_config *config) ++{ ++ unsigned long *interfaces = config->supported_interfaces; ++ ++ if (port == KS8995_CPU_PORT) ++ __set_bit(PHY_INTERFACE_MODE_MII, interfaces); ++ ++ if (port <= 3) { ++ /* Internal PHYs */ ++ __set_bit(PHY_INTERFACE_MODE_INTERNAL, interfaces); ++ /* phylib default */ ++ __set_bit(PHY_INTERFACE_MODE_MII, interfaces); ++ } ++ ++ config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100; ++} ++ ++/* Huge packet support up to 1916 byte packages "inclusive" ++ * which means that tags are included. If the bit is not set ++ * it is 1536 bytes "inclusive". We present the length without ++ * tags or ethernet headers. The setting affects all ports. ++ */ ++static int ks8995_change_mtu(struct dsa_switch *ds, int port, int new_mtu) ++{ ++ struct ks8995_switch *ks = ds->priv; ++ unsigned int max_mtu; ++ int ret; ++ u8 val; ++ int i; ++ ++ ks->max_mtu[port] = new_mtu; ++ ++ /* Roof out the MTU for the entire switch to the greatest ++ * common denominator: the biggest set for any one port will ++ * be the biggest MTU for the switch. ++ */ ++ max_mtu = ETH_DATA_LEN; ++ for (i = 0; i < KS8995_NUM_PORTS; i++) { ++ if (ks->max_mtu[i] > max_mtu) ++ max_mtu = ks->max_mtu[i]; ++ } ++ ++ /* Translate to layer 2 size. ++ * Add ethernet and (possible) VLAN headers, and checksum to the size. ++ * For ETH_DATA_LEN (1500 bytes) this will add up to 1522 bytes. ++ */ ++ max_mtu += VLAN_ETH_HLEN; ++ max_mtu += ETH_FCS_LEN; ++ ++ ret = ks8995_read_reg(ks, KS8995_REG_GC2, &val); ++ if (ret) { ++ dev_err(ks->dev, "failed to read KS8995_REG_GC2\n"); ++ return ret; ++ } ++ ++ if (max_mtu <= 1522) { ++ val &= ~KS8995_GC2_HUGE; ++ val &= ~KS8995_GC2_LEGAL; ++ } else if (max_mtu > 1522 && max_mtu <= 1536) { ++ /* This accepts packets up to 1536 bytes */ ++ val &= ~KS8995_GC2_HUGE; ++ val |= KS8995_GC2_LEGAL; ++ } else { ++ /* This accepts packets up to 1916 bytes */ ++ val |= KS8995_GC2_HUGE; ++ val |= KS8995_GC2_LEGAL; ++ } ++ ++ dev_dbg(ks->dev, "new max MTU %d bytes (inclusive)\n", max_mtu); ++ ++ ret = ks8995_write_reg(ks, KS8995_REG_GC2, val); ++ if (ret) ++ dev_err(ks->dev, "failed to set KS8995_REG_GC2\n"); ++ ++ return ret; ++} ++ ++static int ks8995_get_max_mtu(struct dsa_switch *ds, int port) ++{ ++ return 1916 - ETH_HLEN - ETH_FCS_LEN; ++} ++ ++static const struct dsa_switch_ops ks8995_ds_ops = { ++ .get_tag_protocol = ks8995_get_tag_protocol, ++ .setup = ks8995_setup, ++ .port_pre_bridge_flags = ks8995_port_pre_bridge_flags, ++ .port_bridge_flags = ks8995_port_bridge_flags, ++ .port_enable = ks8995_port_enable, ++ .port_disable = ks8995_port_disable, ++ .port_stp_state_set = ks8995_port_stp_state_set, ++ .port_change_mtu = ks8995_change_mtu, ++ .port_max_mtu = ks8995_get_max_mtu, ++ .phylink_get_caps = ks8995_phylink_get_caps, ++}; ++ + /* ------------------------------------------------------------------------ */ + static int ks8995_probe(struct spi_device *spi) + { +@@ -388,6 +759,7 @@ static int ks8995_probe(struct spi_devic + + mutex_init(&ks->lock); + ks->spi = spi; ++ ks->dev = &spi->dev; + ks->chip = &ks8995_chip[variant]; + + ks->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", +@@ -434,6 +806,25 @@ static int ks8995_probe(struct spi_devic + dev_info(&spi->dev, "%s device found, Chip ID:%x, Revision:%x\n", + ks->chip->name, ks->chip->chip_id, ks->revision_id); + ++ err = ks8995_check_config(ks); ++ if (err) ++ return err; ++ ++ ks->ds = devm_kzalloc(&spi->dev, sizeof(*ks->ds), GFP_KERNEL); ++ if (!ks->ds) ++ return -ENOMEM; ++ ++ ks->ds->dev = &spi->dev; ++ ks->ds->num_ports = KS8995_NUM_PORTS; ++ ks->ds->ops = &ks8995_ds_ops; ++ ks->ds->phylink_mac_ops = &ks8995_phylink_mac_ops; ++ ks->ds->priv = ks; ++ ++ err = dsa_register_switch(ks->ds); ++ if (err) ++ return dev_err_probe(&spi->dev, err, ++ "unable to register DSA switch\n"); ++ + return 0; + } + +@@ -441,6 +832,7 @@ static void ks8995_remove(struct spi_dev + { + struct ks8995_switch *ks = spi_get_drvdata(spi); + ++ dsa_unregister_switch(ks->ds); + /* assert reset */ + gpiod_set_value_cansleep(ks->reset_gpio, 1); + } diff --git a/lede/target/linux/generic/backport-6.12/784-01-v6.17-net-phy-realtek-add-error-handling-to-rtl8211f_get_w.patch b/lede/target/linux/generic/backport-6.12/784-01-v6.17-net-phy-realtek-add-error-handling-to-rtl8211f_get_w.patch new file mode 100644 index 0000000000..5f3b119a89 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/784-01-v6.17-net-phy-realtek-add-error-handling-to-rtl8211f_get_w.patch @@ -0,0 +1,39 @@ +From a9b24b3583ae1da7dbda031f141264f2da260219 Mon Sep 17 00:00:00 2001 +From: Daniel Braunwarth +Date: Tue, 24 Jun 2025 16:17:33 +0200 +Subject: [PATCH] net: phy: realtek: add error handling to rtl8211f_get_wol + +We should check if the WOL settings was successfully read from the PHY. + +In case this fails we cannot just use the error code and proceed. + +Signed-off-by: Daniel Braunwarth +Reported-by: Jon Hunter +Closes: https://lore.kernel.org/baaa083b-9a69-460f-ab35-2a7cb3246ffd@nvidia.com +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250624-realtek_fixes-v1-1-02a0b7c369bc@kuka.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -436,9 +436,15 @@ static irqreturn_t rtl8211f_handle_inter + + static void rtl8211f_get_wol(struct phy_device *dev, struct ethtool_wolinfo *wol) + { ++ int wol_events; ++ + wol->supported = WAKE_MAGIC; +- if (phy_read_paged(dev, RTL8211F_WOL_SETTINGS_PAGE, RTL8211F_WOL_SETTINGS_EVENTS) +- & RTL8211F_WOL_EVENT_MAGIC) ++ ++ wol_events = phy_read_paged(dev, RTL8211F_WOL_SETTINGS_PAGE, RTL8211F_WOL_SETTINGS_EVENTS); ++ if (wol_events < 0) ++ return; ++ ++ if (wol_events & RTL8211F_WOL_EVENT_MAGIC) + wol->wolopts = WAKE_MAGIC; + } + diff --git a/lede/target/linux/generic/backport-6.12/784-02-v6.18-net-phy-realtek-Avoid-PHYCR2-access-if-PHYCR2-not-pr.patch b/lede/target/linux/generic/backport-6.12/784-02-v6.18-net-phy-realtek-Avoid-PHYCR2-access-if-PHYCR2-not-pr.patch new file mode 100644 index 0000000000..681b234fc5 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/784-02-v6.18-net-phy-realtek-Avoid-PHYCR2-access-if-PHYCR2-not-pr.patch @@ -0,0 +1,61 @@ +From 2c67301584f2671e320236df6bbe75ae09feb4d0 Mon Sep 17 00:00:00 2001 +From: Marek Vasut +Date: Sat, 11 Oct 2025 13:02:49 +0200 +Subject: [PATCH] net: phy: realtek: Avoid PHYCR2 access if PHYCR2 not present + +The driver is currently checking for PHYCR2 register presence in +rtl8211f_config_init(), but it does so after accessing PHYCR2 to +disable EEE. This was introduced in commit bfc17c165835 ("net: +phy: realtek: disable PHY-mode EEE"). Move the PHYCR2 presence +test before the EEE disablement and simplify the code. + +Fixes: bfc17c165835 ("net: phy: realtek: disable PHY-mode EEE") +Signed-off-by: Marek Vasut +Reviewed-by: Maxime Chevallier +Reviewed-by: Russell King (Oracle) +Link: https://patch.msgid.link/20251011110309.12664-1-marek.vasut@mailbox.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 23 +++++++++++------------ + 1 file changed, 11 insertions(+), 12 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -589,26 +589,25 @@ static int rtl8211f_config_init(struct p + str_enabled_disabled(val_rxdly)); + } + ++ if (!priv->has_phycr2) ++ return 0; ++ + /* Disable PHY-mode EEE so LPI is passed to the MAC */ + ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2, + RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); + if (ret) + return ret; + +- if (priv->has_phycr2) { +- ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, +- RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, +- priv->phycr2); +- if (ret < 0) { +- dev_err(dev, "clkout configuration failed: %pe\n", +- ERR_PTR(ret)); +- return ret; +- } +- +- return genphy_soft_reset(phydev); ++ ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, ++ RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, ++ priv->phycr2); ++ if (ret < 0) { ++ dev_err(dev, "clkout configuration failed: %pe\n", ++ ERR_PTR(ret)); ++ return ret; + } + +- return 0; ++ return genphy_soft_reset(phydev); + } + + static int rtl821x_suspend(struct phy_device *phydev) diff --git a/lede/target/linux/generic/backport-6.12/784-02-v6.18-net-phy-realtek-fix-RTL8211F-wake-on-lan-support.patch b/lede/target/linux/generic/backport-6.12/784-02-v6.18-net-phy-realtek-fix-RTL8211F-wake-on-lan-support.patch new file mode 100644 index 0000000000..b5c4f8f9fc --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/784-02-v6.18-net-phy-realtek-fix-RTL8211F-wake-on-lan-support.patch @@ -0,0 +1,352 @@ +From b826bf795564ddef6402cf2cb522ae035bd117ae Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 13 Aug 2025 11:04:45 +0100 +Subject: [PATCH] net: phy: realtek: fix RTL8211F wake-on-lan support + +Implement Wake-on-Lan for RTL8211F correctly. The existing +implementation has multiple issues: + +1. It assumes that Wake-on-Lan can always be used, whether or not the + interrupt is wired, and whether or not the interrupt is capable of + waking the system. This breaks the ability for MAC drivers to detect + whether the PHY WoL is functional. +2. switching the interrupt pin in the .set_wol() method to PMEB mode + immediately silences link-state interrupts, which breaks phylib + when interrupts are being used rather than polling mode. +3. the code claiming to "reset WOL status" was doing nothing of the + sort. Bit 15 in page 0xd8a register 17 controls WoL reset, and + needs to be pulsed low to reset the WoL state. This bit was always + written as '1', resulting in no reset. +4. not resetting WoL state results in the PMEB pin remaining asserted, + which in turn leads to an interrupt storm. Only resetting the WoL + state in .set_wol() is not sufficient. +5. PMEB mode does not allow software detection of the wake-up event as + there is no status bit to indicate we received the WoL packet. +6. across reboots of at least the Jetson Xavier NX system, the WoL + configuration is preserved. + +Fix all of these issues by essentially rewriting the support. We: +1. clear the WoL event enable register at probe time. +2. detect whether we can support wake-up by having a valid interrupt, + and the "wakeup-source" property in DT. If we can, then we mark + the MDIO device as wakeup capable, and associate the interrupt + with the wakeup source. +3. arrange for the get_wol() and set_wol() implementations to handle + the case where the MDIO device has not been marked as wakeup + capable (thereby returning no WoL support, and refusing to enable + WoL support.) +4. avoid switching to PMEB mode, instead using INTB mode with the + interrupt enable, reconfiguring the interrupt enables at suspend + time, and restoring their original state at resume time (we track + the state of the interrupt enable register in .config_intr() + register.) +5. move WoL reset from .set_wol() to the suspend function to ensure + that WoL state is cleared prior to suspend. This is necessary + after the PME interrupt has been enabled as a second WoL packet + will not re-raise a previously cleared PME interrupt. +6. when a PME interrupt (for wakeup) is asserted, pass this to the + PM wakeup so it knows which device woke the system. + +This fixes WoL support in the Realtek RTL8211F driver when used on the +nVidia Jetson Xavier NX platform, and needs to be applied before stmmac +patches which allow these platforms to forward the ethtool WoL commands +to the Realtek PHY. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/E1um8Ld-008jxD-Mc@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 172 ++++++++++++++++++++----- + 1 file changed, 140 insertions(+), 32 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -31,6 +32,7 @@ + #define RTL821x_INER 0x12 + #define RTL8211B_INER_INIT 0x6400 + #define RTL8211E_INER_LINK_STATUS BIT(10) ++#define RTL8211F_INER_PME BIT(7) + #define RTL8211F_INER_LINK_STATUS BIT(4) + + #define RTL821x_INSR 0x13 +@@ -96,17 +98,13 @@ + #define RTL8211F_RXCR 0x15 + #define RTL8211F_RX_DELAY BIT(3) + +-/* RTL8211F WOL interrupt configuration */ +-#define RTL8211F_INTBCR_PAGE 0xd40 +-#define RTL8211F_INTBCR 0x16 +-#define RTL8211F_INTBCR_INTB_PMEB BIT(5) +- + /* RTL8211F WOL settings */ +-#define RTL8211F_WOL_SETTINGS_PAGE 0xd8a ++#define RTL8211F_WOL_PAGE 0xd8a + #define RTL8211F_WOL_SETTINGS_EVENTS 16 + #define RTL8211F_WOL_EVENT_MAGIC BIT(12) +-#define RTL8211F_WOL_SETTINGS_STATUS 17 +-#define RTL8211F_WOL_STATUS_RESET (BIT(15) | 0x1fff) ++#define RTL8211F_WOL_RST_RMSQ 17 ++#define RTL8211F_WOL_RG_RSTB BIT(15) ++#define RTL8211F_WOL_RMSQ 0x1fff + + /* RTL8211F Unique phyiscal and multicast address (WOL) */ + #define RTL8211F_PHYSICAL_ADDR_PAGE 0xd8c +@@ -172,7 +170,8 @@ struct rtl821x_priv { + u16 phycr2; + bool has_phycr2; + struct clk *clk; +- u32 saved_wolopts; ++ /* rtl8211f */ ++ u16 iner; + }; + + static int rtl821x_read_page(struct phy_device *phydev) +@@ -255,6 +254,34 @@ static int rtl821x_probe(struct phy_devi + return 0; + } + ++static int rtl8211f_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ int ret; ++ ++ ret = rtl821x_probe(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* Disable all PME events */ ++ ret = phy_write_paged(phydev, RTL8211F_WOL_PAGE, ++ RTL8211F_WOL_SETTINGS_EVENTS, 0); ++ if (ret < 0) ++ return ret; ++ ++ /* Mark this PHY as wakeup capable and register the interrupt as a ++ * wakeup IRQ if the PHY is marked as a wakeup source in firmware, ++ * and the interrupt is valid. ++ */ ++ if (device_property_read_bool(dev, "wakeup-source") && ++ phy_interrupt_is_valid(phydev)) { ++ device_set_wakeup_capable(dev, true); ++ devm_pm_set_wake_irq(dev, phydev->irq); ++ } ++ ++ return ret; ++} ++ + static int rtl8201_ack_interrupt(struct phy_device *phydev) + { + int err; +@@ -352,6 +379,7 @@ static int rtl8211e_config_intr(struct p + + static int rtl8211f_config_intr(struct phy_device *phydev) + { ++ struct rtl821x_priv *priv = phydev->priv; + u16 val; + int err; + +@@ -362,8 +390,10 @@ static int rtl8211f_config_intr(struct p + + val = RTL8211F_INER_LINK_STATUS; + err = phy_write_paged(phydev, 0xa42, RTL821x_INER, val); ++ if (err == 0) ++ priv->iner = val; + } else { +- val = 0; ++ priv->iner = val = 0; + err = phy_write_paged(phydev, 0xa42, RTL821x_INER, val); + if (err) + return err; +@@ -426,21 +456,34 @@ static irqreturn_t rtl8211f_handle_inter + return IRQ_NONE; + } + +- if (!(irq_status & RTL8211F_INER_LINK_STATUS)) +- return IRQ_NONE; ++ if (irq_status & RTL8211F_INER_LINK_STATUS) { ++ phy_trigger_machine(phydev); ++ return IRQ_HANDLED; ++ } + +- phy_trigger_machine(phydev); ++ if (irq_status & RTL8211F_INER_PME) { ++ pm_wakeup_event(&phydev->mdio.dev, 0); ++ return IRQ_HANDLED; ++ } + +- return IRQ_HANDLED; ++ return IRQ_NONE; + } + + static void rtl8211f_get_wol(struct phy_device *dev, struct ethtool_wolinfo *wol) + { + int wol_events; + ++ /* If the PHY is not capable of waking the system, then WoL can not ++ * be supported. ++ */ ++ if (!device_can_wakeup(&dev->mdio.dev)) { ++ wol->supported = 0; ++ return; ++ } ++ + wol->supported = WAKE_MAGIC; + +- wol_events = phy_read_paged(dev, RTL8211F_WOL_SETTINGS_PAGE, RTL8211F_WOL_SETTINGS_EVENTS); ++ wol_events = phy_read_paged(dev, RTL8211F_WOL_PAGE, RTL8211F_WOL_SETTINGS_EVENTS); + if (wol_events < 0) + return; + +@@ -453,6 +496,9 @@ static int rtl8211f_set_wol(struct phy_d + const u8 *mac_addr = dev->attached_dev->dev_addr; + int oldpage; + ++ if (!device_can_wakeup(&dev->mdio.dev)) ++ return -EOPNOTSUPP; ++ + oldpage = phy_save_page(dev); + if (oldpage < 0) + goto err; +@@ -464,25 +510,23 @@ static int rtl8211f_set_wol(struct phy_d + __phy_write(dev, RTL8211F_PHYSICAL_ADDR_WORD1, mac_addr[3] << 8 | (mac_addr[2])); + __phy_write(dev, RTL8211F_PHYSICAL_ADDR_WORD2, mac_addr[5] << 8 | (mac_addr[4])); + +- /* Enable magic packet matching and reset WOL status */ +- rtl821x_write_page(dev, RTL8211F_WOL_SETTINGS_PAGE); ++ /* Enable magic packet matching */ ++ rtl821x_write_page(dev, RTL8211F_WOL_PAGE); + __phy_write(dev, RTL8211F_WOL_SETTINGS_EVENTS, RTL8211F_WOL_EVENT_MAGIC); +- __phy_write(dev, RTL8211F_WOL_SETTINGS_STATUS, RTL8211F_WOL_STATUS_RESET); +- +- /* Enable the WOL interrupt */ +- rtl821x_write_page(dev, RTL8211F_INTBCR_PAGE); +- __phy_set_bits(dev, RTL8211F_INTBCR, RTL8211F_INTBCR_INTB_PMEB); ++ /* Set the maximum packet size, and assert WoL reset */ ++ __phy_write(dev, RTL8211F_WOL_RST_RMSQ, RTL8211F_WOL_RMSQ); + } else { +- /* Disable the WOL interrupt */ +- rtl821x_write_page(dev, RTL8211F_INTBCR_PAGE); +- __phy_clear_bits(dev, RTL8211F_INTBCR, RTL8211F_INTBCR_INTB_PMEB); +- +- /* Disable magic packet matching and reset WOL status */ +- rtl821x_write_page(dev, RTL8211F_WOL_SETTINGS_PAGE); ++ /* Disable magic packet matching */ ++ rtl821x_write_page(dev, RTL8211F_WOL_PAGE); + __phy_write(dev, RTL8211F_WOL_SETTINGS_EVENTS, 0); +- __phy_write(dev, RTL8211F_WOL_SETTINGS_STATUS, RTL8211F_WOL_STATUS_RESET); ++ ++ /* Place WoL in reset */ ++ __phy_clear_bits(dev, RTL8211F_WOL_RST_RMSQ, ++ RTL8211F_WOL_RG_RSTB); + } + ++ device_set_wakeup_enable(&dev->mdio.dev, !!(wol->wolopts & WAKE_MAGIC)); ++ + err: + return phy_restore_page(dev, oldpage, 0); + } +@@ -627,6 +671,52 @@ static int rtl821x_suspend(struct phy_de + return ret; + } + ++static int rtl8211f_suspend(struct phy_device *phydev) ++{ ++ u16 wol_rst; ++ int ret; ++ ++ ret = rtl821x_suspend(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* If a PME event is enabled, then configure the interrupt for ++ * PME events only, disabling link interrupt. We avoid switching ++ * to PMEB mode as we don't have a status bit for that. ++ */ ++ if (device_may_wakeup(&phydev->mdio.dev)) { ++ ret = phy_write_paged(phydev, 0xa42, RTL821x_INER, ++ RTL8211F_INER_PME); ++ if (ret < 0) ++ goto err; ++ ++ /* Read the INSR to clear any pending interrupt */ ++ phy_read_paged(phydev, RTL8211F_INSR_PAGE, RTL8211F_INSR); ++ ++ /* Reset the WoL to ensure that an event is picked up. ++ * Unless we do this, even if we receive another packet, ++ * we may not have a PME interrupt raised. ++ */ ++ ret = phy_read_paged(phydev, RTL8211F_WOL_PAGE, ++ RTL8211F_WOL_RST_RMSQ); ++ if (ret < 0) ++ goto err; ++ ++ wol_rst = ret & ~RTL8211F_WOL_RG_RSTB; ++ ret = phy_write_paged(phydev, RTL8211F_WOL_PAGE, ++ RTL8211F_WOL_RST_RMSQ, wol_rst); ++ if (ret < 0) ++ goto err; ++ ++ wol_rst |= RTL8211F_WOL_RG_RSTB; ++ ret = phy_write_paged(phydev, RTL8211F_WOL_PAGE, ++ RTL8211F_WOL_RST_RMSQ, wol_rst); ++ } ++ ++err: ++ return ret; ++} ++ + static int rtl821x_resume(struct phy_device *phydev) + { + struct rtl821x_priv *priv = phydev->priv; +@@ -644,6 +734,24 @@ static int rtl821x_resume(struct phy_dev + return 0; + } + ++static int rtl8211f_resume(struct phy_device *phydev) ++{ ++ struct rtl821x_priv *priv = phydev->priv; ++ int ret; ++ ++ ret = rtl821x_resume(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* If the device was programmed for a PME event, restore the interrupt ++ * enable so phylib can receive link state interrupts. ++ */ ++ if (device_may_wakeup(&phydev->mdio.dev)) ++ ret = phy_write_paged(phydev, 0xa42, RTL821x_INER, priv->iner); ++ ++ return ret; ++} ++ + static int rtl8211x_led_hw_is_supported(struct phy_device *phydev, u8 index, + unsigned long rules) + { +@@ -1639,15 +1747,15 @@ static struct phy_driver realtek_drvs[] + }, { + PHY_ID_MATCH_EXACT(0x001cc916), + .name = "RTL8211F Gigabit Ethernet", +- .probe = rtl821x_probe, ++ .probe = rtl8211f_probe, + .config_init = &rtl8211f_config_init, + .read_status = rtlgen_read_status, + .config_intr = &rtl8211f_config_intr, + .handle_interrupt = rtl8211f_handle_interrupt, + .set_wol = rtl8211f_set_wol, + .get_wol = rtl8211f_get_wol, +- .suspend = rtl821x_suspend, +- .resume = rtl821x_resume, ++ .suspend = rtl8211f_suspend, ++ .resume = rtl8211f_resume, + .read_page = rtl821x_read_page, + .write_page = rtl821x_write_page, + .flags = PHY_ALWAYS_CALL_SUSPEND, diff --git a/lede/target/linux/generic/backport-6.12/784-03-v6.18-net-phy-realtek-fix-rtl8221b-vm-cg-name.patch b/lede/target/linux/generic/backport-6.12/784-03-v6.18-net-phy-realtek-fix-rtl8221b-vm-cg-name.patch new file mode 100644 index 0000000000..ab319f0806 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/784-03-v6.18-net-phy-realtek-fix-rtl8221b-vm-cg-name.patch @@ -0,0 +1,70 @@ +From ffff5c8fc2af2218a3332b3d5b97654599d50cde Mon Sep 17 00:00:00 2001 +From: Aleksander Jan Bajkowski +Date: Thu, 16 Oct 2025 21:22:52 +0200 +Subject: [PATCH] net: phy: realtek: fix rtl8221b-vm-cg name + +When splitting the RTL8221B-VM-CG into C22 and C45 variants, the name was +accidentally changed to RTL8221B-VN-CG. This patch brings back the previous +part number. + +Fixes: ad5ce743a6b0 ("net: phy: realtek: Add driver instances for rtl8221b via Clause 45") +Signed-off-by: Aleksander Jan Bajkowski +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251016192325.2306757-1-olek2@wp.pl +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -154,7 +154,7 @@ + #define RTL_8211FVD_PHYID 0x001cc878 + #define RTL_8221B 0x001cc840 + #define RTL_8221B_VB_CG 0x001cc849 +-#define RTL_8221B_VN_CG 0x001cc84a ++#define RTL_8221B_VM_CG 0x001cc84a + #define RTL_8251B 0x001cc862 + #define RTL_8261C 0x001cc890 + +@@ -1498,16 +1498,16 @@ static int rtl8221b_vb_cg_c45_match_phy_ + return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true); + } + +-static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev, ++static int rtl8221b_vm_cg_c22_match_phy_device(struct phy_device *phydev, + const struct phy_driver *phydrv) + { +- return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false); ++ return rtlgen_is_c45_match(phydev, RTL_8221B_VM_CG, false); + } + +-static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev, ++static int rtl8221b_vm_cg_c45_match_phy_device(struct phy_device *phydev, + const struct phy_driver *phydrv) + { +- return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true); ++ return rtlgen_is_c45_match(phydev, RTL_8221B_VM_CG, true); + } + + static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev, +@@ -1854,7 +1854,7 @@ static struct phy_driver realtek_drvs[] + .suspend = genphy_c45_pma_suspend, + .resume = rtlgen_c45_resume, + }, { +- .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, ++ .match_phy_device = rtl8221b_vm_cg_c22_match_phy_device, + .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", + .probe = rtl822x_probe, + .get_features = rtl822x_get_features, +@@ -1867,8 +1867,8 @@ static struct phy_driver realtek_drvs[] + .read_page = rtl821x_read_page, + .write_page = rtl821x_write_page, + }, { +- .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, +- .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", ++ .match_phy_device = rtl8221b_vm_cg_c45_match_phy_device, ++ .name = "RTL8221B-VM-CG 2.5Gbps PHY (C45)", + .probe = rtl822x_probe, + .config_init = rtl822xb_config_init, + .get_rate_matching = rtl822xb_get_rate_matching, diff --git a/lede/target/linux/generic/backport-6.12/784-03-v6.18-net-phy-realtek-support-for-TRIGGER_NETDEV_LINK-on-R.patch b/lede/target/linux/generic/backport-6.12/784-03-v6.18-net-phy-realtek-support-for-TRIGGER_NETDEV_LINK-on-R.patch new file mode 100644 index 0000000000..dc8d247dae --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/784-03-v6.18-net-phy-realtek-support-for-TRIGGER_NETDEV_LINK-on-R.patch @@ -0,0 +1,105 @@ +From f63f21e82ecafd288b100ea161247820bf1e92c4 Mon Sep 17 00:00:00 2001 +From: Aleksander Jan Bajkowski +Date: Mon, 25 Aug 2025 23:09:49 +0200 +Subject: [PATCH] net: phy: realtek: support for TRIGGER_NETDEV_LINK on + RTL8211E and RTL8211F + +This patch adds support for the TRIGGER_NETDEV_LINK trigger. It activates +the LED when a link is established, regardless of the speed. + +Tested on Orange Pi PC2 with RTL8211E PHY. + +Signed-off-by: Aleksander Jan Bajkowski +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250825211059.143231-1-olek2@wp.pl +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 39 +++++++++++++++++++++----- + 1 file changed, 32 insertions(+), 7 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -755,7 +755,8 @@ static int rtl8211f_resume(struct phy_de + static int rtl8211x_led_hw_is_supported(struct phy_device *phydev, u8 index, + unsigned long rules) + { +- const unsigned long mask = BIT(TRIGGER_NETDEV_LINK_10) | ++ const unsigned long mask = BIT(TRIGGER_NETDEV_LINK) | ++ BIT(TRIGGER_NETDEV_LINK_10) | + BIT(TRIGGER_NETDEV_LINK_100) | + BIT(TRIGGER_NETDEV_LINK_1000) | + BIT(TRIGGER_NETDEV_RX) | +@@ -813,6 +814,12 @@ static int rtl8211f_led_hw_control_get(s + if (val & RTL8211F_LEDCR_LINK_1000) + __set_bit(TRIGGER_NETDEV_LINK_1000, rules); + ++ if ((val & RTL8211F_LEDCR_LINK_10) && ++ (val & RTL8211F_LEDCR_LINK_100) && ++ (val & RTL8211F_LEDCR_LINK_1000)) { ++ __set_bit(TRIGGER_NETDEV_LINK, rules); ++ } ++ + if (val & RTL8211F_LEDCR_ACT_TXRX) { + __set_bit(TRIGGER_NETDEV_RX, rules); + __set_bit(TRIGGER_NETDEV_TX, rules); +@@ -830,14 +837,20 @@ static int rtl8211f_led_hw_control_set(s + if (index >= RTL8211x_LED_COUNT) + return -EINVAL; + +- if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) ++ if (test_bit(TRIGGER_NETDEV_LINK, &rules) || ++ test_bit(TRIGGER_NETDEV_LINK_10, &rules)) { + reg |= RTL8211F_LEDCR_LINK_10; ++ } + +- if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ if (test_bit(TRIGGER_NETDEV_LINK, &rules) || ++ test_bit(TRIGGER_NETDEV_LINK_100, &rules)) { + reg |= RTL8211F_LEDCR_LINK_100; ++ } + +- if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ if (test_bit(TRIGGER_NETDEV_LINK, &rules) || ++ test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) { + reg |= RTL8211F_LEDCR_LINK_1000; ++ } + + if (test_bit(TRIGGER_NETDEV_RX, &rules) || + test_bit(TRIGGER_NETDEV_TX, &rules)) { +@@ -885,6 +898,12 @@ static int rtl8211e_led_hw_control_get(s + if (cr2 & RTL8211E_LEDCR2_LINK_1000) + __set_bit(TRIGGER_NETDEV_LINK_1000, rules); + ++ if ((cr2 & RTL8211E_LEDCR2_LINK_10) && ++ (cr2 & RTL8211E_LEDCR2_LINK_100) && ++ (cr2 & RTL8211E_LEDCR2_LINK_1000)) { ++ __set_bit(TRIGGER_NETDEV_LINK, rules); ++ } ++ + return ret; + } + +@@ -912,14 +931,20 @@ static int rtl8211e_led_hw_control_set(s + if (ret < 0) + return ret; + +- if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) ++ if (test_bit(TRIGGER_NETDEV_LINK, &rules) || ++ test_bit(TRIGGER_NETDEV_LINK_10, &rules)) { + cr2 |= RTL8211E_LEDCR2_LINK_10; ++ } + +- if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ if (test_bit(TRIGGER_NETDEV_LINK, &rules) || ++ test_bit(TRIGGER_NETDEV_LINK_100, &rules)) { + cr2 |= RTL8211E_LEDCR2_LINK_100; ++ } + +- if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ if (test_bit(TRIGGER_NETDEV_LINK, &rules) || ++ test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) { + cr2 |= RTL8211E_LEDCR2_LINK_1000; ++ } + + cr2 <<= RTL8211E_LEDCR2_SHIFT * index; + ret = rtl821x_modify_ext_page(phydev, RTL8211E_LEDCR_EXT_PAGE, diff --git a/lede/target/linux/generic/backport-6.12/784-06-v6.19-net-phy-realtek-Add-RTL8224-cable-testing-support.patch b/lede/target/linux/generic/backport-6.12/784-06-v6.19-net-phy-realtek-Add-RTL8224-cable-testing-support.patch new file mode 100644 index 0000000000..d95211dc65 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/784-06-v6.19-net-phy-realtek-Add-RTL8224-cable-testing-support.patch @@ -0,0 +1,272 @@ +From 61958b33ef0bab1c1874c933cd3910f495526782 Mon Sep 17 00:00:00 2001 +From: Issam Hamdi +Date: Fri, 24 Oct 2025 11:49:00 +0200 +Subject: [PATCH] net: phy: realtek: Add RTL8224 cable testing support + +The RTL8224 can detect open pairs and short types (in same pair or some +other pair). The distance to this problem can be estimated. This is done +for each of the 4 pairs separately. + +It is not meant to be run while there is an active link partner because +this interferes with the active test pulses. + +Output with open 50 m cable: + + Pair A code Open Circuit, source: TDR + Pair A, fault length: 51.79m, source: TDR + Pair B code Open Circuit, source: TDR + Pair B, fault length: 51.28m, source: TDR + Pair C code Open Circuit, source: TDR + Pair C, fault length: 50.46m, source: TDR + Pair D code Open Circuit, source: TDR + Pair D, fault length: 51.12m, source: TDR + +Terminated cable: + + Pair A code OK, source: TDR + Pair B code OK, source: TDR + Pair C code OK, source: TDR + Pair D code OK, source: TDR + +Shorted cable (both short types are at roughly the same distance) + + Pair A code Short to another pair, source: TDR + Pair A, fault length: 2.35m, source: TDR + Pair B code Short to another pair, source: TDR + Pair B, fault length: 2.15m, source: TDR + Pair C code OK, source: TDR + Pair D code Short within Pair, source: TDR + Pair D, fault length: 1.94m, source: TDR + +Signed-off-by: Issam Hamdi +Co-developed-by: Sven Eckelmann +Signed-off-by: Sven Eckelmann +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20251024-rtl8224-cable-test-v1-1-e3cda89ac98f@simonwunderlich.de +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 187 +++++++++++++++++++++++++ + 1 file changed, 187 insertions(+) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -8,6 +8,7 @@ + * Copyright (c) 2004 Freescale Semiconductor, Inc. + */ + #include ++#include + #include + #include + #include +@@ -127,6 +128,27 @@ + */ + #define RTL822X_VND2_C22_REG(reg) (0xa400 + 2 * (reg)) + ++#define RTL8224_MII_RTCT 0x11 ++#define RTL8224_MII_RTCT_ENABLE BIT(0) ++#define RTL8224_MII_RTCT_PAIR_A BIT(4) ++#define RTL8224_MII_RTCT_PAIR_B BIT(5) ++#define RTL8224_MII_RTCT_PAIR_C BIT(6) ++#define RTL8224_MII_RTCT_PAIR_D BIT(7) ++#define RTL8224_MII_RTCT_DONE BIT(15) ++ ++#define RTL8224_MII_SRAM_ADDR 0x1b ++#define RTL8224_MII_SRAM_DATA 0x1c ++ ++#define RTL8224_SRAM_RTCT_FAULT(pair) (0x8026 + (pair) * 4) ++#define RTL8224_SRAM_RTCT_FAULT_BUSY BIT(0) ++#define RTL8224_SRAM_RTCT_FAULT_OPEN BIT(3) ++#define RTL8224_SRAM_RTCT_FAULT_SAME_SHORT BIT(4) ++#define RTL8224_SRAM_RTCT_FAULT_OK BIT(5) ++#define RTL8224_SRAM_RTCT_FAULT_DONE BIT(6) ++#define RTL8224_SRAM_RTCT_FAULT_CROSS_SHORT BIT(7) ++ ++#define RTL8224_SRAM_RTCT_LEN(pair) (0x8028 + (pair) * 4) ++ + #define RTL8366RB_POWER_SAVE 0x15 + #define RTL8366RB_POWER_SAVE_ON BIT(12) + +@@ -1453,6 +1475,168 @@ static int rtl822xb_c45_read_status(stru + return 0; + } + ++static int rtl8224_cable_test_start(struct phy_device *phydev) ++{ ++ u32 val; ++ int ret; ++ ++ /* disable auto-negotiation and force 1000/Full */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, ++ RTL822X_VND2_C22_REG(MII_BMCR), ++ BMCR_ANENABLE | BMCR_SPEED100 | BMCR_SPEED10, ++ BMCR_SPEED1000 | BMCR_FULLDPLX); ++ if (ret) ++ return ret; ++ ++ mdelay(500); ++ ++ /* trigger cable test */ ++ val = RTL8224_MII_RTCT_ENABLE; ++ val |= RTL8224_MII_RTCT_PAIR_A; ++ val |= RTL8224_MII_RTCT_PAIR_B; ++ val |= RTL8224_MII_RTCT_PAIR_C; ++ val |= RTL8224_MII_RTCT_PAIR_D; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, ++ RTL822X_VND2_C22_REG(RTL8224_MII_RTCT), ++ RTL8224_MII_RTCT_DONE, val); ++} ++ ++static int rtl8224_sram_read(struct phy_device *phydev, u32 reg) ++{ ++ int ret; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, ++ RTL822X_VND2_C22_REG(RTL8224_MII_SRAM_ADDR), ++ reg); ++ if (ret) ++ return ret; ++ ++ return phy_read_mmd(phydev, MDIO_MMD_VEND2, ++ RTL822X_VND2_C22_REG(RTL8224_MII_SRAM_DATA)); ++} ++ ++static int rtl8224_pair_len_get(struct phy_device *phydev, u32 pair) ++{ ++ int cable_len; ++ u32 reg_len; ++ int ret; ++ u32 cm; ++ ++ reg_len = RTL8224_SRAM_RTCT_LEN(pair); ++ ++ ret = rtl8224_sram_read(phydev, reg_len); ++ if (ret < 0) ++ return ret; ++ ++ cable_len = ret & 0xff00; ++ ++ ret = rtl8224_sram_read(phydev, reg_len + 1); ++ if (ret < 0) ++ return ret; ++ ++ cable_len |= (ret & 0xff00) >> 8; ++ ++ cable_len -= 620; ++ cable_len = max(cable_len, 0); ++ ++ cm = cable_len * 100 / 78; ++ ++ return cm; ++} ++ ++static int rtl8224_cable_test_result_trans(u32 result) ++{ ++ if (!(result & RTL8224_SRAM_RTCT_FAULT_DONE)) ++ return -EBUSY; ++ ++ if (result & RTL8224_SRAM_RTCT_FAULT_OK) ++ return ETHTOOL_A_CABLE_RESULT_CODE_OK; ++ ++ if (result & RTL8224_SRAM_RTCT_FAULT_OPEN) ++ return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; ++ ++ if (result & RTL8224_SRAM_RTCT_FAULT_SAME_SHORT) ++ return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; ++ ++ if (result & RTL8224_SRAM_RTCT_FAULT_BUSY) ++ return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; ++ ++ if (result & RTL8224_SRAM_RTCT_FAULT_CROSS_SHORT) ++ return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; ++ ++ return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; ++} ++ ++static int rtl8224_cable_test_report_pair(struct phy_device *phydev, unsigned int pair) ++{ ++ int fault_rslt; ++ int ret; ++ ++ ret = rtl8224_sram_read(phydev, RTL8224_SRAM_RTCT_FAULT(pair)); ++ if (ret < 0) ++ return ret; ++ ++ fault_rslt = rtl8224_cable_test_result_trans(ret); ++ if (fault_rslt < 0) ++ return 0; ++ ++ ret = ethnl_cable_test_result(phydev, pair, fault_rslt); ++ if (ret < 0) ++ return ret; ++ ++ switch (fault_rslt) { ++ case ETHTOOL_A_CABLE_RESULT_CODE_OPEN: ++ case ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT: ++ case ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT: ++ ret = rtl8224_pair_len_get(phydev, pair); ++ if (ret < 0) ++ return ret; ++ ++ return ethnl_cable_test_fault_length(phydev, pair, ret); ++ default: ++ return 0; ++ } ++} ++ ++static int rtl8224_cable_test_report(struct phy_device *phydev, bool *finished) ++{ ++ unsigned int pair; ++ int ret; ++ ++ for (pair = ETHTOOL_A_CABLE_PAIR_A; pair <= ETHTOOL_A_CABLE_PAIR_D; pair++) { ++ ret = rtl8224_cable_test_report_pair(phydev, pair); ++ if (ret == -EBUSY) { ++ *finished = false; ++ return 0; ++ } ++ ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int rtl8224_cable_test_get_status(struct phy_device *phydev, bool *finished) ++{ ++ int ret; ++ ++ *finished = false; ++ ++ ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, ++ RTL822X_VND2_C22_REG(RTL8224_MII_RTCT)); ++ if (ret < 0) ++ return ret; ++ ++ if (!(ret & RTL8224_MII_RTCT_DONE)) ++ return 0; ++ ++ *finished = true; ++ ++ return rtl8224_cable_test_report(phydev, finished); ++} ++ + static bool rtlgen_supports_2_5gbps(struct phy_device *phydev) + { + int val; +@@ -1930,11 +2114,14 @@ static struct phy_driver realtek_drvs[] + }, { + PHY_ID_MATCH_EXACT(0x001ccad0), + .name = "RTL8224 2.5Gbps PHY", ++ .flags = PHY_POLL_CABLE_TEST, + .get_features = rtl822x_c45_get_features, + .config_aneg = rtl822x_c45_config_aneg, + .read_status = rtl822x_c45_read_status, + .suspend = genphy_c45_pma_suspend, + .resume = rtlgen_c45_resume, ++ .cable_test_start = rtl8224_cable_test_start, ++ .cable_test_get_status = rtl8224_cable_test_get_status, + }, { + PHY_ID_MATCH_EXACT(0x001cc961), + .name = "RTL8366RB Gigabit Ethernet", diff --git a/lede/target/linux/generic/backport-6.12/784-07-v6.19-net-phy-realtek-add-interrupt-support-for-RTL8221B.patch b/lede/target/linux/generic/backport-6.12/784-07-v6.19-net-phy-realtek-add-interrupt-support-for-RTL8221B.patch new file mode 100644 index 0000000000..2efa4e961b --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/784-07-v6.19-net-phy-realtek-add-interrupt-support-for-RTL8221B.patch @@ -0,0 +1,105 @@ +From 18aa36238a4d835c1644dcccd63d32c7fdd4b310 Mon Sep 17 00:00:00 2001 +From: Jianhui Zhao +Date: Sun, 2 Nov 2025 16:26:37 +0100 +Subject: [PATCH] net: phy: realtek: add interrupt support for RTL8221B + +This commit introduces interrupt support for RTL8221B (C45 mode). +Interrupts are mapped on the VEND2 page. VEND2 registers are only +accessible via C45 reads and cannot be accessed by C45 over C22. + +Signed-off-by: Jianhui Zhao +[Enable only link state change interrupts] +Signed-off-by: Aleksander Jan Bajkowski +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20251102152644.1676482-1-olek2@wp.pl +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 56 ++++++++++++++++++++++++++ + 1 file changed, 56 insertions(+) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -128,6 +128,11 @@ + */ + #define RTL822X_VND2_C22_REG(reg) (0xa400 + 2 * (reg)) + ++#define RTL8221B_VND2_INER 0xa4d2 ++#define RTL8221B_VND2_INER_LINK_STATUS BIT(4) ++ ++#define RTL8221B_VND2_INSR 0xa4d4 ++ + #define RTL8224_MII_RTCT 0x11 + #define RTL8224_MII_RTCT_ENABLE BIT(0) + #define RTL8224_MII_RTCT_PAIR_A BIT(4) +@@ -1880,6 +1885,53 @@ static irqreturn_t rtl9000a_handle_inter + return IRQ_HANDLED; + } + ++static int rtl8221b_ack_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL8221B_VND2_INSR); ++ ++ return (err < 0) ? err : 0; ++} ++ ++static int rtl8221b_config_intr(struct phy_device *phydev) ++{ ++ int err; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { ++ err = rtl8221b_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND2, RTL8221B_VND2_INER, ++ RTL8221B_VND2_INER_LINK_STATUS); ++ } else { ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND2, ++ RTL8221B_VND2_INER, 0); ++ if (err) ++ return err; ++ ++ err = rtl8221b_ack_interrupt(phydev); ++ } ++ ++ return err; ++} ++ ++static irqreturn_t rtl8221b_handle_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = rtl8221b_ack_interrupt(phydev); ++ if (err) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ + static struct phy_driver realtek_drvs[] = { + { + PHY_ID_MATCH_EXACT(0x00008201), +@@ -2054,6 +2106,8 @@ static struct phy_driver realtek_drvs[] + }, { + .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, + .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", ++ .config_intr = rtl8221b_config_intr, ++ .handle_interrupt = rtl8221b_handle_interrupt, + .probe = rtl822x_probe, + .config_init = rtl822xb_config_init, + .get_rate_matching = rtl822xb_get_rate_matching, +@@ -2078,6 +2132,8 @@ static struct phy_driver realtek_drvs[] + }, { + .match_phy_device = rtl8221b_vm_cg_c45_match_phy_device, + .name = "RTL8221B-VM-CG 2.5Gbps PHY (C45)", ++ .config_intr = rtl8221b_config_intr, ++ .handle_interrupt = rtl8221b_handle_interrupt, + .probe = rtl822x_probe, + .config_init = rtl822xb_config_init, + .get_rate_matching = rtl822xb_get_rate_matching, diff --git a/lede/target/linux/generic/backport-6.12/784-08-v6.19-net-phy-realtek-create-rtl8211f_config_rgmii_delay.patch b/lede/target/linux/generic/backport-6.12/784-08-v6.19-net-phy-realtek-create-rtl8211f_config_rgmii_delay.patch new file mode 100644 index 0000000000..0c523ee683 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/784-08-v6.19-net-phy-realtek-create-rtl8211f_config_rgmii_delay.patch @@ -0,0 +1,128 @@ +From 8e982441ba601d982dd0739972115d85ae01d99b Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Tue, 18 Nov 2025 01:40:28 +0200 +Subject: [PATCH] net: phy: realtek: create rtl8211f_config_rgmii_delay() + +The control flow in rtl8211f_config_init() has some pitfalls which were +probably unintended. Specifically it has an early return: + + switch (phydev->interface) { + ... + default: /* the rest of the modes imply leaving delay as is. */ + return 0; + } + +which exits the entire config_init() function. This means it also skips +doing things such as disabling CLKOUT or disabling PHY-mode EEE. + +For the RTL8211FS, which uses PHY_INTERFACE_MODE_SGMII, this might be a +problem. However, I don't know that it is, so there is no Fixes: tag. +The issue was observed through code inspection. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20251117234033.345679-2-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 65 +++++++++++++++----------- + 1 file changed, 39 insertions(+), 26 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -587,22 +587,11 @@ static int rtl8211c_config_init(struct p + CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER); + } + +-static int rtl8211f_config_init(struct phy_device *phydev) ++static int rtl8211f_config_rgmii_delay(struct phy_device *phydev) + { +- struct rtl821x_priv *priv = phydev->priv; +- struct device *dev = &phydev->mdio.dev; + u16 val_txdly, val_rxdly; + int ret; + +- ret = phy_modify_paged_changed(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1, +- RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF, +- priv->phycr1); +- if (ret < 0) { +- dev_err(dev, "aldps mode configuration failed: %pe\n", +- ERR_PTR(ret)); +- return ret; +- } +- + switch (phydev->interface) { + case PHY_INTERFACE_MODE_RGMII: + val_txdly = 0; +@@ -632,34 +621,58 @@ static int rtl8211f_config_init(struct p + RTL8211F_TXCR, RTL8211F_TX_DELAY, + val_txdly); + if (ret < 0) { +- dev_err(dev, "Failed to update the TX delay register\n"); ++ phydev_err(phydev, "Failed to update the TX delay register: %pe\n", ++ ERR_PTR(ret)); + return ret; + } else if (ret) { +- dev_dbg(dev, +- "%s 2ns TX delay (and changing the value from pin-strapping RXD1 or the bootloader)\n", +- str_enable_disable(val_txdly)); ++ phydev_dbg(phydev, ++ "%s 2ns TX delay (and changing the value from pin-strapping RXD1 or the bootloader)\n", ++ str_enable_disable(val_txdly)); + } else { +- dev_dbg(dev, +- "2ns TX delay was already %s (by pin-strapping RXD1 or bootloader configuration)\n", +- str_enabled_disabled(val_txdly)); ++ phydev_dbg(phydev, ++ "2ns TX delay was already %s (by pin-strapping RXD1 or bootloader configuration)\n", ++ str_enabled_disabled(val_txdly)); + } + + ret = phy_modify_paged_changed(phydev, RTL8211F_RGMII_PAGE, + RTL8211F_RXCR, RTL8211F_RX_DELAY, + val_rxdly); + if (ret < 0) { +- dev_err(dev, "Failed to update the RX delay register\n"); ++ phydev_err(phydev, "Failed to update the RX delay register: %pe\n", ++ ERR_PTR(ret)); + return ret; + } else if (ret) { +- dev_dbg(dev, +- "%s 2ns RX delay (and changing the value from pin-strapping RXD0 or the bootloader)\n", +- str_enable_disable(val_rxdly)); ++ phydev_dbg(phydev, ++ "%s 2ns RX delay (and changing the value from pin-strapping RXD0 or the bootloader)\n", ++ str_enable_disable(val_rxdly)); + } else { +- dev_dbg(dev, +- "2ns RX delay was already %s (by pin-strapping RXD0 or bootloader configuration)\n", +- str_enabled_disabled(val_rxdly)); ++ phydev_dbg(phydev, ++ "2ns RX delay was already %s (by pin-strapping RXD0 or bootloader configuration)\n", ++ str_enabled_disabled(val_rxdly)); + } + ++ return 0; ++} ++ ++static int rtl8211f_config_init(struct phy_device *phydev) ++{ ++ struct rtl821x_priv *priv = phydev->priv; ++ struct device *dev = &phydev->mdio.dev; ++ int ret; ++ ++ ret = phy_modify_paged_changed(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1, ++ RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF, ++ priv->phycr1); ++ if (ret < 0) { ++ dev_err(dev, "aldps mode configuration failed: %pe\n", ++ ERR_PTR(ret)); ++ return ret; ++ } ++ ++ ret = rtl8211f_config_rgmii_delay(phydev); ++ if (ret) ++ return ret; ++ + if (!priv->has_phycr2) + return 0; + diff --git a/lede/target/linux/generic/backport-6.12/784-09-v6.19-net-phy-realtek-eliminate-priv-phycr2-variable.patch b/lede/target/linux/generic/backport-6.12/784-09-v6.19-net-phy-realtek-eliminate-priv-phycr2-variable.patch new file mode 100644 index 0000000000..1c67961d2e --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/784-09-v6.19-net-phy-realtek-eliminate-priv-phycr2-variable.patch @@ -0,0 +1,101 @@ +From 27033d06917758d47162581da7e9de8004049dee Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Tue, 18 Nov 2025 01:40:29 +0200 +Subject: [PATCH] net: phy: realtek: eliminate priv->phycr2 variable + +The RTL8211F(D)(I)-VD-CG PHY also has support for disabling the CLKOUT, +and we'd like to introduce the "realtek,clkout-disable" property for +that. + +But it isn't done through the PHYCR2 register, and it becomes awkward to +have the driver pretend that it is. So just replace the machine-level +"u16 phycr2" variable with a logical "bool disable_clk_out", which +scales better to the other PHY as well. + +The change is a complete functional equivalent. Before, if the device +tree property was absent, priv->phycr2 would contain the RTL8211F_CLKOUT_EN +bit as read from hardware. Now, we don't save priv->phycr2, but we just +don't call phy_modify_paged() on it. Also, we can simply call +phy_modify_paged() with the "set" argument to 0. + +Signed-off-by: Vladimir Oltean +Link: https://patch.msgid.link/20251117234033.345679-3-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 38 ++++++++++++++++---------- + 1 file changed, 23 insertions(+), 15 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -194,8 +194,8 @@ MODULE_LICENSE("GPL"); + + struct rtl821x_priv { + u16 phycr1; +- u16 phycr2; + bool has_phycr2; ++ bool disable_clk_out; + struct clk *clk; + /* rtl8211f */ + u16 iner; +@@ -266,15 +266,8 @@ static int rtl821x_probe(struct phy_devi + priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF; + + priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID); +- if (priv->has_phycr2) { +- ret = phy_read_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2); +- if (ret < 0) +- return ret; +- +- priv->phycr2 = ret & RTL8211F_CLKOUT_EN; +- if (of_property_read_bool(dev->of_node, "realtek,clkout-disable")) +- priv->phycr2 &= ~RTL8211F_CLKOUT_EN; +- } ++ priv->disable_clk_out = of_property_read_bool(dev->of_node, ++ "realtek,clkout-disable"); + + phydev->priv = priv; + +@@ -654,6 +647,23 @@ static int rtl8211f_config_rgmii_delay(s + return 0; + } + ++static int rtl8211f_config_clk_out(struct phy_device *phydev) ++{ ++ struct rtl821x_priv *priv = phydev->priv; ++ int ret; ++ ++ /* The value is preserved if the device tree property is absent */ ++ if (!priv->disable_clk_out) ++ return 0; ++ ++ ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, ++ RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 0); ++ if (ret) ++ return ret; ++ ++ return genphy_soft_reset(phydev); ++} ++ + static int rtl8211f_config_init(struct phy_device *phydev) + { + struct rtl821x_priv *priv = phydev->priv; +@@ -682,16 +692,14 @@ static int rtl8211f_config_init(struct p + if (ret) + return ret; + +- ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, +- RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, +- priv->phycr2); +- if (ret < 0) { ++ ret = rtl8211f_config_clk_out(phydev); ++ if (ret) { + dev_err(dev, "clkout configuration failed: %pe\n", + ERR_PTR(ret)); + return ret; + } + +- return genphy_soft_reset(phydev); ++ return 0; + } + + static int rtl821x_suspend(struct phy_device *phydev) diff --git a/lede/target/linux/generic/backport-6.12/784-10-v6.19-net-phy-realtek-eliminate-has_phycr2-variable.patch b/lede/target/linux/generic/backport-6.12/784-10-v6.19-net-phy-realtek-eliminate-has_phycr2-variable.patch new file mode 100644 index 0000000000..a78cb3d1cc --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/784-10-v6.19-net-phy-realtek-eliminate-has_phycr2-variable.patch @@ -0,0 +1,55 @@ +From 910ac7bfb1af1ae4cd141ef80e03a6729213c189 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Tue, 18 Nov 2025 01:40:30 +0200 +Subject: [PATCH] net: phy: realtek: eliminate has_phycr2 variable + +This variable is assigned in rtl821x_probe() and used in +rtl8211f_config_init(), which is more complex than it needs to be. +Simply testing the same condition from rtl821x_probe() in +rtl8211f_config_init() yields the same result (the PHY driver ID is a +runtime invariant), but with one temporary variable less. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20251117234033.345679-4-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -194,7 +194,6 @@ MODULE_LICENSE("GPL"); + + struct rtl821x_priv { + u16 phycr1; +- bool has_phycr2; + bool disable_clk_out; + struct clk *clk; + /* rtl8211f */ +@@ -245,7 +244,6 @@ static int rtl821x_probe(struct phy_devi + { + struct device *dev = &phydev->mdio.dev; + struct rtl821x_priv *priv; +- u32 phy_id = phydev->drv->phy_id; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +@@ -265,7 +263,6 @@ static int rtl821x_probe(struct phy_devi + if (of_property_read_bool(dev->of_node, "realtek,aldps-enable")) + priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF; + +- priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID); + priv->disable_clk_out = of_property_read_bool(dev->of_node, + "realtek,clkout-disable"); + +@@ -683,7 +680,8 @@ static int rtl8211f_config_init(struct p + if (ret) + return ret; + +- if (!priv->has_phycr2) ++ /* RTL8211FVD has no PHYCR2 register */ ++ if (phydev->drv->phy_id == RTL_8211FVD_PHYID) + return 0; + + /* Disable PHY-mode EEE so LPI is passed to the MAC */ diff --git a/lede/target/linux/generic/backport-6.12/784-11-v6.19-net-phy-realtek-allow-CLKOUT-to-be-disabled-on-RTL82.patch b/lede/target/linux/generic/backport-6.12/784-11-v6.19-net-phy-realtek-allow-CLKOUT-to-be-disabled-on-RTL82.patch new file mode 100644 index 0000000000..2a3239d4a2 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/784-11-v6.19-net-phy-realtek-allow-CLKOUT-to-be-disabled-on-RTL82.patch @@ -0,0 +1,101 @@ +From e1a31c41bef678afe0d99b7f0dc3711a80c68447 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Tue, 18 Nov 2025 01:40:31 +0200 +Subject: [PATCH] net: phy: realtek: allow CLKOUT to be disabled on + RTL8211F(D)(I)-VD-CG + +Add CLKOUT disable support for RTL8211F(D)(I)-VD-CG. Like with other PHY +variants, this feature might be requested by customers when the clock +output is not used, in order to reduce electromagnetic interference (EMI). + +In the common driver, the CLKOUT configuration is done through PHYCR2. +The RTL_8211FVD_PHYID is singled out as not having that register, and +execution in rtl8211f_config_init() returns early after commit +2c67301584f2 ("net: phy: realtek: Avoid PHYCR2 access if PHYCR2 not +present"). + +But actually CLKOUT is configured through a different register for this +PHY. Instead of pretending this is PHYCR2 (which it is not), just add +some code for modifying this register inside the rtl8211f_disable_clk_out() +function, and move that outside the code portion that runs only if +PHYCR2 exists. + +In practice this reorders the PHYCR2 writes to disable PHY-mode EEE and +to disable the CLKOUT for the normal RTL8211F variants, but this should +be perfectly fine. + +It was not noted that RTL8211F(D)(I)-VD-CG would need a genphy_soft_reset() +call after disabling the CLKOUT. Despite that, we do it out of caution +and for symmetry with the other RTL8211F models. + +Co-developed-by: Clark Wang +Signed-off-by: Clark Wang +Signed-off-by: Vladimir Oltean +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20251117234033.345679-5-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 31 ++++++++++++++++++-------- + 1 file changed, 22 insertions(+), 9 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -90,6 +90,14 @@ + #define RTL8211F_LEDCR_MASK GENMASK(4, 0) + #define RTL8211F_LEDCR_SHIFT 5 + ++/* RTL8211F(D)(I)-VD-CG CLKOUT configuration is specified via magic values ++ * to undocumented register pages. The names here do not reflect the datasheet. ++ * Unlike other PHY models, CLKOUT configuration does not go through PHYCR2. ++ */ ++#define RTL8211FVD_CLKOUT_PAGE 0xd05 ++#define RTL8211FVD_CLKOUT_REG 0x11 ++#define RTL8211FVD_CLKOUT_EN BIT(8) ++ + /* RTL8211F RGMII configuration */ + #define RTL8211F_RGMII_PAGE 0xd08 + +@@ -653,8 +661,13 @@ static int rtl8211f_config_clk_out(struc + if (!priv->disable_clk_out) + return 0; + +- ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, +- RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 0); ++ if (phydev->drv->phy_id == RTL_8211FVD_PHYID) ++ ret = phy_modify_paged(phydev, RTL8211FVD_CLKOUT_PAGE, ++ RTL8211FVD_CLKOUT_REG, ++ RTL8211FVD_CLKOUT_EN, 0); ++ else ++ ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, ++ RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 0); + if (ret) + return ret; + +@@ -680,6 +693,13 @@ static int rtl8211f_config_init(struct p + if (ret) + return ret; + ++ ret = rtl8211f_config_clk_out(phydev); ++ if (ret) { ++ dev_err(dev, "clkout configuration failed: %pe\n", ++ ERR_PTR(ret)); ++ return ret; ++ } ++ + /* RTL8211FVD has no PHYCR2 register */ + if (phydev->drv->phy_id == RTL_8211FVD_PHYID) + return 0; +@@ -690,13 +710,6 @@ static int rtl8211f_config_init(struct p + if (ret) + return ret; + +- ret = rtl8211f_config_clk_out(phydev); +- if (ret) { +- dev_err(dev, "clkout configuration failed: %pe\n", +- ERR_PTR(ret)); +- return ret; +- } +- + return 0; + } + diff --git a/lede/target/linux/generic/backport-6.12/784-12-v6.19-net-phy-realtek-eliminate-priv-phycr1-variable.patch b/lede/target/linux/generic/backport-6.12/784-12-v6.19-net-phy-realtek-eliminate-priv-phycr1-variable.patch new file mode 100644 index 0000000000..a2e5abe93f --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/784-12-v6.19-net-phy-realtek-eliminate-priv-phycr1-variable.patch @@ -0,0 +1,107 @@ +From bb78b71faf60d11a15f07e3390fcfd31e5e523bb Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Tue, 18 Nov 2025 01:40:32 +0200 +Subject: [PATCH] net: phy: realtek: eliminate priv->phycr1 variable + +Previous changes have replaced the machine-level priv->phycr2 with a +high-level priv->disable_clk_out. This created a discrepancy with +priv->phycr1 which is resolved here, for uniformity. + +One advantage of this new implementation is that we don't read +priv->phycr1 in rtl821x_probe() if we're never going to modify it. + +We never test the positive return code from phy_modify_mmd_changed(), so +we could just as well use phy_modify_mmd(). + +I took the ALDPS feature description from commit d90db36a9e74 ("net: +phy: realtek: add dt property to enable ALDPS mode") and transformed it +into a function comment - the feature is sufficiently non-obvious to +deserve that. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20251117234033.345679-6-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 44 ++++++++++++++++---------- + 1 file changed, 28 insertions(+), 16 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -201,7 +201,7 @@ MODULE_AUTHOR("Johnson Leung"); + MODULE_LICENSE("GPL"); + + struct rtl821x_priv { +- u16 phycr1; ++ bool enable_aldps; + bool disable_clk_out; + struct clk *clk; + /* rtl8211f */ +@@ -252,7 +252,6 @@ static int rtl821x_probe(struct phy_devi + { + struct device *dev = &phydev->mdio.dev; + struct rtl821x_priv *priv; +- int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -263,14 +262,8 @@ static int rtl821x_probe(struct phy_devi + return dev_err_probe(dev, PTR_ERR(priv->clk), + "failed to get phy clock\n"); + +- ret = phy_read_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1); +- if (ret < 0) +- return ret; +- +- priv->phycr1 = ret & (RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF); +- if (of_property_read_bool(dev->of_node, "realtek,aldps-enable")) +- priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF; +- ++ priv->enable_aldps = of_property_read_bool(dev->of_node, ++ "realtek,aldps-enable"); + priv->disable_clk_out = of_property_read_bool(dev->of_node, + "realtek,clkout-disable"); + +@@ -674,17 +667,36 @@ static int rtl8211f_config_clk_out(struc + return genphy_soft_reset(phydev); + } + +-static int rtl8211f_config_init(struct phy_device *phydev) ++/* Advance Link Down Power Saving (ALDPS) mode changes crystal/clock behaviour, ++ * which causes the RXC clock signal to stop for tens to hundreds of ++ * milliseconds. ++ * ++ * Some MACs need the RXC clock to support their internal RX logic, so ALDPS is ++ * only enabled based on an opt-in device tree property. ++ */ ++static int rtl8211f_config_aldps(struct phy_device *phydev) + { + struct rtl821x_priv *priv = phydev->priv; ++ u16 mask = RTL8211F_ALDPS_PLL_OFF | ++ RTL8211F_ALDPS_ENABLE | ++ RTL8211F_ALDPS_XTAL_OFF; ++ ++ /* The value is preserved if the device tree property is absent */ ++ if (!priv->enable_aldps) ++ return 0; ++ ++ return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1, ++ mask, mask); ++} ++ ++static int rtl8211f_config_init(struct phy_device *phydev) ++{ + struct device *dev = &phydev->mdio.dev; + int ret; + +- ret = phy_modify_paged_changed(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1, +- RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF, +- priv->phycr1); +- if (ret < 0) { +- dev_err(dev, "aldps mode configuration failed: %pe\n", ++ ret = rtl8211f_config_aldps(phydev); ++ if (ret) { ++ dev_err(dev, "aldps mode configuration failed: %pe\n", + ERR_PTR(ret)); + return ret; + } diff --git a/lede/target/linux/generic/backport-6.12/784-13-v6.19-net-phy-realtek-create-rtl8211f_config_phy_eee-helpe.patch b/lede/target/linux/generic/backport-6.12/784-13-v6.19-net-phy-realtek-create-rtl8211f_config_phy_eee-helpe.patch new file mode 100644 index 0000000000..54ec217aff --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/784-13-v6.19-net-phy-realtek-create-rtl8211f_config_phy_eee-helpe.patch @@ -0,0 +1,58 @@ +From 4465ae435ddc0162d5033a543658449d53d46d08 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Tue, 18 Nov 2025 01:40:33 +0200 +Subject: [PATCH] net: phy: realtek: create rtl8211f_config_phy_eee() helper + +To simplify the rtl8211f_config_init() control flow and get rid of +"early" returns for PHYs where the PHYCR2 register is absent, move the +entire logic sub-block that deals with disabling PHY-mode EEE to a +separate function. There, it is much more obvious what the early +"return 0" skips, and it becomes more difficult to accidentally skip +unintended stuff. + +Signed-off-by: Vladimir Oltean +Link: https://patch.msgid.link/20251117234033.345679-7-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/realtek_main.c | 23 ++++++++++++----------- + 1 file changed, 12 insertions(+), 11 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -689,6 +689,17 @@ static int rtl8211f_config_aldps(struct + mask, mask); + } + ++static int rtl8211f_config_phy_eee(struct phy_device *phydev) ++{ ++ /* RTL8211FVD has no PHYCR2 register */ ++ if (phydev->drv->phy_id == RTL_8211FVD_PHYID) ++ return 0; ++ ++ /* Disable PHY-mode EEE so LPI is passed to the MAC */ ++ return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2, ++ RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); ++} ++ + static int rtl8211f_config_init(struct phy_device *phydev) + { + struct device *dev = &phydev->mdio.dev; +@@ -712,17 +723,7 @@ static int rtl8211f_config_init(struct p + return ret; + } + +- /* RTL8211FVD has no PHYCR2 register */ +- if (phydev->drv->phy_id == RTL_8211FVD_PHYID) +- return 0; +- +- /* Disable PHY-mode EEE so LPI is passed to the MAC */ +- ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2, +- RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); +- if (ret) +- return ret; +- +- return 0; ++ return rtl8211f_config_phy_eee(phydev); + } + + static int rtl821x_suspend(struct phy_device *phydev) diff --git a/lede/target/linux/generic/backport-6.12/786-01-v6.18-net-phy-introduce-phy_id_compare_vendor-PHY-ID-helpe.patch b/lede/target/linux/generic/backport-6.12/786-01-v6.18-net-phy-introduce-phy_id_compare_vendor-PHY-ID-helpe.patch new file mode 100644 index 0000000000..82e9e0695a --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/786-01-v6.18-net-phy-introduce-phy_id_compare_vendor-PHY-ID-helpe.patch @@ -0,0 +1,58 @@ +From 1abe21ef1adf0c5b6dbb5878c2fa4573df8d29fc Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 23 Aug 2025 15:44:28 +0200 +Subject: net: phy: introduce phy_id_compare_vendor() PHY ID helper + +Introduce phy_id_compare_vendor() PHY ID helper to compare a PHY ID with +the PHY ID Vendor using the generic PHY ID Vendor mask. + +While at it also rework the PHY_ID_MATCH macro and move the mask to +dedicated define so that PHY driver can make use of the mask if needed. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250823134431.4854-1-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + include/linux/phy.h | 23 ++++++++++++++++++++--- + 1 file changed, 20 insertions(+), 3 deletions(-) + +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -1266,9 +1266,13 @@ struct phy_driver { + #define PHY_ANY_ID "MATCH ANY PHY" + #define PHY_ANY_UID 0xffffffff + +-#define PHY_ID_MATCH_EXACT(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 0) +-#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) ++#define PHY_ID_MATCH_EXTACT_MASK GENMASK(31, 0) ++#define PHY_ID_MATCH_MODEL_MASK GENMASK(31, 4) ++#define PHY_ID_MATCH_VENDOR_MASK GENMASK(31, 10) ++ ++#define PHY_ID_MATCH_EXACT(id) .phy_id = (id), .phy_id_mask = PHY_ID_MATCH_EXTACT_MASK ++#define PHY_ID_MATCH_MODEL(id) .phy_id = (id), .phy_id_mask = PHY_ID_MATCH_MODEL_MASK ++#define PHY_ID_MATCH_VENDOR(id) .phy_id = (id), .phy_id_mask = PHY_ID_MATCH_VENDOR_MASK + + /** + * phy_id_compare - compare @id1 with @id2 taking account of @mask +@@ -1285,6 +1289,19 @@ static inline bool phy_id_compare(u32 id + } + + /** ++ * phy_id_compare_vendor - compare @id with @vendor mask ++ * @id: PHY ID ++ * @vendor_mask: PHY Vendor mask ++ * ++ * Return: true if the bits from @id match @vendor using the ++ * generic PHY Vendor mask. ++ */ ++static inline bool phy_id_compare_vendor(u32 id, u32 vendor_mask) ++{ ++ return phy_id_compare(id, vendor_mask, PHY_ID_MATCH_VENDOR_MASK); ++} ++ ++/** + * phydev_id_compare - compare @id with the PHY's Clause 22 ID + * @phydev: the PHY device + * @id: the PHY ID to be matched diff --git a/lede/target/linux/generic/backport-6.12/786-02-v6.18-net-phy-as21xxx-better-handle-PHY-HW-reset-on-soft-r.patch b/lede/target/linux/generic/backport-6.12/786-02-v6.18-net-phy-as21xxx-better-handle-PHY-HW-reset-on-soft-r.patch new file mode 100644 index 0000000000..5b00da4024 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/786-02-v6.18-net-phy-as21xxx-better-handle-PHY-HW-reset-on-soft-r.patch @@ -0,0 +1,45 @@ +From b4d5cd20507b252c746fa6971d82ac96f3b3e5b7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 23 Aug 2025 15:44:29 +0200 +Subject: net: phy: as21xxx: better handle PHY HW reset on soft-reboot + +On soft-reboot, with a reset GPIO defined for an Aeonsemi PHY, the +special match_phy_device fails to correctly identify that the PHY +needs to load the firmware again. + +This is caused by the fact that PHY ID is read BEFORE the PHY reset +GPIO (if present) is asserted, so we can be in the scenario where the +phydev have the previous PHY ID (with the PHY firmware loaded) but +after reset the generic AS21xxx PHY is present in the PHY ID registers. + +To better handle this, skip reading the PHY ID register only for the PHY +that are not AS21xxx (by matching for the Aeonsemi Vendor) and always +read the PHY ID for the other case to handle both firmware already +loaded or an HW reset. + +Fixes: 830877d89edc ("net: phy: Add support for Aeonsemi AS21xxx PHYs") +Signed-off-by: Christian Marangi +Link: https://patch.msgid.link/20250823134431.4854-2-ansuelsmth@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/as21xxx.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/as21xxx.c ++++ b/drivers/net/phy/as21xxx.c +@@ -884,11 +884,12 @@ static int as21xxx_match_phy_device(stru + u32 phy_id; + int ret; + +- /* Skip PHY that are not AS21xxx or already have firmware loaded */ +- if (phydev->c45_ids.device_ids[MDIO_MMD_PCS] != PHY_ID_AS21XXX) ++ /* Skip PHY that are not AS21xxx */ ++ if (!phy_id_compare_vendor(phydev->c45_ids.device_ids[MDIO_MMD_PCS], ++ PHY_VENDOR_AEONSEMI)) + return genphy_match_phy_device(phydev, phydrv); + +- /* Read PHY ID to handle firmware just loaded */ ++ /* Read PHY ID to handle firmware loaded or HW reset */ + ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID1); + if (ret < 0) + return ret; diff --git a/lede/target/linux/generic/backport-6.12/787-v6.19-net-phy-RTL8211FVD-Restore-disabling-of-PHY-mode-EEE.patch b/lede/target/linux/generic/backport-6.12/787-v6.19-net-phy-RTL8211FVD-Restore-disabling-of-PHY-mode-EEE.patch new file mode 100644 index 0000000000..37290c4e5d --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/787-v6.19-net-phy-RTL8211FVD-Restore-disabling-of-PHY-mode-EEE.patch @@ -0,0 +1,61 @@ +From 4f0638b12451112de4138689fa679315c8d388dc Mon Sep 17 00:00:00 2001 +From: Ivan Galkin +Date: Tue, 2 Dec 2025 10:07:42 +0100 +Subject: net: phy: RTL8211FVD: Restore disabling of PHY-mode EEE + +When support for RTL8211F(D)(I)-VD-CG was introduced in commit +bb726b753f75 ("net: phy: realtek: add support for RTL8211F(D)(I)-VD-CG") +the implementation assumed that this PHY model doesn't have the +control register PHYCR2 (Page 0xa43 Address 0x19). This +assumption was based on the differences in CLKOUT configurations +between RTL8211FVD and the remaining RTL8211F PHYs. In the latter +commit 2c67301584f2 +("net: phy: realtek: Avoid PHYCR2 access if PHYCR2 not present") +this assumption was expanded to the PHY-mode EEE. + +I performed tests on RTL8211FI-VD-CG and confirmed that disabling +PHY-mode EEE works correctly and is uniform with other PHYs +supported by the driver. To validate the correctness, +I contacted Realtek support. Realtek confirmed that PHY-mode EEE on +RTL8211F(D)(I)-VD-CG is configured via Page 0xa43 Address 0x19 bit 5. + +Moreover, Realtek informed me that the most recent datasheet +for RTL8211F(D)(I)-VD-CG v1.1 is incomplete and the naming of +control registers is partly inconsistent. The errata I +received from Realtek corrects the naming as follows: + +| Register | Datasheet v1.1 | Errata | +|-------------------------|----------------|--------| +| Page 0xa44 Address 0x11 | PHYCR2 | PHYCR3 | +| Page 0xa43 Address 0x19 | N/A | PHYCR2 | + +This information confirms that the supposedly missing control register, +PHYCR2, exists in the RTL8211F(D)(I)-VD-CG under the same address and +the same name. It controls widely the same configs as other PHYs from +the RTL8211F series (e.g. PHY-mode EEE). Clock out configuration is an +exception. + +Given all this information, restore disabling of the PHY-mode EEE. + +Fixes: 2c67301584f2 ("net: phy: realtek: Avoid PHYCR2 access if PHYCR2 not present") +Signed-off-by: Ivan Galkin +Reviewed-by: Vladimir Oltean +Link: https://patch.msgid.link/20251202-phy_eee-v1-1-fe0bf6ab3df0@axis.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/realtek/realtek_main.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -691,10 +691,6 @@ static int rtl8211f_config_aldps(struct + + static int rtl8211f_config_phy_eee(struct phy_device *phydev) + { +- /* RTL8211FVD has no PHYCR2 register */ +- if (phydev->drv->phy_id == RTL_8211FVD_PHYID) +- return 0; +- + /* Disable PHY-mode EEE so LPI is passed to the MAC */ + return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2, + RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); diff --git a/lede/target/linux/generic/backport-6.12/801-01-v6.13-dt-bindings-clocks-add-binding-for-gated-fixed-clock.patch b/lede/target/linux/generic/backport-6.12/801-01-v6.13-dt-bindings-clocks-add-binding-for-gated-fixed-clock.patch new file mode 100644 index 0000000000..f5ab8a0e3b --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/801-01-v6.13-dt-bindings-clocks-add-binding-for-gated-fixed-clock.patch @@ -0,0 +1,82 @@ +From a4a7cbe36623ffaabbae413c0eacf40d033db71f Mon Sep 17 00:00:00 2001 +From: Heiko Stuebner +Date: Fri, 6 Sep 2024 10:25:07 +0200 +Subject: dt-bindings: clocks: add binding for gated-fixed-clocks + +In contrast to fixed clocks that are described as ungateable, boards +sometimes use additional oscillators for things like PCIe reference +clocks, that need actual supplies to get enabled and enable-gpios to be +toggled for them to work. + +This adds a binding for such oscillators that are not configurable +themself, but need to handle supplies for them to work. + +In schematics they often can be seen as + + ---------------- +Enable - | 100MHz,3.3V, | - VDD + | 3225 | + GND - | | - OUT + ---------------- + +or similar. The enable pin might be separate but can also just be tied +to the vdd supply, hence it is optional in the binding. + +Signed-off-by: Heiko Stuebner +Reviewed-by: Rob Herring (Arm) +Reviewed-by: Conor Dooley +Link: https://lore.kernel.org/r/20240906082511.2963890-2-heiko@sntech.de +Signed-off-by: Stephen Boyd + +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/gated-fixed-clock.yaml +@@ -0,0 +1,49 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/clock/gated-fixed-clock.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Gated Fixed clock ++ ++maintainers: ++ - Heiko Stuebner ++ ++properties: ++ compatible: ++ const: gated-fixed-clock ++ ++ "#clock-cells": ++ const: 0 ++ ++ clock-frequency: true ++ ++ clock-output-names: ++ maxItems: 1 ++ ++ enable-gpios: ++ description: ++ Contains a single GPIO specifier for the GPIO that enables and disables ++ the oscillator. ++ maxItems: 1 ++ ++ vdd-supply: ++ description: handle of the regulator that provides the supply voltage ++ ++required: ++ - compatible ++ - "#clock-cells" ++ - clock-frequency ++ - vdd-supply ++ ++additionalProperties: false ++ ++examples: ++ - | ++ clock-1000000000 { ++ compatible = "gated-fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <1000000000>; ++ vdd-supply = <®_vdd>; ++ }; ++... diff --git a/lede/target/linux/generic/backport-6.12/880-v6.14-gpio-regmap-Use-generic-request-free-ops.patch b/lede/target/linux/generic/backport-6.12/810-v6.14-gpio-regmap-Use-generic-request-free-ops.patch similarity index 95% rename from lede/target/linux/generic/backport-6.12/880-v6.14-gpio-regmap-Use-generic-request-free-ops.patch rename to lede/target/linux/generic/backport-6.12/810-v6.14-gpio-regmap-Use-generic-request-free-ops.patch index f9299f9733..d696acfea4 100644 --- a/lede/target/linux/generic/backport-6.12/880-v6.14-gpio-regmap-Use-generic-request-free-ops.patch +++ b/lede/target/linux/generic/backport-6.12/810-v6.14-gpio-regmap-Use-generic-request-free-ops.patch @@ -19,7 +19,7 @@ Signed-off-by: Bartosz Golaszewski --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c -@@ -262,6 +262,8 @@ struct gpio_regmap *gpio_regmap_register +@@ -276,6 +276,8 @@ struct gpio_regmap *gpio_regmap_register chip->label = config->label ?: dev_name(config->parent); chip->can_sleep = regmap_might_sleep(config->regmap); diff --git a/lede/target/linux/generic/backport-6.12/820-v6.15-power-supply-sysfs-remove-duplicate-nul-termination-to-fix-build-with-GCC15.patch b/lede/target/linux/generic/backport-6.12/820-v6.15-power-supply-sysfs-remove-duplicate-nul-termination-to-fix-build-with-GCC15.patch new file mode 100644 index 0000000000..48f9c1c264 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/820-v6.15-power-supply-sysfs-remove-duplicate-nul-termination-to-fix-build-with-GCC15.patch @@ -0,0 +1,39 @@ +From 77f5bb150132bbbcd6bc37ffdc80c9e140e373a4 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 16 Apr 2025 15:27:41 -0700 +Subject: [PATCH] power: supply: sysfs: Remove duplicate NUL termination + +GCC 15's new -Wunterminated-string-initialization notices that one of +the sysfs attr strings would lack the implicit trailing NUL byte during +initialization: + +drivers/power/supply/power_supply_sysfs.c:183:57: warning: initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute (32 chars into 31 available) [-Wunterminated-string-initialization] + 183 | POWER_SUPPLY_ATTR(CHARGE_CONTROL_START_THRESHOLD), + | ^ +drivers/power/supply/power_supply_sysfs.c:36:23: note: in definition of macro '_POWER_SUPPLY_ATTR' + 36 | .attr_name = #_name "\0", \ + | ^~~~~ +drivers/power/supply/power_supply_sysfs.c:183:9: note: in expansion of macro 'POWER_SUPPLY_ATTR' + 183 | POWER_SUPPLY_ATTR(CHARGE_CONTROL_START_THRESHOLD), + | ^~~~~~~~~~~~~~~~~ + +However, the macro used was explicitly adding a trailing NUL byte (which +is not needed). Remove this to avoid the GCC warning. No binary +differences are seen after this change (there was always run for a NUL +byte, it's just that the _second_ NUL byte was getting truncated). + +Signed-off-by: Kees Cook +Link: https://lore.kernel.org/r/20250416222740.work.569-kees@kernel.org +Signed-off-by: Sebastian Reichel + +--- a/drivers/power/supply/power_supply_sysfs.c ++++ b/drivers/power/supply/power_supply_sysfs.c +@@ -33,7 +33,7 @@ struct power_supply_attr { + [POWER_SUPPLY_PROP_ ## _name] = \ + { \ + .prop_name = #_name, \ +- .attr_name = #_name "\0", \ ++ .attr_name = #_name, \ + .text_values = _text, \ + .text_values_len = _len, \ + } diff --git a/lede/target/linux/generic/pending-6.12/891-dt-bindings-leds-Add-LED1202-LED-Controller.patch b/lede/target/linux/generic/backport-6.12/891-v6.14-dt-bindings-leds-Add-LED1202-LED-Controller.patch similarity index 76% rename from lede/target/linux/generic/pending-6.12/891-dt-bindings-leds-Add-LED1202-LED-Controller.patch rename to lede/target/linux/generic/backport-6.12/891-v6.14-dt-bindings-leds-Add-LED1202-LED-Controller.patch index 164256081a..9901d13241 100644 --- a/lede/target/linux/generic/pending-6.12/891-dt-bindings-leds-Add-LED1202-LED-Controller.patch +++ b/lede/target/linux/generic/backport-6.12/891-v6.14-dt-bindings-leds-Add-LED1202-LED-Controller.patch @@ -1,17 +1,7 @@ +From 599b92fd0efa8b7c43e7f58c9dd0f7951f7cbf09 Mon Sep 17 00:00:00 2001 From: Vicentiu Galanopulo -To: Pavel Machek , Lee Jones , - Rob Herring , - Krzysztof Kozlowski , - Conor Dooley , - Jonathan Corbet , - Vicentiu Galanopulo , - linux-leds@vger.kernel.org, devicetree@vger.kernel.org, - linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org -Cc: Krzysztof Kozlowski -Subject: [PATCH v11 2/3] dt-bindings: leds: Add LED1202 LED Controller -Date: Wed, 18 Dec 2024 18:33:58 +0000 [thread overview] -Message-ID: <20241218183401.41687-3-vicentiu.galanopulo@remote-tech.co.uk> (raw) -In-Reply-To: <20241218183401.41687-1-vicentiu.galanopulo@remote-tech.co.uk> +Date: Wed, 18 Dec 2024 18:33:58 +0000 +Subject: dt-bindings: leds: Add LED1202 LED Controller The LED1202 is a 12-channel low quiescent current LED driver with: * Supply range from 2.6 V to 5 V @@ -26,20 +16,9 @@ set to active. Signed-off-by: Vicentiu Galanopulo Reviewed-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20241218183401.41687-3-vicentiu.galanopulo@remote-tech.co.uk +Signed-off-by: Lee Jones --- - v1: https://lore.kernel.org/lkml/ZnCnnQfwuRueCIQ0@admins-Air/T/ - v2: https://lore.kernel.org/all/ZniNdGgKyUMV-hjq@admins-Air/T/ - v3: https://lore.kernel.org/all/ZniNdGgKyUMV-hjq@admins-Air/T/ - - Changes in v4: - - remove label property, use devm_led_classdev_register_ext instead - Changes in v3: - - remove active property - Changes in v2: - - renamed label to remove color from it - - add color property for each node - - add function and function-enumerator property for each node - .../devicetree/bindings/leds/st,led1202.yaml | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/st,led1202.yaml diff --git a/lede/target/linux/generic/pending-6.12/892-leds-Add-LED1202-I2C-driver.patch b/lede/target/linux/generic/backport-6.12/892-v6.14-leds-Add-LED1202-I2C-driver.patch similarity index 86% rename from lede/target/linux/generic/pending-6.12/892-leds-Add-LED1202-I2C-driver.patch rename to lede/target/linux/generic/backport-6.12/892-v6.14-leds-Add-LED1202-I2C-driver.patch index 089f0921ff..ee2ea076fa 100644 --- a/lede/target/linux/generic/pending-6.12/892-leds-Add-LED1202-I2C-driver.patch +++ b/lede/target/linux/generic/backport-6.12/892-v6.14-leds-Add-LED1202-I2C-driver.patch @@ -1,16 +1,7 @@ +From 939757aafeb9c266dda37657ee5f7a73ffd35ae2 Mon Sep 17 00:00:00 2001 From: Vicentiu Galanopulo -To: Pavel Machek , Lee Jones , - Rob Herring , - Krzysztof Kozlowski , - Conor Dooley , - Jonathan Corbet , - Vicentiu Galanopulo , - linux-leds@vger.kernel.org, devicetree@vger.kernel.org, - linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org -Subject: [PATCH v11 3/3] leds: Add LED1202 I2C driver -Date: Wed, 18 Dec 2024 18:33:59 +0000 [thread overview] -Message-ID: <20241218183401.41687-4-vicentiu.galanopulo@remote-tech.co.uk> (raw) -In-Reply-To: <20241218183401.41687-1-vicentiu.galanopulo@remote-tech.co.uk> +Date: Wed, 18 Dec 2024 18:33:59 +0000 +Subject: leds: Add LED1202 I2C driver The output current can be adjusted separately for each channel by 8-bit analog (current sink input) and 12-bit digital (PWM) dimming control. The @@ -25,38 +16,9 @@ corresponds to the per channel analog dimming, while the patterns[1-8] to the PWM dimming control. Signed-off-by: Vicentiu Galanopulo +Link: https://lore.kernel.org/r/20241218183401.41687-4-vicentiu.galanopulo@remote-tech.co.uk +Signed-off-by: Lee Jones --- - Changes in v10: - - update description help in Kconfig - - move st1202_led and st1202_chip into one line, declaration and definition - Changes in v9: - - log errors directly in st1202_write_reg and st1202_read_reg - - use mutex guards instead of lock/unlock - - remove i2c_set_clientdata - Changes in v7: - - fix st1202_brightness_get() error: uninitialized symbol 'value' - Changes in v6: - - fix build error - Changes in v5: - - remove unused macros - - switch to using devm_led_classdev_register_ext (struct st1202_led update) - - add prescalar_to_milliseconds (convert [22..5660]ms to [0..255] reg value) - - remove register range check in dt_init (range protected by yaml) - - address all review comments in v4 - Changes in v4: - - Remove attributes/extended attributes implementation - - Use /sys/class/leds//hw_pattern (Pavel suggestion) - - Implement review findings of Christophe JAILLET - Changes in v3: - - Rename all ll1202 to st1202, including driver file name - - Convert all magic numbers to defines - - Refactor the show/store callbacks as per Lee's and Thomas's review - - Remove ll1202_get_channel and use dev_ext_attributes instead - - Log all error values for all the functions - - Use sysfs_emit for show callbacks - Changes in v2: - - Fix build error for device_attribute modes - drivers/leds/Kconfig | 10 + drivers/leds/Makefile | 1 + drivers/leds/leds-st1202.c | 416 +++++++++++++++++++++++++++++++++++++ @@ -84,14 +46,14 @@ Signed-off-by: Vicentiu Galanopulo depends on LEDS_CLASS --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile -@@ -82,6 +82,7 @@ obj-$(CONFIG_LEDS_PWM) += leds-pwm.o +@@ -81,6 +81,7 @@ obj-$(CONFIG_LEDS_POWERNV) += leds-powe + obj-$(CONFIG_LEDS_PWM) += leds-pwm.o obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o - obj-$(CONFIG_LEDS_SUN50I_A100) += leds-sun50i-a100.o +obj-$(CONFIG_LEDS_ST1202) += leds-st1202.o + obj-$(CONFIG_LEDS_SUN50I_A100) += leds-sun50i-a100.o obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o - obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o --- /dev/null +++ b/drivers/leds/leds-st1202.c @@ -0,0 +1,416 @@ diff --git a/lede/target/linux/generic/pending-6.12/893-leds_st1202-Fix-NULL-pointer-access-error.patch b/lede/target/linux/generic/backport-6.12/893-v6.14-leds_st1202-Fix-NULL-pointer-access-error.patch similarity index 77% rename from lede/target/linux/generic/pending-6.12/893-leds_st1202-Fix-NULL-pointer-access-error.patch rename to lede/target/linux/generic/backport-6.12/893-v6.14-leds_st1202-Fix-NULL-pointer-access-error.patch index d763c5dfbd..39d8ddbf74 100644 --- a/lede/target/linux/generic/pending-6.12/893-leds_st1202-Fix-NULL-pointer-access-error.patch +++ b/lede/target/linux/generic/backport-6.12/893-v6.14-leds_st1202-Fix-NULL-pointer-access-error.patch @@ -1,18 +1,21 @@ -From e3da313ebcace17f1227566fe1b0d0c3883061f9 Mon Sep 17 00:00:00 2001 +From c72e455b89f216b43cd0dbb518036ec4c98f5c46 Mon Sep 17 00:00:00 2001 From: Manuel Fombuena -Date: Fri, 17 Jan 2025 12:31:49 +0000 -Subject: [PATCH 1/5] leds: leds-st1202: fix NULL pointer access on race - condition +Date: Tue, 25 Feb 2025 22:01:02 +0000 +Subject: leds: leds-st1202: Fix NULL pointer access on race condition st1202_dt_init() calls devm_led_classdev_register_ext() before the -internal data structures are properly setup, so the leds become visible +internal data structures are properly set up, so the LEDs become visible to user space while being partially initialized, leading to a window where trying to access them causes a NULL pointer access. -This change moves devm_led_classdev_register_ext() to the last thing to -happen during initialization to eliminate it. +Move devm_led_classdev_register_ext() from DT initialization +to the end of the probe function when DT and hardware are fully +initialized and ready to interact with user space. +Fixes: 259230378c65 ("leds: Add LED1202 I2C driver") Signed-off-by: Manuel Fombuena +Link: https://lore.kernel.org/r/CWLP123MB54732771AC0CE5491B3C84DCC5C32@CWLP123MB5473.GBRP123.PROD.OUTLOOK.COM +Signed-off-by: Lee Jones --- drivers/leds/leds-st1202.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/lede/target/linux/generic/backport-6.12/900-v6.14-driver-core-add-a-faux-bus-for-use-when-a-simple-dev.patch b/lede/target/linux/generic/backport-6.12/900-v6.14-driver-core-add-a-faux-bus-for-use-when-a-simple-dev.patch index 324d22d6a4..1ada8a6ef4 100644 --- a/lede/target/linux/generic/backport-6.12/900-v6.14-driver-core-add-a-faux-bus-for-use-when-a-simple-dev.patch +++ b/lede/target/linux/generic/backport-6.12/900-v6.14-driver-core-add-a-faux-bus-for-use-when-a-simple-dev.patch @@ -16,7 +16,7 @@ can be used instead. Reviewed-by: Jonathan Cameron Reviewed-by: Danilo Krummrich Reviewed-by: Lyude Paul -Reviewed-by: Thomas Wei?schuh +Reviewed-by: Thomas Weißschuh Reviewed-by: Zijun Hu Link: https://lore.kernel.org/r/2025021026-atlantic-gibberish-3f0c@gregkh Signed-off-by: Greg Kroah-Hartman diff --git a/lede/target/linux/generic/files/drivers/bcma/fallback-sprom.c b/lede/target/linux/generic/files/drivers/bcma/fallback-sprom.c index db583fca9c..4c361cc000 100644 --- a/lede/target/linux/generic/files/drivers/bcma/fallback-sprom.c +++ b/lede/target/linux/generic/files/drivers/bcma/fallback-sprom.c @@ -16,6 +16,7 @@ #include #include #include +#include "fallback-sprom.h" #define BCMA_FBS_MAX_SIZE 468 @@ -478,6 +479,7 @@ static int bcma_fbs_probe(struct platform_device *pdev) struct bcma_fbs *priv; unsigned long flags; u8 mac[ETH_ALEN]; + int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -490,7 +492,10 @@ static int bcma_fbs_probe(struct platform_device *pdev) of_property_read_u32(node, "pci-bus", &priv->pci_bus); of_property_read_u32(node, "pci-dev", &priv->pci_dev); - of_get_mac_address(node, mac); + ret = of_get_mac_address(node, mac); + if (ret == -EPROBE_DEFER) + return ret; + if (is_valid_ether_addr(mac)) { dev_info(dev, "mtd mac %pM\n", mac); } else { diff --git a/lede/target/linux/generic/files/drivers/bcma/fallback-sprom.h b/lede/target/linux/generic/files/drivers/bcma/fallback-sprom.h new file mode 100644 index 0000000000..363663413d --- /dev/null +++ b/lede/target/linux/generic/files/drivers/bcma/fallback-sprom.h @@ -0,0 +1,7 @@ +#ifndef _FALLBACK_SPROM_H +#define _FALLBACK_SPROM_H + +int __init bcma_fbs_register(void); +int bcma_get_fallback_sprom(struct bcma_bus *dev, struct ssb_sprom *out); + +#endif /* _FALLBACK_SPROM_H */ diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/Kconfig b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/Kconfig new file mode 100644 index 0000000000..cdb5cb7488 --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/Kconfig @@ -0,0 +1,5 @@ + +config RTL8261N_PHY + tristate "Driver for Realtek RTL8261N PHYs" + help + Currently supports the RTL8261N,RTL8264B PHYs. diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/Makefile b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/Makefile new file mode 100644 index 0000000000..fd4afb43b5 --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/Makefile @@ -0,0 +1,11 @@ + +obj-$(CONFIG_RTL8261N_PHY) += rtl8261n.o + +rtl8261n-objs += phy_patch.o +rtl8261n-objs += phy_rtl826xb_patch.o +rtl8261n-objs += rtk_osal.o +rtl8261n-objs += rtk_phy.o +rtl8261n-objs += rtk_phylib.o +rtl8261n-objs += rtk_phylib_rtl826xb.o + +ccflags-y += -Werror -DRTK_PHYDRV_IN_LINUX diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/construct/conf_rtl8261n_c.c b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/construct/conf_rtl8261n_c.c new file mode 100644 index 0000000000..8e7c714fc4 --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/construct/conf_rtl8261n_c.c @@ -0,0 +1,1465 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +//Date: Tue Nov 15 19:53:03 2022 + +rtk_hwpatch_t rtl8261n_c_top_conf[] = { + {RTK_PATCH_OP_TOP , 0xf , 2 , 20 , 15, 0 , 0x5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 2 , 21 , 15, 0 , 0x0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 2 , 22 , 15, 0 , 0x280 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 2 , 23 , 15, 0 , 0x0014, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 16 , 15, 0 , 0x0300, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 17 , 15, 0 , 0x01ff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 18 , 15, 0 , 0x000c, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 19 , 15, 0 , 0x01ff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 20 , 15, 0 , 0x0200, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 21 , 15, 0 , 0x0015, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 22 , 15, 0 , 0x0200, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 23 , 15, 0 , 0x0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 4 , 16 , 15, 0 , 0x0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 13 , 23 , 8 , 5 , 0x6 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 90 , 18 , 15, 0 , 0x5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 90 , 19 , 15, 0 , 0x5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 90 , 20 , 15, 8 , 0x01 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8261n_c_sds_conf[] = { + {RTK_PATCH_OP_TOP , 0xf , 24 , 18 , 15, 0 , 0x881F, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 19 , 15, 0 , 0x003F, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 20 , 15, 0 , 0x003F, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 21 , 15, 0 , 0x003F, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 22 , 15, 0 , 0x001F, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x06 , 0x0D , 15, 0 , 0x0F00, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x06 , 0x0E , 15, 0 , 0x3F5A, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x07 , 0x10 , 15, 12, 0x8 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x07 , 0x10 , 7 , 0 , 0x3 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x06 , 0x1D , 15, 0 , 0x0600, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x21 , 0x00 , 15, 0 , 0x4902, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x21 , 0x08 , 15, 0 , 0x0FC0, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x21 , 0x09 , 15, 0 , 0x33F0, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x21 , 0x0C , 15, 0 , 0x08BF, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x21 , 0x12 , 15, 0 , 0x8000, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x36 , 0x07 , 15, 0 , 0x04C0, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x36 , 0x08 , 15, 0 , 0x2000, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2E , 0x0B , 15, 0 , 0x2390, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2E , 0x0C , 15, 0 , 0xAA17, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2E , 0x0D , 15, 0 , 0xFE40, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2E , 0x0E , 15, 0 , 0x12F4, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2E , 0x11 , 15, 0 , 0xF2AD, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2E , 0x15 , 15, 0 , 0x7A41, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2E , 0x16 , 15, 0 , 0x0041, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2F , 0x00 , 15, 0 , 0x1F00, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2F , 0x01 , 15, 0 , 0x2800, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2F , 0x02 , 15, 0 , 0x0FC8, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2F , 0x11 , 15, 0 , 0x3000, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2F , 0x13 , 15, 0 , 0xF400, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2F , 0x1E , 15, 0 , 0x0500, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x34 , 0x0B , 15, 0 , 0x2390, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x34 , 0x0C , 15, 0 , 0xA517, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x34 , 0x0D , 15, 0 , 0xFE41, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x34 , 0x0E , 15, 0 , 0x12F4, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x34 , 0x11 , 15, 0 , 0xF2AD, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x34 , 0x15 , 15, 0 , 0x7A41, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x34 , 0x16 , 15, 0 , 0x0041, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x35 , 0x00 , 15, 0 , 0x1F80, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x35 , 0x01 , 15, 0 , 0x0800, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x35 , 0x02 , 15, 0 , 0x0FC8, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x35 , 0x11 , 15, 0 , 0x3001, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x35 , 0x13 , 15, 0 , 0xF400, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x35 , 0x1E , 15, 0 , 0x0100, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2C , 0x0B , 15, 0 , 0x2390, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2C , 0x0C , 15, 0 , 0xA517, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2C , 0x0D , 15, 0 , 0xFE41, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2C , 0x0E , 15, 0 , 0x12F4, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2C , 0x11 , 15, 0 , 0xF2AD, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2C , 0x15 , 15, 0 , 0x7A61, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2C , 0x16 , 15, 0 , 0x0041, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2D , 0x00 , 15, 0 , 0x1F80, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2D , 0x01 , 15, 0 , 0x0800, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2D , 0x02 , 15, 0 , 0x0FC8, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2D , 0x11 , 15, 0 , 0x3001, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2D , 0x13 , 15, 0 , 0xF400, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2D , 0x1E , 15, 0 , 0x0100, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x28 , 0x0B , 15, 0 , 0x2390, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x28 , 0x0C , 15, 0 , 0xA514, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x28 , 0x0D , 15, 0 , 0xFE43, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x28 , 0x0E , 15, 0 , 0x12F4, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x28 , 0x11 , 15, 0 , 0xF2AD, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x28 , 0x15 , 15, 0 , 0x7A61, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x28 , 0x16 , 15, 0 , 0x0041, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x29 , 0x00 , 15, 0 , 0x1F80, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x29 , 0x01 , 15, 0 , 0x0800, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x29 , 0x02 , 15, 0 , 0x0FC8, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x29 , 0x11 , 15, 0 , 0x3001, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x29 , 0x13 , 15, 0 , 0xF400, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x29 , 0x1E , 15, 0 , 0x0100, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x26 , 0x0B , 15, 0 , 0x2390, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x26 , 0x0C , 15, 0 , 0xA514, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x26 , 0x0D , 15, 0 , 0xFE43, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x26 , 0x0E , 15, 0 , 0x12F4, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x26 , 0x11 , 15, 0 , 0xF2AD, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x26 , 0x15 , 15, 0 , 0x7A41, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x26 , 0x16 , 15, 0 , 0x0041, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x27 , 0x00 , 15, 0 , 0x1F80, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x27 , 0x01 , 15, 0 , 0x0800, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x27 , 0x02 , 15, 0 , 0x0FC8, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x27 , 0x11 , 15, 0 , 0x3001, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x27 , 0x13 , 15, 0 , 0xF400, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x27 , 0x1E , 15, 0 , 0x0100, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x24 , 0x0B , 15, 0 , 0x2390, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x24 , 0x0C , 15, 0 , 0xA514, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x24 , 0x0D , 15, 0 , 0xFE43, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x24 , 0x0E , 15, 0 , 0x12F4, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x24 , 0x11 , 15, 0 , 0xF2AD, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x24 , 0x15 , 15, 0 , 0x7A41, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x24 , 0x16 , 15, 0 , 0x0041, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x25 , 0x00 , 15, 0 , 0x1F80, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x25 , 0x01 , 15, 0 , 0x0800, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x25 , 0x02 , 15, 0 , 0x0FC8, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x25 , 0x11 , 15, 0 , 0x3001, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x25 , 0x13 , 15, 0 , 0xF400, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x25 , 0x1E , 15, 0 , 0x0100, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 18 , 15, 0 , 0x880D, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 19 , 15, 0 , 0x0024, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 20 , 15, 0 , 0x0036, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 21 , 15, 0 , 0x0035, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 22 , 15, 0 , 0x001A, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x1F , 0x00 , 15, 0 , 0x001B, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x1F , 0x00 , 15, 0 , 0x0000, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 90 , 20 , 7 , 0 , 0x01 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8261n_c_afe_conf[] = { +}; + +rtk_hwpatch_t rtl8261n_c_uc_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x0 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbd8a, 5 , 3 , 0x3 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbd8c, 6 , 4 , 0x5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x8060, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 12, 10, 0x3 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x8061, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 13, 0x5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa466, 1 , 1 , 0x1 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x8491, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x3D , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8261n_c_uc2_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x1 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb87c, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8af6, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb87e, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf8b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8af6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0eaf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8af8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8b41, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8afa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf8b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8afc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4faf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8afe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8b5b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b00}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf8b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b02}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xb4af, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b04}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8bc0, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b06}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf8b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b08}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdaaf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b0a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8bda, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b0c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf8ef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b0e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x49f8, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b10}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf70, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b12}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3f02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b14}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6772, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b16}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xad28, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b18}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13e1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b1a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8a55, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b1c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xad28, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b1e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0502, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b20}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5ee2, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b22}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xae0e, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b24}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x025d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b26}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8f02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b28}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8bda, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b2a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xae06, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b2c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x025d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b2e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7002, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b30}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c22, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b32}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe087, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b34}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1ef6, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b36}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x27e4, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b38}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x871e, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b3a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfcef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b3c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x94fc, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b3e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x04a1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b40}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0103, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b42}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x028b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b44}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfee0, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b46}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8a09, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b48}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef23, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b4a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf5e, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b4c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5bac, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b4e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5003, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b50}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf62, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b52}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8a02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b54}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c22, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b56}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf62, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b58}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xb0bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b5a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x68e0, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b5c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0267, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b5e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x72ef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b60}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x31bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b62}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x68dd, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b64}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0267, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b66}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x721e, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b68}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x31ac, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b6a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3819, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b6c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf68, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b6e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe902, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b70}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6772, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b72}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef31, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b74}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf68, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b76}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe602, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b78}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6772, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b7a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1e31, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b7c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xac38, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b7e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cee, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b80}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8933, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b82}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x02ae, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b84}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0aee, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b86}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8933, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b88}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x00ae, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b8a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x04ee, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b8c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8933, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b8e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x01bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b90}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8ff9, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b92}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe189, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b94}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x331a, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b96}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x91db, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b98}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf69, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b9a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4c02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b9c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6772, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b9e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1f00, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ba0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1f22, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ba2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1b45, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ba4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xad27, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ba6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x05e1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ba8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x870d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8baa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xae03, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bac}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe187, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bae}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0eaf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bb0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2d1a, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bb2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0248, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bb4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf702, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bb6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c46, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bb8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0222, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bba}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4faf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bbc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4176, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bbe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf8c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bc0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9002, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bc2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70eb, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bc4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf8c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bc6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9f02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bc8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70eb, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bca}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf8c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bcc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa502, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bce}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70eb, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bd0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd300, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bd2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0241, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bd4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7caf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bd6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x46b2, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bd8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf8ef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bda}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x49f8, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bdc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bde}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3a02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8be0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6772, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8be2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xac28, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8be4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x12bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8be6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6d63, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8be8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0267, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bea}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x72e5, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bec}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8ffc, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bee}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bf0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6f02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bf2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6772, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bf4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe58f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bf6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfdfc, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bf8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef94, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bfa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfc04, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bfc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf8ef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bfe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x49f8, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c00}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c02}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3a02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c04}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6772, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c06}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xac28, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c08}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x12e1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c0a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8ffe, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c0c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c0e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6302, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c10}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6753, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c12}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe18f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c14}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffbf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c16}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6d6f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c18}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0267, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c1a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x53fc, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c1c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef94, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c1e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfc04, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c20}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf8ef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c22}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x49f8, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c24}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c26}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3a02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c28}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6772, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c2a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xac28, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c2c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x12e1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c2e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8ffc, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c30}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c32}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6302, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c34}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6753, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c36}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe18f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c38}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfdbf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c3a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6d6f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c3c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0267, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c3e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x53fc, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c40}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef94, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c42}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfc04, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c44}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf8fa, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c46}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef69, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c48}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c4a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3a02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c4c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6772, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c4e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xad28, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c50}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0ebf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c52}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c93, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c54}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c56}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf4bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c58}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c90, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c5a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c5c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf4ae, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c5e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2ad1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c60}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0fbf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c62}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c96, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c64}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0267, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c66}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x53bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c68}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c99, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c6a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c6c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xebd1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c6e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x00bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c70}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c9c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c72}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0267, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c74}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x53bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c76}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c9f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c78}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c7a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf4d1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c7c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x00bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c7e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8ca2, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c80}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0267, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c82}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x53bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c84}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8ca5, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c86}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c88}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf4ef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c8a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x96fe, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c8c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfc04, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c8e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x77bd, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c90}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6c66, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c92}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbd6c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c94}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x30bd, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c96}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5444, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c98}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbd54, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c9a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x85bd, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c9c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5e55, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c9e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbd54, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ca0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa7bd, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ca2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5cbb, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ca4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbd5c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ca6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb85e, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x62ba, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb860, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5e56, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb862, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6287, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb864, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2d07, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb886, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4170, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb888, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x46ad, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb88a, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb88c, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb838, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x003f, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x0 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8261n_c_nctl0_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x1 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA016, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA012, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA014, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8010, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x801a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x801a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x801a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x801a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x801a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x801a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x801a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd719, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3bb7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8014, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd704, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x406e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x12db, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1301, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA026, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA024, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA022, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA020, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA006, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA004, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA002, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA000, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x12d7, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA008, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0100, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x0 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8261n_c_nctl1_conf[] = { +}; + +rtk_hwpatch_t rtl8261n_c_nctl2_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x1 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA016, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0020, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA012, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA014, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8010, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8029, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8217, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x82d0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x82f9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8322, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8322, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8322, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcb0a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cc7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4127, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c0f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b05, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c38, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0d28, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c0f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b0a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c38, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0d18, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0f73, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8034, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8031, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1bf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd06d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1dd, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd06d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x32}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x33}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x34}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd06e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x35}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x36}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x37}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x38}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5fba, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x39}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd05a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60f1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6113, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6135, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x40}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6157, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x41}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x42}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x43}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x44}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x45}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x46}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x47}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x48}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x49}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf004, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf002, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x142d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x50}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x51}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0ccf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x52}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b40, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x53}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x54}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c24, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x55}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x56}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa340, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x57}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x58}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x147c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x59}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa110, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1435, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8110, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1485, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa304, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x60}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa8c0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x61}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8810, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x62}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x63}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x64}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa310, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x65}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cfc, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x66}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0224, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x67}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0ca0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x68}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0480, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x69}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa340, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd162, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x70}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x71}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x72}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5fba, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x73}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8840, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x74}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1c4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x75}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd045, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x76}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x77}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x78}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x79}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5fba, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6127, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f3b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x88c0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x800a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x80}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x81}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8350, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x82}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x84a0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x83}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffb6, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x84}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xb920, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x85}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd33, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x86}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x87}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x88}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x89}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7fb4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9920, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6065, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f94, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x90}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffee, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x91}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xb820, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x92}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x93}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x94}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x95}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7fa5, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x96}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9820, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x97}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x800a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x98}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x99}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x147c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa108, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1435, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8108, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1485, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa2fc, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa304, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8880, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cc0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0440, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd34, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cc0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xaa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b80, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xab}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xac3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xac}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c38, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xad}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0d08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xae}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xaf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa810, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa480, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa604, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x80bb, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xba}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd19f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xbb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xbc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xbd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xbe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xbf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x63f4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4368, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cc0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b40, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d38, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xca}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xcb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xcc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xcd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x80d7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xce}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xcf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x80d4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1f4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1b7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1c6, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xda}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xdb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6074, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xdc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xdd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xde}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xdf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4056, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf004, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x61fc, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfff9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xea}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4070, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xeb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xec}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x81a4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xed}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xee}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xef}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xae80, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x81a4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd05a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60f1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6113, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6135, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xfa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6157, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xfb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xfc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xfd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xfe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xff}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x100}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x101}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x102}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x103}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf004, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x104}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x105}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf002, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x106}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x107}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x108}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x142d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x109}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0ccf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b40, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c24, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x110}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa340, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x111}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x112}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x147c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x113}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa110, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x114}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x115}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1435, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x116}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8110, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x117}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x118}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1485, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x119}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa304, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa8c0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8810, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa310, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cfc, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x120}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0224, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x121}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0ca0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x122}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0480, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x123}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8604, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x124}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd35, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x125}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd162, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x126}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x127}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x128}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x129}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5fba, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8840, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1c4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd045, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x130}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x131}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5fba, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x132}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x133}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6127, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x134}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x135}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f3b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x136}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x88c0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x137}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x800a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x138}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x139}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8350, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x84a0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffb8, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbb80, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x140}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5fb4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x141}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xb920, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x142}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd36, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x143}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x144}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x145}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x146}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7fb4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x147}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9920, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x148}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9b80, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x149}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6065, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f94, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffe8, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xb820, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x150}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x151}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x152}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x153}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7fa5, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x154}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9820, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x155}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x800a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x156}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x157}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x158}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x147c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x159}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa108, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1435, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8108, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1485, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa2fc, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x160}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa304, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x161}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8880, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x162}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cc0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x163}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0440, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x164}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd37, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x165}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x166}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x167}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cc0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x168}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b80, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x169}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xac3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c38, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0d08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa810, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x170}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa480, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x171}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa604, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x172}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x173}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x174}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x817e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x175}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x176}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x817b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x177}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x178}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x179}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x180}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x181}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x182}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1463, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x183}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x184}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x185}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x186}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f28, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x187}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x188}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x189}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cc0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b40, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d38, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x190}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x819a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x191}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x192}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8197, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x193}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x194}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x195}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x196}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x197}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x198}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x199}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd189, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1463, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f28, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c0f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b05, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1aa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60f1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ab}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6113, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ac}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6135, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ad}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6157, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ae}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1af}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf004, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf002, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ba}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1bb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x142d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1bc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa180, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1bd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd38, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1be}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1bf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x81d4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x81cc, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf013, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd100, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ca}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf010, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1cb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1cc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1cd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1b7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ce}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1cf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd100, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1da}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd13b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1db}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd055, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1dc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1dd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1de}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1df}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1463, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa302, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1463, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ea}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f28, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1eb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ec}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ed}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ee}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c12, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ef}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8206, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x81fe, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf013, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1fa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd100, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1fb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1fc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf010, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1fd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1fe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ff}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x200}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x201}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x202}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd100, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x203}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd040, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x204}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x205}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x206}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x207}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x208}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x209}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd16b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1463, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x210}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x211}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x212}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x213}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f2a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x214}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x215}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x087a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x216}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x217}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x646d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x218}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x219}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8231, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8227, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x220}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd100, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x221}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x222}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf01a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x223}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x224}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x225}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf017, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x226}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x227}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x228}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x229}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd100, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf010, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x230}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x231}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x232}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x233}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x234}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x235}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x236}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x237}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x238}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x239}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1463, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x240}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x241}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x242}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x243}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f29, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x244}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x245}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x246}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60f1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x247}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6113, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x248}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6135, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x249}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6157, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x250}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x251}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x252}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf004, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x253}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x254}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf002, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x255}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x256}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x257}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x142d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x258}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x259}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8bc0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c09, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa310, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x260}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa420, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x261}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd3b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x262}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x263}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x65ad, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x264}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x43c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x265}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x266}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x267}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x827b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x268}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x269}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8273, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf024, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd15d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x270}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x271}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf021, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x272}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x273}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x274}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1c6, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x275}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x276}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf01c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x277}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd15d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x278}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x279}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf019, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf014, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x280}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x281}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf011, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x282}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x283}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x284}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x828e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x285}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x286}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x828b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x287}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1e5, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x288}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x289}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf009, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd191, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x290}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd16b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x291}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x292}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x293}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1418, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x294}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x295}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1463, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x296}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x297}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x298}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x299}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f2c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40e7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c0f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b05, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c0f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b0a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd3c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x644d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2aa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x43c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ab}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ac}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ad}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x82c1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ae}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2af}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x82b9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf019, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf016, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ba}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2bb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2bc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf011, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2bd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd13e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2be}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2bf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf009, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ca}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2cb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2cc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2cd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ce}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0956, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2cf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2969, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x82f5, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x82eb, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x82e1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2da}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd15c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2db}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2dc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf01a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2dd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2de}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2df}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf017, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd13e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf010, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ea}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2eb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ec}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ed}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ee}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ef}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x09a0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2969, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2fa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x831e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2fb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2fc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8314, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2fd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2fe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x830a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ff}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x300}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x301}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x302}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x303}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd15d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x304}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x305}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf01a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x306}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x307}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x308}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf017, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x309}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd16b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf010, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x310}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x311}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x312}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x313}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x314}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x315}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x316}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x317}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x318}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x319}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1b7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x320}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0a39, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x321}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA10E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA10C, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA10A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA108, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0a12, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA106, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0979, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA104, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x089f, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA102, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0692, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA100, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0f60, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA110, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x001f, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA016, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0020, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA012, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1ff8, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA014, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b0e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ff8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b0e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ff9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b0e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ffa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ffb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ffc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ffd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ffe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1fff}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA164, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0baa, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA166, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c19, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA168, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1293, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA16A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3fff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA16C, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3fff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA16E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3fff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA170, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3fff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA172, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3fff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA162, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0007, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x0 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8261n_c_algxg_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8165, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x22 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8167, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x33 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x827E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x68 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8013, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x39 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8ffb, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x14 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8ffa, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x1e , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8ff9, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x1e , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x82D9, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x20 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x82DA, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x00 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x816E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0xab , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8159, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x58 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x815A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x99 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8139, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x25 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8125, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x67 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8126, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x89 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x827D, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x42 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8261n_c_alg_giga_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x8367, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x5d , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8261n_c_normal_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x817d, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x07 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb516, 6 , 0 , 0x0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8ffe, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x04 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8fff, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x05 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8132, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x77 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8134, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x88 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x80ca, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x77 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x80cc, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x88 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8062, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x77 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8064, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x88 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x801E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0005, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8261n_c_dataram_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x0 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb896, 0 , 0 , 0x0 , RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb892, 15, 8 , 0x0 , RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC10B, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xD5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC10C, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xD5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC10D, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xD5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC10E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xD5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC10F, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xD5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC110, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xD5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC149, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x08 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC14A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x08 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC14B, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x08 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC14C, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x08 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC14D, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x08 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC14E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x08 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC166, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xEE , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC167, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xEE , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC168, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x07 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC169, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x09 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC16A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x0B , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC16B, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x0D , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC16C, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x13 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC16D, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x0E , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC16E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x11 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC16F, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x14 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC170, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x17 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC171, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x15 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC172, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x10 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC173, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x0B , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC128, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xF7 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC129, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xF7 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC12A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xF8 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC12B, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xF7 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC12C, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xF6 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC12D, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xF5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC12E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xF2 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC12F, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xF7 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC130, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xF5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC131, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xF2 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC132, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xF0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC133, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xF1 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC134, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xF4 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC135, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xF7 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb896, 0 , 0 , 0x1 , RTK_PATCH_CMP_W , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8261n_c_rtct_conf[] = { +}; + diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/construct/conf_rtl8264b.c b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/construct/conf_rtl8264b.c new file mode 100644 index 0000000000..d5cae3fd3b --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/construct/conf_rtl8264b.c @@ -0,0 +1,2177 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +//Date: Thu Dec 15 16:01:01 2022 + +rtk_hwpatch_t rtl8264b_top_conf[] = { + {RTK_PATCH_OP_TOP , 0xf , 2 , 20 , 15, 0 , 0x5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 2 , 21 , 15, 0 , 0x0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 2 , 22 , 15, 0 , 0x280 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 2 , 23 , 15, 0 , 0x0014, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 16 , 15, 0 , 0x0300, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 17 , 15, 0 , 0x01ff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 18 , 15, 0 , 0x000c, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 19 , 15, 0 , 0x01ff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 20 , 15, 0 , 0x0200, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 21 , 15, 0 , 0x0015, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 22 , 15, 0 , 0x0200, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 3 , 23 , 15, 0 , 0x0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 4 , 16 , 15, 0 , 0x0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 13 , 23 , 8 , 5 , 0x6 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 90 , 18 , 15, 0 , 0xc , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 90 , 19 , 15, 0 , 0xc , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 90 , 20 , 15, 8 , 0x01 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8264b_sds_conf[] = { + {RTK_PATCH_OP_TOP , 0xf , 24 , 18 , 15, 0 , 0x881F, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 19 , 15, 0 , 0x003F, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 20 , 15, 0 , 0x003F, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 21 , 15, 0 , 0x003F, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 22 , 15, 0 , 0x001F, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x06 , 0x0D , 15, 0 , 0x0F00, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x06 , 0x0E , 15, 0 , 0x3F5A, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x07 , 0x10 , 15, 12, 0x8 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x07 , 0x10 , 7 , 0 , 0x3 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x06 , 0x1D , 15, 0 , 0x0600, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x21 , 0x00 , 15, 0 , 0x4902, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x21 , 0x08 , 15, 0 , 0x0FC0, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x21 , 0x09 , 15, 0 , 0x33F0, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x21 , 0x0C , 15, 0 , 0x08BF, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x21 , 0x12 , 15, 0 , 0x8000, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x36 , 0x07 , 15, 0 , 0x04C0, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x36 , 0x08 , 15, 0 , 0x2000, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2E , 0x0B , 15, 0 , 0x2390, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2E , 0x0C , 15, 0 , 0xAA17, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2E , 0x0D , 15, 0 , 0xFE40, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2E , 0x0E , 15, 0 , 0x12F4, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2E , 0x11 , 15, 0 , 0xF2AD, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2E , 0x15 , 15, 0 , 0x7A41, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2E , 0x16 , 15, 0 , 0x0041, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2F , 0x00 , 15, 0 , 0x1F00, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2F , 0x01 , 15, 0 , 0x2800, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2F , 0x02 , 15, 0 , 0x0FC8, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2F , 0x11 , 15, 0 , 0x3000, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2F , 0x13 , 15, 0 , 0xF400, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2F , 0x1E , 15, 0 , 0x0500, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x34 , 0x0B , 15, 0 , 0x2390, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x34 , 0x0C , 15, 0 , 0xA517, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x34 , 0x0D , 15, 0 , 0xFE41, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x34 , 0x0E , 15, 0 , 0x12F4, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x34 , 0x11 , 15, 0 , 0xF2AD, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x34 , 0x15 , 15, 0 , 0x7A41, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x34 , 0x16 , 15, 0 , 0x0041, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x35 , 0x00 , 15, 0 , 0x1F80, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x35 , 0x01 , 15, 0 , 0x0800, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x35 , 0x02 , 15, 0 , 0x0FC8, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x35 , 0x11 , 15, 0 , 0x3001, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x35 , 0x13 , 15, 0 , 0xF400, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x35 , 0x1E , 15, 0 , 0x0100, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2C , 0x0B , 15, 0 , 0x2390, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2C , 0x0C , 15, 0 , 0xA517, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2C , 0x0D , 15, 0 , 0xFE41, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2C , 0x0E , 15, 0 , 0x12F4, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2C , 0x11 , 15, 0 , 0xF2AD, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2C , 0x15 , 15, 0 , 0x7A61, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2C , 0x16 , 15, 0 , 0x0041, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2D , 0x00 , 15, 0 , 0x1F80, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2D , 0x01 , 15, 0 , 0x0800, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2D , 0x02 , 15, 0 , 0x0FC8, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2D , 0x11 , 15, 0 , 0x3001, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2D , 0x13 , 15, 0 , 0xF400, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x2D , 0x1E , 15, 0 , 0x0100, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x28 , 0x0B , 15, 0 , 0x2390, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x28 , 0x0C , 15, 0 , 0xA514, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x28 , 0x0D , 15, 0 , 0xFE43, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x28 , 0x0E , 15, 0 , 0x12F4, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x28 , 0x11 , 15, 0 , 0xF2AD, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x28 , 0x15 , 15, 0 , 0x7A61, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x28 , 0x16 , 15, 0 , 0x0041, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x29 , 0x00 , 15, 0 , 0x1F80, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x29 , 0x01 , 15, 0 , 0x0800, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x29 , 0x02 , 15, 0 , 0x0FC8, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x29 , 0x11 , 15, 0 , 0x3001, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x29 , 0x13 , 15, 0 , 0xF400, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x29 , 0x1E , 15, 0 , 0x0100, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x26 , 0x0B , 15, 0 , 0x2390, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x26 , 0x0C , 15, 0 , 0xA514, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x26 , 0x0D , 15, 0 , 0xFE43, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x26 , 0x0E , 15, 0 , 0x12F4, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x26 , 0x11 , 15, 0 , 0xF2AD, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x26 , 0x15 , 15, 0 , 0x7A41, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x26 , 0x16 , 15, 0 , 0x0041, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x27 , 0x00 , 15, 0 , 0x1F80, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x27 , 0x01 , 15, 0 , 0x0800, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x27 , 0x02 , 15, 0 , 0x0FC8, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x27 , 0x11 , 15, 0 , 0x3001, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x27 , 0x13 , 15, 0 , 0xF400, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x27 , 0x1E , 15, 0 , 0x0100, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x24 , 0x0B , 15, 0 , 0x2390, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x24 , 0x0C , 15, 0 , 0xA514, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x24 , 0x0D , 15, 0 , 0xFE43, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x24 , 0x0E , 15, 0 , 0x12F4, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x24 , 0x11 , 15, 0 , 0xF2AD, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x24 , 0x15 , 15, 0 , 0x7A41, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x24 , 0x16 , 15, 0 , 0x0041, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x25 , 0x00 , 15, 0 , 0x1F80, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x25 , 0x01 , 15, 0 , 0x0800, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x25 , 0x02 , 15, 0 , 0x0FC8, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x25 , 0x11 , 15, 0 , 0x3001, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x25 , 0x13 , 15, 0 , 0xF400, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x25 , 0x1E , 15, 0 , 0x0100, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 18 , 15, 0 , 0x880D, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 19 , 15, 0 , 0x0024, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 20 , 15, 0 , 0x0036, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 21 , 15, 0 , 0x0035, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 24 , 22 , 15, 0 , 0x001A, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x1F , 0x00 , 15, 0 , 0x001B, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xf , 0x1F , 0x00 , 15, 0 , 0x0000, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 90 , 20 , 7 , 0 , 0x03 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8264b_afe_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbf92, 15, 11, 0x1C , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbfaa, 10, 8 , 0x5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbfae, 8 , 6 , 0x5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbfaa, 12, 11, 0x1 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbf1c, 4 , 4 , 0x1 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbf0e, 5 , 4 , 0x3 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbf1c, 15, 13, 0x5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbf16, 12, 12, 0x0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbc24, 3 , 2 , 0x1 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbc24, 1 , 0 , 0x1 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbf08, 2 , 0 , 0x6 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbf0c, 5 , 3 , 0x7 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbf0c, 8 , 6 , 0x7 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbf0c, 11, 9 , 0x7 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbf0c, 14, 12, 0x7 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_TOP , 0xf , 90 , 21 , 15, 8 , 0x03 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8264b_uc_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x0 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbd8a, 5 , 3 , 0x3 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbd8c, 6 , 4 , 0x5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x8060, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 12, 10, 0x3 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x8061, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 13, 0x5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa466, 1 , 1 , 0x1 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x8491, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x1D , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x8018, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 12, 12, 0x1 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x85af, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf85, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85af}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xc7af, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85b1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x85df, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85b3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf86, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85b5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1baf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85b7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8674, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85b9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf86, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85bb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7daf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85bd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x875b, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85bf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf87, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85c1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x67af, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85c3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8774, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85c5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf85, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85c7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdc02, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85c9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6957, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85cb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe48f, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85cd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2ce5, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85cf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8f2d, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85d1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe084, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85d3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x11e1, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85d5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8412, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85d7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf5d, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85d9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x73f6, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85db}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xb01a, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85dd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe08f, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85df}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2ce1, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85e1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8f2d, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85e3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85e5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6802, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85e7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6938, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85e9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85eb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6b02, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85ed}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6938, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85ef}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85f1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6e02, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85f3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6938, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85f5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85f7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7102, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85f9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6938, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85fb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85fd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7402, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x85ff}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70e5, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8601}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8603}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7702, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8605}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70e5, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8607}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8609}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7a02, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x860b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70e5, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x860d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x860f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7d02, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8611}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70e5, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8613}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd784, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8615}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa2af, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8617}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5eed, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8619}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0286, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x861b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x21af, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x861d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x07ad, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x861f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf8f9, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8621}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfaef, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8623}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x69e0, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8625}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8018, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8627}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xad24, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8629}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x39d4, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x862b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x002e, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x862d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6e, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x862f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0402, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8631}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6938, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8633}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd480, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8635}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x03bf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8637}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x866e, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8639}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0269, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x863b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x38d4, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x863d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x000f, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x863f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf86, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8641}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7102, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8643}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6938, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8645}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf86, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8647}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7102, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8649}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70dc, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x864b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd480, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x864d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0bbf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x864f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x866e, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8651}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0269, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8653}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x38d4, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8655}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x000f, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8657}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf86, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8659}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7102, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x865b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6938, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x865d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf86, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x865f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7102, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8661}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70dc, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8663}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0208, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8665}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1eef, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8667}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x96fe, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8669}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfdfc, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x866b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x04f0, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x866d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbd94, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x866f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x30bd, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8671}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9602, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8673}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8621, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8675}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0254, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8677}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdcaf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8679}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x03c1, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x867b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0286, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x867d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2102, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x867f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8686, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8681}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf04, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8683}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x41f8, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8685}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfbef, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8687}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x79e0, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8689}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8018, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x868b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xac20, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x868d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x03af, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x868f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8756, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8691}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6b, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8693}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3402, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8695}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70dc, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8697}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6b, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8699}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3102, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x869b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70e5, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x869d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6f, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x869f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4902, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86a1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70dc, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86a3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6f, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86a5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4c02, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86a7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70e5, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86a9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6f, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86ab}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4f02, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86ad}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70e5, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86af}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6b, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86b1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3702, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86b3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70dc, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86b5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6c, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86b7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c02, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86b9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70dc, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86bb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6b, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86bd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3402, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86bf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70e5, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86c1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1f00, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86c3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe183, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86c5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd4bf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86c7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6bcd, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86c9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0269, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86cb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x38bf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86cd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6bd0, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86cf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0269, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86d1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x38bf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86d3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6bd3, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86d5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0269, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86d7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x38bf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86d9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6bd6, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86db}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0269, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86dd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x38bf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86df}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6bd9, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86e1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86e3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe5bf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86e5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6bdc, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86e7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86e9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe5bf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86eb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6bdf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86ed}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86ef}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe5bf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86f1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6be2, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86f3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86f5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe5bf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86f7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6f46, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86f9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86fb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdce1, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86fd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x83d3, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x86ff}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6f, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8701}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3a02, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8703}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6938, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8705}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0d14, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8707}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6f, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8709}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4002, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x870b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6938, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x870d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0d12, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x870f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6f, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8711}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3d02, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8713}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6938, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8715}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6f, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8717}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4302, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8719}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70dc, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x871b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0238, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x871d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xb5bf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x871f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6bd9, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8721}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8723}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdcbf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8725}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6bdc, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8727}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8729}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdcbf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x872b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6bdf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x872d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x872f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdcbf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8731}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6be2, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8733}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8735}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdcbf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8737}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6b34, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8739}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x873b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdcbf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x873d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6b37, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x873f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8741}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe5bf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8743}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6f4f, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8745}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8747}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdcbf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8749}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6b31, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x874b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x874d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdcbf, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x874f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6f4c, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8751}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0270, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8753}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdcef, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8755}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x97ff, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8757}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfc04, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8759}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xac2f, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x875b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x03af, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x875d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b2a, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x875f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x020e, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8761}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x95af, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8763}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b3f, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8765}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xee84, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8767}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3c00, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8769}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6c, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x876b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c02, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x876d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x70e5, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x876f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf01, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8771}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0300, RTK_PATCH_CMP_SWC , 0, 0xa438, 0xa436, 0x8773}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb818, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5d6d, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb81a, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5eea, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb81c, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x07aa, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb81e, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x03be, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb850, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x043e, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb852, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b26, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb878, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x00fd, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb884, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb832, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x007f, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8264b_uc2_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x1 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb87c, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8acf, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb87e, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf8a, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8acf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe7af, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ad1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8b40, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ad3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf8b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ad5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4caf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ad7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8b6a, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ad9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf8b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8adb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xb5af, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8add}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8bd1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8adf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf8c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ae1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x04af, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ae3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c12, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ae5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf67, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ae7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6302, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ae9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x65f5, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8aeb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef31, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8aed}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf67, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8aef}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6002, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8af1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x65f5, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8af3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1e31, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8af5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xac38, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8af7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x19bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8af9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x676c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8afb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0265, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8afd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf5ef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8aff}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x31bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b01}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6769, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b03}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0265, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b05}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf51e, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b07}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x31ac, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b09}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x380c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b0b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xee89, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b0d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2c02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b0f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xae0a, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b11}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xee89, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b13}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2c00, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b15}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xae04, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b17}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xee89, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b19}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2c01, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b1b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf8f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b1d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd5e1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b1f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x892c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b21}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1a91, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b23}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdbbf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b25}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x67cf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b27}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0265, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b29}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf51f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b2b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x001f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b2d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x221b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b2f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x45ad, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b31}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2705, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b33}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe187, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b35}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x06ae, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b37}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x03e1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b39}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8707, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b3b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf2d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b3d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1a02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b3f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c1e, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b41}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x028c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b43}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7b02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b45}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x224f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b47}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf40, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b49}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xb8ac, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b4b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2f0f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b4d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0210, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b4f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x62bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b51}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6d36, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b53}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0265, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b55}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf5e5, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b57}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8fde, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b59}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf10, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b5b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4ae1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b5d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8fde, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b5f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b61}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3602, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b63}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x65d6, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b65}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf10, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b67}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x59e1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b69}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8fdd, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b6b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa100, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b6d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0dbf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b6f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6d36, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b71}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0265, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b73}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf5e5, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b75}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8fdc, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b77}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xee8f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b79}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdd01, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b7b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b7d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3602, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b7f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6f77, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b81}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf86, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b83}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xc7e1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b85}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x892c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b87}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4903, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b89}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1a91, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b8b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef69, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b8d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdbbf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b8f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x67cf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b91}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0265, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b93}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf51f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b95}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x001f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b97}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x22ef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b99}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x741b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b9b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x45ad, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b9d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2711, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8b9f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf86, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ba1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd0d0, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ba3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x00e1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ba5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8fdc, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ba7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ba9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3602, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bab}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x65d6, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bad}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf35, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8baf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x46af, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bb1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3527, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bb3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x026f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bb5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6eee, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bb7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8fdd, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bb9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x00bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bbb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d31, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bbd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x026f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bbf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6ebf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bc1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d40, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bc3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x026f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bc5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6ebf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bc7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d46, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bc9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x026f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bcb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6eaf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bcd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x36a9, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bcf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf8ef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bd1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x49f8, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bd3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6e, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bd5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xc202, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bd7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x65f5, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bd9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xad28, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bdb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13e1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bdd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8a4e, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bdf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xad28, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8be1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0502, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8be3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5d65, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8be5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xae0e, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8be7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x025c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8be9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1202, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8beb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8cc5, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bed}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xae06, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bef}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x025b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bf1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf302, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bf3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d0d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bf5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe087, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bf7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x17f6, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bf9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x27e4, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bfb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8717, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bfd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfcef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8bff}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x94fc, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c01}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x04a1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c03}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0103, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c05}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x028c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c07}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe9e0, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c09}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8a02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c0b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef23, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c0d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf5c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c0f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdeac, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c11}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5003, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c13}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf61, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c15}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0d02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c17}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d0d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c19}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaf61, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c1b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33f8, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c1d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfafb, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c1f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef79, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c21}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfbbf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c23}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6766, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c25}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0265, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c27}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf5ad, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c29}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2810, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c2b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xad30, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c2d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x05d7, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c2f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0002, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c31}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xae16, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c33}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xad32, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c35}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x24d7, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c37}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0003, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c39}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xae0e, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c3b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xad31, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c3d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x05d7, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c3f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c41}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xae06, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c43}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xad33, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c45}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x14d7, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c47}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0001, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c49}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf8f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c4b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdf4f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c4d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0008, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c4f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1a97, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c51}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd78c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c53}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x63d6, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c55}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c7b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c57}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0265, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c59}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3bff, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c5b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef97, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c5d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfffe, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c5f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfc04, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c61}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x206b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c63}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0e20, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c65}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6b11, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c67}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x206b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c69}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1420, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c6b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6b17, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c6d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x206b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c6f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2020, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c71}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6b23, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c73}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x206b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c75}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2600, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c77}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6b29, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c79}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf8fa, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c7b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef69, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c7d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c7f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbd02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c81}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x65f5, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c83}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xad28, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c85}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0ebf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c87}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d34, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c89}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x026f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c8b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x77bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c8d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d31, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c8f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x026f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c91}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x77ae, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c93}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2ad1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c95}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0fbf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c97}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d37, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c99}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0265, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c9b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd6bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c9d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d3a, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8c9f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x026f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ca1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6ed1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ca3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x00bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ca5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d3d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ca7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0265, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ca9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd6bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cab}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d40, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cad}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x026f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8caf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x77d1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cb1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x00bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cb3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d43, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cb5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0265, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cb7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd6bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cb9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d46, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cbb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x026f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cbd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x77ef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cbf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x96fe, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cc1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfc04, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cc3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf8ef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cc5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x49f8, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cc7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cc9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbd02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ccb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x65f5, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ccd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xac28, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ccf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x12bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cd1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6be6, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cd3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0265, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cd5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf5e5, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cd7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8fd8, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cd9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cdb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf202, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cdd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x65f5, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cdf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe58f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ce1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd9fc, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ce3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef94, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ce5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfc04, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ce7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf8ef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ce9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x49f8, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ceb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8ced}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbd02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cef}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x65f5, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cf1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xac28, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cf3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x12e1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cf5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8fda, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cf7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cf9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe602, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cfb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x65d6, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cfd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe18f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8cff}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xdbbf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d01}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6bf2, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d03}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0265, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d05}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd6fc, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d07}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef94, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d09}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfc04, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d0b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf8ef, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d0d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x49f8, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d0f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6d, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d11}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbd02, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d13}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x65f5, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d15}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xac28, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d17}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x12e1, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d19}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8fd8, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d1b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf6b, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d1d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe602, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d1f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x65d6, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d21}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xe18f, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d23}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd9bf, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d25}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6bf2, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d27}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0265, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d29}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd6fc, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d2b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xef94, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d2d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfc04, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d2f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x77bd, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d31}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6c66, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d33}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbd6c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d35}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x30bd, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d37}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5444, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d39}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbd54, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d3b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x85bd, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d3d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5e55, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d3f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbd54, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d41}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa7bd, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d43}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5cbb, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d45}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbd5c, RTK_PATCH_CMP_SWC , 0, 0xb87e, 0xb87c, 0x8d47}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb85e, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2d07, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb860, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40b5, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb862, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1047, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb864, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3504, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb886, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x36A6, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb888, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x613d, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb88a, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5cd9, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb88c, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x610a, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xb838, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x00ff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x0 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8264b_nctl0_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x1 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA016, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA012, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA014, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8010, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8015, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8020, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x802a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8030, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8035, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8046, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x806b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd707, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x606f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x801a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd707, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x606f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x801a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce10, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcf01, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd705, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4004, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcf02, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd719, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3bb7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8024, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd704, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x406e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x12bd, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x12e3, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xab80, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd500, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xc402, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x004a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8b80, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd500, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x32}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x33}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0108, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x34}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c0f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x35}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x090f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x36}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c0f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x37}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0a03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x38}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd004, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x39}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1c1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x401c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce00, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd500, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x801a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x40}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd501, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x41}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce01, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x42}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x43}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x44}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0aa9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x45}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd500, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x46}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x47}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2a69, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x48}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8056, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x49}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3f48, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8058, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3f4b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x805a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x618c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3f40, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x805c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x50}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3f43, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x51}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x805e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x52}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x616b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x53}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6187, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x54}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x55}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcc8f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x56}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x57}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcc8d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x58}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x59}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcc8b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcc89, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf004, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcc87, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf002, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcc91, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x60}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x61}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b9a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x62}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x63}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xca80, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x64}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x65}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0ba0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x66}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xca00, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x67}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd504, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x68}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x69}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1658, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa208, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0a88, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0d91, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA026, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0d90, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA024, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1657, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA022, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0aa1, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA020, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0047, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA006, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0049, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA004, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x12b9, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA002, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0be5, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA000, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1811, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA008, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xff00, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA016, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA012, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0ff8, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA014, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xc483, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x0ff8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xc483, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xff9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xffa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xffb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xffc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xffd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xffe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xfff}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA152, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1a83, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA154, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1d29, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA156, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3fff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA158, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3fff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA15A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3fff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA15C, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3fff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA15E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3fff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA160, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3fff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA150, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0003, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x0 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8264b_nctl1_conf[] = { +}; + +rtk_hwpatch_t rtl8264b_nctl2_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x1 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA016, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0020, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA012, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA014, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8010, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8022, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8029, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8085, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x808c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8093, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8281, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x829a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8370, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd707, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x416f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd05a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa501, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd701, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5fbd, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8501, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0427, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x040b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8501, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd707, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x406f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x01d8, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x01cb, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd705, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3fa7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8030, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd75f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x699c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1340, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd704, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4066, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x800a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x32}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf002, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x33}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x34}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd705, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x35}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x61b4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x36}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd704, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x37}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x609f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x38}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6150, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x39}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x2d71, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8043, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cf0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x05a0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x3f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x40}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x41}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13b1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x42}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x43}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x44}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8220, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x45}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c30, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x46}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0410, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x47}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x48}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x800a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x49}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x81a0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8302, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8480, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8684, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x4f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8203, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x50}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8340, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x51}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x52}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xaa10, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x53}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8b07, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x54}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x55}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x56}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60f1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x57}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6113, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x58}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6135, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x59}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6157, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce0b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce0b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x5f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce0a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x60}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x61}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce0a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x62}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf004, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x63}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce09, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x64}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf002, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x65}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce09, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x66}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x67}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x68}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa204, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x69}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13e4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xab08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcda0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd705, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x6f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40de, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x70}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd162, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x71}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd045, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x72}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbf10, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x73}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x74}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13b1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x75}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9f10, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x76}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x77}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13b1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x78}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x79}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x607a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13b1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9f10, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x7f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8210, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x80}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa210, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x81}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x82}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x83}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1340, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x84}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x85}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x86}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8df8, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x87}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8370, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x88}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x89}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x01c1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8df8, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8370, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x8f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x90}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x91}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x009e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x92}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x93}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x94}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x809e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x95}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x96}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x809b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x97}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1bf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x98}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd06d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x99}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1dd, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd06d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd06e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x9f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5fba, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd05a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60f1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6113, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xa9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6135, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xaa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6157, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xab}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xac}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xad}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xae}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xaf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf004, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf002, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13e4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xb9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xba}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xbb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0ccf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xbc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b40, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xbd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xbe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c24, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xbf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa340, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1433, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa110, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13ec, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8110, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x143c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xc9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa304, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xca}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa8c0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xcb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8810, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xcc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xcd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xce}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa310, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xcf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cfc, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0224, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0ca0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0480, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa340, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd162, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xd9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xda}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xdb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xdc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5fba, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xdd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8840, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xde}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1c4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xdf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd045, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5fba, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6127, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f3b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x88c0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xe9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x800a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xea}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xeb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8350, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xec}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x84a0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xed}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffb6, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xee}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xb920, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xef}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd33, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7fb4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9920, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6065, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xf9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f94, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xfa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffee, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xfb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xb820, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xfc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xfd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xfe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0xff}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7fa5, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x100}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9820, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x101}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x800a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x102}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x103}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x104}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1433, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x105}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa108, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x106}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x107}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13ec, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x108}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8108, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x109}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x143c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa2fc, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa304, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8880, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cc0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x10f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0440, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x110}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd34, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x111}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x112}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x113}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cc0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x114}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b80, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x115}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xac3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x116}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c38, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x117}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0d08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x118}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x119}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa810, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa480, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa604, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x11f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x120}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8125, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x121}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x122}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x123}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x124}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd19f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x125}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x126}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x127}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x128}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x129}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x63f4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4368, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x12f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x130}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cc0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x131}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b40, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x132}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x133}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d38, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x134}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x135}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x136}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x137}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8141, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x138}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x139}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x813e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1f4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1b7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x13f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x140}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1c6, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x141}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x142}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x143}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x144}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x145}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6074, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x146}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x147}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x148}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x149}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4056, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf004, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x61fc, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x14f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xfff9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x150}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x151}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x152}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x153}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x154}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4070, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x155}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x156}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x820e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x157}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x158}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x159}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xae80, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x820e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd05a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x15f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x160}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x161}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60f1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x162}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6113, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x163}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6135, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x164}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6157, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x165}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x166}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x167}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x168}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x169}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf004, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x16f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf002, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x170}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x171}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x172}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13e4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x173}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x174}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x175}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0ccf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x176}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b40, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x177}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x178}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c24, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x179}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa340, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1433, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa110, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x17f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13ec, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x180}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8110, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x181}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x182}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x143c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x183}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa304, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x184}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa8c0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x185}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8810, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x186}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x187}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x188}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa310, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x189}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cfc, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0224, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0ca0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0480, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8604, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd35, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x18f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd162, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x190}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x191}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x192}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x193}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x194}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5fba, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x195}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8840, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x196}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1c4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x197}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd045, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x198}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x199}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5fba, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6127, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x19f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f3b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x88c0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x800a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8350, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x84a0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffb8, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xbb80, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1a9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1aa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5fb4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ab}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xb920, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ac}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd36, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ad}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ae}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1af}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7fb4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9920, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9b80, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6065, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f94, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xffe8, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1b9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xb820, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ba}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1bb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1bc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd71f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1bd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x7fa5, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1be}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9820, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1bf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x800a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1433, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa108, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13ec, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8108, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x143c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1c9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa2fc, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ca}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa304, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1cb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8880, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1cc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cc0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1cd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0440, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ce}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd37, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1cf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cc0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b80, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xac3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c38, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0d08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa810, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1d9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1da}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa480, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1db}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa604, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1dc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1dd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1de}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x81e8, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1df}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x81e5, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1e9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ea}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1eb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ec}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x141a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ed}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ee}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ef}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f28, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cc0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b40, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8c3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8d38, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1f9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1fa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8204, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1fb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1fc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8201, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1fd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1fe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ff}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x200}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x201}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x202}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x203}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd189, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x204}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x205}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x206}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x207}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x208}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x141a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x209}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f28, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x20f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c0f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x210}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b05, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x211}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x212}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x213}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x214}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60f1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x215}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6113, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x216}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6135, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x217}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6157, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x218}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x219}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x21f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x220}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf004, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x221}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x222}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf002, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x223}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce08, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x224}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x225}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13e4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x226}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa180, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x227}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd38, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x228}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x229}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x823e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8236, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x22f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x230}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x231}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf013, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x232}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd100, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x233}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x234}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf010, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x235}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x236}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x237}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1b7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x238}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x239}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd100, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x23f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x240}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x241}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x242}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x243}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x244}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd13b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x245}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd055, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x246}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x247}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x248}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x249}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x141a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa302, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x24f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x250}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x141a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x251}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x252}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x253}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x254}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f28, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x255}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x256}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x257}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x258}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c12, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x259}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8270, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8268, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x25f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x260}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x261}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x262}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x263}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf013, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x264}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd100, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x265}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x266}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf010, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x267}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x268}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x269}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd100, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd040, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x26f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x270}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x271}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x272}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x273}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x274}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd16b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x275}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x276}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x277}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x278}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x279}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x141a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f2a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x27f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x085e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x280}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x281}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x282}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcb0a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x283}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0cc7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x284}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x285}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x286}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x287}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4127, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x288}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x289}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c0f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b05, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c38, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0d28, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x28f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x290}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x291}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x292}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c0f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x293}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b0a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x294}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c38, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x295}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0d18, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x296}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x297}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x298}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0f45, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x299}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x646d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x82b4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x82aa, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x29f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd100, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf01a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf017, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2a9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2aa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ab}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ac}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ad}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd100, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ae}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2af}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf010, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2b9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ba}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2bb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2bc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2bd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2be}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2bf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x141a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f29, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2c9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x60f1, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ca}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6113, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2cb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6135, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2cc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x6157, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2cd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ce}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2cf}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf008, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf004, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf002, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xce06, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2d9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2da}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13e4, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2db}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2dc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2dd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8bc0, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2de}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c3f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2df}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c09, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa120, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa310, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xa420, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd3b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x65ad, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x43c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2e9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ea}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x82fe, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2eb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ec}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x82f6, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ed}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ee}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ef}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f1}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf024, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f2}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd15d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f3}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f4}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf021, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f5}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f6}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f7}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1c6, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2f9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf01c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2fa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd15d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2fb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2fc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf019, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2fd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2fe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x2ff}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd199, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x300}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x301}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf014, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x302}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x303}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x304}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf011, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x305}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x306}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x307}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8311, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x308}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x309}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x830e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd1e5, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf009, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd191, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x30f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x310}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x311}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x312}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x313}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd16b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x314}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x315}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x316}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x13cf, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x317}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x318}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x141a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x319}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f7a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd706, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x5f2c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x40e7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x31f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x320}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x321}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c0f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x322}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b05, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x323}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x324}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x325}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c03, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x326}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1502, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x327}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0c0f, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x328}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b0a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x329}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x9503, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x32a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xcd3c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x32b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x32c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x644d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x32d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x43c7, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x32e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd700, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x32f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x37c9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x330}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x8344, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x331}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x33a9, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x332}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x833c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x333}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x334}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x335}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x336}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x337}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf019, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x338}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x339}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x33a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf016, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x33b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x33c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x33d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x33e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x33f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf011, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x340}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd13e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x341}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x342}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf00e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x343}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd702, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x344}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x4098, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x345}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x346}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x347}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf009, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x348}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x349}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd049, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x34a}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf006, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x34b}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x34c}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd04b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x34d}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf003, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x34e}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd17a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x34f}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd048, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x350}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1800, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x351}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x093a, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x352}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA10E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0883, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA10C, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0f32, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA10A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0676, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA108, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x00fa, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA106, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x021d, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA104, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x12fe, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA102, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x01ca, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA100, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x047f, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA110, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x00ff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA016, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0020, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA012, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x1ff8, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA014, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd13e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ff8}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd15c, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ff9}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd16b, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ffa}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xd15d, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ffb}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b0e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ffc}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b0e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ffd}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b0e, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1ffe}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_SWC , 0, 0xa014, 0xa012, 0x1fff}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA164, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0972, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA166, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0968, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA168, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0a0b, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA16A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0a01, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA16C, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0b8a, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA16E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0bf9, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA170, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x125c, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA172, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x3fff, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0xA162, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x007F, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x0 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8264b_algxg_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x815B, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x75 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x80CD, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x25 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8065, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x15 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8175, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0xa2 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8176, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0xc5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8077, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x40 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8078, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0xcc , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8969, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x0f , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8957, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x2C , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8959, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x15 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x895A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x3E , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x895F, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x1E , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8165, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x22 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x827E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x68 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8167, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x33 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8013, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x39 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8fd7, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x14 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8fd6, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x1e , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8fd5, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x1e , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x82D9, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x20 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x82DA, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x00 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x816E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0xab , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8159, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x58 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x815A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x99 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8139, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x25 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8125, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x67 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8126, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x89 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x827D, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x42 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8264b_alg_giga_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80b8, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x4d , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80b9, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0xcc , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80ba, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80bb, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 13, 8 , 0x0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80bc, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x37 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80bd, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 12, 8 , 0x0c , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80be, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0xBB , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80bf, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0xca , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80c0, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x45 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80c2, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x3b , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80cc, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x16 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80cd, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 10, 8 , 0x4 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80ce, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80cf, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 13, 8 , 0x0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80d0, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x53 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80d1, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 12, 8 , 0x0a , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80d2, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0xB9 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80d3, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0xd0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80d4, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x4a , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80d6, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x35 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80a4, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x0d , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80a5, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0xa4 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80a6, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x59 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80a7, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 13, 8 , 0x05 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80a8, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0xab , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80a9, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 12, 8 , 0x0b , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80aa, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0xef , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80ab, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0xae , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80ac, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0xdf , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x80ae, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x28 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x8367, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x5d , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8264b_normal_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbd92, 15, 0 , 0x002e, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbd94, 15, 0 , 0x8003, RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbd96, 3 , 0 , 0xf , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbd96, 3 , 0 , 0x0 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbd94, 15, 0 , 0x800b, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbd96, 3 , 0 , 0xf , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xbd96, 3 , 0 , 0x0 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x817D, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x07 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x8426, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x46 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x8428, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x46 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x84de, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x84e0, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x00fc, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x84e2, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf61a, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x84e4, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x58 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x84e6, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x84e8, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x00fc, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x84ea, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf61a, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x84ec, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x58 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x84ee, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0000, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x84f0, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x00fc, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x84f2, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0xf61a, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x84f4, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 8 , 0x58 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xae32, 5 , 5 , 0x1 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x8018, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 12, 12, 0x1 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8fdf, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x0496, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8fe1, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x03a5, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8fe3, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x02e5, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8fe5, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x020d, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8fe7, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x0496, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8fe9, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x03a5, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8feb, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x02e5, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8fed, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x020d, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8fef, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x0496, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8ff1, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x03a5, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8ff3, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x02e5, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8ff5, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x020d, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8ff7, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x0496, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8ff9, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x03a5, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8ffb, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x02e5, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8ffd, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 0 , 0x020d, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb516, 6 , 0 , 0x0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8fda, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x04 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8fdb, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x05 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8132, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x77 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8134, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x88 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x80ca, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x77 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x80cc, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x88 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8062, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x77 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87c, 15, 0 , 0x8064, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb87e, 15, 8 , 0x88 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa436, 15, 0 , 0x801E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xa438, 15, 0 , 0x0012, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8264b_dataram_conf[] = { + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb820, 7 , 7 , 0x0 , RTK_PATCH_CMP_WS , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb896, 0 , 0 , 0x0 , RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb892, 15, 8 , 0x0 , RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC037, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x33 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC038, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x2A , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC039, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x25 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC03A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x20 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC03B, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x1C , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC03C, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x17 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC03D, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x13 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC075, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xA1 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC076, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xB1 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC077, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x2E , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC078, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x55 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC079, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x19 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC07A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xDC , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC07B, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xA0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC10B, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xD5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC10C, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xD5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC10D, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xD5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC10E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xD5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC10F, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xD5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC110, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xD5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC149, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x08 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC14A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x08 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC14B, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x08 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC14C, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x08 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC14D, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x08 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC14E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x08 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC166, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xEE , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC167, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xEE , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC168, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x07 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC169, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x09 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC16A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x0B , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC16B, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x0D , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC16C, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x13 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC16D, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x0E , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC16E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x11 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC16F, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x14 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC170, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x17 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC171, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x15 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC172, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0x10 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC173, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0x0B , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC128, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xF7 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC129, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xF7 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC12A, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xF8 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC12B, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xF7 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC12C, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xF6 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC12D, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xF5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC12E, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xF2 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC12F, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xF7 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC130, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xF5 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC131, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xF2 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC132, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xF0 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC133, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xF1 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC134, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 15, 8 , 0xF4 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb88e, 15, 0 , 0xC135, RTK_PATCH_CMP_W , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb890, 7 , 0 , 0xF7 , RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PHYOCP , 0xf , 0 , 0xb896, 0 , 0 , 0x1 , RTK_PATCH_CMP_W , 0, 0, 0, 0}, +}; + +rtk_hwpatch_t rtl8264b_rtct_conf[] = { +}; + diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/error.h b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/error.h new file mode 100644 index 0000000000..d99a996f8c --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/error.h @@ -0,0 +1,165 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +#ifndef __COMMON_ERROR_H__ +#define __COMMON_ERROR_H__ + +/* + * Include Files + */ +#if defined(RTK_PHYDRV_IN_LINUX) + #include "type.h" +#else + #include +#endif +/* + * Data Type Declaration + */ +typedef enum rt_error_common_e +{ + RT_ERR_FAILED = -1, /* General Error */ + + /* 0x0000xxxx for common error code */ + RT_ERR_OK = 0, /* 0x00000000, OK */ + RT_ERR_INPUT = 0xF001, /* 0x0000F001, invalid input parameter */ + RT_ERR_UNIT_ID, /* 0x0000F002, invalid unit id */ + RT_ERR_PORT_ID, /* 0x0000F003, invalid port id */ + RT_ERR_PORT_MASK, /* 0x0000F004, invalid port mask */ + RT_ERR_PORT_LINKDOWN, /* 0x0000F005, link down port status */ + RT_ERR_ENTRY_INDEX, /* 0x0000F006, invalid entry index */ + RT_ERR_NULL_POINTER, /* 0x0000F007, input parameter is null pointer */ + RT_ERR_QUEUE_ID, /* 0x0000F008, invalid queue id */ + RT_ERR_QUEUE_NUM, /* 0x0000F009, invalid queue number */ + RT_ERR_BUSYWAIT_TIMEOUT, /* 0x0000F00a, busy watting time out */ + RT_ERR_MAC, /* 0x0000F00b, invalid mac address */ + RT_ERR_OUT_OF_RANGE, /* 0x0000F00c, input parameter out of range */ + RT_ERR_CHIP_NOT_SUPPORTED, /* 0x0000F00d, functions not supported by this chip model */ + RT_ERR_SMI, /* 0x0000F00e, SMI error */ + RT_ERR_NOT_INIT, /* 0x0000F00f, The module is not initial */ + RT_ERR_CHIP_NOT_FOUND, /* 0x0000F010, The chip can not found */ + RT_ERR_NOT_ALLOWED, /* 0x0000F011, actions not allowed by the function */ + RT_ERR_DRIVER_NOT_FOUND, /* 0x0000F012, The driver can not found */ + RT_ERR_SEM_LOCK_FAILED, /* 0x0000F013, Failed to lock semaphore */ + RT_ERR_SEM_UNLOCK_FAILED, /* 0x0000F014, Failed to unlock semaphore */ + RT_ERR_THREAD_EXIST, /* 0x0000F015, Thread exist */ + RT_ERR_THREAD_CREATE_FAILED, /* 0x0000F016, Thread create fail */ + RT_ERR_FWD_ACTION, /* 0x0000F017, Invalid forwarding Action */ + RT_ERR_IPV4_ADDRESS, /* 0x0000F018, Invalid IPv4 address */ + RT_ERR_IPV6_ADDRESS, /* 0x0000F019, Invalid IPv6 address */ + RT_ERR_PRIORITY, /* 0x0000F01a, Invalid Priority value */ + RT_ERR_FID, /* 0x0000F01b, invalid fid */ + RT_ERR_ENTRY_NOTFOUND, /* 0x0000F01c, specified entry not found */ + RT_ERR_DROP_PRECEDENCE, /* 0x0000F01d, invalid drop precedence */ + RT_ERR_NOT_FINISH, /* 0x0000F01e, Action not finish, still need to wait */ + RT_ERR_TIMEOUT, /* 0x0000F01f, Time out */ + RT_ERR_REG_ARRAY_INDEX_1, /* 0x0000F020, invalid index 1 of register array */ + RT_ERR_REG_ARRAY_INDEX_2, /* 0x0000F021, invalid index 2 of register array */ + RT_ERR_ETHER_TYPE, /* 0x0000F022, invalid ether type */ + RT_ERR_MBUF_PKT_NOT_AVAILABLE, /* 0x0000F023, mbuf->packet is not available */ + RT_ERR_QOS_INVLD_RSN, /* 0x0000F024, invalid pkt to CPU reason */ + RT_ERR_CB_FUNCTION_EXIST, /* 0x0000F025, Callback function exist */ + RT_ERR_CB_FUNCTION_FULL, /* 0x0000F026, Callback function number is full */ + RT_ERR_CB_FUNCTION_NOT_FOUND, /* 0x0000F027, Callback function can not found */ + RT_ERR_TBL_FULL, /* 0x0000F028, The table is full */ + RT_ERR_TRUNK_ID, /* 0x0000F029, invalid trunk id */ + RT_ERR_TYPE, /* 0x0000F02a, invalid type */ + RT_ERR_ENTRY_EXIST, /* 0x0000F02b, entry exists */ + RT_ERR_CHIP_UNDEFINED_VALUE, /* 0x0000F02c, chip returned an undefined value */ + RT_ERR_EXCEEDS_CAPACITY, /* 0x0000F02d, exceeds the capacity of hardware */ + RT_ERR_ENTRY_REFERRED, /* 0x0000F02e, entry is still being referred */ + RT_ERR_OPER_DENIED, /* 0x0000F02f, operation denied */ + RT_ERR_PORT_NOT_SUPPORTED, /* 0x0000F030, functions not supported by this port */ + RT_ERR_SOCKET, /* 0x0000F031, socket error */ + RT_ERR_MEM_ALLOC, /* 0x0000F032, insufficient memory resource */ + RT_ERR_ABORT, /* 0x0000F033, operation aborted */ + RT_ERR_DEV_ID, /* 0x0000F034, invalid device id */ + RT_ERR_DRIVER_NOT_SUPPORTED, /* 0x0000F035, functions not supported by this driver */ + RT_ERR_NOT_SUPPORTED, /* 0x0000F036, functions not supported */ + RT_ERR_SER, /* 0x0000F037, ECC or parity error */ + RT_ERR_MEM_NOT_ALIGN, /* 0x0000F038, memory address is not aligned */ + RT_ERR_SEM_FAKELOCK_OK, /* 0x0000F039, attach thread lock a semaphore which was already locked */ + RT_ERR_CHECK_FAILED, /* 0x0000F03a, check result is failed */ + + RT_ERR_COMMON_END = 0xFFFF /* The symbol is the latest symbol of common error */ +} rt_error_common_t; + +/* + * Macro Definition + */ +#define RT_PARAM_CHK(expr, errCode)\ +do {\ + if ((int32)(expr)) {\ + return errCode; \ + }\ +} while (0) + +#define RT_PARAM_CHK_EHDL(expr, errCode, err_hdl)\ +do {\ + if ((int32)(expr)) {\ + {err_hdl}\ + return errCode; \ + }\ +} while (0) + +#define RT_INIT_CHK(state)\ +do {\ + if (INIT_COMPLETED != (state)) {\ + return RT_ERR_NOT_INIT;\ + }\ +} while (0) + +#define RT_INIT_REENTRY_CHK(state)\ +do {\ + if (INIT_COMPLETED == (state)) {\ + osal_printf(" %s had already been initialized!\n", __FUNCTION__);\ + return RT_ERR_OK;\ + }\ +} while (0) + +#define RT_INIT_REENTRY_CHK_NO_WARNING(state)\ + do {\ + if (INIT_COMPLETED == (state)) {\ + return RT_ERR_OK;\ + }\ + } while (0) + +#define RT_ERR_CHK(op, ret)\ +do {\ + if ((ret = (op)) != RT_ERR_OK)\ + return ret;\ +} while(0) + +#define RT_ERR_HDL(op, errHandle, ret)\ +do {\ + if ((ret = (op)) != RT_ERR_OK)\ + goto errHandle;\ +} while(0) + +#define RT_ERR_CHK_EHDL(op, ret, err_hdl)\ +do {\ + if ((ret = (op)) != RT_ERR_OK)\ + {\ + {err_hdl}\ + return ret;\ + }\ +} while(0) + +#define RT_NULL_HDL(pointer, err_label)\ +do {\ + if (NULL == (pointer)) {\ + goto err_label;\ + }\ +} while (0) + +#define RT_ERR_VOID_CHK(op, ret)\ +do {\ + if ((ret = (op)) != RT_ERR_OK) {\ + osal_printf("Fail in %s %d, ret %x!\n", __FUNCTION__, __LINE__, ret);\ + return ;}\ +} while(0) + +#endif /* __COMMON_ERROR_H__ */ + diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_patch.c b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_patch.c new file mode 100644 index 0000000000..3614dc2833 --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_patch.c @@ -0,0 +1,190 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +/* + * Include Files + */ +#if defined(RTK_PHYDRV_IN_LINUX) + #include "rtk_osal.h" +#else + #include + #include + #include + #include + #include +#endif + +/* + * Function Declaration + */ +uint8 phy_patch_op_translate(uint8 patch_mode, uint8 patch_op, uint8 compare_op) +{ + if (patch_mode != PHY_PATCH_MODE_CMP) + { + return patch_op; + } + else + { + switch (compare_op) + { + case RTK_PATCH_CMP_WS: + return RTK_PATCH_OP_SKIP; + case RTK_PATCH_CMP_W: + case RTK_PATCH_CMP_WC: + case RTK_PATCH_CMP_SWC: + default: + return RTK_PATCH_OP_TO_CMP(patch_op, compare_op); + } + } +} + +int32 phy_patch_op(rt_phy_patch_db_t *pPhy_patchDb, uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_op, uint16 portmask, uint16 pagemmd, uint16 addr, uint8 msb, uint8 lsb, uint16 data, uint8 patch_mode) +{ + rtk_hwpatch_t op; + + op.patch_op = patch_op; + op.portmask = portmask; + op.pagemmd = pagemmd; + op.addr = addr; + op.msb = msb; + op.lsb = lsb; + op.data = data; + op.compare_op = RTK_PATCH_CMP_W; + + return pPhy_patchDb->fPatch_op(unit, port, portOffset, &op, patch_mode); +} + +static int32 _phy_patch_process(uint32 unit, rtk_port_t port, uint8 portOffset, rtk_hwpatch_t *pPatch, int32 size, uint8 patch_mode) +{ + int32 i = 0; + int32 ret = 0; + int32 chk_ret = RT_ERR_OK; + int32 n; + rtk_hwpatch_t *patch = pPatch; + rt_phy_patch_db_t *pPatchDb = NULL; + + PHYPATCH_DB_GET(unit, port, pPatchDb); + + if (size <= 0) + { + return RT_ERR_OK; + } + n = size / sizeof(rtk_hwpatch_t); + + for (i = 0; i < n; i++) + { + ret = pPatchDb->fPatch_op(unit, port, portOffset, &patch[i], patch_mode); + if ((ret != RT_ERR_ABORT) && (ret != RT_ERR_OK)) + { + if ((ret == RT_ERR_CHECK_FAILED) && (patch_mode == PHY_PATCH_MODE_CMP)) + { + osal_printf("PATCH CHECK: Failed entry:%u|%u|0x%X|0x%X|%u|%u|0x%X\n", + i + 1, patch[i].patch_op, patch[i].pagemmd, patch[i].addr, patch[i].msb, patch[i].lsb, patch[i].data); + chk_ret = RT_ERR_CHECK_FAILED; + continue; + } + else + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u %s failed! %u[%u][0x%X][0x%X][0x%X] ret=0x%X\n", unit, port, __FUNCTION__, + i+1, patch[i].patch_op, patch[i].pagemmd, patch[i].addr, patch[i].data, ret); + return ret; + } + } + + } + return (chk_ret == RT_ERR_CHECK_FAILED) ? chk_ret : RT_ERR_OK; +} + +rtk_hwpatch_t rtl826XB_patch_rtk_conf[] = { + {RTK_PATCH_OP_PSDS0 , 0xff , 0x07 , 0x10 , 15, 0, 0x80aa, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, + {RTK_PATCH_OP_PSDS0 , 0xff , 0x06 , 0x12 , 15, 0, 0x5078, RTK_PATCH_CMP_WC , 0, 0, 0, 0}, +}; + +/* Function Name: + * phy_patch + * Description: + * apply initial patch data to PHY + * Input: + * unit - unit id + * port - port id + * portOffset - the index offset of port based the base port in the PHY chip + * Output: + * None + * Return: + * RT_ERR_OK + * RT_ERR_FAILED + * RT_ERR_CHECK_FAILED + * RT_ERR_NOT_SUPPORTED + * Note: + * None + */ +int32 phy_patch(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + int32 chk_ret = RT_ERR_OK; + uint32 i = 0; + uint8 patch_type = 0; + rt_phy_patch_db_t *pPatchDb = NULL; + rtk_hwpatch_seq_t *table = NULL; + + PHYPATCH_DB_GET(unit, port, pPatchDb); + + if ((pPatchDb == NULL) || (pPatchDb->fPatch_op == NULL) || (pPatchDb->fPatch_flow == NULL)) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u phy_patch, db is NULL\n", unit, port); + return RT_ERR_DRIVER_NOT_SUPPORTED; + } + + if (patch_mode == PHY_PATCH_MODE_CMP) + { + table = pPatchDb->cmp_table; + } + else + { + table = pPatchDb->seq_table; + } + RT_LOG(LOG_INFO, (MOD_HAL | MOD_PHY), "phy_patch: U%u P%u portOffset:%u patch_mode:%u\n", unit, port, portOffset, patch_mode); + + for (i = 0; i < RTK_PATCH_SEQ_MAX; i++) + { + patch_type = table[i].patch_type; + RT_LOG(LOG_INFO, (MOD_HAL | MOD_PHY), "phy_patch: table[%u] patch_type:%u\n", i, patch_type); + + if (RTK_PATCH_TYPE_IS_DATA(patch_type)) + { + ret = _phy_patch_process(unit, port, portOffset, table[i].patch.data.conf, table[i].patch.data.size, patch_mode); + + if (ret == RT_ERR_CHECK_FAILED) + chk_ret = ret; + else if (ret != RT_ERR_OK) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u patch_mode:%u id:%u patch-%u failed. ret:0x%X\n", unit, port, patch_mode, i, patch_type, ret); + return ret; + } + } + else if (RTK_PATCH_TYPE_IS_FLOW(patch_type)) + { + RT_ERR_CHK_EHDL(pPatchDb->fPatch_flow(unit, port, portOffset, table[i].patch.flow_id, patch_mode), + ret, RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u patch_mode:%u id:%u patch-%u failed. ret:0x%X\n", unit, port, patch_mode, i, patch_type, ret);); + } + else + { + break; + } + } +#ifdef CONFIG_MACH_REALTEK_RTL + ret = _phy_patch_process(unit, port, portOffset, rtl826XB_patch_rtk_conf, sizeof(rtl826XB_patch_rtk_conf), patch_mode); + if (ret == RT_ERR_CHECK_FAILED) + chk_ret = ret; + else if (ret != RT_ERR_OK) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u patch_mode:%u id:%u patch-%u failed. ret:0x%X\n", unit, port, patch_mode, i, patch_type, ret); + return ret; + } +#endif + + return (chk_ret == RT_ERR_CHECK_FAILED) ? chk_ret : RT_ERR_OK; +} diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_patch.h b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_patch.h new file mode 100644 index 0000000000..c2b7b1279c --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_patch.h @@ -0,0 +1,174 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +#ifndef __HAL_PHY_PATCH_H__ +#define __HAL_PHY_PATCH_H__ + +/* + * Include Files + */ +#if defined(RTK_PHYDRV_IN_LINUX) + #include "rtk_phylib_def.h" +#else + #include + #include +#endif + +/* + * Symbol Definition + */ +#define PHYPATCH_PHYCTRL_IN_HALCTRL 0 /* 3.6.x: 1 ,4.0.x: 1, 4.1.x+: 0 */ +#define PHYPATCH_FMAILY_IN_HWP 0 /* 3.6.x: 1 ,4.0.x: 0, 4.1.x+: 0 */ +#define PHY_PATCH_MODE_BCAST_DEFAULT PHY_PATCH_MODE_BCAST /* 3.6.x: PHY_PATCH_MODE_BCAST_BUS ,4.0.x+: PHY_PATCH_MODE_BCAST */ + +#define PHY_PATCH_MODE_NORMAL 0 +#define PHY_PATCH_MODE_CMP 1 +#define PHY_PATCH_MODE_BCAST 2 +#define PHY_PATCH_MODE_BCAST_BUS 3 + +#define RTK_PATCH_CMP_W 0 /* write */ +#define RTK_PATCH_CMP_WC 1 /* compare */ +#define RTK_PATCH_CMP_SWC 2 /* sram compare */ +#define RTK_PATCH_CMP_WS 3 /* skip */ + +#define RTK_PATCH_OP_SECTION_SIZE 50 +#define RTK_PATCH_OP_TO_CMP(_op, _cmp) (_op + (RTK_PATCH_OP_SECTION_SIZE * _cmp)) +/* 0~49 normal op */ +#define RTK_PATCH_OP_PHY 0 +#define RTK_PATCH_OP_PHYOCP 1 +#define RTK_PATCH_OP_TOP 2 +#define RTK_PATCH_OP_TOPOCP 3 +#define RTK_PATCH_OP_PSDS0 4 +#define RTK_PATCH_OP_PSDS1 5 +#define RTK_PATCH_OP_MSDS 6 +#define RTK_PATCH_OP_MAC 7 + +/* 50~99 normal op for compare */ +#define RTK_PATCH_OP_CMP_PHY RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PHY , RTK_PATCH_CMP_WC) +#define RTK_PATCH_OP_CMP_PHYOCP RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PHYOCP , RTK_PATCH_CMP_WC) +#define RTK_PATCH_OP_CMP_TOP RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_TOP , RTK_PATCH_CMP_WC) +#define RTK_PATCH_OP_CMP_TOPOCP RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_TOPOCP , RTK_PATCH_CMP_WC) +#define RTK_PATCH_OP_CMP_PSDS0 RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PSDS0 , RTK_PATCH_CMP_WC) +#define RTK_PATCH_OP_CMP_PSDS1 RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PSDS1 , RTK_PATCH_CMP_WC) +#define RTK_PATCH_OP_CMP_MSDS RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_MSDS , RTK_PATCH_CMP_WC) +#define RTK_PATCH_OP_CMP_MAC RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_MAC , RTK_PATCH_CMP_WC) + +/* 100~149 normal op for sram compare */ +#define RTK_PATCH_OP_CMP_SRAM_PHY RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PHY , RTK_PATCH_CMP_SWC) +#define RTK_PATCH_OP_CMP_SRAM_PHYOCP RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PHYOCP , RTK_PATCH_CMP_SWC) +#define RTK_PATCH_OP_CMP_SRAM_TOP RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_TOP , RTK_PATCH_CMP_SWC) +#define RTK_PATCH_OP_CMP_SRAM_TOPOCP RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_TOPOCP , RTK_PATCH_CMP_SWC) +#define RTK_PATCH_OP_CMP_SRAM_PSDS0 RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PSDS0 , RTK_PATCH_CMP_SWC) +#define RTK_PATCH_OP_CMP_SRAM_PSDS1 RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_PSDS1 , RTK_PATCH_CMP_SWC) +#define RTK_PATCH_OP_CMP_SRAM_MSDS RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_MSDS , RTK_PATCH_CMP_SWC) +#define RTK_PATCH_OP_CMP_SRAM_MAC RTK_PATCH_OP_TO_CMP(RTK_PATCH_OP_MAC , RTK_PATCH_CMP_SWC) + +/* 200~255 control op */ +#define RTK_PATCH_OP_DELAY_MS 200 +#define RTK_PATCH_OP_SKIP 255 + + +/* + patch type PHY_PATCH_TYPE_NONE => empty + patch type: PHY_PATCH_TYPE_TOP ~ (PHY_PATCH_TYPE_END-1) => data array + patch type: PHY_PATCH_TYPE_END ~ (PHY_PATCH_TYPE_END + RTK_PATCH_TYPE_FLOW_MAX) => flow +*/ +#define RTK_PATCH_TYPE_IS_DATA(_patch_type) (_patch_type > PHY_PATCH_TYPE_NONE && _patch_type < PHY_PATCH_TYPE_END) +#define RTK_PATCH_TYPE_IS_FLOW(_patch_type) (_patch_type >= PHY_PATCH_TYPE_END && _patch_type <= (PHY_PATCH_TYPE_END + RTK_PATCH_TYPE_FLOWID_MAX)) + + +/* + * Macro Definition + */ +#if PHYPATCH_PHYCTRL_IN_HALCTRL + #define PHYPATCH_DB_GET(_unit, _port, _pPatchDb) \ + do {\ + hal_control_t *pHalCtrl = NULL;\ + if ((pHalCtrl = hal_ctrlInfo_get(_unit)) == NULL)\ + return RT_ERR_FAILED;\ + _pPatchDb = (pHalCtrl->pPhy_ctrl[_port]->pPhy_patchDb);\ + } while(0) +#else + #if defined(RTK_PHYDRV_IN_LINUX) + #else + #include + #include + #endif + #define PHYPATCH_DB_GET(_unit, _port, _pPatchDb) \ + do {\ + rt_phyctrl_t *pPhyCtrl = NULL;\ + if ((pPhyCtrl = phy_phyctrl_get(_unit, _port)) == NULL)\ + return RT_ERR_FAILED;\ + _pPatchDb = (pPhyCtrl->pPhy_patchDb);\ + } while(0) +#endif + +#if PHYPATCH_FMAILY_IN_HWP + #define PHYPATCH_IS_RTKSDS(_unit) (HWP_9300_FAMILY_ID(_unit) || HWP_9310_FAMILY_ID(_unit)) +#else + #define PHYPATCH_IS_RTKSDS(_unit) (RTK_9300_FAMILY_ID(_unit) || RTK_9310_FAMILY_ID(_unit) || RTK_9311B_FAMILY_ID(_unit) || RTK_9330_FAMILY_ID(_unit)) +#endif + +#define PHYPATCH_TABLE_ASSIGN(_pPatchDb, _table, _idx, _patch_type, _para) \ + do {\ + if (RTK_PATCH_TYPE_IS_DATA(_patch_type)) {\ + _pPatchDb->_table[_idx].patch_type = _patch_type;\ + _pPatchDb->_table[_idx].patch.data.conf = _para;\ + _pPatchDb->_table[_idx].patch.data.size = sizeof(_para);\ + }\ + else if (RTK_PATCH_TYPE_IS_FLOW(_patch_type)) {\ + _pPatchDb->_table[_idx].patch_type = _patch_type;\ + _pPatchDb->_table[_idx].patch.flow_id = _patch_type;\ + }\ + else {\ + _pPatchDb->_table[_idx].patch_type = PHY_PATCH_TYPE_NONE;\ + }\ + } while(0) +#define PHYPATCH_SEQ_TABLE_ASSIGN(_pPatchDb, _idx, _patch_type, _para) PHYPATCH_TABLE_ASSIGN(_pPatchDb, seq_table, _idx, _patch_type, _para) +#define PHYPATCH_CMP_TABLE_ASSIGN(_pPatchDb, _idx, _patch_type, _para) PHYPATCH_TABLE_ASSIGN(_pPatchDb, cmp_table, _idx, _patch_type, _para) + +#define PHYPATCH_COMPARE(_mmdpage, _reg, _msb, _lsb, _exp, _real, _mask) \ + do {\ + uint32 _rData = REG32_FIELD_GET(_real, _lsb, _mask);\ + if (_exp != _rData) {\ + osal_printf("PATCH CHECK: %u(0x%X).%u(0x%X)[%u:%u] = 0x%X (!= 0x%X)\n", _mmdpage, _mmdpage, _reg, _reg, _msb, _lsb, _rData, _exp);\ + return RT_ERR_CHECK_FAILED;\ + }\ + } while (0) + +/* + * Function Declaration + */ + +extern uint8 phy_patch_op_translate(uint8 patch_mode, uint8 patch_op, uint8 compare_op); +extern int32 phy_patch_op(rt_phy_patch_db_t *pPhy_patchDb, uint32 unit, rtk_port_t port, uint8 portOffset, + uint8 patch_op, uint16 portmask, uint16 pagemmd, uint16 addr, uint8 msb, uint8 lsb, uint16 data, + uint8 patch_mode); + + +/* Function Name: + * phy_patch + * Description: + * apply initial patch data to PHY + * Input: + * unit - unit id + * port - port id + * portOffset - the index offset of port based the base port in the PHY chip + * Output: + * None + * Return: + * RT_ERR_OK + * RT_ERR_FAILED + * RT_ERR_CHECK_FAILED + * RT_ERR_NOT_SUPPORTED + * Note: + * None + */ +extern int32 phy_patch(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode); + + + +#endif /* __HAL_PHY_PATCH_H__ */ diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_rtl826xb_patch.c b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_rtl826xb_patch.c new file mode 100644 index 0000000000..0bfd93033f --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_rtl826xb_patch.c @@ -0,0 +1,1031 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +/* + * Include Files + */ +#if defined(RTK_PHYDRV_IN_LINUX) + #include "phy_rtl826xb_patch.h" + #include "construct/conf_rtl8264b.c" + #include "construct/conf_rtl8261n_c.c" +#else + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #if defined(CONFIG_SDK_RTL826XB) + #include + #include + #include + #endif +#endif +/* + * Symbol Definition + */ +#define PHY_PATCH_WAIT_TIMEOUT 10000000 + +#define PHY_PATCH_LOG LOG_INFO + +/* + * Data Declaration + */ + +/* + * Macro Declaration + */ + +/* + * Function Declaration + */ +static uint16 _phy_rtl826xb_mmd_convert(uint16 page, uint16 addr) +{ + uint16 reg = 0; + if (addr < 16) + { + reg = 0xA400 + (page * 2); + } + else if (addr < 24) + { + reg = (16*page) + ((addr - 16) * 2); + } + else + { + reg = 0xA430 + ((addr - 24) * 2); + } + return reg; +} + +static int32 +_phy_rtl826xb_patch_wait(uint32 unit, rtk_port_t port, uint32 mmdAddr, uint32 mmdReg, uint32 data, uint32 mask, uint8 patch_mode) +{ + int32 ret = 0; + uint32 rData = 0; + uint32 cnt = 0; + WAIT_COMPLETE_VAR() + + rtk_port_t p = 0; + uint8 smiBus = HWP_PORT_SMI(unit, port); + uint32 phyChip = HWP_PHY_MODEL_BY_PORT(unit, port); + uint8 bcast_phyad = HWP_PHY_ADDR(unit, port);; + + + if (patch_mode == PHY_PATCH_MODE_BCAST_BUS) + { + if ((ret = phy_826xb_ctrl_set(unit, port, RTK_PHY_CTRL_MIIM_BCAST, 0)) != RT_ERR_OK) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826XB patch wait disable broadcast failed! 0x%X\n", unit, p, ret); + return ret; + } + + HWP_PORT_TRAVS_EXCEPT_CPU(unit, p) + { + if ((HWP_PORT_SMI(unit, p) == smiBus) && (HWP_PHY_MODEL_BY_PORT(unit, p) == phyChip)) + { + WAIT_COMPLETE(PHY_PATCH_WAIT_TIMEOUT) + { + if ((ret = phy_common_general_reg_mmd_get(unit, p, mmdAddr, mmdReg, &rData)) != RT_ERR_OK) + { + return ret; + } + ++cnt; + + if ((rData & mask) == data) + break; + + //osal_time_udelay(10); + } + + if (WAIT_COMPLETE_IS_TIMEOUT()) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826XB patch wait[%u,0x%X,0x%X,0x%X]:0x%X cnt:%u\n", unit, p, mmdAddr, mmdReg, data, mask, rData, cnt); + return RT_ERR_TIMEOUT; + } + } + } + + osal_time_mdelay(1); + //for port in same SMI bus, set mdio broadcast ENABLE + HWP_PORT_TRAVS_EXCEPT_CPU(unit, p) + { + if ((HWP_PORT_SMI(unit, p) == smiBus) && (HWP_PHY_MODEL_BY_PORT(unit, p) == phyChip)) + { + if ((ret = phy_826xb_ctrl_set(unit, p, RTK_PHY_CTRL_MIIM_BCAST_PHYAD, (uint32)bcast_phyad)) != RT_ERR_OK) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826XB patch wait set broadcast PHYAD failed! 0x%X\n", unit, p, ret); + return ret; + } + + if ((ret = phy_826xb_ctrl_set(unit, p, RTK_PHY_CTRL_MIIM_BCAST, 1)) != RT_ERR_OK) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826XB patch wait enable broadcast failed! 0x%X\n", unit, p, ret); + return ret; + } + } + } + } + else if (patch_mode == PHY_PATCH_MODE_BCAST) + { + if ((ret = phy_826xb_ctrl_set(unit, port, RTK_PHY_CTRL_MIIM_BCAST, 0)) != RT_ERR_OK) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826x patch wait disable broadcast failed! 0x%X\n", unit, p, ret); + return ret; + } + + HWP_PORT_TRAVS_EXCEPT_CPU(unit, p) + { + if (HWP_PHY_BASE_MACID(unit, p) == HWP_PHY_BASE_MACID(unit, port)) + { + WAIT_COMPLETE(PHY_PATCH_WAIT_TIMEOUT) + { + if ((ret = phy_common_general_reg_mmd_get(unit, p, mmdAddr, mmdReg, &rData)) != RT_ERR_OK) + { + return ret; + } + ++cnt; + + if ((rData & mask) == data) + break; + //osal_time_udelay(10); + } + + if (WAIT_COMPLETE_IS_TIMEOUT()) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826x patch wait[%u,0x%X,0x%X,0x%X]:0x%X cnt:%u\n", unit, p, mmdAddr, mmdReg, data, mask, rData, cnt); + return RT_ERR_TIMEOUT; + } + } + } + + osal_time_mdelay(1); + //for port in same PHY, set mdio broadcast ENABLE + HWP_PORT_TRAVS_EXCEPT_CPU(unit, p) + { + if (HWP_PHY_BASE_MACID(unit, p) == HWP_PHY_BASE_MACID(unit, port)) + { + if ((ret = phy_826xb_ctrl_set(unit, p, RTK_PHY_CTRL_MIIM_BCAST_PHYAD, (uint32)bcast_phyad)) != RT_ERR_OK) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826XB patch wait set broadcast PHYAD failed! 0x%X\n", unit, p, ret); + return ret; + } + + if ((ret = phy_826xb_ctrl_set(unit, p, RTK_PHY_CTRL_MIIM_BCAST, 1)) != RT_ERR_OK) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826XB patch wait enable broadcast failed! 0x%X\n", unit, p, ret); + return ret; + } + } + } + } + else + { + WAIT_COMPLETE(PHY_PATCH_WAIT_TIMEOUT) + { + if ((ret = phy_common_general_reg_mmd_get(unit, port, mmdAddr, mmdReg, &rData)) != RT_ERR_OK) + return ret; + + ++cnt; + if ((rData & mask) == data) + break; + + osal_time_mdelay(1); + } + + if (WAIT_COMPLETE_IS_TIMEOUT()) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826XB patch wait[%u,0x%X,0x%X,0x%X]:0x%X cnt:%u\n", unit, port, mmdAddr, mmdReg, data, mask, rData, cnt); + return RT_ERR_TIMEOUT; + } + } + + return RT_ERR_OK; +} + +static int32 +_phy_rtl826xb_patch_wait_not_equal(uint32 unit, rtk_port_t port, uint32 mmdAddr, uint32 mmdReg, uint32 data, uint32 mask, uint8 patch_mode) +{ + int32 ret = 0; + uint32 rData = 0; + uint32 cnt = 0; + WAIT_COMPLETE_VAR() + + rtk_port_t p = 0; + uint8 smiBus = HWP_PORT_SMI(unit, port); + uint32 phyChip = HWP_PHY_MODEL_BY_PORT(unit, port); + uint8 bcast_phyad = HWP_PHY_ADDR(unit, port); + + if (patch_mode == PHY_PATCH_MODE_BCAST_BUS) + { + if ((ret = phy_826xb_ctrl_set(unit, port, RTK_PHY_CTRL_MIIM_BCAST, 0)) != RT_ERR_OK) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826XB patch wait disable broadcast failed! 0x%X\n", unit, p, ret); + return ret; + } + + HWP_PORT_TRAVS_EXCEPT_CPU(unit, p) + { + if ((HWP_PORT_SMI(unit, p) == smiBus) && (HWP_PHY_MODEL_BY_PORT(unit, p) == phyChip)) + { + WAIT_COMPLETE(PHY_PATCH_WAIT_TIMEOUT) + { + if ((ret = phy_common_general_reg_mmd_get(unit, p, mmdAddr, mmdReg, &rData)) != RT_ERR_OK) + { + return ret; + } + ++cnt; + + if ((rData & mask) != data) + break; + + //osal_time_udelay(10); + } + if (WAIT_COMPLETE_IS_TIMEOUT()) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826XB patch wait[%u,0x%X,0x%X,0x%X]:0x%X cnt:%u\n", unit, p, mmdAddr, mmdReg, data, mask, rData, cnt); + return RT_ERR_TIMEOUT; + } + } + } + + osal_time_mdelay(1); + //for port in same SMI bus, set mdio broadcast ENABLE + HWP_PORT_TRAVS_EXCEPT_CPU(unit, p) + { + if ((HWP_PORT_SMI(unit, p) == smiBus) && (HWP_PHY_MODEL_BY_PORT(unit, p) == phyChip)) + { + if ((ret = phy_826xb_ctrl_set(unit, p, RTK_PHY_CTRL_MIIM_BCAST_PHYAD, (uint32)bcast_phyad)) != RT_ERR_OK) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826XB patch wait set broadcast PHYAD failed! 0x%X\n", unit, p, ret); + return ret; + } + + if ((ret = phy_826xb_ctrl_set(unit, p, RTK_PHY_CTRL_MIIM_BCAST, 1)) != RT_ERR_OK) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826XB patch wait enable broadcast failed! 0x%X\n", unit, p, ret); + return ret; + } + } + } + } + else if (patch_mode == PHY_PATCH_MODE_BCAST) + { + if ((ret = phy_826xb_ctrl_set(unit, port, RTK_PHY_CTRL_MIIM_BCAST, 0)) != RT_ERR_OK) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826x patch wait disable broadcast failed! 0x%X\n", unit, p, ret); + return ret; + } + + HWP_PORT_TRAVS_EXCEPT_CPU(unit, p) + { + if (HWP_PHY_BASE_MACID(unit, p) == HWP_PHY_BASE_MACID(unit, port)) + { + WAIT_COMPLETE(PHY_PATCH_WAIT_TIMEOUT) + { + if ((ret = phy_common_general_reg_mmd_get(unit, p, mmdAddr, mmdReg, &rData)) != RT_ERR_OK) + { + return ret; + } + ++cnt; + + if (((rData & mask) != data)) + break; + + //osal_time_udelay(10); + } + + if (WAIT_COMPLETE_IS_TIMEOUT()) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826XB patch wait[%u,0x%X,0x%X,0x%X]:0x%X cnt:%u\n", unit, p, mmdAddr, mmdReg, data, mask, rData, cnt); + return RT_ERR_TIMEOUT; + } + } + } + + osal_time_mdelay(1); + //for port in same PHY, set mdio broadcast ENABLE + HWP_PORT_TRAVS_EXCEPT_CPU(unit, p) + { + if (HWP_PHY_BASE_MACID(unit, p) == HWP_PHY_BASE_MACID(unit, port)) + { + if ((ret = phy_826xb_ctrl_set(unit, p, RTK_PHY_CTRL_MIIM_BCAST_PHYAD, (uint32)bcast_phyad)) != RT_ERR_OK) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826XB patch wait set broadcast PHYAD failed! 0x%X\n", unit, p, ret); + return ret; + } + + if ((ret = phy_826xb_ctrl_set(unit, p, RTK_PHY_CTRL_MIIM_BCAST, 1)) != RT_ERR_OK) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826XB patch wait enable broadcast failed! 0x%X\n", unit, p, ret); + return ret; + } + } + } + } + else + { + WAIT_COMPLETE(PHY_PATCH_WAIT_TIMEOUT) + { + if ((ret = phy_common_general_reg_mmd_get(unit, port, mmdAddr, mmdReg, &rData)) != RT_ERR_OK) + return ret; + + ++cnt; + if ((rData & mask) != data) + break; + + osal_time_mdelay(1); + } + if (WAIT_COMPLETE_IS_TIMEOUT()) + { + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u 826xb patch wait[%u,0x%X,0x%X,0x%X]:0x%X cnt:%u\n", unit, port, mmdAddr, mmdReg, data, mask, rData, cnt); + return RT_ERR_TIMEOUT; + } + + } + + return RT_ERR_OK; +} + +static int32 +_phy_rtl826xb_patch_top_get(uint32 unit, rtk_port_t port, uint32 topPage, uint32 topReg, uint32 *pData) +{ + int32 ret = 0; + uint32 rData = 0; + uint32 topAddr = (topPage * 8) + (topReg - 16); + + if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND1, topAddr, &rData)) != RT_ERR_OK) + return ret; + *pData = rData; + return RT_ERR_OK; +} + +static int32 +_phy_rtl826xb_patch_top_set(uint32 unit, rtk_port_t port, uint32 topPage, uint32 topReg, uint32 wData) +{ + int32 ret = 0; + uint32 topAddr = (topPage * 8) + (topReg - 16); + if ((ret = phy_common_general_reg_mmd_set(unit, port, PHY_MMD_VEND1, topAddr, wData)) != RT_ERR_OK) + return ret; + return RT_ERR_OK; +} + +static int32 +_phy_rtl826xb_patch_sds_get(uint32 unit, rtk_port_t port, uint32 sdsPage, uint32 sdsReg, uint32 *pData) +{ + int32 ret = 0; + uint32 rData = 0; + uint32 sdsAddr = 0x8000 + (sdsReg << 6) + sdsPage; + + if ((ret = _phy_rtl826xb_patch_top_set(unit, port, 40, 19, sdsAddr)) != RT_ERR_OK) + return ret; + if ((ret = _phy_rtl826xb_patch_top_get(unit, port, 40, 18, &rData)) != RT_ERR_OK) + return ret; + *pData = rData; + return _phy_rtl826xb_patch_wait(unit, port, PHY_MMD_VEND1, 0x143, 0, BIT_15, PHY_PATCH_MODE_NORMAL); +} + +static int32 +_phy_rtl826xb_patch_sds_set(uint32 unit, rtk_port_t port, uint32 sdsPage, uint32 sdsReg, uint32 wData, uint8 patch_mode) +{ + int32 ret = 0; + uint32 sdsAddr = 0x8800 + (sdsReg << 6) + sdsPage; + + if ((ret = _phy_rtl826xb_patch_top_set(unit, port, 40, 17, wData)) != RT_ERR_OK) + return ret; + if ((ret = _phy_rtl826xb_patch_top_set(unit, port, 40, 19, sdsAddr)) != RT_ERR_OK) + return ret; + return _phy_rtl826xb_patch_wait(unit, port, PHY_MMD_VEND1, 0x143, 0, BIT_15, patch_mode); +} + +static int32 _phy_rtl826xb_flow_r1(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + rt_phy_patch_db_t *pPatchDb = NULL; + + PHYPATCH_DB_GET(unit, port, pPatchDb); + + //PHYReg_bit w $PHYID 0xb82 16 4 4 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xb82, 16, 4, 4, 0x1, patch_mode), ret); + //PHYReg_bit w $PHYID 0xb82 16 4 4 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xb82, 16, 4, 4, 0x1, patch_mode), ret); + + //set patch_rdy [PHYReg_bit r $PHYID 0xb80 16 6 6] ; Wait for patch ready = 1 + RT_ERR_CHK(_phy_rtl826xb_patch_wait(unit, port, 31, _phy_rtl826xb_mmd_convert(0xb80, 16), BIT_6, BIT_6, patch_mode), ret); + + //PHYReg w $PHYID 0xa43 27 $0x8023 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa43, 27, 15, 0, 0x8023, patch_mode), ret); + //PHYReg w $PHYID 0xa43 28 $0x3802 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa43, 28, 15, 0, 0x3802, patch_mode), ret); + //PHYReg w $PHYID 0xa43 27 0xB82E + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa43, 27, 15, 0, 0xB82E, patch_mode), ret); + //PHYReg w $PHYID 0xa43 28 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa43, 28, 15, 0, 0x1, patch_mode), ret); + + return RT_ERR_OK; +} + +static int32 _phy_rtl826xb_flow_r12(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + rt_phy_patch_db_t *pPatchDb = NULL; + + PHYPATCH_DB_GET(unit, port, pPatchDb); + + //PHYReg_bit w $PHYID 0xb82 16 4 4 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xb82, 16, 4, 4, 0x1, patch_mode), ret); + //PHYReg_bit w $PHYID 0xb82 16 4 4 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xb82, 16, 4, 4, 0x1, patch_mode), ret); + + //set patch_rdy [PHYReg_bit r $PHYID 0xb80 16 6 6] ; Wait for patch ready = 1 + RT_ERR_CHK(_phy_rtl826xb_patch_wait(unit, port, 31, _phy_rtl826xb_mmd_convert(0xb80, 16), BIT_6, BIT_6, patch_mode), ret); + + //PHYReg w $PHYID 0xa43 27 $0x8023 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa43, 27, 15, 0, 0x8023, patch_mode), ret); + //PHYReg w $PHYID 0xa43 28 $0x3800 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa43, 28, 15, 0, 0x3800, patch_mode), ret); + //PHYReg w $PHYID 0xa43 27 0xB82E + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa43, 27, 15, 0, 0xB82E, patch_mode), ret); + //PHYReg w $PHYID 0xa43 28 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa43, 28, 15, 0, 0x1, patch_mode), ret); + + return RT_ERR_OK; +} + + +static int32 _phy_rtl826xb_flow_r2(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + rt_phy_patch_db_t *pPatchDb = NULL; + + PHYPATCH_DB_GET(unit, port, pPatchDb); + + //PHYReg w $PHYID 0xa43 27 0x0000 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa43, 27, 15, 0, 0x0000, patch_mode), ret); + //PHYReg w $PHYID 0xa43 28 0x0000 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa43, 28, 15, 0, 0x0000, patch_mode), ret); + //PHYReg_bit w $PHYID 0xB82 23 0 0 0x0 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xB82, 23, 0, 0, 0x0, patch_mode), ret); + //PHYReg w $PHYID 0xa43 27 $0x8023 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa43, 27, 15, 0, 0x8023, patch_mode), ret); + //PHYReg w $PHYID 0xa43 28 0x0000 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa43, 28, 15, 0, 0x0000, patch_mode), ret); + + //PHYReg_bit w $PHYID 0xb82 16 4 4 0x0 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xb82, 16, 4, 4, 0x0, patch_mode), ret); + //set patch_rdy [PHYReg_bit r $PHYID 0xb80 16 6 6] ; Wait for patch ready != 1 + RT_ERR_CHK( _phy_rtl826xb_patch_wait_not_equal(unit, port, 31, _phy_rtl826xb_mmd_convert(0xb80, 16), BIT_6, BIT_6, patch_mode), ret); + + return RT_ERR_OK; +} + +static int32 _phy_rtl826xb_flow_l1(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + rt_phy_patch_db_t *pPatchDb = NULL; + + PHYPATCH_DB_GET(unit, port, pPatchDb); + + //PHYReg_bit w $PHYID 0xa4a 16 10 10 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa4a, 16, 10, 10, 0x1, patch_mode), ret); + //PHYReg_bit w $PHYID 0xa4a 16 10 10 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa4a, 16, 10, 10, 0x1, patch_mode), ret); + + //set pcs_state [PHYReg_bit r $PHYID 0xa60 16 7 0] ; Wait for pcs state = 1 + RT_ERR_CHK( _phy_rtl826xb_patch_wait(unit, port, 31, _phy_rtl826xb_mmd_convert(0xa60, 16), 0x1, 0xFF, patch_mode), ret); + + return RT_ERR_OK; +} + +static int32 _phy_rtl826xb_flow_l2(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + rt_phy_patch_db_t *pPatchDb = NULL; + + PHYPATCH_DB_GET(unit, port, pPatchDb); + + //PHYReg_bit w $PHYID 0xa4a 16 10 10 0x0 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa4a, 16, 10, 10, 0x0, patch_mode), ret); + + //set pcs_state [PHYReg_bit r $PHYID 0xa60 16 7 0] ; Wait for pcs state != 1 + RT_ERR_CHK( _phy_rtl826xb_patch_wait_not_equal(unit, port, 31, _phy_rtl826xb_mmd_convert(0xa60, 16), 0x1, 0xFF, patch_mode), ret); + + return RT_ERR_OK; +} + +static int32 _phy_rtl826xb_flow_pi(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + rt_phy_patch_db_t *pPatchDb = NULL; + uint32 rData = 0, cnt = 0; + + PHYPATCH_DB_GET(unit, port, pPatchDb); + + _phy_rtl826xb_flow_l1(unit, port, portOffset, patch_mode); + + // PP_PHYReg_bit w $PHYID 0xbf86 9 9 0x1; #SS_EN_XG = 1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbf86, 9, 9, 0x1, patch_mode), ret); + // PP_PHYReg_bit w $PHYID 0xbf86 8 8 0x0; + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbf86, 8, 8, 0x0, patch_mode), ret); + // PP_PHYReg_bit w $PHYID 0xbf86 7 7 0x1; + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbf86, 7, 7, 0x1, patch_mode), ret); + // PP_PHYReg_bit w $PHYID 0xbf86 6 6 0x1; + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbf86, 6, 6, 0x1, patch_mode), ret); + // PP_PHYReg_bit w $PHYID 0xbf86 5 5 0x1; + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbf86, 5, 5, 0x1, patch_mode), ret); + // PP_PHYReg_bit w $PHYID 0xbf86 4 4 0x1; + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbf86, 4, 4, 0x1, patch_mode), ret); + // PP_PHYReg_bit w $PHYID 0xbf86 6 6 0x0; + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbf86, 6, 6, 0x0, patch_mode), ret); + // PP_PHYReg_bit w $PHYID 0xbf86 9 9 0x0; + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbf86, 9, 9, 0x0, patch_mode), ret); + // PP_PHYReg_bit w $PHYID 0xbf86 7 7 0x0; + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbf86, 7, 7, 0x0, patch_mode), ret); + + //PP_PHYReg_bit r $PHYID 0xbc62 12 8 + if ((ret = phy_common_general_reg_mmd_get(unit, port, PHY_MMD_VEND2, 0xbc62, &rData)) != RT_ERR_OK) + return ret; + rData = REG32_FIELD_GET(rData, 8, 0x1F00); + for (cnt = 0; cnt <= rData; cnt++) + { + //PP_PHYReg_bit w $PHYID 0xbc62 12 8 $t + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbc62, 12, 8, cnt, patch_mode), ret); + } + + // PP_PHYReg_bit w $PHYID 0xbc02 2 2 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbc02, 2, 2, 0x1, patch_mode), ret); + // PP_PHYReg_bit w $PHYID 0xbc02 3 3 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbc02, 3, 3, 0x1, patch_mode), ret); + // PP_PHYReg_bit w $PHYID 0xbf86 6 6 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbf86, 6, 6, 0x1, patch_mode), ret); + // PP_PHYReg_bit w $PHYID 0xbf86 9 9 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbf86, 9, 9, 0x1, patch_mode), ret); + // PP_PHYReg_bit w $PHYID 0xbf86 7 7 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbf86, 7, 7, 0x1, patch_mode), ret); + // PP_PHYReg_bit w $PHYID 0xbc04 9 2 0xff + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHYOCP, 0xFF, 31, 0xbc04, 9, 2, 0xff, patch_mode), ret); + + _phy_rtl826xb_flow_l2(unit, port, portOffset, patch_mode); + return RT_ERR_OK; +} + +static int32 _phy_rtl826xb_flow_n01(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + rt_phy_patch_db_t *pPatchDb = NULL; + + PHYPATCH_DB_GET(unit, port, pPatchDb); + + //PHYReg_bit w $PHYID 0xa01 21 15 0 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 21, 15, 0, 0x1, patch_mode), ret); + //PHYReg_bit w $PHYID 0xa01 19 15 0 0x0000 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 19, 15, 0, 0x0000, patch_mode), ret); + //# PHYReg_bit w $PHYID 0xa01 17 15 0 0x0000 + //RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 17, 15, 0, 0x0000, patch_mode), ret); + + return RT_ERR_OK; +} + +static int32 _phy_rtl826xb_flow_n02(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + rt_phy_patch_db_t *pPatchDb = NULL; + + PHYPATCH_DB_GET(unit, port, pPatchDb); + + //PHYReg_bit w $PHYID 0xa01 21 15 0 0x0 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 21, 15, 0, 0x0, patch_mode), ret); + //PHYReg_bit w $PHYID 0xa01 19 15 0 0x0000 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 19, 15, 0, 0x0000, patch_mode), ret); + //PHYReg_bit w $PHYID 0xa01 17 15 0 0x0000 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 17, 15, 0, 0x0000, patch_mode), ret); + return RT_ERR_OK; +} + +static int32 _phy_rtl826xb_flow_n11(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + rt_phy_patch_db_t *pPatchDb = NULL; + + PHYPATCH_DB_GET(unit, port, pPatchDb); + + //PHYReg_bit w $PHYID 0xa01 21 15 0 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 21, 15, 0, 0x1, patch_mode), ret); + //PHYReg_bit w $PHYID 0xa01 19 15 0 0x0010 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 19, 15, 0, 0x0010, patch_mode), ret); + //# PHYReg_bit w $PHYID 0xa01 17 15 0 0x0000 + //RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 17, 15, 0, 0x0000, patch_mode), ret); + + return RT_ERR_OK; +} + +static int32 _phy_rtl826xb_flow_n12(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + rt_phy_patch_db_t *pPatchDb = NULL; + + PHYPATCH_DB_GET(unit, port, pPatchDb); + + //PHYReg_bit w $PHYID 0xa01 21 15 0 0x0 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 21, 15, 0, 0x0, patch_mode), ret); + //PHYReg_bit w $PHYID 0xa01 19 15 0 0x0010 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 19, 15, 0, 0x0010, patch_mode), ret); + //PHYReg_bit w $PHYID 0xa01 17 15 0 0x0000 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 17, 15, 0, 0x0000, patch_mode), ret); + + return RT_ERR_OK; +} + +static int32 _phy_rtl826xb_flow_n21(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + rt_phy_patch_db_t *pPatchDb = NULL; + + PHYPATCH_DB_GET(unit, port, pPatchDb); + + //PHYReg_bit w $PHYID 0xa01 21 15 0 0x1 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 21, 15, 0, 0x1, patch_mode), ret); + //PHYReg_bit w $PHYID 0xa01 19 15 0 0x0020 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 19, 15, 0, 0x0020, patch_mode), ret); + //# PHYReg_bit w $PHYID 0xa01 17 15 0 0x0000 + //RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 17, 15, 0, 0x0000, patch_mode), ret); + + return RT_ERR_OK; +} + +static int32 _phy_rtl826xb_flow_n22(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + rt_phy_patch_db_t *pPatchDb = NULL; + + PHYPATCH_DB_GET(unit, port, pPatchDb); + + //PHYReg_bit w $PHYID 0xa01 21 15 0 0x0 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 21, 15, 0, 0x0, patch_mode), ret); + //PHYReg_bit w $PHYID 0xa01 19 15 0 0x0020 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 19, 15, 0, 0x0020, patch_mode), ret); + //PHYReg_bit w $PHYID 0xa01 17 15 0 0x0000 + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PHY, 0xFF, 0xa01, 17, 15, 0, 0x0000, patch_mode), ret); + + return RT_ERR_OK; +} + +static int32 _phy_rtl826xb_flow_s(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + rt_phy_patch_db_t *pPatchDb = NULL; + + if (PHYPATCH_IS_RTKSDS(unit)) + { + PHYPATCH_DB_GET(unit, port, pPatchDb); + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PSDS0, 0xff, 0x07, 0x10, 15, 0, 0x80aa, patch_mode), ret); + RT_ERR_CHK(phy_patch_op(pPatchDb, unit, port, portOffset, RTK_PATCH_OP_PSDS0, 0xff, 0x06, 0x12, 15, 0, 0x5078, patch_mode), ret); + } + + return RT_ERR_OK; +} + +static int32 phy_rtl826xb_patch_op(uint32 unit, rtk_port_t port, uint8 portOffset, rtk_hwpatch_t *pPatch_data, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + uint32 rData = 0, wData = 0; + uint16 reg = 0; + uint8 patch_op = 0; + uint32 mask = 0; + + if ((pPatch_data->portmask & (1 << portOffset)) == 0) + { + return RT_ERR_ABORT; + } + mask = UINT32_BITS_MASK(pPatch_data->msb, pPatch_data->lsb); + patch_op = phy_patch_op_translate(patch_mode, pPatch_data->patch_op, pPatch_data->compare_op); + + #if 0 + osal_printf("[%s,%d]u%up%u, patch_mode:%u/patch_op:%u/compare_op:%u => op: %u\n", __FUNCTION__, __LINE__, unit, port, + patch_mode, pPatch_data->patch_op, pPatch_data->compare_op, + patch_op); + #endif + + switch (patch_op) + { + case RTK_PATCH_OP_PHY: + reg = _phy_rtl826xb_mmd_convert(pPatch_data->pagemmd, pPatch_data->addr); + if ((pPatch_data->msb != 15) || (pPatch_data->lsb != 0)) + { + RT_ERR_CHK(phy_common_general_reg_mmd_get(unit, port, 31, reg, &rData), ret); + } + wData = REG32_FIELD_SET(rData, pPatch_data->data, pPatch_data->lsb, mask); + RT_ERR_CHK(phy_common_general_reg_mmd_set(unit, port, 31, reg, wData), ret); + break; + case RTK_PATCH_OP_CMP_PHY: + reg = _phy_rtl826xb_mmd_convert(pPatch_data->pagemmd, pPatch_data->addr); + RT_ERR_CHK(phy_common_general_reg_mmd_get(unit, port, 31, reg, &rData), ret); + PHYPATCH_COMPARE(pPatch_data->pagemmd, pPatch_data->addr, pPatch_data->msb, pPatch_data->lsb, pPatch_data->data, rData, mask); + break; + case RTK_PATCH_OP_CMP_SRAM_PHY: + reg = _phy_rtl826xb_mmd_convert(pPatch_data->sram_p, pPatch_data->sram_rw); + RT_ERR_CHK(phy_common_general_reg_mmd_set(unit, port, 31, reg, pPatch_data->sram_a), ret); + reg = _phy_rtl826xb_mmd_convert(pPatch_data->sram_p, pPatch_data->sram_rr); + RT_ERR_CHK(phy_common_general_reg_mmd_get(unit, port, 31, reg, &rData), ret); + PHYPATCH_COMPARE(pPatch_data->pagemmd, pPatch_data->addr, pPatch_data->msb, pPatch_data->lsb, pPatch_data->data, rData, mask); + break; + + case RTK_PATCH_OP_PHYOCP: + if ((pPatch_data->msb != 15) || (pPatch_data->lsb != 0)) + { + RT_ERR_CHK(phy_common_general_reg_mmd_get(unit, port, 31, pPatch_data->addr, &rData), ret); + } + wData = REG32_FIELD_SET(rData, pPatch_data->data, pPatch_data->lsb, mask); + RT_ERR_CHK(phy_common_general_reg_mmd_set(unit, port, 31, pPatch_data->addr, wData), ret); + break; + case RTK_PATCH_OP_CMP_PHYOCP: + RT_ERR_CHK(phy_common_general_reg_mmd_get(unit, port, 31, pPatch_data->addr, &rData), ret); + PHYPATCH_COMPARE(pPatch_data->pagemmd, pPatch_data->addr, pPatch_data->msb, pPatch_data->lsb, pPatch_data->data, rData, mask); + break; + case RTK_PATCH_OP_CMP_SRAM_PHYOCP: + RT_ERR_CHK(phy_common_general_reg_mmd_set(unit, port, 31, pPatch_data->sram_rw, pPatch_data->sram_a), ret); + RT_ERR_CHK(phy_common_general_reg_mmd_get(unit, port, 31, pPatch_data->sram_rr, &rData), ret); + PHYPATCH_COMPARE(pPatch_data->pagemmd, pPatch_data->addr, pPatch_data->msb, pPatch_data->lsb, pPatch_data->data, rData, mask); + break; + + case RTK_PATCH_OP_TOP: + if ((pPatch_data->msb != 15) || (pPatch_data->lsb != 0)) + { + RT_ERR_CHK(_phy_rtl826xb_patch_top_get(unit, port, pPatch_data->pagemmd, pPatch_data->addr, &rData), ret); + } + wData = REG32_FIELD_SET(rData, pPatch_data->data, pPatch_data->lsb, mask); + RT_ERR_CHK(_phy_rtl826xb_patch_top_set(unit, port, pPatch_data->pagemmd, pPatch_data->addr, wData), ret); + break; + case RTK_PATCH_OP_CMP_TOP: + RT_ERR_CHK(_phy_rtl826xb_patch_top_get(unit, port, pPatch_data->pagemmd, pPatch_data->addr, &rData), ret); + PHYPATCH_COMPARE(pPatch_data->pagemmd, pPatch_data->addr, pPatch_data->msb, pPatch_data->lsb, pPatch_data->data, rData, mask); + break; + case RTK_PATCH_OP_CMP_SRAM_TOP: + RT_ERR_CHK(_phy_rtl826xb_patch_top_set(unit, port, pPatch_data->sram_p, pPatch_data->sram_rw, pPatch_data->sram_a), ret); + RT_ERR_CHK(_phy_rtl826xb_patch_top_get(unit, port, pPatch_data->sram_p, pPatch_data->sram_rr, &rData), ret); + PHYPATCH_COMPARE(pPatch_data->pagemmd, pPatch_data->addr, pPatch_data->msb, pPatch_data->lsb, pPatch_data->data, rData, mask); + break; + + case RTK_PATCH_OP_PSDS0: + if ((pPatch_data->msb != 15) || (pPatch_data->lsb != 0)) + { + RT_ERR_CHK(_phy_rtl826xb_patch_sds_get(unit, port, pPatch_data->pagemmd, pPatch_data->addr, &rData), ret); + } + wData = REG32_FIELD_SET(rData, pPatch_data->data, pPatch_data->lsb, mask); + RT_ERR_CHK(_phy_rtl826xb_patch_sds_set(unit, port, pPatch_data->pagemmd, pPatch_data->addr, wData, patch_mode), ret); + break; + case RTK_PATCH_OP_CMP_PSDS0: + RT_ERR_CHK(_phy_rtl826xb_patch_sds_get(unit, port, pPatch_data->pagemmd, pPatch_data->addr, &rData), ret); + PHYPATCH_COMPARE(pPatch_data->pagemmd, pPatch_data->addr, pPatch_data->msb, pPatch_data->lsb, pPatch_data->data, rData, mask); + break; + case RTK_PATCH_OP_CMP_SRAM_PSDS0: + RT_ERR_CHK(_phy_rtl826xb_patch_sds_set(unit, port, pPatch_data->sram_p, pPatch_data->sram_rw, pPatch_data->sram_a, patch_mode), ret); + RT_ERR_CHK(_phy_rtl826xb_patch_sds_get(unit, port, pPatch_data->sram_p, pPatch_data->sram_rr, &rData), ret); + PHYPATCH_COMPARE(pPatch_data->pagemmd, pPatch_data->addr, pPatch_data->msb, pPatch_data->lsb, pPatch_data->data, rData, mask); + break; + + case RTK_PATCH_OP_SKIP: + return RT_ERR_ABORT; + + default: + RT_LOG(LOG_MAJOR_ERR, (MOD_HAL | MOD_PHY), "U%u P%u patch_op:%u not implemented yet!\n", unit, port, pPatch_data->patch_op); + return RT_ERR_DRIVER_NOT_SUPPORTED; + } + + return ret; +} + +static int32 phy_rtl826xb_patch_flow(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_flow, uint8 patch_mode) +{ + int32 ret = RT_ERR_OK; + + RT_LOG(LOG_INFO, (MOD_HAL | MOD_PHY), "[%s]U%u,P%u,flow%u\n", __FUNCTION__, unit, port, (patch_flow - PHY_PATCH_TYPE_END)); + switch (patch_flow) + { + case RTK_PATCH_TYPE_FLOW(0): + RT_ERR_CHK(_phy_rtl826xb_flow_r1(unit, port, portOffset, patch_mode), ret); + break; + case RTK_PATCH_TYPE_FLOW(1): + RT_ERR_CHK(_phy_rtl826xb_flow_r2(unit, port, portOffset, patch_mode), ret); + break; + + case RTK_PATCH_TYPE_FLOW(2): + RT_ERR_CHK(_phy_rtl826xb_flow_l1(unit, port, portOffset, patch_mode), ret); + break; + case RTK_PATCH_TYPE_FLOW(3): + RT_ERR_CHK(_phy_rtl826xb_flow_l2(unit, port, portOffset, patch_mode), ret); + break; + + case RTK_PATCH_TYPE_FLOW(4): + RT_ERR_CHK(_phy_rtl826xb_flow_n01(unit, port, portOffset, patch_mode), ret); + break; + case RTK_PATCH_TYPE_FLOW(5): + RT_ERR_CHK(_phy_rtl826xb_flow_n02(unit, port, portOffset, patch_mode), ret); + break; + + case RTK_PATCH_TYPE_FLOW(6): + RT_ERR_CHK(_phy_rtl826xb_flow_n11(unit, port, portOffset, patch_mode), ret); + break; + case RTK_PATCH_TYPE_FLOW(7): + RT_ERR_CHK(_phy_rtl826xb_flow_n12(unit, port, portOffset, patch_mode), ret); + break; + + case RTK_PATCH_TYPE_FLOW(8): + RT_ERR_CHK(_phy_rtl826xb_flow_n21(unit, port, portOffset, patch_mode), ret); + break; + case RTK_PATCH_TYPE_FLOW(9): + RT_ERR_CHK(_phy_rtl826xb_flow_n22(unit, port, portOffset, patch_mode), ret); + break; + + case RTK_PATCH_TYPE_FLOW(10): + RT_ERR_CHK(_phy_rtl826xb_flow_s(unit, port, portOffset, patch_mode), ret); + break; + + case RTK_PATCH_TYPE_FLOW(11): + RT_ERR_CHK(_phy_rtl826xb_flow_pi(unit, port, portOffset, patch_mode), ret); + break; + case RTK_PATCH_TYPE_FLOW(12): + RT_ERR_CHK(_phy_rtl826xb_flow_r12(unit, port, portOffset, patch_mode), ret); + break; + + default: + return RT_ERR_INPUT; + } + return RT_ERR_OK; +} + +int32 phy_rtl826xb_patch_db_init(uint32 unit, rtk_port_t port, rt_phy_patch_db_t **pPhy_patchDb) +{ + int32 ret = RT_ERR_OK; + rt_phy_patch_db_t *patch_db = NULL; + uint32 rData = 0; + + patch_db = osal_alloc(sizeof(rt_phy_patch_db_t)); + RT_PARAM_CHK(NULL == patch_db, RT_ERR_MEM_ALLOC); + osal_memset(patch_db, 0x0, sizeof(rt_phy_patch_db_t)); + + /* patch callback */ + patch_db->fPatch_op = phy_rtl826xb_patch_op; + patch_db->fPatch_flow = phy_rtl826xb_patch_flow; + + /* patch table */ + RT_ERR_CHK(phy_common_general_reg_mmd_get(unit, port, 30, 0x104, &rData), ret); + if ((rData & 0x7) == 0x0) + { + /* patch */ + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 0, RTK_PATCH_TYPE_FLOW(12), NULL); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 1, PHY_PATCH_TYPE_NCTL0, rtl8264b_nctl0_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 2, PHY_PATCH_TYPE_NCTL1, rtl8264b_nctl1_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 3, PHY_PATCH_TYPE_NCTL2, rtl8264b_nctl2_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 4, PHY_PATCH_TYPE_UC2, rtl8264b_uc2_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 5, PHY_PATCH_TYPE_UC, rtl8264b_uc_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 6, PHY_PATCH_TYPE_DATARAM, rtl8264b_dataram_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 7, RTK_PATCH_TYPE_FLOW(1), NULL); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 8, RTK_PATCH_TYPE_FLOW(2), NULL); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 9, PHY_PATCH_TYPE_ALGXG, rtl8264b_algxg_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 10, PHY_PATCH_TYPE_ALG1G, rtl8264b_alg_giga_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 11, PHY_PATCH_TYPE_NORMAL, rtl8264b_normal_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 12, PHY_PATCH_TYPE_TOP, rtl8264b_top_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 13, PHY_PATCH_TYPE_SDS, rtl8264b_sds_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 14, PHY_PATCH_TYPE_AFE, rtl8264b_afe_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 15, PHY_PATCH_TYPE_RTCT, rtl8264b_rtct_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 16, RTK_PATCH_TYPE_FLOW(3), NULL); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 17, RTK_PATCH_TYPE_FLOW(11), NULL); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 18, RTK_PATCH_TYPE_FLOW(10), NULL); + + /* compare */ + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 0, PHY_PATCH_TYPE_TOP, rtl8264b_top_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 1, PHY_PATCH_TYPE_SDS, rtl8264b_sds_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 2, PHY_PATCH_TYPE_AFE, rtl8264b_afe_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 3, RTK_PATCH_TYPE_FLOW(4), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 4, PHY_PATCH_TYPE_NCTL0, rtl8264b_nctl0_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 5, RTK_PATCH_TYPE_FLOW(5), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 6, RTK_PATCH_TYPE_FLOW(6), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 7, PHY_PATCH_TYPE_NCTL1, rtl8264b_nctl1_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 8, RTK_PATCH_TYPE_FLOW(7), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 9, RTK_PATCH_TYPE_FLOW(8), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 10, PHY_PATCH_TYPE_NCTL2, rtl8264b_nctl2_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 11, RTK_PATCH_TYPE_FLOW(9), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 12, PHY_PATCH_TYPE_UC, rtl8264b_uc_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 13, PHY_PATCH_TYPE_UC2, rtl8264b_uc2_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 14, RTK_PATCH_TYPE_FLOW(12), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 15, PHY_PATCH_TYPE_DATARAM, rtl8264b_dataram_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 16, RTK_PATCH_TYPE_FLOW(1), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 17, PHY_PATCH_TYPE_ALGXG, rtl8264b_algxg_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 18, PHY_PATCH_TYPE_ALG1G, rtl8264b_alg_giga_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 19, PHY_PATCH_TYPE_NORMAL, rtl8264b_normal_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 20, PHY_PATCH_TYPE_RTCT, rtl8264b_rtct_conf); + } + else + { + /* patch */ + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 0, RTK_PATCH_TYPE_FLOW(0), NULL); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 1, PHY_PATCH_TYPE_NCTL0, rtl8261n_c_nctl0_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 2, PHY_PATCH_TYPE_NCTL1, rtl8261n_c_nctl1_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 3, PHY_PATCH_TYPE_NCTL2, rtl8261n_c_nctl2_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 4, PHY_PATCH_TYPE_UC2, rtl8261n_c_uc2_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 5, PHY_PATCH_TYPE_UC, rtl8261n_c_uc_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 6, PHY_PATCH_TYPE_DATARAM, rtl8261n_c_dataram_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 7, RTK_PATCH_TYPE_FLOW(1), NULL); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 8, RTK_PATCH_TYPE_FLOW(2), NULL); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 9, PHY_PATCH_TYPE_ALGXG, rtl8261n_c_algxg_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 10, PHY_PATCH_TYPE_ALG1G, rtl8261n_c_alg_giga_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 11, PHY_PATCH_TYPE_NORMAL, rtl8261n_c_normal_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 12, PHY_PATCH_TYPE_TOP, rtl8261n_c_top_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 13, PHY_PATCH_TYPE_SDS, rtl8261n_c_sds_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 14, PHY_PATCH_TYPE_AFE, rtl8261n_c_afe_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 15, PHY_PATCH_TYPE_RTCT, rtl8261n_c_rtct_conf); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 16, RTK_PATCH_TYPE_FLOW(3), NULL); + PHYPATCH_SEQ_TABLE_ASSIGN(patch_db, 17, RTK_PATCH_TYPE_FLOW(10), NULL); + + /* compare */ + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 0, PHY_PATCH_TYPE_TOP, rtl8261n_c_top_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 1, PHY_PATCH_TYPE_SDS, rtl8261n_c_sds_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 2, PHY_PATCH_TYPE_AFE, rtl8261n_c_afe_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 3, RTK_PATCH_TYPE_FLOW(4), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 4, PHY_PATCH_TYPE_NCTL0, rtl8261n_c_nctl0_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 5, RTK_PATCH_TYPE_FLOW(5), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 6, RTK_PATCH_TYPE_FLOW(6), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 7, PHY_PATCH_TYPE_NCTL1, rtl8261n_c_nctl1_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 8, RTK_PATCH_TYPE_FLOW(7), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 9, RTK_PATCH_TYPE_FLOW(8), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 10, PHY_PATCH_TYPE_NCTL2, rtl8261n_c_nctl2_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 11, RTK_PATCH_TYPE_FLOW(9), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 12, PHY_PATCH_TYPE_UC, rtl8261n_c_uc_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 13, PHY_PATCH_TYPE_UC2, rtl8261n_c_uc2_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 14, RTK_PATCH_TYPE_FLOW(0), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 15, PHY_PATCH_TYPE_DATARAM, rtl8261n_c_dataram_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 16, RTK_PATCH_TYPE_FLOW(1), NULL); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 17, PHY_PATCH_TYPE_ALGXG, rtl8261n_c_algxg_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 18, PHY_PATCH_TYPE_ALG1G, rtl8261n_c_alg_giga_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 19, PHY_PATCH_TYPE_NORMAL, rtl8261n_c_normal_conf); + PHYPATCH_CMP_TABLE_ASSIGN(patch_db, 20, PHY_PATCH_TYPE_RTCT, rtl8261n_c_rtct_conf); + } + *pPhy_patchDb = patch_db; + return ret; +} + +/* Function Name: + * phy_rtl826xb_patch + * Description: + * apply initial patch data to PHY + * Input: + * unit - unit id + * baseport - base port id on the PHY chip + * portOffset - the index offset base on baseport for the port to patch + * Output: + * None + * Return: + * RT_ERR_OK + * RT_ERR_FAILED + * RT_ERR_NOT_SUPPORTED + * RT_ERR_ABORT + * Note: + * None + */ +int32 phy_rtl826xb_patch(uint32 unit, rtk_port_t port, uint8 portOffset) +{ + return phy_patch( unit, port, portOffset, PHY_PATCH_MODE_NORMAL); +} + +/* Function Name: + * phy_rtl826xb_broadcast_patch + * Description: + * apply patch data to PHY + * Input: + * unit - unit id + * baseport - base port id on the PHY chip + * portOffset - the index offset base on baseport for the port to patch + * perChip - 1 for per-chip mode, 0 for per-bus mode + * Output: + * None + * Return: + * RT_ERR_OK + * RT_ERR_FAILED + * RT_ERR_NOT_SUPPORTED + * RT_ERR_ABORT + * Note: + * None + */ +int32 phy_rtl826xb_broadcast_patch(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 perChip) +{ + int32 ret = 0; + if (perChip == 0) + { + ret = phy_patch(unit, port, portOffset, PHY_PATCH_MODE_BCAST_BUS); + } + else + { + ret = phy_patch(unit, port, portOffset, PHY_PATCH_MODE_BCAST); + } + return ret; +} + diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_rtl826xb_patch.h b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_rtl826xb_patch.h new file mode 100644 index 0000000000..c2311ef2bf --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/phy_rtl826xb_patch.h @@ -0,0 +1,63 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +#ifndef __HAL_PHY_PHY_RTL826XB_PATCH_H__ +#define __HAL_PHY_PHY_RTL826XB_PATCH_H__ + +/* + * Include Files + */ +#if defined(RTK_PHYDRV_IN_LINUX) + #include "rtk_osal.h" + #include "rtk_phylib_def.h" +#else + #include + #include +#endif + +/* Function Name: + * phy_rtl826xb_patch + * Description: + * apply patch data to PHY + * Input: + * unit - unit id + * baseport - base port id on the PHY chip + * portOffset - the index offset base on baseport for the port to patch + * Output: + * None + * Return: + * RT_ERR_OK + * RT_ERR_FAILED + * RT_ERR_NOT_SUPPORTED + * RT_ERR_ABORT + * Note: + * None + */ +extern int32 phy_rtl826xb_patch(uint32 unit, rtk_port_t baseport, uint8 portOffset); + +/* Function Name: + * phy_rtl826xb_broadcast_patch + * Description: + * apply patch data to PHY + * Input: + * unit - unit id + * baseport - base port id on the PHY chip + * portOffset - the index offset base on baseport for the port to patch + * perChip - 1 for per-chip mode, 0 for per-bus mode + * Output: + * None + * Return: + * RT_ERR_OK + * RT_ERR_FAILED + * RT_ERR_NOT_SUPPORTED + * RT_ERR_ABORT + * Note: + * None + */ +extern int32 phy_rtl826xb_broadcast_patch(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 perChip); + +extern int32 phy_rtl826xb_patch_db_init(uint32 unit, rtk_port_t port, rt_phy_patch_db_t **pPhy_patchDb); +#endif /* __HAL_PHY_PHY_RTL826XB_PATCH_H__ */ diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_osal.c b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_osal.c new file mode 100644 index 0000000000..35339400d0 --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_osal.c @@ -0,0 +1,57 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +#include "type.h" +#include "error.h" +#include "rtk_phylib_def.h" +#include "rtk_osal.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +int32 +osal_time_usecs_get(osal_usecs_t *pUsec) +{ + struct timespec64 ts; + + RT_PARAM_CHK((NULL == pUsec), RT_ERR_NULL_POINTER); + + ktime_get_ts64(&ts); + *pUsec = (osal_usecs_t)((ts.tv_sec * USEC_PER_SEC) + (ts.tv_nsec / NSEC_PER_USEC)); + return RT_ERR_OK; +} + +void * +osal_alloc(uint32 size) +{ + void *p; + p = kmalloc((size_t)size, GFP_ATOMIC); + return p; +} + +int32 +phy_common_general_reg_mmd_get(uint32 unit, rtk_port_t port, uint32 mmdAddr, uint32 mmdReg, uint32 *pData) +{ + int32 rData = 0; + rData = phy_read_mmd(port, mmdAddr, mmdReg); + if (rData < 0) + return RT_ERR_FAILED; + *pData = (uint32)rData; + return RT_ERR_OK; +} + +int32 +phy_common_general_reg_mmd_set(uint32 unit, rtk_port_t port, uint32 mmdAddr, uint32 mmdReg, uint32 data) +{ + int ret = phy_write_mmd(port, mmdAddr, mmdReg, data); + return (ret < 0) ? RT_ERR_FAILED : RT_ERR_OK; +} diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_osal.h b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_osal.h new file mode 100644 index 0000000000..edf674611e --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_osal.h @@ -0,0 +1,99 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +#ifndef __RTK_PHY_OSAL_H +#define __RTK_PHY_OSAL_H + +#include +#include +#include "type.h" +#include "error.h" +#include "phy_patch.h" +#include "rtk_phylib.h" + +#ifdef PHYPATCH_DB_GET + #undef PHYPATCH_DB_GET +#endif + +#define PHYPATCH_DB_GET(_unit, _pPhy_device, _pPatchDb) \ + do { \ + struct rtk_phy_priv *_pPriv = (_pPhy_device)->priv; \ + rt_phy_patch_db_t *_pDb = _pPriv->patch; _pPatchDb = _pDb; \ + /*printk("[PHYPATCH_DB_GET] ? [%s]\n", (_pDb != NULL) ? "E":"N");*/ \ + } while(0) + +#define HWP_9300_FAMILY_ID(_unit) 0 +#define HWP_9310_FAMILY_ID(_unit) 0 +#define RTK_9300_FAMILY_ID(_unit) 0 +#define RTK_9310_FAMILY_ID(_unit) 0 +#define RTK_9311B_FAMILY_ID(_unit) 0 +#define RTK_9330_FAMILY_ID(_unit) 0 + +#ifndef WAIT_COMPLETE_VAR +#define WAIT_COMPLETE_VAR() \ + osal_usecs_t _t, _now, _t_wait=0, _timeout; \ + int32 _chkCnt=0; + +#define WAIT_COMPLETE(_timeout_us) \ + _timeout = _timeout_us; \ + for(osal_time_usecs_get(&_t),osal_time_usecs_get(&_now),_t_wait=0,_chkCnt=0 ; \ + (_t_wait <= _timeout); \ + osal_time_usecs_get(&_now), _chkCnt++, _t_wait += ((_now >= _t) ? (_now - _t) : (0xFFFFFFFF - _t + _now)),_t = _now \ + ) + +#define WAIT_COMPLETE_IS_TIMEOUT() (_t_wait > _timeout) +#endif + +/* OSAL */ +#include +int32 osal_time_usecs_get(osal_usecs_t *pUsec); +void *osal_alloc(uint32 size); +#define osal_time_mdelay mdelay + +#include /* for Kernel Space */ +#include +#include +#define osal_strlen strlen +#define osal_strcmp strcmp +#define osal_strcpy strcpy +#define osal_strncpy strncpy +#define osal_strcat strcat +#define osal_strchr strchr +#define osal_memset memset +#define osal_memcpy memcpy +#define osal_memcmp memcmp +#define osal_strdup strdup +#define osal_strncmp strncmp +#define osal_strstr strstr +#define osal_strtok strtok +#define osal_strtok_r strtok_r +#define osal_toupper toupper + +#define osal_printf printk + +/* HWP */ +#define HWP_PORT_SMI(unit, port) 0 +#define HWP_PHY_MODEL_BY_PORT(unit, port) 0 +#define HWP_PHY_ADDR(unit, port) 0 +#define HWP_PHY_BASE_MACID(unit, p) 0 +#define HWP_PORT_TRAVS_EXCEPT_CPU(unit, p) if (bcast_phyad < 0x1F && p != NULL) + + +/* RT_LOG */ +//#define RT_LOG(level, module, fmt, args...) do { printk("RT_LOG:"fmt, ## args); } while(0) +#define RT_LOG(level, module, fmt, args...) do {} while(0) +#define RT_ERR(error_code, module, fmt, args...) do {} while(0) +#define RT_INIT_ERR(error_code, module, fmt, args...) do {} while(0) +#define RT_INIT_MSG(fmt, args...) do {} while(0) + +#define phy_826xb_ctrl_set(unit, p, RTK_PHY_CTRL_MIIM_BCAST_PHYAD, bcast_phyad) 0 + +/* reg access */ +int32 phy_common_general_reg_mmd_get(uint32 unit, rtk_port_t port, uint32 mmdAddr, uint32 mmdReg, uint32 *pData); +int32 phy_common_general_reg_mmd_set(uint32 unit, rtk_port_t port, uint32 mmdAddr, uint32 mmdReg, uint32 data); + + +#endif /* __RTK_PHY_OSAL_H */ diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phy.c b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phy.c new file mode 100644 index 0000000000..a1eb2c1614 --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phy.c @@ -0,0 +1,324 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +#include +#include +#include + +#include "phy_rtl826xb_patch.h" +#include "rtk_phylib_rtl826xb.h" +#include "rtk_phylib.h" + +#define REALTEK_PHY_ID_RTL8261N 0x001CCAF3 +#define REALTEK_PHY_ID_RTL8264B 0x001CC813 +#define REALTEK_PHY_ID_RTL8264 0x001CCAF2 + +#define REALTEK_SERDES_GLOBAL_CFG 0xC1 +#define REALTEK_HSO_INV BIT(7) +#define REALTEK_HSI_INV BIT(6) + +static int rtl826xb_get_features(struct phy_device *phydev) +{ + int ret; + ret = genphy_c45_pma_read_abilities(phydev); + if (ret) + return ret; + + linkmode_or(phydev->supported, phydev->supported, PHY_BASIC_FEATURES); + + + linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, + phydev->supported); + + /* not support 10M modes */ + linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, + phydev->supported); + linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, + phydev->supported); + + return 0; +} + +static int rtl826xb_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct rtk_phy_priv *priv = NULL; + + priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct rtk_phy_priv), GFP_KERNEL); + if (!priv) + { + return -ENOMEM; + } + memset(priv, 0, sizeof(struct rtk_phy_priv)); + + if (phy_rtl826xb_patch_db_init(0, phydev, &(priv->patch)) != RT_ERR_OK) + return -ENOMEM; + + priv->phytype = (phydev->drv->phy_id == REALTEK_PHY_ID_RTL8261N) ? (RTK_PHYLIB_RTL8261N) : (RTK_PHYLIB_RTL8264B); + priv->isBasePort = (phydev->drv->phy_id == REALTEK_PHY_ID_RTL8261N) ? (1) : (((phydev->mdio.addr % 4) == 0) ? (1) : (0)); + priv->pnswap_rx = device_property_read_bool(dev, "realtek,pnswap-rx"); + priv->pnswap_tx = device_property_read_bool(dev, "realtek,pnswap-tx"); + phydev->priv = priv; + + return 0; +} + +static int rtkphy_config_init(struct phy_device *phydev) +{ + struct rtk_phy_priv *priv = phydev->priv; + int ret = 0; + switch (phydev->drv->phy_id) + { + case REALTEK_PHY_ID_RTL8261N: + case REALTEK_PHY_ID_RTL8264B: + case REALTEK_PHY_ID_RTL8264: + phydev_info(phydev, "%s:%u [RTL8261N/RTL8264/RTL826XB] phy_id: 0x%X PHYAD:%d\n", __FUNCTION__, __LINE__, phydev->drv->phy_id, phydev->mdio.addr); +#ifdef CONFIG_MACH_REALTEK_RTL + return 0; +#endif + + #if 1 /* toggle reset */ + phy_modify_mmd_changed(phydev, 30, 0x145, BIT(0) , 1); + phy_modify_mmd_changed(phydev, 30, 0x145, BIT(0) , 0); + mdelay(30); + #endif + + ret = phy_patch(0, phydev, 0, PHY_PATCH_MODE_NORMAL); + if (ret) + { + phydev_err(phydev, "%s:%u [RTL8261N/RTL826XB] patch failed!! 0x%X\n", __FUNCTION__, __LINE__, ret); + return ret; + } + #if 0 /* Debug: patch check */ + ret = phy_patch(0, phydev, 0, PHY_PATCH_MODE_CMP); + if (ret) + { + phydev_err(phydev, "%s:%u [RTL8261N/RTL826XB] phy_patch failed!! 0x%X\n", __FUNCTION__, __LINE__, ret); + return ret; + } + printk("[%s,%u] patch chk %s\n", __FUNCTION__, __LINE__, (ret == 0) ? "PASS" : "FAIL"); + #endif + #if 0 /* Debug: USXGMII*/ + { + uint32 data = 0; + rtk_phylib_826xb_sds_read(phydev, 0x07, 0x10, 15, 0, &data); + printk("[%s,%u] SDS 0x07, 0x10 : 0x%X\n", __FUNCTION__, __LINE__, data); + rtk_phylib_826xb_sds_read(phydev, 0x06, 0x12, 15, 0, &data); + printk("[%s,%u] SDS 0x06, 0x12 : 0x%X\n", __FUNCTION__, __LINE__, data); + } + { + u16 sdspage = 0x5, sdsreg = 0x0; + u16 regData = (sdspage & 0x3f) | ((sdsreg & 0x1f) << 6) | BIT(15); + u16 readData = 0; + phy_write_mmd(phydev, 30, 323, regData); + do + { + udelay(10); + readData = phy_read_mmd(phydev, 30, 323); + } while ((readData & BIT(15)) != 0); + readData = phy_read_mmd(phydev, 30, 322); + printk("[%s,%d] sds link [%s] (0x%X)\n", __FUNCTION__, __LINE__, (readData & BIT(12)) ? "UP" : "DOWN", readData); + } + #endif + + if (priv->pnswap_rx) + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + REALTEK_SERDES_GLOBAL_CFG, + REALTEK_HSI_INV); + + if (priv->pnswap_tx) + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + REALTEK_SERDES_GLOBAL_CFG, + REALTEK_HSO_INV); + + break; + default: + phydev_err(phydev, "%s:%u Unknow phy_id: 0x%X\n", __FUNCTION__, __LINE__, phydev->drv->phy_id); + return -EPERM; + } + + return ret; +} + +static int rtkphy_c45_suspend(struct phy_device *phydev) +{ + int ret = 0; + +#ifndef CONFIG_MACH_REALTEK_RTL + ret = rtk_phylib_c45_power_low(phydev); +#endif + + phydev->speed = SPEED_UNKNOWN; + phydev->duplex = DUPLEX_UNKNOWN; + phydev->pause = 0; + phydev->asym_pause = 0; + + return ret; +} + +static int rtkphy_c45_resume(struct phy_device *phydev) +{ +#ifndef CONFIG_MACH_REALTEK_RTL + return rtk_phylib_c45_power_normal(phydev); +#else + return 0; +#endif +} + +static int rtkphy_c45_config_aneg(struct phy_device *phydev) +{ + bool changed = false; + u16 reg = 0; + int ret = 0; + + phydev->mdix_ctrl = ETH_TP_MDI_AUTO; + 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; + + reg = 0; + if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + phydev->advertising)) + reg |= BIT(9); + + if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, + phydev->advertising)) + reg |= BIT(8); + + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, 0xA412, + BIT(9) | BIT(8) , reg); + if (ret < 0) + return ret; + if (ret > 0) + changed = true; + + return genphy_c45_check_and_restart_aneg(phydev, changed); +} + +static int rtkphy_c45_aneg_done(struct phy_device *phydev) +{ + return genphy_c45_aneg_done(phydev); +} + +static int rtkphy_c45_read_status(struct phy_device *phydev) +{ + int ret = 0, status = 0; + phydev->speed = SPEED_UNKNOWN; + phydev->duplex = DUPLEX_UNKNOWN; + phydev->pause = 0; + phydev->asym_pause = 0; + + ret = genphy_c45_read_link(phydev); + if (ret) + return ret; + + if (phydev->autoneg == AUTONEG_ENABLE) + { + linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + phydev->lp_advertising); + + ret = genphy_c45_read_lpa(phydev); + if (ret) + return ret; + + status = phy_read_mmd(phydev, 31, 0xA414); + if (status < 0) + return status; + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + phydev->lp_advertising, status & BIT(11)); + + phy_resolve_aneg_linkmode(phydev); + } + else + { + ret = genphy_c45_read_pma(phydev); + } + + /* mdix*/ + status = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_SWAPPOL); + if (status < 0) + return status; + + switch (status & 0x3) + { + case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX: + phydev->mdix = ETH_TP_MDI; + break; + + case 0: + phydev->mdix = ETH_TP_MDI_X; + break; + + default: + phydev->mdix = ETH_TP_MDI_INVALID; + break; + } + + return ret; +} + + +static struct phy_driver rtk_phy_drivers[] = { + { + PHY_ID_MATCH_EXACT(REALTEK_PHY_ID_RTL8261N), + .name = "Realtek RTL8261N", + .get_features = rtl826xb_get_features, + .config_init = rtkphy_config_init, + .probe = rtl826xb_probe, + .suspend = rtkphy_c45_suspend, + .resume = rtkphy_c45_resume, + .config_aneg = rtkphy_c45_config_aneg, + .aneg_done = rtkphy_c45_aneg_done, + .read_status = rtkphy_c45_read_status, + }, + { + PHY_ID_MATCH_EXACT(REALTEK_PHY_ID_RTL8264B), + .name = "Realtek RTL8264B", + .get_features = rtl826xb_get_features, + .config_init = rtkphy_config_init, + .probe = rtl826xb_probe, + .suspend = rtkphy_c45_suspend, + .resume = rtkphy_c45_resume, + .config_aneg = rtkphy_c45_config_aneg, + .aneg_done = rtkphy_c45_aneg_done, + .read_status = rtkphy_c45_read_status, + }, + { + PHY_ID_MATCH_EXACT(REALTEK_PHY_ID_RTL8264), + .name = "Realtek RTL8264", + .get_features = rtl826xb_get_features, + .config_init = rtkphy_config_init, + .probe = rtl826xb_probe, + .suspend = rtkphy_c45_suspend, + .resume = rtkphy_c45_resume, + .config_aneg = rtkphy_c45_config_aneg, + .aneg_done = rtkphy_c45_aneg_done, + .read_status = rtkphy_c45_read_status, + }, +}; + +module_phy_driver(rtk_phy_drivers); + + +static struct mdio_device_id __maybe_unused rtk_phy_tbl[] = { + { PHY_ID_MATCH_EXACT(REALTEK_PHY_ID_RTL8261N) }, + { PHY_ID_MATCH_EXACT(REALTEK_PHY_ID_RTL8264B) }, + { PHY_ID_MATCH_EXACT(REALTEK_PHY_ID_RTL8264) }, + { }, +}; + +MODULE_DEVICE_TABLE(mdio, rtk_phy_tbl); + +MODULE_AUTHOR("Realtek"); +MODULE_DESCRIPTION("Realtek PHY drivers"); +MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib.c b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib.c new file mode 100644 index 0000000000..7dd593ce72 --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib.c @@ -0,0 +1,108 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +#include "rtk_phylib.h" +#include + + +/* OSAL */ + +void rtk_phylib_mdelay(uint32 msec) +{ +#if defined(RTK_PHYDRV_IN_LINUX) + mdelay(msec); +#else + osal_time_mdelay(msec); +#endif +} + + +void rtk_phylib_udelay(uint32 usec) +{ +#if defined(RTK_PHYDRV_IN_LINUX) + if (1000 <= usec) + { + mdelay(usec/1000); + usec = usec % 1000; + } + udelay(usec); +#else + osal_time_udelay(usec); +#endif +} + + +/* Register Access APIs */ +int32 rtk_phylib_mmd_write(rtk_phydev *phydev, uint32 mmd, uint32 reg, uint8 msb, uint8 lsb, uint32 data) +{ + int32 ret = 0; + uint32 mask = 0; + mask = UINT32_BITS_MASK(msb,lsb); + +#if defined(RTK_PHYDRV_IN_LINUX) + ret = phy_modify_mmd(phydev, mmd, reg, mask, data); +#else + { + uint32 rData = 0, wData = 0; + if ((msb != 15) || (lsb != 0)) + { + if ((ret = phy_common_general_reg_mmd_get(phydev->unit, phydev->port, page, reg, &rData)) != RT_ERR_OK) + return ret; + } + wData = REG32_FIELD_SET(rData, data, lsb, mask); + ret = phy_common_general_reg_mmd_set(phydev->unit, phydev->port, page, reg, wData); + } +#endif + + return ret; +} + +int32 rtk_phylib_mmd_read(rtk_phydev *phydev, uint32 mmd, uint32 reg, uint8 msb, uint8 lsb, uint32 *pData) +{ + int32 ret = 0; + uint32 rData = 0; + uint32 mask = 0; + mask = UINT32_BITS_MASK(msb,lsb); + +#if defined(RTK_PHYDRV_IN_LINUX) + rData = phy_read_mmd(phydev, mmd, reg); +#else + { + ret = phy_common_general_reg_mmd_get(phydev->unit, phydev->port, page, reg, &rData); + } +#endif + + *pData = REG32_FIELD_GET(rData, lsb, mask); + return ret; +} + +/* Function Driver */ + +int32 rtk_phylib_c45_power_normal(rtk_phydev *phydev) +{ + int32 ret = 0; + RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 1, 0, 11, 11, 0)); + + return 0; +} + +int32 rtk_phylib_c45_power_low(rtk_phydev *phydev) +{ + int32 ret = 0; + RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 1, 0, 11, 11, 1)); + + return 0; +} + +int32 rtk_phylib_c45_pcs_loopback(rtk_phydev *phydev, uint32 enable) +{ + int32 ret = 0; + RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 3, 0, 14, 14, (enable == 0) ? 0 : 1)); + + return 0; +} + + diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib.h b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib.h new file mode 100644 index 0000000000..c1253b1ec9 --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib.h @@ -0,0 +1,106 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +#ifndef __RTK_PHYLIB_H +#define __RTK_PHYLIB_H + +#if defined(RTK_PHYDRV_IN_LINUX) + #include + + #include "type.h" + #include "rtk_phylib_def.h" +#else + //#include SDK headers +#endif + +#if defined(RTK_PHYDRV_IN_LINUX) + #define PR_INFO(_fmt, _args...) pr_info(_fmt, ##_args) + #define PR_DBG(_fmt, _args...) pr_debug(_fmt, ##_args) + #define PR_ERR(_fmt, _args...) pr_err("ERROR: "_fmt, ##_args) + + #define RTK_PHYLIB_ERR_FAILED (-EPERM) + #define RTK_PHYLIB_ERR_INPUT (-EINVAL) + #define RTK_PHYLIB_ERR_EXCEEDS_CAPACITY (-ENOSPC) + #define RTK_PHYLIB_ERR_TIMEOUT (-ETIME) + #define RTK_PHYLIB_ERR_ENTRY_NOTFOUND (-ENODATA) +#else + #define PR_INFO(_fmt, _args...) RT_LOG(LOG_INFO, (MOD_HAL|MOD_PHY), _fmt, ##_args) + #define PR_DBG(_fmt, _args...) RT_LOG(LOG_DEBUG, (MOD_HAL|MOD_PHY), _fmt, ##_args) + #define PR_ERR(_fmt, _args...) RT_LOG(LOG_MAJOR_ERR, (MOD_HAL|MOD_PHY), _fmt, ##_args) + + #define RTK_PHYLIB_ERR_FAILED (RT_ERR_FAILED) + #define RTK_PHYLIB_ERR_INPUT (RT_ERR_INPUT) + #define RTK_PHYLIB_ERR_EXCEEDS_CAPACITY (RT_ERR_EXCEEDS_CAPACITY) + #define RTK_PHYLIB_ERR_TIMEOUT (RT_ERR_BUSYWAIT_TIMEOUT) + #define RTK_PHYLIB_ERR_ENTRY_NOTFOUND (RT_ERR_ENTRY_NOTFOUND) +#endif + +typedef enum rtk_phylib_phy_e +{ + RTK_PHYLIB_NONE, + RTK_PHYLIB_RTL8261N, + RTK_PHYLIB_RTL8264B, + RTK_PHYLIB_END +} rtk_phylib_phy_t; + +struct rtk_phy_priv { + rtk_phylib_phy_t phytype; + uint8 isBasePort; + rt_phy_patch_db_t *patch; + + bool pnswap_rx; + bool pnswap_tx; +}; + +#if defined(RTK_PHYDRV_IN_LINUX) + typedef struct phy_device rtk_phydev; +#else + struct rtk_phy_dev_s + { + uint32 unit; + rtk_port_t port; + + struct rtk_phy_priv *priv; + }; + typedef struct rtk_phy_dev_s rtk_phydev; +#endif + +#define RTK_PHYLIB_ERR_CHK(op)\ +do {\ + if ((ret = (op)) != 0)\ + return ret;\ +} while(0) + +#define RTK_PHYLIB_VAL_TO_BYTE_ARRAY(_val, _valbytes, _array, _start, _bytes)\ +do{\ + uint32 _i = 0;\ + for (_i = 0; _i < _bytes; _i++)\ + _array[_start+_i] = (_val >> (8* (_valbytes - _i - 1)));\ +}while(0) + +#define RTK_PHYLIB_BYTE_ARRAY_TO_VAL(_val, _array, _start, _bytes)\ +do{\ + uint32 _i = 0;\ + for (_i = 0; _i < _bytes; _i++)\ + _val = (_val << 8) | _array[_start + _i];\ +}while(0) + + +/* OSAL */ +void rtk_phylib_mdelay(uint32 msec); +void rtk_phylib_udelay(uint32 usec); + +/* Register Access APIs */ +int32 rtk_phylib_mmd_write(rtk_phydev *phydev, uint32 mmd, uint32 reg, uint8 msb, uint8 lsb, uint32 data); +int32 rtk_phylib_mmd_read(rtk_phydev *phydev, uint32 mmd, uint32 reg, uint8 msb, uint8 lsb, uint32 *pData); + +/* Function Driver */ +int32 rtk_phylib_c45_power_normal(rtk_phydev *phydev); +int32 rtk_phylib_c45_power_low(rtk_phydev *phydev); +int32 rtk_phylib_c45_pcs_loopback(rtk_phydev *phydev, uint32 enable); + + +#endif /* __RTK_PHYLIB_H */ diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib_def.h b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib_def.h new file mode 100644 index 0000000000..f49f0b547c --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib_def.h @@ -0,0 +1,166 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ +#ifndef __RTK_PHYLIB_DEF_H +#define __RTK_PHYLIB_DEF_H + +#include "type.h" + +//#define PHY_C22_MMD_PAGE 0 +#define PHY_C22_MMD_PAGE 0x0A41 +#define PHY_C22_MMD_DEV_REG 13 +#define PHY_C22_MMD_ADD_REG 14 + +/* MDIO Manageable Device(MDD) address*/ +#define PHY_MMD_PMAPMD 1 +#define PHY_MMD_PCS 3 +#define PHY_MMD_AN 7 +#define PHY_MMD_VEND1 30 /* Vendor specific 1 */ +#define PHY_MMD_VEND2 31 /* Vendor specific 2 */ + +#define BIT_0 0x00000001U +#define BIT_1 0x00000002U +#define BIT_2 0x00000004U +#define BIT_3 0x00000008U +#define BIT_4 0x00000010U +#define BIT_5 0x00000020U +#define BIT_6 0x00000040U +#define BIT_7 0x00000080U +#define BIT_8 0x00000100U +#define BIT_9 0x00000200U +#define BIT_10 0x00000400U +#define BIT_11 0x00000800U +#define BIT_12 0x00001000U +#define BIT_13 0x00002000U +#define BIT_14 0x00004000U +#define BIT_15 0x00008000U +#define BIT_16 0x00010000U +#define BIT_17 0x00020000U +#define BIT_18 0x00040000U +#define BIT_19 0x00080000U +#define BIT_20 0x00100000U +#define BIT_21 0x00200000U +#define BIT_22 0x00400000U +#define BIT_23 0x00800000U +#define BIT_24 0x01000000U +#define BIT_25 0x02000000U +#define BIT_26 0x04000000U +#define BIT_27 0x08000000U +#define BIT_28 0x10000000U +#define BIT_29 0x20000000U +#define BIT_30 0x40000000U +#define BIT_31 0x80000000U + +#define MASK_1_BITS (BIT_1 - 1) +#define MASK_2_BITS (BIT_2 - 1) +#define MASK_3_BITS (BIT_3 - 1) +#define MASK_4_BITS (BIT_4 - 1) +#define MASK_5_BITS (BIT_5 - 1) +#define MASK_6_BITS (BIT_6 - 1) +#define MASK_7_BITS (BIT_7 - 1) +#define MASK_8_BITS (BIT_8 - 1) +#define MASK_9_BITS (BIT_9 - 1) +#define MASK_10_BITS (BIT_10 - 1) +#define MASK_11_BITS (BIT_11 - 1) +#define MASK_12_BITS (BIT_12 - 1) +#define MASK_13_BITS (BIT_13 - 1) +#define MASK_14_BITS (BIT_14 - 1) +#define MASK_15_BITS (BIT_15 - 1) +#define MASK_16_BITS (BIT_16 - 1) +#define MASK_17_BITS (BIT_17 - 1) +#define MASK_18_BITS (BIT_18 - 1) +#define MASK_19_BITS (BIT_19 - 1) +#define MASK_20_BITS (BIT_20 - 1) +#define MASK_21_BITS (BIT_21 - 1) +#define MASK_22_BITS (BIT_22 - 1) +#define MASK_23_BITS (BIT_23 - 1) +#define MASK_24_BITS (BIT_24 - 1) +#define MASK_25_BITS (BIT_25 - 1) +#define MASK_26_BITS (BIT_26 - 1) +#define MASK_27_BITS (BIT_27 - 1) +#define MASK_28_BITS (BIT_28 - 1) +#define MASK_29_BITS (BIT_29 - 1) +#define MASK_30_BITS (BIT_30 - 1) +#define MASK_31_BITS (BIT_31 - 1) + +#define REG32_FIELD_SET(_data, _val, _fOffset, _fMask) ((_data & ~(_fMask)) | ((_val << (_fOffset)) & (_fMask))) +#define REG32_FIELD_GET(_data, _fOffset, _fMask) ((_data & (_fMask)) >> (_fOffset)) +#define UINT32_BITS_MASK(_mBit, _lBit) ((0xFFFFFFFF >> (31 - _mBit)) ^ ((1 << _lBit) - 1)) + +typedef struct phy_device * rtk_port_t; + +#if 1 /* ss\sdk\include\hal\phy\phydef.h */ +/* unified patch format */ +typedef enum rtk_phypatch_type_e +{ + PHY_PATCH_TYPE_NONE = 0, + PHY_PATCH_TYPE_TOP = 1, + PHY_PATCH_TYPE_SDS, + PHY_PATCH_TYPE_AFE, + PHY_PATCH_TYPE_UC, + PHY_PATCH_TYPE_UC2, + PHY_PATCH_TYPE_NCTL0, + PHY_PATCH_TYPE_NCTL1, + PHY_PATCH_TYPE_NCTL2, + PHY_PATCH_TYPE_ALGXG, + PHY_PATCH_TYPE_ALG1G, + PHY_PATCH_TYPE_NORMAL, + PHY_PATCH_TYPE_DATARAM, + PHY_PATCH_TYPE_RTCT, + PHY_PATCH_TYPE_END +} rtk_phypatch_type_t; + +#define RTK_PATCH_TYPE_FLOW(_id) (PHY_PATCH_TYPE_END + _id) +#define RTK_PATCH_TYPE_FLOWID_MAX PHY_PATCH_TYPE_END +#define RTK_PATCH_SEQ_MAX ( PHY_PATCH_TYPE_END + RTK_PATCH_TYPE_FLOWID_MAX -1) + +typedef struct rtk_hwpatch_s +{ + uint8 patch_op; + uint8 portmask; + uint16 pagemmd; + uint16 addr; + uint8 msb; + uint8 lsb; + uint16 data; + uint8 compare_op; + uint16 sram_p; + uint16 sram_rr; + uint16 sram_rw; + uint16 sram_a; +} rtk_hwpatch_t; + +typedef struct rtk_hwpatch_data_s +{ + rtk_hwpatch_t *conf; + uint32 size; +} rtk_hwpatch_data_t; + +typedef struct rtk_hwpatch_seq_s +{ + uint8 patch_type; + union + { + rtk_hwpatch_data_t data; + uint8 flow_id; + } patch; +} rtk_hwpatch_seq_t; + +typedef struct rt_phy_patch_db_s +{ + /* patch operation */ + int32 (*fPatch_op)(uint32 unit, rtk_port_t port, uint8 portOffset, rtk_hwpatch_t *pPatch_data, uint8 patch_mode); + int32 (*fPatch_flow)(uint32 unit, rtk_port_t port, uint8 portOffset, uint8 patch_flow, uint8 patch_mode); + + /* patch data */ + rtk_hwpatch_seq_t seq_table[RTK_PATCH_SEQ_MAX]; + rtk_hwpatch_seq_t cmp_table[RTK_PATCH_SEQ_MAX]; + +} rt_phy_patch_db_t; +#endif + + + +#endif /* __RTK_PHYLIB_DEF_H */ diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib_rtl826xb.c b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib_rtl826xb.c new file mode 100644 index 0000000000..1c33846a70 --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib_rtl826xb.c @@ -0,0 +1,57 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +#include "rtk_phylib_rtl826xb.h" + +/* Indirect Register Access APIs */ +int rtk_phylib_826xb_sds_read(rtk_phydev *phydev, uint32 page, uint32 reg, uint8 msb, uint8 lsb, uint32 *pData) +{ + int32 ret = 0; + uint32 rData = 0; + uint32 op = (page & 0x3f) | ((reg & 0x1f) << 6) | (0x8000); + uint32 i = 0; + uint32 mask = 0; + mask = UINT32_BITS_MASK(msb,lsb); + + RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 323, 15, 0, op)); + + for (i = 0; i < 10; i++) + { + RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 323, 15, 15, &rData)); + if (rData == 0) + { + break; + } + rtk_phylib_udelay(10); + } + if (i == 10) + { + return -1; + } + + RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_read(phydev, 30, 322, 15, 0, &rData)); + *pData = REG32_FIELD_GET(rData, lsb, mask); + + return ret; +} + +int rtk_phylib_826xb_sds_write(rtk_phydev *phydev, uint32 page, uint32 reg, uint8 msb, uint8 lsb, uint32 data) +{ + int32 ret = 0; + uint32 wData = 0, rData = 0; + uint32 op = (page & 0x3f) | ((reg & 0x1f) << 6) | (0x8800); + uint32 mask = 0; + mask = UINT32_BITS_MASK(msb,lsb); + + RTK_PHYLIB_ERR_CHK(rtk_phylib_826xb_sds_read(phydev, page, reg, 15, 0, &rData)); + + wData = REG32_FIELD_SET(rData, data, lsb, mask); + + RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 321, 15, 0, wData)); + RTK_PHYLIB_ERR_CHK(rtk_phylib_mmd_write(phydev, 30, 323, 15, 0, op)); + + return ret; +} diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib_rtl826xb.h b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib_rtl826xb.h new file mode 100644 index 0000000000..9f827d4ba2 --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib_rtl826xb.h @@ -0,0 +1,19 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +#ifndef __RTK_PHYLIB_RTL826XB_H +#define __RTK_PHYLIB_RTL826XB_H + +#if defined(RTK_PHYDRV_IN_LINUX) + #include "rtk_phylib.h" +#else + //#include SDK headers +#endif + +int rtk_phylib_826xb_sds_read(rtk_phydev *phydev, uint32 page, uint32 reg, uint8 msb, uint8 lsb, uint32 *pData); +int rtk_phylib_826xb_sds_write(rtk_phydev *phydev, uint32 page, uint32 reg, uint8 msb, uint8 lsb, uint32 data); + +#endif /* __RTK_PHYLIB_RTL826XB_H */ diff --git a/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/type.h b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/type.h new file mode 100644 index 0000000000..98d7e15e1e --- /dev/null +++ b/lede/target/linux/generic/files/drivers/net/phy/rtl8261n/type.h @@ -0,0 +1,117 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2023 Realtek Semiconductor Corp. All rights reserved. + */ + +#ifndef __COMMON_TYPE_H__ +#define __COMMON_TYPE_H__ + +/* + * Symbol Definition + */ + +#define USING_RTSTK_PKT_AS_RAIL + + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef ETHER_ADDR_LEN +#define ETHER_ADDR_LEN 6 +#endif + +#ifndef IP6_ADDR_LEN +#define IP6_ADDR_LEN 16 +#endif + + +/* + * Data Type Declaration + */ +#ifndef uint64 +typedef unsigned long long uint64; +#endif + +#ifndef int64 +typedef signed long long int64; +#endif + +#ifndef uint32 +typedef unsigned int uint32; +#endif + +#ifndef int32 +typedef signed int int32; +#endif + +#ifndef uint16 +typedef unsigned short uint16; +#endif + +#ifndef int16 +typedef signed short int16; +#endif + +#ifndef uint8 +typedef unsigned char uint8; +#endif + +#ifndef int8 +typedef signed char int8; +#endif + +//#define CONFIG_SDK_WORDSIZE_64 /* not ready */ +#ifdef CONFIG_SDK_WORDSIZE_64 + typedef long int intptr; + typedef unsigned long int uintptr; +#else + typedef int intptr; + typedef unsigned int uintptr; +#endif + + +#ifndef ipaddr_t +typedef uint32 ipaddr_t; /* ipv4 address type */ +#endif + +/* configuration mode type */ +typedef enum rtk_enable_e +{ + DISABLED = 0, + ENABLED, + RTK_ENABLE_END +} rtk_enable_t; + +/* initial state of module */ +typedef enum init_state_e +{ + INIT_NOT_COMPLETED = 0, + INIT_COMPLETED, + INIT_STATE_END +} init_state_t; + +/* ethernet address type */ +typedef struct rtk_mac_s +{ + uint8 octet[ETHER_ADDR_LEN]; +} rtk_mac_t; + +typedef uint32 osal_time_t; +typedef uint32 osal_usecs_t; + +/* + * Macro Definition + */ + +#endif /* __COMMON_TYPE_H__ */ + diff --git a/lede/target/linux/generic/files/drivers/ssb/fallback-sprom.c b/lede/target/linux/generic/files/drivers/ssb/fallback-sprom.c index b8a4dcedcf..e2ba3da4e4 100644 --- a/lede/target/linux/generic/files/drivers/ssb/fallback-sprom.c +++ b/lede/target/linux/generic/files/drivers/ssb/fallback-sprom.c @@ -16,6 +16,7 @@ #include #include #include +#include "fallback-sprom.h" #define SSB_FBS_MAX_SIZE 440 @@ -689,6 +690,7 @@ static int ssb_fbs_probe(struct platform_device *pdev) struct ssb_fbs *priv; unsigned long flags; u8 mac[ETH_ALEN]; + int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -701,7 +703,10 @@ static int ssb_fbs_probe(struct platform_device *pdev) of_property_read_u32(node, "pci-bus", &priv->pci_bus); of_property_read_u32(node, "pci-dev", &priv->pci_dev); - of_get_mac_address(node, mac); + ret = of_get_mac_address(node, mac); + if (ret == -EPROBE_DEFER) + return ret; + if (is_valid_ether_addr(mac)) { dev_info(dev, "mtd mac %pM\n", mac); } else { diff --git a/lede/target/linux/generic/files/drivers/ssb/fallback-sprom.h b/lede/target/linux/generic/files/drivers/ssb/fallback-sprom.h new file mode 100644 index 0000000000..3966a18b86 --- /dev/null +++ b/lede/target/linux/generic/files/drivers/ssb/fallback-sprom.h @@ -0,0 +1,7 @@ +#ifndef _FALLBACK_SPROM_H +#define _FALLBACK_SPROM_H + +int __init ssb_fbs_register(void); +int ssb_get_fallback_sprom(struct ssb_bus *dev, struct ssb_sprom *out); + +#endif /* _FALLBACK_SPROM_H */ diff --git a/lede/target/linux/generic/hack-6.12/249-udp-tunnel-selection.patch b/lede/target/linux/generic/hack-6.12/249-udp-tunnel-selection.patch new file mode 100644 index 0000000000..7f7e5f11f4 --- /dev/null +++ b/lede/target/linux/generic/hack-6.12/249-udp-tunnel-selection.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andy Chiang +Date: Thu, 20 Nov 2025 20:37:53 +0700 +Subject: [PATCH] kernel: fix build of kmod-udptunnel4 and kmod-udptunnel6 + +This fixes the following errors: +``` +make[4]: Entering directory '/home/runner/work/OP/OP/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_filogic/linux-6.12.57' + MODPOST /home/runner/work/OP/OP/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_filogic/ovpn-dco-0.2.20250801/drivers/net/ovpn-dco/Module.symvers +ERROR: modpost: "udp_tunnel6_xmit_skb" [/home/runner/work/OP/OP/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_filogic/ovpn-dco-0.2.20250801/drivers/net/ovpn-dco/ovpn-dco-v2.ko] undefined! +ERROR: modpost: "setup_udp_tunnel_sock" [/home/runner/work/OP/OP/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_filogic/ovpn-dco-0.2.20250801/drivers/net/ovpn-dco/ovpn-dco-v2.ko] undefined! +ERROR: modpost: "udp_tunnel_xmit_skb" [/home/runner/work/OP/OP/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_filogic/ovpn-dco-0.2.20250801/drivers/net/ovpn-dco/ovpn-dco-v2.ko] undefined! +make[6]: *** [scripts/Makefile.modpost:145: /home/runner/work/OP/OP/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_filogic/ovpn-dco-0.2.20250801/drivers/net/ovpn-dco/Module.symvers] Error 1 +make[5]: *** [/home/runner/work/OP/OP/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_filogic/linux-6.12.57/Makefile:1897: modpost] Error 2 +make[4]: *** [Makefile:224: __sub-make] Error 2 +``` + +ref https://github.com/openwrt/openwrt/commit/1d15a96b29dcd0947690951a7c36aead79a27129 +fixes: https://github.com/openwrt/packages/issues/22998 + +Signed-off-by: Andy Chiang +--- + net/ipv4/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ipv4/Kconfig ++++ b/net/ipv4/Kconfig +@@ -315,7 +315,7 @@ config NET_IPVTI + on top. + + config NET_UDP_TUNNEL +- tristate ++ tristate "IP: UDP tunneling support" + select NET_IP_TUNNEL + default n + diff --git a/lede/target/linux/generic/hack-6.12/253-ksmbd-config.patch b/lede/target/linux/generic/hack-6.12/253-ksmbd-config.patch index d5474d9799..d9587fbe84 100644 --- a/lede/target/linux/generic/hack-6.12/253-ksmbd-config.patch +++ b/lede/target/linux/generic/hack-6.12/253-ksmbd-config.patch @@ -10,7 +10,7 @@ Subject: [PATCH] Kconfig: add tristate for OID and ASNI string --- a/init/Kconfig +++ b/init/Kconfig -@@ -2062,7 +2062,7 @@ config PADATA +@@ -2063,7 +2063,7 @@ config PADATA bool config ASN1 diff --git a/lede/target/linux/generic/hack-6.12/259-regmap_dynamic.patch b/lede/target/linux/generic/hack-6.12/259-regmap_dynamic.patch index cbd6c42234..4f48fc0690 100644 --- a/lede/target/linux/generic/hack-6.12/259-regmap_dynamic.patch +++ b/lede/target/linux/generic/hack-6.12/259-regmap_dynamic.patch @@ -137,7 +137,7 @@ Signed-off-by: Felix Fietkau #include #include #include -@@ -3521,3 +3522,5 @@ static int __init regmap_initcall(void) +@@ -3523,3 +3524,5 @@ static int __init regmap_initcall(void) return 0; } postcore_initcall(regmap_initcall); diff --git a/lede/target/linux/generic/hack-6.12/402-mtd-blktrans-call-add-disks-after-mtd-device.patch b/lede/target/linux/generic/hack-6.12/402-mtd-blktrans-call-add-disks-after-mtd-device.patch index 5ccb6bc7d8..d5a68d681b 100644 --- a/lede/target/linux/generic/hack-6.12/402-mtd-blktrans-call-add-disks-after-mtd-device.patch +++ b/lede/target/linux/generic/hack-6.12/402-mtd-blktrans-call-add-disks-after-mtd-device.patch @@ -91,7 +91,7 @@ Signed-off-by: Daniel Golle #include "mtdcore.h" -@@ -1132,6 +1133,8 @@ int mtd_device_parse_register(struct mtd +@@ -1109,6 +1110,8 @@ int mtd_device_parse_register(struct mtd register_reboot_notifier(&mtd->reboot_notifier); } diff --git a/lede/target/linux/generic/hack-6.12/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch b/lede/target/linux/generic/hack-6.12/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch index 5296541800..1b17c2fe88 100644 --- a/lede/target/linux/generic/hack-6.12/420-mtd-support-OpenWrt-s-MTD_ROOTFS_ROOT_DEV.patch +++ b/lede/target/linux/generic/hack-6.12/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 -@@ -803,7 +803,8 @@ int add_mtd_device(struct mtd_info *mtd) +@@ -780,7 +780,8 @@ int add_mtd_device(struct mtd_info *mtd) mutex_unlock(&mtd_table_mutex); diff --git a/lede/target/linux/generic/hack-6.12/430-mtk-bmt-support.patch b/lede/target/linux/generic/hack-6.12/430-mtk-bmt-support.patch index 90b5a64b51..8d1c16503f 100644 --- a/lede/target/linux/generic/hack-6.12/430-mtk-bmt-support.patch +++ b/lede/target/linux/generic/hack-6.12/430-mtk-bmt-support.patch @@ -28,6 +28,6 @@ Subject: [PATCH] mtd/nand: add MediaTek NAND bad block managment table obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o +obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o - ifeq ($(CONFIG_SPI_QPIC_SNAND),y) obj-$(CONFIG_SPI_QPIC_SNAND) += qpic_common.o - else + obj-$(CONFIG_MTD_NAND_QCOM) += qpic_common.o + obj-y += onenand/ diff --git a/lede/target/linux/generic/hack-6.12/610-net-page_pool-try-to-free-deferred-skbs-while-waitin.patch b/lede/target/linux/generic/hack-6.12/610-net-page_pool-try-to-free-deferred-skbs-while-waitin.patch index 5db35ac9a5..7f79e041df 100644 --- a/lede/target/linux/generic/hack-6.12/610-net-page_pool-try-to-free-deferred-skbs-while-waitin.patch +++ b/lede/target/linux/generic/hack-6.12/610-net-page_pool-try-to-free-deferred-skbs-while-waitin.patch @@ -16,16 +16,18 @@ Signed-off-by: Felix Fietkau --- a/net/core/page_pool.c +++ b/net/core/page_pool.c -@@ -1124,7 +1124,7 @@ static void page_pool_release_retry(stru +@@ -1155,8 +1155,9 @@ static void page_pool_release_retry(stru + { struct delayed_work *dwq = to_delayed_work(wq); struct page_pool *pool = container_of(dwq, typeof(*pool), release_dw); ++ unsigned long flags; void *netdev; - int inflight; + int cpu, inflight; inflight = page_pool_release(pool); /* In rare cases, a driver bug may cause inflight to go negative. -@@ -1136,6 +1136,17 @@ static void page_pool_release_retry(stru +@@ -1168,6 +1169,21 @@ static void page_pool_release_retry(stru if (inflight <= 0) return; @@ -33,12 +35,16 @@ Signed-off-by: Felix Fietkau + * defer_list that can stay in the list until we have enough queued + * traffic. + */ ++ local_irq_save(flags); + for_each_online_cpu(cpu) { + struct softnet_data *sd = &per_cpu(softnet_data, cpu); + -+ if (!cmpxchg(&sd->defer_ipi_scheduled, 0, 1)) ++ if (cpu == raw_smp_processor_id()) ++ raise_softirq_irqoff(NET_RX_SOFTIRQ); ++ else if (!cmpxchg(&sd->defer_ipi_scheduled, 0, 1)) + smp_call_function_single_async(cpu, &sd->defer_csd); + } ++ local_irq_restore(flags); + /* Periodic warning for page pools the user can't see */ netdev = READ_ONCE(pool->slow.netdev); diff --git a/lede/target/linux/generic/hack-6.12/700-swconfig_switch_drivers.patch b/lede/target/linux/generic/hack-6.12/700-swconfig_switch_drivers.patch index 9b1f53af3e..ff235dd252 100644 --- a/lede/target/linux/generic/hack-6.12/700-swconfig_switch_drivers.patch +++ b/lede/target/linux/generic/hack-6.12/700-swconfig_switch_drivers.patch @@ -85,7 +85,7 @@ Signed-off-by: Felix Fietkau + select SWCONFIG + +config RTL8367B_PHY -+ tristate "Driver fot the Realtek RTL8367R-VB switch" ++ tristate "Driver for the Realtek RTL8367R-VB switch" + select SWCONFIG + +endif # RTL8366_SMI diff --git a/lede/target/linux/generic/hack-6.12/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch b/lede/target/linux/generic/hack-6.12/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch index b8d8652d8f..29ac3e9734 100644 --- a/lede/target/linux/generic/hack-6.12/711-net-dsa-mv88e6xxx-disable-ATU-violation.patch +++ b/lede/target/linux/generic/hack-6.12/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 -@@ -3582,6 +3582,9 @@ static int mv88e6xxx_setup_port(struct m +@@ -3583,6 +3583,9 @@ static int mv88e6xxx_setup_port(struct m else reg = 1 << port; diff --git a/lede/target/linux/generic/hack-6.12/721-net-add-packet-mangeling.patch b/lede/target/linux/generic/hack-6.12/721-net-add-packet-mangeling.patch index 842c9b0d30..599713bc23 100644 --- a/lede/target/linux/generic/hack-6.12/721-net-add-packet-mangeling.patch +++ b/lede/target/linux/generic/hack-6.12/721-net-add-packet-mangeling.patch @@ -97,7 +97,7 @@ Signed-off-by: Felix Fietkau help --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -3658,6 +3658,11 @@ static int xmit_one(struct sk_buff *skb, +@@ -3671,6 +3671,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.12/730-net-ethernet-mtk_eth_soc-add-hw-dump-for-forced-rese.patch b/lede/target/linux/generic/hack-6.12/730-net-ethernet-mtk_eth_soc-add-hw-dump-for-forced-rese.patch index c4bf08b594..4cb8c2903c 100644 --- a/lede/target/linux/generic/hack-6.12/730-net-ethernet-mtk_eth_soc-add-hw-dump-for-forced-rese.patch +++ b/lede/target/linux/generic/hack-6.12/730-net-ethernet-mtk_eth_soc-add-hw-dump-for-forced-rese.patch @@ -13,7 +13,7 @@ Signed-off-by: Bo-Cun Chen --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -66,6 +66,7 @@ static const struct mtk_reg_map mtk_reg_ +@@ -74,6 +74,7 @@ static const struct mtk_reg_map mtk_reg_ .rx_ptr = 0x1900, .rx_cnt_cfg = 0x1904, .qcrx_ptr = 0x1908, @@ -21,7 +21,7 @@ Signed-off-by: Bo-Cun Chen .glo_cfg = 0x1a04, .rst_idx = 0x1a08, .delay_irq = 0x1a0c, -@@ -132,6 +133,7 @@ static const struct mtk_reg_map mt7986_r +@@ -140,6 +141,7 @@ static const struct mtk_reg_map mt7986_r .rx_ptr = 0x4500, .rx_cnt_cfg = 0x4504, .qcrx_ptr = 0x4508, @@ -29,7 +29,7 @@ Signed-off-by: Bo-Cun Chen .glo_cfg = 0x4604, .rst_idx = 0x4608, .delay_irq = 0x460c, -@@ -183,6 +185,7 @@ static const struct mtk_reg_map mt7988_r +@@ -191,6 +193,7 @@ static const struct mtk_reg_map mt7988_r .rx_ptr = 0x4500, .rx_cnt_cfg = 0x4504, .qcrx_ptr = 0x4508, @@ -37,7 +37,7 @@ Signed-off-by: Bo-Cun Chen .glo_cfg = 0x4604, .rst_idx = 0x4608, .delay_irq = 0x460c, -@@ -3901,6 +3904,56 @@ static void mtk_set_mcr_max_rx(struct mt +@@ -4060,6 +4063,56 @@ static void mtk_set_mcr_max_rx(struct mt mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id)); } @@ -94,7 +94,7 @@ Signed-off-by: Bo-Cun Chen static void mtk_hw_reset(struct mtk_eth *eth) { u32 val; -@@ -4380,6 +4433,8 @@ static void mtk_pending_work(struct work +@@ -4539,6 +4592,8 @@ static void mtk_pending_work(struct work rtnl_lock(); set_bit(MTK_RESETTING, ð->state); @@ -105,7 +105,7 @@ Signed-off-by: Bo-Cun Chen /* Run again reset preliminary configuration in order to avoid any --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -1191,6 +1191,7 @@ struct mtk_reg_map { +@@ -1185,6 +1185,7 @@ struct mtk_reg_map { u32 rx_ptr; /* rx base pointer */ u32 rx_cnt_cfg; /* rx max count configuration */ u32 qcrx_ptr; /* rx cpu pointer */ diff --git a/lede/target/linux/generic/hack-6.12/735-net-phy-realtek-rtl8261n.patch b/lede/target/linux/generic/hack-6.12/735-net-phy-realtek-rtl8261n.patch new file mode 100644 index 0000000000..c9dc2508ac --- /dev/null +++ b/lede/target/linux/generic/hack-6.12/735-net-phy-realtek-rtl8261n.patch @@ -0,0 +1,21 @@ +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -431,6 +431,8 @@ config QSEMI_PHY + + source "drivers/net/phy/realtek/Kconfig" + ++source "drivers/net/phy/rtl8261n/Kconfig" ++ + config RENESAS_PHY + tristate "Renesas PHYs" + help +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -110,6 +110,7 @@ obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja + obj-y += qcom/ + obj-$(CONFIG_QSEMI_PHY) += qsemi.o + obj-$(CONFIG_REALTEK_PHY) += realtek/ ++obj-y += rtl8261n/ + obj-$(CONFIG_RENESAS_PHY) += uPD60620.o + obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o + obj-$(CONFIG_SMSC_PHY) += smsc.o diff --git a/lede/target/linux/generic/hack-6.12/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch b/lede/target/linux/generic/hack-6.12/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch index 30a502a237..bf26a2f6ec 100644 --- a/lede/target/linux/generic/hack-6.12/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch +++ b/lede/target/linux/generic/hack-6.12/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 -@@ -114,14 +114,23 @@ static void mtk_pcs_lynxi_get_state(stru +@@ -129,14 +129,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); @@ -41,7 +41,7 @@ Signed-off-by: Daniel Golle } static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs) -@@ -142,7 +151,7 @@ static int mtk_pcs_lynxi_config(struct p +@@ -157,7 +166,7 @@ static int mtk_pcs_lynxi_config(struct p { struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); bool mode_changed = false, changed; @@ -50,7 +50,7 @@ Signed-off-by: Daniel Golle int advertise, link_timer; advertise = phylink_mii_c22_pcs_encode_advertisement(interface, -@@ -165,9 +174,8 @@ static int mtk_pcs_lynxi_config(struct p +@@ -180,9 +189,8 @@ static int mtk_pcs_lynxi_config(struct p if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { if (interface == PHY_INTERFACE_MODE_SGMII) sgm_mode |= SGMII_SPEED_DUPLEX_AN; diff --git a/lede/target/linux/generic/hack-6.12/755-net-phy-motorcomm-yt8821-bus-collision-workaround.patch b/lede/target/linux/generic/hack-6.12/755-net-phy-motorcomm-yt8821-bus-collision-workaround.patch new file mode 100644 index 0000000000..28c4c702b3 --- /dev/null +++ b/lede/target/linux/generic/hack-6.12/755-net-phy-motorcomm-yt8821-bus-collision-workaround.patch @@ -0,0 +1,85 @@ +From 63161fb6353493c648a260244f6ac7eca65fd48e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jakub=20Van=C4=9Bk?= +Date: Mon, 2 Mar 2026 20:31:37 +0100 +Subject: [PATCH] net: phy: Work around MDIO collisions in the YT8821 driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Cudy M3000 router suffers from a MDIO bus collision: +- The MT7981B internal gigabit PHY listens on address 0. +- The Motorcomm YT8821 is strapped to listen on address 1, + but it initially also listens on address 0 (Motorcomm + incorrectly considers that address a broadcast address). + +Without this patch, the YT8821 reacts to MDIO commands intended +for the internal gigabit PHY and that makes it work unreliably. +The YT8821 state somehow gets corrupted by the commands for the MT7981 +(e.g. we get 100Mbps speeds on gigabit links). + +This dirty workaround resets the PHY to cancel out any earlier +YT8821 register corruption and then it disables the address 0 +as soon as possible. This should make the YT8821 work reliably. + +BEWARE though: the PHY will be reset only if the device tree +node that defines the PHY carries the reset-gpios attribute. +The PHY will not be reset if the reset GPIO is either on the MDIO +bus node or is not defined at all. This might not always be a problem -- +some routers do not require the PHY to be reset (e.g. Cudy WR3000H, +where there likely is less communication with the MT7981B PHY, +and so the YT8821 PHY works reasonably well there even without this patch). + +This patch also does not address the possible MDIO bus collisions +when the MT7981B PHY driver initially configures that PHY and invokes +some read transactions on the bus. I am hoping that the MT7981B MDIO +bus controller gives priority to the internal PHY and so it would +not be affected by these collisions. However, I don't have anything +to base this on apart from it "seeming to be working okay". + +This patch is unlikely to be mergeable into the mainline kernel. +Upstream has strongly indicated that they would prefer this problem +to be resolved by the platform bootloader (e.g. U-Boot), see +- https://lore.kernel.org/all/d3bb9c36-5a0e-4339-901d-2dd21bdba395@gmail.com/ +- https://lore.kernel.org/all/20260228232241.1274236-1-linuxtardis@gmail.com/ + +Signed-off-by: Jakub Vaněk +--- + drivers/net/phy/motorcomm.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -214,6 +214,9 @@ + #define YT8521_RC1R_RGMII_2_100_NS 14 + #define YT8521_RC1R_RGMII_2_250_NS 15 + ++#define YTPHY_MDIO_ADDRESS_CONTROL_REG 0xA005 ++#define YTPHY_MACR_EN_PHY_ADDR_0 BIT(6) ++ + #define YTPHY_MISC_CONFIG_REG 0xA006 + #define YTPHY_MCR_FIBER_SPEED_MASK BIT(0) + #define YTPHY_MCR_FIBER_1000BX (0x1 << 0) +@@ -2659,6 +2662,23 @@ static int yt8821_config_init(struct phy + int ret; + u16 set; + ++ /* Hard-reset the PHY to clear out any register corruption ++ * from preceding MDIO bus conflicts. ++ */ ++ phy_device_reset(phydev, 1); ++ ++ /* Deassert the reset GPIO under the MDIO bus lock to make ++ * sure that nothing will communicate on the bus until we ++ * disable the broadcast address in the YT8821. ++ */ ++ phy_lock_mdio_bus(phydev); ++ phy_device_reset(phydev, 0); ++ ret = ytphy_modify_ext(phydev, ++ YTPHY_MDIO_ADDRESS_CONTROL_REG, ++ YTPHY_MACR_EN_PHY_ADDR_0, ++ 0); ++ phy_unlock_mdio_bus(phydev); ++ + if (phydev->interface == PHY_INTERFACE_MODE_2500BASEX) + mode = YT8821_CHIP_MODE_FORCE_BX2500; + diff --git a/lede/target/linux/generic/hack-6.12/780-usb-net-MeigLink_modem_support.patch b/lede/target/linux/generic/hack-6.12/780-usb-net-MeigLink_modem_support.patch index f0b9a2f646..eff038fbd0 100644 --- a/lede/target/linux/generic/hack-6.12/780-usb-net-MeigLink_modem_support.patch +++ b/lede/target/linux/generic/hack-6.12/780-usb-net-MeigLink_modem_support.patch @@ -10,7 +10,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c -@@ -1076,6 +1076,11 @@ static const struct usb_device_id produc +@@ -1082,6 +1082,11 @@ static const struct usb_device_id produc USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7), .driver_info = (unsigned long)&qmi_wwan_info, }, @@ -22,7 +22,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0122)}, /* Quectel RG650V */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0125)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0306)}, /* Quectel EP06/EG06/EM06 */ -@@ -1083,6 +1088,7 @@ static const struct usb_device_id produc +@@ -1089,6 +1094,7 @@ static const struct usb_device_id produc {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0620)}, /* Quectel EM160R-GL */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0800)}, /* Quectel RM500Q-GL */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0801)}, /* Quectel RM520N */ @@ -44,7 +44,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support #define QUECTEL_VENDOR_ID 0x2c7c /* These Quectel products use Quectel's vendor ID */ -@@ -1154,6 +1159,11 @@ static const struct usb_device_id option +@@ -1156,6 +1161,11 @@ static const struct usb_device_id option { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000), /* SIMCom SIM5218 */ .driver_info = NCTRL(0) | NCTRL(1) | NCTRL(2) | NCTRL(3) | RSVD(4) }, @@ -56,7 +56,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support /* Quectel products using Qualcomm vendor ID */ { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)}, { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20), -@@ -1195,6 +1205,11 @@ static const struct usb_device_id option +@@ -1197,6 +1207,11 @@ static const struct usb_device_id option .driver_info = ZLP }, { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96), .driver_info = RSVD(4) }, diff --git a/lede/target/linux/generic/hack-6.12/800-GPIO-add-named-gpio-exports.patch b/lede/target/linux/generic/hack-6.12/800-GPIO-add-named-gpio-exports.patch index bf75cedafd..f9b540f0d6 100644 --- a/lede/target/linux/generic/hack-6.12/800-GPIO-add-named-gpio-exports.patch +++ b/lede/target/linux/generic/hack-6.12/800-GPIO-add-named-gpio-exports.patch @@ -22,7 +22,7 @@ Signed-off-by: John Crispin + +#ifdef CONFIG_GPIO_SYSFS + -+static struct of_device_id gpio_export_ids[] = { ++static const struct of_device_id gpio_export_ids[] = { + { .compatible = "gpio-export" }, + { /* sentinel */ } +}; diff --git a/lede/target/linux/generic/hack-6.12/810-bcma-ssb-fallback-sprom.patch b/lede/target/linux/generic/hack-6.12/810-bcma-ssb-fallback-sprom.patch index a011cf8ffa..392c873b0e 100644 --- a/lede/target/linux/generic/hack-6.12/810-bcma-ssb-fallback-sprom.patch +++ b/lede/target/linux/generic/hack-6.12/810-bcma-ssb-fallback-sprom.patch @@ -6,15 +6,15 @@ Subject: [PATCH] ssb_sprom: add generic kernel support for Broadcom Fallback SP --- drivers/bcma/Kconfig | 4 ++++ drivers/bcma/Makefile | 1 + - drivers/bcma/bcma_private.h | 4 ++++ + drivers/bcma/bcma_private.h | 1 + drivers/bcma/main.c | 8 ++++++++ drivers/bcma/sprom.c | 23 ++++++++++++++--------- drivers/ssb/Kconfig | 5 +++++ drivers/ssb/Makefile | 1 + drivers/ssb/main.c | 8 ++++++++ drivers/ssb/sprom.c | 12 +++++++++++- - drivers/ssb/ssb_private.h | 4 ++++ - 10 files changed, 60 insertions(+), 10 deletions(-) + drivers/ssb/ssb_private.h | 2 +- + 10 files changed, 54 insertions(+), 11 deletions(-) --- a/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig @@ -41,20 +41,17 @@ Subject: [PATCH] ssb_sprom: add generic kernel support for Broadcom Fallback SP obj-$(CONFIG_BCMA) += bcma.o --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h -@@ -38,6 +38,10 @@ int bcma_bus_resume(struct bcma_bus *bus - void bcma_detect_chip(struct bcma_bus *bus); - int bcma_bus_scan(struct bcma_bus *bus); +@@ -8,6 +8,7 @@ -+/* fallback-sprom.c */ -+int __init bcma_fbs_register(void); -+int bcma_get_fallback_sprom(struct bcma_bus *dev, struct ssb_sprom *out); -+ - /* sprom.c */ - int bcma_sprom_get(struct bcma_bus *bus); + #include + #include ++#include "fallback-sprom.h" + #define bcma_err(bus, fmt, ...) \ + dev_err((bus)->dev, "bus%d: " fmt, (bus)->num, ##__VA_ARGS__) --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c -@@ -671,6 +671,14 @@ static int __init bcma_modinit(void) +@@ -677,6 +677,14 @@ static int __init bcma_modinit(void) { int err; @@ -174,14 +171,12 @@ Subject: [PATCH] ssb_sprom: add generic kernel support for Broadcom Fallback SP /* https://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */ --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h -@@ -143,6 +143,10 @@ extern int ssb_bus_scan(struct ssb_bus * - extern void ssb_iounmap(struct ssb_bus *ssb); +@@ -8,7 +8,7 @@ + #include + #include + #include +- ++#include "fallback-sprom.h" - -+/* fallback-sprom.c */ -+int __init ssb_fbs_register(void); -+int ssb_get_fallback_sprom(struct ssb_bus *dev, struct ssb_sprom *out); -+ - /* sprom.c */ - extern - ssize_t ssb_attr_sprom_show(struct ssb_bus *bus, char *buf, + /* pci.c */ + #ifdef CONFIG_SSB_PCIHOST diff --git a/lede/target/linux/generic/hack-6.12/902-debloat_proc.patch b/lede/target/linux/generic/hack-6.12/902-debloat_proc.patch index 4b74ad24fb..465a0ae018 100644 --- a/lede/target/linux/generic/hack-6.12/902-debloat_proc.patch +++ b/lede/target/linux/generic/hack-6.12/902-debloat_proc.patch @@ -29,7 +29,7 @@ Signed-off-by: Felix Fietkau --- a/fs/locks.c +++ b/fs/locks.c -@@ -2971,6 +2971,8 @@ static const struct seq_operations locks +@@ -2979,6 +2979,8 @@ static const struct seq_operations locks static int __init proc_locks_init(void) { @@ -235,7 +235,7 @@ Signed-off-by: Felix Fietkau if (!pe) --- a/mm/vmalloc.c +++ b/mm/vmalloc.c -@@ -5074,6 +5074,9 @@ static int vmalloc_info_show(struct seq_ +@@ -5071,6 +5071,9 @@ static int vmalloc_info_show(struct seq_ static int __init proc_vmalloc_init(void) { @@ -247,7 +247,7 @@ Signed-off-by: Felix Fietkau } --- a/mm/vmstat.c +++ b/mm/vmstat.c -@@ -2195,10 +2195,12 @@ void __init init_mm_internals(void) +@@ -2197,10 +2197,12 @@ void __init init_mm_internals(void) start_shepherd_timer(); #endif #ifdef CONFIG_PROC_FS @@ -331,7 +331,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -4273,6 +4273,8 @@ static __net_initdata struct pernet_oper +@@ -4285,6 +4285,8 @@ static __net_initdata struct pernet_oper static int __init proto_init(void) { @@ -342,7 +342,7 @@ Signed-off-by: Felix Fietkau --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c -@@ -3015,11 +3015,13 @@ static const struct seq_operations fib_r +@@ -3016,11 +3016,13 @@ static const struct seq_operations fib_r int __net_init fib_proc_init(struct net *net) { @@ -358,7 +358,7 @@ Signed-off-by: Felix Fietkau fib_triestat_seq_show, NULL)) goto out2; -@@ -3030,17 +3032,21 @@ int __net_init fib_proc_init(struct net +@@ -3031,17 +3033,21 @@ int __net_init fib_proc_init(struct net return 0; out3: diff --git a/lede/target/linux/generic/hack-6.12/904-debloat_dma_buf.patch b/lede/target/linux/generic/hack-6.12/904-debloat_dma_buf.patch index bceb474f1a..af566ec964 100644 --- a/lede/target/linux/generic/hack-6.12/904-debloat_dma_buf.patch +++ b/lede/target/linux/generic/hack-6.12/904-debloat_dma_buf.patch @@ -74,7 +74,7 @@ Signed-off-by: Felix Fietkau +MODULE_LICENSE("GPL"); --- a/kernel/sched/core.c +++ b/kernel/sched/core.c -@@ -4433,6 +4433,7 @@ int wake_up_state(struct task_struct *p, +@@ -4434,6 +4434,7 @@ int wake_up_state(struct task_struct *p, { return try_to_wake_up(p, state, 0); } diff --git a/lede/target/linux/generic/pending-6.12/150-bridge_allow_receiption_on_disabled_port.patch b/lede/target/linux/generic/pending-6.12/150-bridge_allow_receiption_on_disabled_port.patch index d8fd9cdf42..530f2c3a38 100644 --- a/lede/target/linux/generic/pending-6.12/150-bridge_allow_receiption_on_disabled_port.patch +++ b/lede/target/linux/generic/pending-6.12/150-bridge_allow_receiption_on_disabled_port.patch @@ -15,7 +15,7 @@ Signed-off-by: Felix Fietkau --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c -@@ -244,6 +244,9 @@ static void __br_handle_local_finish(str +@@ -245,6 +245,9 @@ static void __br_handle_local_finish(str /* note: already called with rcu_read_lock */ static int br_handle_local_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { @@ -25,7 +25,7 @@ Signed-off-by: Felix Fietkau __br_handle_local_finish(skb); /* return 1 to signal the okfn() was called so it's ok to use the skb */ -@@ -415,6 +418,17 @@ forward: +@@ -416,6 +419,17 @@ forward: goto defer_stp_filtering; switch (p->state) { diff --git a/lede/target/linux/generic/pending-6.12/203-kallsyms_uncompressed.patch b/lede/target/linux/generic/pending-6.12/203-kallsyms_uncompressed.patch index 9855ce03c8..40de8f6072 100644 --- a/lede/target/linux/generic/pending-6.12/203-kallsyms_uncompressed.patch +++ b/lede/target/linux/generic/pending-6.12/203-kallsyms_uncompressed.patch @@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau --- a/init/Kconfig +++ b/init/Kconfig -@@ -1533,6 +1533,17 @@ config SYSCTL_ARCH_UNALIGN_ALLOW +@@ -1534,6 +1534,17 @@ config SYSCTL_ARCH_UNALIGN_ALLOW the unaligned access emulation. see arch/parisc/kernel/unaligned.c for reference @@ -55,7 +55,7 @@ Signed-off-by: Felix Fietkau +#endif /* * Get just the first code, look it up in the token table, - * and return the first char from this token. + * and return the first char from this token. If MSB of length --- a/kernel/vmcore_info.c +++ b/kernel/vmcore_info.c @@ -214,8 +214,10 @@ static int __init crash_save_vmcoreinfo_ diff --git a/lede/target/linux/generic/pending-6.12/303-Revert-powerpc-dts-mpc85xx-remove-simple-bus-compatible-from-ifc-node.patch b/lede/target/linux/generic/pending-6.12/303-Revert-powerpc-dts-mpc85xx-remove-simple-bus-compatible-from-ifc-node.patch new file mode 100644 index 0000000000..31f15a576f --- /dev/null +++ b/lede/target/linux/generic/pending-6.12/303-Revert-powerpc-dts-mpc85xx-remove-simple-bus-compatible-from-ifc-node.patch @@ -0,0 +1,125 @@ +From patchwork Wed Nov 5 20:55:24 2025 +From: Rosen Penev +Subject: [PATCH] Revert "powerpc: dts: mpc85xx: remove "simple-bus" compatible + from ifc node" +Date: Wed, 5 Nov 2025 12:55:24 -0800 + +This reverts commit 0bf51cc9e9e57a751b4c5dacbfa499ba5cd8bd72. + +simple-bus is needed for legacy platforms such as P1010 so that nodes +are populated properly. + +Fixes fsl,ifc-nand probing under at least P1010. + +Signed-off-by: Rosen Penev +--- + arch/powerpc/boot/dts/fsl/b4si-post.dtsi | 2 +- + arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi | 2 +- + arch/powerpc/boot/dts/fsl/bsc9132si-post.dtsi | 2 +- + arch/powerpc/boot/dts/fsl/c293si-post.dtsi | 2 +- + arch/powerpc/boot/dts/fsl/p1010si-post.dtsi | 2 +- + arch/powerpc/boot/dts/fsl/t1023si-post.dtsi | 2 +- + arch/powerpc/boot/dts/fsl/t1040si-post.dtsi | 2 +- + arch/powerpc/boot/dts/fsl/t2081si-post.dtsi | 2 +- + arch/powerpc/boot/dts/fsl/t4240si-post.dtsi | 2 +- + 9 files changed, 9 insertions(+), 9 deletions(-) + +--- a/arch/powerpc/boot/dts/fsl/b4si-post.dtsi ++++ b/arch/powerpc/boot/dts/fsl/b4si-post.dtsi +@@ -50,7 +50,7 @@ + &ifc { + #address-cells = <2>; + #size-cells = <1>; +- compatible = "fsl,ifc"; ++ compatible = "fsl,ifc", "simple-bus"; + interrupts = <25 2 0 0>; + }; + +--- a/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi ++++ b/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi +@@ -35,7 +35,7 @@ + &ifc { + #address-cells = <2>; + #size-cells = <1>; +- compatible = "fsl,ifc"; ++ compatible = "fsl,ifc", "simple-bus"; + interrupts = <16 2 0 0 20 2 0 0>; + }; + +--- a/arch/powerpc/boot/dts/fsl/bsc9132si-post.dtsi ++++ b/arch/powerpc/boot/dts/fsl/bsc9132si-post.dtsi +@@ -35,7 +35,7 @@ + &ifc { + #address-cells = <2>; + #size-cells = <1>; +- compatible = "fsl,ifc"; ++ compatible = "fsl,ifc", "simple-bus"; + /* FIXME: Test whether interrupts are split */ + interrupts = <16 2 0 0 20 2 0 0>; + }; +--- a/arch/powerpc/boot/dts/fsl/c293si-post.dtsi ++++ b/arch/powerpc/boot/dts/fsl/c293si-post.dtsi +@@ -35,7 +35,7 @@ + &ifc { + #address-cells = <2>; + #size-cells = <1>; +- compatible = "fsl,ifc"; ++ compatible = "fsl,ifc", "simple-bus"; + interrupts = <19 2 0 0>; + }; + +--- a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi ++++ b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi +@@ -35,7 +35,7 @@ + &ifc { + #address-cells = <2>; + #size-cells = <1>; +- compatible = "fsl,ifc"; ++ compatible = "fsl,ifc", "simple-bus"; + interrupts = <16 2 0 0 19 2 0 0>; + }; + +--- a/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi ++++ b/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi +@@ -52,7 +52,7 @@ + &ifc { + #address-cells = <2>; + #size-cells = <1>; +- compatible = "fsl,ifc"; ++ compatible = "fsl,ifc", "simple-bus"; + interrupts = <25 2 0 0>; + }; + +--- a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi ++++ b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi +@@ -52,7 +52,7 @@ + &ifc { + #address-cells = <2>; + #size-cells = <1>; +- compatible = "fsl,ifc"; ++ compatible = "fsl,ifc", "simple-bus"; + interrupts = <25 2 0 0>; + }; + +--- a/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi ++++ b/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi +@@ -50,7 +50,7 @@ + &ifc { + #address-cells = <2>; + #size-cells = <1>; +- compatible = "fsl,ifc"; ++ compatible = "fsl,ifc", "simple-bus"; + interrupts = <25 2 0 0>; + }; + +--- a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi ++++ b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi +@@ -50,7 +50,7 @@ + &ifc { + #address-cells = <2>; + #size-cells = <1>; +- compatible = "fsl,ifc"; ++ compatible = "fsl,ifc", "simple-bus"; + interrupts = <25 2 0 0>; + }; + diff --git a/lede/target/linux/generic/pending-6.12/360-Revert-MIPS-mm-kmalloc-tlb_vpn-array-to-avoid-stack-.patch b/lede/target/linux/generic/pending-6.12/360-Revert-MIPS-mm-kmalloc-tlb_vpn-array-to-avoid-stack-.patch new file mode 100644 index 0000000000..522fccd8e2 --- /dev/null +++ b/lede/target/linux/generic/pending-6.12/360-Revert-MIPS-mm-kmalloc-tlb_vpn-array-to-avoid-stack-.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Mon, 15 Dec 2025 01:45:07 +0100 +Subject: Revert "MIPS: mm: kmalloc tlb_vpn array to avoid stack overflow" + +This reverts commit 63a93d1cd6077d79735f804f5a4957bfb240280c. +--- + arch/mips/mm/tlb-r4k.c | 18 ++---------------- + 1 file changed, 2 insertions(+), 16 deletions(-) + +--- a/arch/mips/mm/tlb-r4k.c ++++ b/arch/mips/mm/tlb-r4k.c +@@ -12,7 +12,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -523,26 +522,17 @@ static int r4k_vpn_cmp(const void *a, co + * Initialise all TLB entries with unique values that do not clash with + * what we have been handed over and what we'll be using ourselves. + */ +-static void __ref r4k_tlb_uniquify(void) ++static void r4k_tlb_uniquify(void) + { ++ unsigned long tlb_vpns[1 << MIPS_CONF1_TLBS_SIZE]; + int tlbsize = current_cpu_data.tlbsize; +- bool use_slab = slab_is_available(); + int start = num_wired_entries(); +- phys_addr_t tlb_vpn_size; +- unsigned long *tlb_vpns; + unsigned long vpn_mask; + int cnt, ent, idx, i; + + vpn_mask = GENMASK(cpu_vmbits - 1, 13); + vpn_mask |= IS_ENABLED(CONFIG_64BIT) ? 3ULL << 62 : 1 << 31; + +- tlb_vpn_size = tlbsize * sizeof(*tlb_vpns); +- tlb_vpns = (use_slab ? +- kmalloc(tlb_vpn_size, GFP_KERNEL) : +- memblock_alloc_raw(tlb_vpn_size, sizeof(*tlb_vpns))); +- if (WARN_ON(!tlb_vpns)) +- return; /* Pray local_flush_tlb_all() is good enough. */ +- + htw_stop(); + + for (i = start, cnt = 0; i < tlbsize; i++, cnt++) { +@@ -595,10 +585,6 @@ static void __ref r4k_tlb_uniquify(void) + tlbw_use_hazard(); + htw_start(); + flush_micro_tlb(); +- if (use_slab) +- kfree(tlb_vpns); +- else +- memblock_free(tlb_vpns, tlb_vpn_size); + } + + /* diff --git a/lede/target/linux/generic/pending-6.12/361-Revert-MIPS-mm-Prevent-a-TLB-shutdown-on-initial-uni.patch b/lede/target/linux/generic/pending-6.12/361-Revert-MIPS-mm-Prevent-a-TLB-shutdown-on-initial-uni.patch new file mode 100644 index 0000000000..826ed8efb2 --- /dev/null +++ b/lede/target/linux/generic/pending-6.12/361-Revert-MIPS-mm-Prevent-a-TLB-shutdown-on-initial-uni.patch @@ -0,0 +1,146 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Mon, 15 Dec 2025 01:45:20 +0100 +Subject: Revert "MIPS: mm: Prevent a TLB shutdown on initial uniquification" + +This reverts commit 135178e90aa43ad949534e1d6e376c4034942caa. +--- + arch/mips/mm/tlb-r4k.c | 100 +++++++++++++++-------------------------- + 1 file changed, 37 insertions(+), 63 deletions(-) + +--- a/arch/mips/mm/tlb-r4k.c ++++ b/arch/mips/mm/tlb-r4k.c +@@ -15,7 +15,6 @@ + #include + #include + #include +-#include + + #include + #include +@@ -509,79 +508,55 @@ static int __init set_ntlb(char *str) + + __setup("ntlb=", set_ntlb); + +- +-/* Comparison function for EntryHi VPN fields. */ +-static int r4k_vpn_cmp(const void *a, const void *b) +-{ +- long v = *(unsigned long *)a - *(unsigned long *)b; +- int s = sizeof(long) > sizeof(int) ? sizeof(long) * 8 - 1: 0; +- return s ? (v != 0) | v >> s : v; +-} +- +-/* +- * Initialise all TLB entries with unique values that do not clash with +- * what we have been handed over and what we'll be using ourselves. +- */ ++/* Initialise all TLB entries with unique values */ + static void r4k_tlb_uniquify(void) + { +- unsigned long tlb_vpns[1 << MIPS_CONF1_TLBS_SIZE]; +- int tlbsize = current_cpu_data.tlbsize; +- int start = num_wired_entries(); +- unsigned long vpn_mask; +- int cnt, ent, idx, i; +- +- vpn_mask = GENMASK(cpu_vmbits - 1, 13); +- vpn_mask |= IS_ENABLED(CONFIG_64BIT) ? 3ULL << 62 : 1 << 31; ++ int entry = num_wired_entries(); + + htw_stop(); ++ write_c0_entrylo0(0); ++ write_c0_entrylo1(0); + +- for (i = start, cnt = 0; i < tlbsize; i++, cnt++) { +- unsigned long vpn; ++ while (entry < current_cpu_data.tlbsize) { ++ unsigned long asid_mask = cpu_asid_mask(¤t_cpu_data); ++ unsigned long asid = 0; ++ int idx; + +- write_c0_index(i); +- mtc0_tlbr_hazard(); +- tlb_read(); +- tlb_read_hazard(); +- vpn = read_c0_entryhi(); +- vpn &= vpn_mask & PAGE_MASK; +- tlb_vpns[cnt] = vpn; ++ /* Skip wired MMID to make ginvt_mmid work */ ++ if (cpu_has_mmid) ++ asid = MMID_KERNEL_WIRED + 1; + +- /* Prevent any large pages from overlapping regular ones. */ +- write_c0_pagemask(read_c0_pagemask() & PM_DEFAULT_MASK); ++ /* Check for match before using UNIQUE_ENTRYHI */ ++ do { ++ if (cpu_has_mmid) { ++ write_c0_memorymapid(asid); ++ write_c0_entryhi(UNIQUE_ENTRYHI(entry)); ++ } else { ++ write_c0_entryhi(UNIQUE_ENTRYHI(entry) | asid); ++ } ++ mtc0_tlbw_hazard(); ++ tlb_probe(); ++ tlb_probe_hazard(); ++ idx = read_c0_index(); ++ /* No match or match is on current entry */ ++ if (idx < 0 || idx == entry) ++ break; ++ /* ++ * If we hit a match, we need to try again with ++ * a different ASID. ++ */ ++ asid++; ++ } while (asid < asid_mask); ++ ++ if (idx >= 0 && idx != entry) ++ panic("Unable to uniquify TLB entry %d", idx); ++ ++ write_c0_index(entry); + mtc0_tlbw_hazard(); + tlb_write_indexed(); +- tlbw_use_hazard(); ++ entry++; + } + +- sort(tlb_vpns, cnt, sizeof(tlb_vpns[0]), r4k_vpn_cmp, NULL); +- +- write_c0_pagemask(PM_DEFAULT_MASK); +- write_c0_entrylo0(0); +- write_c0_entrylo1(0); +- +- idx = 0; +- ent = tlbsize; +- for (i = start; i < tlbsize; i++) +- while (1) { +- unsigned long entryhi, vpn; +- +- entryhi = UNIQUE_ENTRYHI(ent); +- vpn = entryhi & vpn_mask & PAGE_MASK; +- +- if (idx >= cnt || vpn < tlb_vpns[idx]) { +- write_c0_entryhi(entryhi); +- write_c0_index(i); +- mtc0_tlbw_hazard(); +- tlb_write_indexed(); +- ent++; +- break; +- } else if (vpn == tlb_vpns[idx]) { +- ent++; +- } else { +- idx++; +- } +- } +- + tlbw_use_hazard(); + htw_start(); + flush_micro_tlb(); +@@ -627,7 +602,6 @@ static void r4k_tlb_configure(void) + + /* From this point on the ARC firmware is dead. */ + r4k_tlb_uniquify(); +- local_flush_tlb_all(); + + /* Did I tell you that ARC SUCKS? */ + } diff --git a/lede/target/linux/generic/pending-6.12/400-mtd-mtdsplit-support.patch b/lede/target/linux/generic/pending-6.12/400-mtd-mtdsplit-support.patch index 838f9ac990..2a3a285a82 100644 --- a/lede/target/linux/generic/pending-6.12/400-mtd-mtdsplit-support.patch +++ b/lede/target/linux/generic/pending-6.12/400-mtd-mtdsplit-support.patch @@ -198,7 +198,7 @@ Subject: [PATCH] mtd: mtdsplit support + if (rootfs_found) + return; + -+ if (of_find_property(mtd_get_of_node(part), "linux,rootfs", NULL) || ++ if (of_property_present(mtd_get_of_node(part), "linux,rootfs") || + !strcmp(part->name, "rootfs")) { + run_parsers_by_type(part, MTD_PARSER_TYPE_ROOTFS); + @@ -207,7 +207,7 @@ Subject: [PATCH] mtd: mtdsplit support + + if (IS_ENABLED(CONFIG_MTD_SPLIT_FIRMWARE) && + !strcmp(part->name, SPLIT_FIRMWARE_NAME) && -+ !of_find_property(mtd_get_of_node(part), "compatible", NULL)) ++ !of_property_present(mtd_get_of_node(part), "compatible")) + split_firmware(master, part); +} + @@ -229,8 +229,8 @@ Subject: [PATCH] mtd: mtdsplit support + mtd_partition_split(master, child); mtd_add_partition_attrs(child); - /* Look for subpartitions */ -@@ -443,31 +588,6 @@ err_del_partitions: + /* Look for subpartitions (skip if no maching parser found) */ +@@ -446,31 +591,6 @@ err_del_partitions: return ret; } diff --git a/lede/target/linux/generic/pending-6.12/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch b/lede/target/linux/generic/pending-6.12/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch deleted file mode 100644 index 119f1da6dc..0000000000 --- a/lede/target/linux/generic/pending-6.12/401-mtd-don-t-register-NVMEM-devices-for-partitions-with.patch +++ /dev/null @@ -1,48 +0,0 @@ -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 -@@ -549,6 +549,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 = NVMEM_DEVID_NONE; - config.dev = &mtd->dev; - config.name = dev_name(&mtd->dev); diff --git a/lede/target/linux/generic/pending-6.12/416-11-next-2-2-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch b/lede/target/linux/generic/pending-6.12/416-11-next-2-2-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch deleted file mode 100644 index 5b1dee3eb1..0000000000 --- a/lede/target/linux/generic/pending-6.12/416-11-next-2-2-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch +++ /dev/null @@ -1,388 +0,0 @@ -From: Gabor Juhos -Date: Fri, 02 May 2025 21:31:17 +0200 -Subject: [PATCH next 2/2] spi: spi-qpic-snand: add support for 8 bits ECC - strength - -Even though the hardware supports 8 bits ECC strength, but that is not -handled in the driver yet. This change adds the missing bits in order -to allow using the driver with chips which require 8 bits ECC strength. - -No functional changes intended with regard to the existing 4 bits ECC -strength support. - -Tested on an IPQ9574 platform using a GigaDevice GD5F2GM7REYIG chip. - -Signed-off-by: Gabor Juhos ---- -mtdtest results: - - # dmesg | grep nand - [ 0.678143] spi-nand spi0.0: GigaDevice SPI NAND was found. - [ 0.687393] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128 - # cat /proc/mtd - dev: size erasesize name - mtd0: 10000000 00020000 "spi0.0" - # insmod mtd_test - # insmod mtd_speedtest dev=0 - [ 63.128425] - [ 63.128452] ================================================= - [ 63.128979] mtd_speedtest: MTD device: 0 - [ 63.134622] mtd_speedtest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128 - [ 63.139561] mtd_test: scanning for bad eraseblocks - [ 63.756447] mtd_test: scanned 2048 eraseblocks, 0 are bad - [ 71.085514] mtd_speedtest: testing eraseblock write speed - [ 202.745977] mtd_speedtest: eraseblock write speed is 1991 KiB/s - [ 202.746022] mtd_speedtest: testing eraseblock read speed - [ 284.104591] mtd_speedtest: eraseblock read speed is 3222 KiB/s - [ 291.405533] mtd_speedtest: testing page write speed - [ 422.516341] mtd_speedtest: page write speed is 1999 KiB/s - [ 422.516384] mtd_speedtest: testing page read speed - [ 504.144630] mtd_speedtest: page read speed is 3211 KiB/s - [ 511.476726] mtd_speedtest: testing 2 page write speed - [ 643.114443] mtd_speedtest: 2 page write speed is 1991 KiB/s - [ 643.114485] mtd_speedtest: testing 2 page read speed - [ 724.434752] mtd_speedtest: 2 page read speed is 3223 KiB/s - [ 724.434796] mtd_speedtest: Testing erase speed - [ 731.792729] mtd_speedtest: erase speed is 35648 KiB/s - [ 731.792772] mtd_speedtest: Testing 2x multi-block erase speed - [ 739.162513] mtd_speedtest: 2x multi-block erase speed is 35589 KiB/s - [ 739.162558] mtd_speedtest: Testing 4x multi-block erase speed - [ 746.486241] mtd_speedtest: 4x multi-block erase speed is 35820 KiB/s - [ 746.486287] mtd_speedtest: Testing 8x multi-block erase speed - [ 753.789683] mtd_speedtest: 8x multi-block erase speed is 35919 KiB/s - [ 753.789728] mtd_speedtest: Testing 16x multi-block erase speed - [ 761.093075] mtd_speedtest: 16x multi-block erase speed is 35920 KiB/s - [ 761.093120] mtd_speedtest: Testing 32x multi-block erase speed - [ 768.396145] mtd_speedtest: 32x multi-block erase speed is 35922 KiB/s - [ 768.396222] mtd_speedtest: Testing 64x multi-block erase speed - [ 775.699819] mtd_speedtest: 64x multi-block erase speed is 35918 KiB/s - [ 775.699863] mtd_speedtest: finished - [ 775.705259] ================================================= - # insmod mtd_readtest dev=0 - [ 919.060671] - [ 919.060699] ================================================= - [ 919.061226] mtd_readtest: MTD device: 0 - [ 919.066957] mtd_readtest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128 - [ 919.070556] mtd_test: scanning for bad eraseblocks - [ 919.086016] mtd_test: scanned 2048 eraseblocks, 0 are bad - [ 919.089465] mtd_readtest: testing page read - [ 1090.778227] mtd_readtest: finished - [ 1090.778286] ================================================= - # insmod mtd_pagetest dev=0 - [ 1216.297313] - [ 1216.297341] ================================================= - [ 1216.297867] mtd_pagetest: MTD device: 0 - [ 1216.303509] mtd_pagetest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128 - [ 1216.307213] mtd_test: scanning for bad eraseblocks - [ 1216.322680] mtd_test: scanned 2048 eraseblocks, 0 are bad - [ 1216.326077] mtd_pagetest: erasing whole device - [ 1223.694968] mtd_pagetest: erased 2048 eraseblocks - [ 1223.695009] mtd_pagetest: writing whole device - [ 1223.763930] mtd_pagetest: written up to eraseblock 0 - [ 1240.268942] mtd_pagetest: written up to eraseblock 256 - [ 1256.641498] mtd_pagetest: written up to eraseblock 512 - [ 1273.139048] mtd_pagetest: written up to eraseblock 768 - [ 1289.718929] mtd_pagetest: written up to eraseblock 1024 - [ 1306.244553] mtd_pagetest: written up to eraseblock 1280 - [ 1322.939723] mtd_pagetest: written up to eraseblock 1536 - [ 1339.246937] mtd_pagetest: written up to eraseblock 1792 - [ 1355.613729] mtd_pagetest: written 2048 eraseblocks - [ 1355.613770] mtd_pagetest: verifying all eraseblocks - [ 1355.854290] mtd_pagetest: verified up to eraseblock 0 - [ 1416.657733] mtd_pagetest: verified up to eraseblock 256 - [ 1477.384593] mtd_pagetest: verified up to eraseblock 512 - [ 1538.008142] mtd_pagetest: verified up to eraseblock 768 - [ 1599.080797] mtd_pagetest: verified up to eraseblock 1024 - [ 1660.775431] mtd_pagetest: verified up to eraseblock 1280 - [ 1722.177149] mtd_pagetest: verified up to eraseblock 1536 - [ 1783.090166] mtd_pagetest: verified up to eraseblock 1792 - [ 1844.450757] mtd_pagetest: verified 2048 eraseblocks - [ 1844.450798] mtd_pagetest: crosstest - [ 1844.455676] mtd_pagetest: reading page at 0x0 - [ 1844.458603] mtd_pagetest: reading page at 0xffff800 - [ 1844.463047] mtd_pagetest: reading page at 0x0 - [ 1844.467790] mtd_pagetest: verifying pages read at 0x0 match - [ 1844.471636] mtd_pagetest: crosstest ok - [ 1844.477062] mtd_pagetest: erasecrosstest - [ 1844.480833] mtd_pagetest: erasing block 0 - [ 1844.488498] mtd_pagetest: writing 1st page of block 0 - [ 1844.489821] mtd_pagetest: reading 1st page of block 0 - [ 1844.494475] mtd_pagetest: verifying 1st page of block 0 - [ 1844.498942] mtd_pagetest: erasing block 0 - [ 1844.507505] mtd_pagetest: writing 1st page of block 0 - [ 1844.509042] mtd_pagetest: erasing block 2047 - [ 1844.516725] mtd_pagetest: reading 1st page of block 0 - [ 1844.518087] mtd_pagetest: verifying 1st page of block 0 - [ 1844.522415] mtd_pagetest: erasecrosstest ok - [ 1844.527495] mtd_pagetest: erasetest - [ 1844.531613] mtd_pagetest: erasing block 0 - [ 1844.538671] mtd_pagetest: writing 1st page of block 0 - [ 1844.540249] mtd_pagetest: erasing block 0 - [ 1844.547869] mtd_pagetest: reading 1st page of block 0 - [ 1844.548927] mtd_pagetest: verifying 1st page of block 0 is all 0xff - [ 1844.553326] mtd_pagetest: erasetest ok - [ 1844.559440] mtd_pagetest: finished with 0 errors - [ 1844.563233] ================================================= - # insmod mtd_subpagetest dev=0 - [ 1942.429708] - [ 1942.429736] ================================================= - [ 1942.430262] mtd_subpagetest: MTD device: 0 - [ 1942.435905] mtd_subpagetest: MTD device size 268435456, eraseblock size 131072, page size 2048, subpage size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128 - [ 1942.439994] mtd_test: scanning for bad eraseblocks - [ 1942.457111] mtd_test: scanned 2048 eraseblocks, 0 are bad - [ 1949.824564] mtd_subpagetest: writing whole device - [ 1949.826670] mtd_subpagetest: written up to eraseblock 0 - [ 1950.351816] mtd_subpagetest: written up to eraseblock 256 - [ 1950.875797] mtd_subpagetest: written up to eraseblock 512 - [ 1951.399912] mtd_subpagetest: written up to eraseblock 768 - [ 1951.923618] mtd_subpagetest: written up to eraseblock 1024 - [ 1952.447361] mtd_subpagetest: written up to eraseblock 1280 - [ 1952.970834] mtd_subpagetest: written up to eraseblock 1536 - [ 1953.494635] mtd_subpagetest: written up to eraseblock 1792 - [ 1954.016265] mtd_subpagetest: written 2048 eraseblocks - [ 1954.016294] mtd_subpagetest: verifying all eraseblocks - [ 1954.021617] mtd_subpagetest: verified up to eraseblock 0 - [ 1954.347458] mtd_subpagetest: verified up to eraseblock 256 - [ 1954.667446] mtd_subpagetest: verified up to eraseblock 512 - [ 1954.987343] mtd_subpagetest: verified up to eraseblock 768 - [ 1955.307385] mtd_subpagetest: verified up to eraseblock 1024 - [ 1955.627462] mtd_subpagetest: verified up to eraseblock 1280 - [ 1955.947277] mtd_subpagetest: verified up to eraseblock 1536 - [ 1956.266834] mtd_subpagetest: verified up to eraseblock 1792 - [ 1956.585581] mtd_subpagetest: verified 2048 eraseblocks - [ 1963.889308] mtd_subpagetest: verifying all eraseblocks for 0xff - [ 1963.930487] mtd_subpagetest: verified up to eraseblock 0 - [ 1974.592567] mtd_subpagetest: verified up to eraseblock 256 - [ 1985.180953] mtd_subpagetest: verified up to eraseblock 512 - [ 1995.805397] mtd_subpagetest: verified up to eraseblock 768 - [ 2006.348859] mtd_subpagetest: verified up to eraseblock 1024 - [ 2016.900530] mtd_subpagetest: verified up to eraseblock 1280 - [ 2027.447587] mtd_subpagetest: verified up to eraseblock 1536 - [ 2037.962383] mtd_subpagetest: verified up to eraseblock 1792 - [ 2048.587863] mtd_subpagetest: verified 2048 eraseblocks - [ 2048.587906] mtd_subpagetest: writing whole device - [ 2048.648174] mtd_subpagetest: written up to eraseblock 0 - [ 2062.643145] mtd_subpagetest: written up to eraseblock 256 - [ 2076.699015] mtd_subpagetest: written up to eraseblock 512 - [ 2091.004910] mtd_subpagetest: written up to eraseblock 768 - [ 2105.149879] mtd_subpagetest: written up to eraseblock 1024 - [ 2119.470691] mtd_subpagetest: written up to eraseblock 1280 - [ 2133.746861] mtd_subpagetest: written up to eraseblock 1536 - [ 2147.776477] mtd_subpagetest: written up to eraseblock 1792 - [ 2161.947734] mtd_subpagetest: written 2048 eraseblocks - [ 2161.947776] mtd_subpagetest: verifying all eraseblocks - [ 2161.986109] mtd_subpagetest: verified up to eraseblock 0 - [ 2170.818316] mtd_subpagetest: verified up to eraseblock 256 - [ 2179.596875] mtd_subpagetest: verified up to eraseblock 512 - [ 2188.405116] mtd_subpagetest: verified up to eraseblock 768 - [ 2197.188588] mtd_subpagetest: verified up to eraseblock 1024 - [ 2206.002204] mtd_subpagetest: verified up to eraseblock 1280 - [ 2214.784815] mtd_subpagetest: verified up to eraseblock 1536 - [ 2223.557141] mtd_subpagetest: verified up to eraseblock 1792 - [ 2232.472832] mtd_subpagetest: verified 2048 eraseblocks - [ 2239.818213] mtd_subpagetest: verifying all eraseblocks for 0xff - [ 2239.861404] mtd_subpagetest: verified up to eraseblock 0 - [ 2250.439035] mtd_subpagetest: verified up to eraseblock 256 - [ 2261.176485] mtd_subpagetest: verified up to eraseblock 512 - [ 2271.713183] mtd_subpagetest: verified up to eraseblock 768 - [ 2282.356892] mtd_subpagetest: verified up to eraseblock 1024 - [ 2292.891424] mtd_subpagetest: verified up to eraseblock 1280 - [ 2303.543110] mtd_subpagetest: verified up to eraseblock 1536 - [ 2314.116690] mtd_subpagetest: verified up to eraseblock 1792 - [ 2324.607804] mtd_subpagetest: verified 2048 eraseblocks - [ 2324.607846] mtd_subpagetest: finished with 0 errors - [ 2324.611859] ================================================= - # insmod mtd_oobtest dev=0 - [ 2336.159109] - [ 2336.159138] ================================================= - [ 2336.159664] mtd_oobtest: MTD device: 0 - [ 2336.165308] mtd_oobtest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128 - [ 2336.169043] mtd_test: scanning for bad eraseblocks - [ 2336.184354] mtd_test: scanned 2048 eraseblocks, 0 are bad - [ 2336.187716] mtd_oobtest: test 1 of 5 - [ 2343.495966] mtd_oobtest: writing OOBs of whole device - [ 2343.496073] mtd_oobtest: written up to eraseblock 0 - [ 2343.516803] mtd_oobtest: written up to eraseblock 256 - [ 2343.533527] mtd_oobtest: written up to eraseblock 512 - [ 2343.549945] mtd_oobtest: written up to eraseblock 768 - [ 2343.563666] mtd_oobtest: written up to eraseblock 1024 - [ 2343.575186] mtd_oobtest: written up to eraseblock 1280 - [ 2343.584310] mtd_oobtest: written up to eraseblock 1536 - [ 2343.593011] mtd_oobtest: written up to eraseblock 1792 - [ 2343.600847] mtd_oobtest: written 2048 eraseblocks - [ 2343.600861] mtd_oobtest: verifying all eraseblocks - [ 2343.604542] mtd_oobtest: verified up to eraseblock 0 - [ 2343.616606] mtd_oobtest: verified up to eraseblock 256 - [ 2343.623992] mtd_oobtest: verified up to eraseblock 512 - [ 2343.631390] mtd_oobtest: verified up to eraseblock 768 - [ 2343.638788] mtd_oobtest: verified up to eraseblock 1024 - [ 2343.646184] mtd_oobtest: verified up to eraseblock 1280 - [ 2343.653570] mtd_oobtest: verified up to eraseblock 1536 - [ 2343.660970] mtd_oobtest: verified up to eraseblock 1792 - [ 2343.668356] mtd_oobtest: verified 2048 eraseblocks - [ 2343.668369] mtd_oobtest: test 2 of 5 - [ 2350.985635] mtd_oobtest: writing OOBs of whole device - [ 2350.985743] mtd_oobtest: written up to eraseblock 0 - [ 2351.006445] mtd_oobtest: written up to eraseblock 256 - [ 2351.023170] mtd_oobtest: written up to eraseblock 512 - [ 2351.039645] mtd_oobtest: written up to eraseblock 768 - [ 2351.053395] mtd_oobtest: written up to eraseblock 1024 - [ 2351.064954] mtd_oobtest: written up to eraseblock 1280 - [ 2351.074144] mtd_oobtest: written up to eraseblock 1536 - [ 2351.082848] mtd_oobtest: written up to eraseblock 1792 - [ 2351.090707] mtd_oobtest: written 2048 eraseblocks - [ 2351.090721] mtd_oobtest: verifying all eraseblocks - [ 2351.094373] mtd_oobtest: verified up to eraseblock 0 - [ 2351.099353] mtd_oobtest: verified up to eraseblock 256 - [ 2351.104460] mtd_oobtest: verified up to eraseblock 512 - [ 2351.109437] mtd_oobtest: verified up to eraseblock 768 - [ 2351.114528] mtd_oobtest: verified up to eraseblock 1024 - [ 2351.119683] mtd_oobtest: verified up to eraseblock 1280 - [ 2351.124772] mtd_oobtest: verified up to eraseblock 1536 - [ 2351.129996] mtd_oobtest: verified up to eraseblock 1792 - [ 2351.135187] mtd_oobtest: verified 2048 eraseblocks - [ 2351.140130] mtd_oobtest: test 3 of 5 - [ 2358.448438] mtd_oobtest: writing OOBs of whole device - [ 2358.448546] mtd_oobtest: written up to eraseblock 0 - [ 2358.469297] mtd_oobtest: written up to eraseblock 256 - [ 2358.486095] mtd_oobtest: written up to eraseblock 512 - [ 2358.501993] mtd_oobtest: written up to eraseblock 768 - [ 2358.515473] mtd_oobtest: written up to eraseblock 1024 - [ 2358.526708] mtd_oobtest: written up to eraseblock 1280 - [ 2358.535426] mtd_oobtest: written up to eraseblock 1536 - [ 2358.544152] mtd_oobtest: written up to eraseblock 1792 - [ 2358.551732] mtd_oobtest: written 2048 eraseblocks - [ 2358.551744] mtd_oobtest: verifying all eraseblocks - [ 2358.555424] mtd_oobtest: verified up to eraseblock 0 - [ 2358.567572] mtd_oobtest: verified up to eraseblock 256 - [ 2358.575045] mtd_oobtest: verified up to eraseblock 512 - [ 2358.582537] mtd_oobtest: verified up to eraseblock 768 - [ 2358.590024] mtd_oobtest: verified up to eraseblock 1024 - [ 2358.597511] mtd_oobtest: verified up to eraseblock 1280 - [ 2358.604984] mtd_oobtest: verified up to eraseblock 1536 - [ 2358.612468] mtd_oobtest: verified up to eraseblock 1792 - [ 2358.619923] mtd_oobtest: verified 2048 eraseblocks - [ 2358.619936] mtd_oobtest: test 4 of 5 - [ 2365.924669] mtd_oobtest: attempting to start write past end of OOB - [ 2365.924711] mtd_oobtest: an error is expected... - [ 2365.929795] mtd_oobtest: error occurred as expected - [ 2365.934520] mtd_oobtest: attempting to start read past end of OOB - [ 2365.939150] mtd_oobtest: an error is expected... - [ 2365.945371] mtd_oobtest: error occurred as expected - [ 2365.950087] mtd_oobtest: attempting to write past end of device - [ 2365.954660] mtd_oobtest: an error is expected... - [ 2365.960623] mtd_oobtest: error occurred as expected - [ 2365.965422] mtd_oobtest: attempting to read past end of device - [ 2365.970064] mtd_oobtest: an error is expected... - [ 2365.975925] mtd_oobtest: error occurred as expected - [ 2365.984256] mtd_oobtest: attempting to write past end of device - [ 2365.985300] mtd_oobtest: an error is expected... - [ 2365.991242] mtd_oobtest: error: wrote past end of device - [ 2365.996064] mtd_oobtest: attempting to read past end of device - [ 2366.001389] mtd_oobtest: an error is expected... - [ 2366.007028] mtd_oobtest: error: read past end of device - [ 2366.011776] mtd_oobtest: test 5 of 5 - [ 2373.317991] mtd_oobtest: writing OOBs of whole device - [ 2373.318034] mtd_oobtest: written up to eraseblock 0 - [ 2373.322028] mtd_oobtest: written up to eraseblock 0 - [ 2373.327465] mtd_oobtest: written up to eraseblock 256 - [ 2373.331576] mtd_oobtest: written up to eraseblock 256 - [ 2373.337501] mtd_oobtest: written up to eraseblock 512 - [ 2373.341820] mtd_oobtest: written up to eraseblock 512 - [ 2373.347566] mtd_oobtest: written up to eraseblock 768 - [ 2373.351888] mtd_oobtest: written up to eraseblock 768 - [ 2373.357634] mtd_oobtest: written up to eraseblock 1024 - [ 2373.361957] mtd_oobtest: written up to eraseblock 1024 - [ 2373.367710] mtd_oobtest: written up to eraseblock 1280 - [ 2373.372113] mtd_oobtest: written up to eraseblock 1280 - [ 2373.377841] mtd_oobtest: written up to eraseblock 1536 - [ 2373.382355] mtd_oobtest: written up to eraseblock 1536 - [ 2373.387962] mtd_oobtest: written up to eraseblock 1792 - [ 2373.392597] mtd_oobtest: written up to eraseblock 1792 - [ 2373.398190] mtd_oobtest: written 2047 eraseblocks - [ 2373.402838] mtd_oobtest: verifying all eraseblocks - [ 2373.407629] mtd_oobtest: verified up to eraseblock 0 - [ 2373.412483] mtd_oobtest: verified up to eraseblock 256 - [ 2373.417625] mtd_oobtest: verified up to eraseblock 512 - [ 2373.422518] mtd_oobtest: verified up to eraseblock 768 - [ 2373.427650] mtd_oobtest: verified up to eraseblock 1024 - [ 2373.432760] mtd_oobtest: verified up to eraseblock 1280 - [ 2373.437912] mtd_oobtest: verified up to eraseblock 1536 - [ 2373.443091] mtd_oobtest: verified up to eraseblock 1792 - [ 2373.448337] mtd_oobtest: verified 2047 eraseblocks - [ 2373.453358] mtd_oobtest: finished with 2 errors - [ 2373.458250] ================================================= - -Note: the two errors are present even even without this patch when testing -the driver with a flash chip requiring 4 bits ECC strength. - - # insmod mtd_stresstest dev=0 - [ 2383.256453] - [ 2383.256482] ================================================= - [ 2383.257008] mtd_stresstest: MTD device: 0 - [ 2383.262650] mtd_stresstest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128 - [ 2383.268254] mtd_test: scanning for bad eraseblocks - [ 2383.281992] mtd_test: scanned 2048 eraseblocks, 0 are bad - [ 2383.285565] mtd_stresstest: doing operations - [ 2383.291047] mtd_stresstest: 0 operations done - [ 2427.841267] mtd_stresstest: 1024 operations done - [ 2471.142229] mtd_stresstest: 2048 operations done - [ 2514.405277] mtd_stresstest: 3072 operations done - [ 2555.451926] mtd_stresstest: 4096 operations done - [ 2598.107133] mtd_stresstest: 5120 operations done - [ 2639.936952] mtd_stresstest: 6144 operations done - [ 2680.724751] mtd_stresstest: 7168 operations done - [ 2720.344163] mtd_stresstest: 8192 operations done - [ 2761.645640] mtd_stresstest: 9216 operations done - [ 2791.760534] mtd_stresstest: finished, 10000 operations done - [ 2791.760817] ================================================= - # ---- - drivers/spi/spi-qpic-snand.c | 21 ++++++++++++++++----- - 1 file changed, 16 insertions(+), 5 deletions(-) - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -283,9 +283,22 @@ static int qcom_spi_ecc_init_ctx_pipelin - goto err_free_ecc_cfg; - } - -- if (ecc_cfg->strength != 4) { -+ switch (ecc_cfg->strength) { -+ case 4: -+ ecc_cfg->ecc_mode = ECC_MODE_4BIT; -+ ecc_cfg->ecc_bytes_hw = 7; -+ ecc_cfg->spare_bytes = 4; -+ break; -+ -+ case 8: -+ ecc_cfg->ecc_mode = ECC_MODE_8BIT; -+ ecc_cfg->ecc_bytes_hw = 13; -+ ecc_cfg->spare_bytes = 2; -+ break; -+ -+ default: - dev_err(snandc->dev, -- "only 4 bits ECC strength is supported\n"); -+ "only 4 or 8 bits ECC strength is supported\n"); - ret = -EOPNOTSUPP; - goto err_free_ecc_cfg; - } -@@ -302,8 +315,6 @@ static int qcom_spi_ecc_init_ctx_pipelin - nand->ecc.ctx.priv = ecc_cfg; - snandc->qspi->mtd = mtd; - -- ecc_cfg->ecc_bytes_hw = 7; -- ecc_cfg->spare_bytes = 4; - ecc_cfg->bbm_size = 1; - ecc_cfg->bch_enabled = true; - ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size; -@@ -349,7 +360,7 @@ static int qcom_spi_ecc_init_ctx_pipelin - FIELD_PREP(ECC_SW_RESET, 0) | - FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, ecc_cfg->cw_data) | - FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) | -- FIELD_PREP(ECC_MODE_MASK, ECC_MODE_4BIT) | -+ FIELD_PREP(ECC_MODE_MASK, ecc_cfg->ecc_mode) | - FIELD_PREP(ECC_PARITY_SIZE_BYTES_BCH_MASK, ecc_cfg->ecc_bytes_hw); - - ecc_cfg->ecc_buf_cfg = 0x203 << NUM_STEPS; diff --git a/lede/target/linux/generic/pending-6.12/417-mtd-spi-nand-macronix-disable-continuous-read-for-MX.patch b/lede/target/linux/generic/pending-6.12/417-mtd-spi-nand-macronix-disable-continuous-read-for-MX.patch new file mode 100644 index 0000000000..65531e099d --- /dev/null +++ b/lede/target/linux/generic/pending-6.12/417-mtd-spi-nand-macronix-disable-continuous-read-for-MX.patch @@ -0,0 +1,39 @@ +From 435afd182e8f5997033da1d69e56094ecb112cad Mon Sep 17 00:00:00 2001 +From: Chukun Pan +Date: Thu, 10 Jun 2025 23:10:16 +0800 +Subject: [PATCH] mtd: spi-nand: macronix: disable continuous read for + MX35LFxGE4AD + +In on-die ECC mode, enabling continuous read will cause ubi_io_read error. +[ 7.852000] ubi0 warning: ubi_io_read: error -5 while reading ... + +So disable it first. Tested on GL.iNet GL-MT3000 with MX35LF2GE4AD flash. + +Fixes: 11813857864f ("mtd: spi-nand: macronix: Continuous read support") +Signed-off-by: Chukun Pan +--- + drivers/mtd/nand/spi/macronix.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/mtd/nand/spi/macronix.c ++++ b/drivers/mtd/nand/spi/macronix.c +@@ -167,8 +167,7 @@ static const struct spinand_info macroni + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, +- macronix_ecc_get_status), +- SPINAND_CONT_READ(macronix_set_cont_read)), ++ macronix_ecc_get_status)), + SPINAND_INFO("MX35LF4GE4AD", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x37, 0x03), + NAND_MEMORG(1, 4096, 128, 64, 2048, 40, 1, 1, 1), +@@ -178,8 +177,7 @@ static const struct spinand_info macroni + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, +- macronix_ecc_get_status), +- SPINAND_CONT_READ(macronix_set_cont_read)), ++ macronix_ecc_get_status)), + SPINAND_INFO("MX35LF1G24AD", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14, 0x03), + NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), diff --git a/lede/target/linux/generic/pending-6.12/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch b/lede/target/linux/generic/pending-6.12/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch index b8c1399f97..f326c61b3a 100644 --- a/lede/target/linux/generic/pending-6.12/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch +++ b/lede/target/linux/generic/pending-6.12/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch @@ -42,21 +42,21 @@ Submitted-by: Daniel Danzberger +++ b/drivers/mtd/nand/spi/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 --spinand-objs := core.o alliancememory.o ato.o esmt.o foresee.o gigadevice.o macronix.o +-spinand-objs := core.o alliancememory.o ato.o esmt.o fmsh.o foresee.o gigadevice.o macronix.o -spinand-objs += micron.o paragon.o toshiba.o winbond.o xtx.o -+spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o foresee.o gigadevice.o ++spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o fmsh.o foresee.o gigadevice.o +spinand-objs += macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o obj-$(CONFIG_MTD_SPI_NAND) += spinand.o --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c -@@ -1116,6 +1116,7 @@ static const struct spinand_manufacturer +@@ -1160,6 +1160,7 @@ static const struct spinand_manufacturer &ato_spinand_manufacturer, &esmt_8c_spinand_manufacturer, &esmt_c8_spinand_manufacturer, + &etron_spinand_manufacturer, + &fmsh_spinand_manufacturer, &foresee_spinand_manufacturer, &gigadevice_spinand_manufacturer, - ¯onix_spinand_manufacturer, --- /dev/null +++ b/drivers/mtd/nand/spi/etron.c @@ -0,0 +1,98 @@ @@ -165,6 +165,6 @@ Submitted-by: Daniel Danzberger extern const struct spinand_manufacturer esmt_8c_spinand_manufacturer; extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; +extern const struct spinand_manufacturer etron_spinand_manufacturer; + extern const struct spinand_manufacturer fmsh_spinand_manufacturer; extern const struct spinand_manufacturer foresee_spinand_manufacturer; extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; - extern const struct spinand_manufacturer macronix_spinand_manufacturer; diff --git a/lede/target/linux/generic/pending-6.12/510-block-add-uImage.FIT-subimage-block-driver.patch b/lede/target/linux/generic/pending-6.12/510-block-add-uImage.FIT-subimage-block-driver.patch index 21615160a9..1ce7c5ab6a 100644 --- a/lede/target/linux/generic/pending-6.12/510-block-add-uImage.FIT-subimage-block-driver.patch +++ b/lede/target/linux/generic/pending-6.12/510-block-add-uImage.FIT-subimage-block-driver.patch @@ -36,7 +36,7 @@ Signed-off-by: Daniel Golle --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -23663,6 +23663,12 @@ F: Documentation/filesystems/ubifs-authe +@@ -23670,6 +23670,12 @@ F: Documentation/filesystems/ubifs-authe F: Documentation/filesystems/ubifs.rst F: fs/ubifs/ diff --git a/lede/target/linux/generic/pending-6.12/620-net-sfp-improve-Huawei-MA5671a-fixup.patch b/lede/target/linux/generic/pending-6.12/620-net-sfp-improve-Huawei-MA5671a-fixup.patch new file mode 100644 index 0000000000..4a5abc4b95 --- /dev/null +++ b/lede/target/linux/generic/pending-6.12/620-net-sfp-improve-Huawei-MA5671a-fixup.patch @@ -0,0 +1,149 @@ +From patchwork Fri Mar 6 12:29:55 2026 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= + +X-Patchwork-Id: 14457090 +X-Patchwork-Delegate: kuba@kernel.org +Received: from mail-wr1-f48.google.com (mail-wr1-f48.google.com + [209.85.221.48]) + (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) + (No client certificate requested) + by smtp.subspace.kernel.org (Postfix) with ESMTPS id AF3F4386459 + for ; Fri, 6 Mar 2026 12:52:18 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + arc=none smtp.client-ip=209.85.221.48 +ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; + t=1772801540; cv=none; + b=LVeywxv8ajenPZ8Kr1arieKosbrf60O9l+ouIPKPFNt5btxWDZ59pIU9BfZjv5n9ifEOyUA/UD0phxnG77+oB/k6UCd7DdGQQASZB3NHq5cvmErbgXm0XG3C8BBxVXU5pF7atPS23kBqM9ptxsv3IaeH/fDFcj6k6SH61rGEpuQ= +ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; + s=arc-20240116; t=1772801540; c=relaxed/simple; + bh=HAy43ssDo0xlUcBDIU7vQZtNnpxG03JPCL6Ldi51ASI=; + h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type; + b=OBk8kI0I91psFRaIxb6nCnAzQlsc7jrXkOPW8lL7cYCosY08yfQDwAlWBFfdFs/VDuVJjD5VEdeQeMt2K4kWGgjLNXhTrRqgs6JNe7PxALDJKvt+kcJ833TRz3hKl2eb2Ft6WnKPf/6hp5Q3qm8+/Q703ixD4sF/0aDNw1BrDY4= +ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=gmail.com; + spf=pass smtp.mailfrom=gmail.com; + dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com + header.b=RCEse1HL; arc=none smtp.client-ip=209.85.221.48 +Authentication-Results: smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=gmail.com +Authentication-Results: smtp.subspace.kernel.org; + spf=pass smtp.mailfrom=gmail.com +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com + header.b="RCEse1HL" +Received: by mail-wr1-f48.google.com with SMTP id + ffacd0b85a97d-439b7c2788dso4008389f8f.1 + for ; Fri, 06 Mar 2026 04:52:18 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20230601; t=1772801537; x=1773406337; + darn=vger.kernel.org; + h=content-transfer-encoding:mime-version:message-id:date:subject:cc + :to:from:from:to:cc:subject:date:message-id:reply-to; + bh=y8B8kg8ACcCsMXy3SgsyRYngVEpIsqkcoCsLOS/nNqQ=; + b=RCEse1HLoUtQApOdbPXFvYItGrEKWhMZ5FH1L4npAxteGeWOhAEAekijg3Ur83ovNu + D7j0Aio5nwazNQz3y4rO88a+svlEbLx5fyxypjkMFUV4PDnOpv7HYjT9Aw1NVdIwO6l+ + sTgZ1jssfWdVnLQwQe6naotyBRoBV2AugdTmASE0Okxrsi3juIOafyTCxnp4K0weRpaH + XodiSWNrkHzZSWM6/wl3D42yExGGPiuDybF+9otR/5TaBWNzrcLkSb73hvP6va35kQWK + mnp6OV+L7iHTbxYpTfTm4axD+IZ/Q/dtFxxA6XolA28oMQbRPK0SIHepheSZx4bgl64w + FM4w== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20230601; t=1772801537; x=1773406337; + h=content-transfer-encoding:mime-version:message-id:date:subject:cc + :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date + :message-id:reply-to; + bh=y8B8kg8ACcCsMXy3SgsyRYngVEpIsqkcoCsLOS/nNqQ=; + b=KomubXrbvHQI4WbFxBztyfrvNNRRWm7V46yQSwx0bP8PXKIJP38kAYzK+ZKWhmcd7e + LpS7422VcYyLywLRxlevD2YaXsF0CK6e00YpTtixakHxYs/4KxGaU21vfwYV8mRhfu7g + HVmxKvNQ6DTdC7wAIGT6TrcZCK4VCvgCx3z9yC62hQc8C6w+9mDnnGPvXNR74ofvvXdC + eVZjm56layRoEr4PTpR2F33OVSt8+HRikH7eBzIKtQ5n/lEKtmJKDHRaodAaCyFGWMWa + qDVoOR8VI4NIJABfsOT6OqisXLPLf+jkKpGkCY2ioRPRKK9GzW4PgIuNcKvPQilQQkgD + Xlnw== +X-Forwarded-Encrypted: i=1; + AJvYcCVcziiSg1n0cDakmiQXH3869FECP24dcIqrZzs8zKakP+vHT958hnq9Bp0alDnLeVtXgo0B8T4=@vger.kernel.org +X-Gm-Message-State: AOJu0Yx2OF1e3PiuR4Zqpe9qXA6kz6T2CCtro6kv8eL2j4Zh2HCjWywo + /rZTavazOZRoq7zTvc4fGZ/yupjkTT9xRPZCKRkM9pc0UuK/KDSP4pan +X-Gm-Gg: ATEYQzx75s3OlYg8XKMgu042++2+ZPa/CZDw09DYtnwEHHBsuylQF0+eXzcFM166JtP + EMuM6Nq/sGQx2WNTPNEyu1BRGci/SV005CzkExhd1KK52D/nC1c76MBxvAtioaI/+5tgNoyCg8v + ZFRyiqDReKfJ6JHa3YRI213dTzMluN1sZTYNSqlWI1MwW66gaDCf0myU81ehAfiAff34wmxnm8C + PUF0YrLYtgZl1I/ZcYM1npoL3PBOnrhaulSqhbn7S5NaZMkHLrNQm6ns1lof+7Ciju05dQpEcBe + pumVg15Dy+PcSXQSSQt4CULH7bbuJvZ0PHJ7dS+74i/OqFSgxD4E7LCqM5ufHYdbESx0/ERaR/z + CAyT3oTz6S1oMQCUTPevHjHjTbDOWhu74SqyTZETzwGnjZnfrPMa56ebQVRfYgOYW0bbx6j3O2M + v3CSEBiXpdFTdaLuRcqIb56JeDryaHx87SOThqnYP6gMiu7EljKYIhr572Rpgz+UIRkrYyNjL9c + BLmrcmhsXX4hU4X5KocoApkO04w +X-Received: by 2002:a05:600c:8b8b:b0:483:103c:b1ee with SMTP id + 5b1f17b1804b1-48526922599mr34173745e9.8.1772801536778; + Fri, 06 Mar 2026 04:52:16 -0800 (PST) +Received: from skynet.lan + (2a02-9142-4581-3c00-0000-0000-0000-0008.red-2a02-914.customerbaf.ipv6.rima-tde.net. + [2a02:9142:4581:3c00::8]) + by smtp.gmail.com with ESMTPSA id + 5b1f17b1804b1-48527681a3esm76085715e9.4.2026.03.06.04.52.14 + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Fri, 06 Mar 2026 04:52:15 -0800 (PST) +From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +To: linux@armlinux.org.uk, + andrew@lunn.ch, + hkallweit1@gmail.com, + davem@davemloft.net, + edumazet@google.com, + kuba@kernel.org, + pabeni@redhat.com, + mnhagan88@gmail.com, + netdev@vger.kernel.org, + linux-kernel@vger.kernel.org +Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= +Subject: [PATCH net v3] net: sfp: improve Huawei MA5671a fixup +Date: Fri, 6 Mar 2026 13:29:55 +0100 +Message-ID: <20260306125139.213637-1-noltari@gmail.com> +X-Mailer: git-send-email 2.47.3 +Precedence: bulk +X-Mailing-List: netdev@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +X-Patchwork-Delegate: kuba@kernel.org + +With the current sfp_fixup_ignore_tx_fault() fixup we ignore the TX_FAULT +signal, but we also need to apply sfp_fixup_ignore_los() in order to be +able to communicate with the module even if the fiber isn't connected for +configuration purposes. +This is needed for all the MA5671a firmwares, excluding the FS modded +firmware. + +Fixes: 2069624dac19 ("net: sfp: Add tx-fault workaround for Huawei MA5671A SFP ONT") +Signed-off-by: Álvaro Fernández Rojas +--- + v3: avoid using a vendor name in the function + v2: rebase on top of net/main instead of linux/master + + drivers/net/phy/sfp.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -360,6 +360,12 @@ static void sfp_fixup_ignore_tx_fault(st + sfp->state_ignore_mask |= SFP_F_TX_FAULT; + } + ++static void sfp_fixup_ignore_tx_fault_and_los(struct sfp *sfp) ++{ ++ sfp_fixup_ignore_tx_fault(sfp); ++ sfp_fixup_ignore_los(sfp); ++} ++ + static void sfp_fixup_ignore_hw(struct sfp *sfp, unsigned int mask) + { + sfp->state_hw_mask &= ~mask; +@@ -523,7 +529,7 @@ static const struct sfp_quirk sfp_quirks + // Huawei MA5671A can operate at 2500base-X, but report 1.2GBd NRZ in + // their EEPROM + SFP_QUIRK("HUAWEI", "MA5671A", sfp_quirk_2500basex, +- sfp_fixup_ignore_tx_fault), ++ sfp_fixup_ignore_tx_fault_and_los), + + // Lantech 8330-262D-E can operate at 2500base-X, but incorrectly report + // 2500MBd NRZ in their EEPROM diff --git a/lede/target/linux/generic/pending-6.12/642-net-bridge-locally-receive-all-multicast-packets-if-.patch b/lede/target/linux/generic/pending-6.12/642-net-bridge-locally-receive-all-multicast-packets-if-.patch deleted file mode 100644 index 98edb315b1..0000000000 --- a/lede/target/linux/generic/pending-6.12/642-net-bridge-locally-receive-all-multicast-packets-if-.patch +++ /dev/null @@ -1,24 +0,0 @@ -From: Felix Fietkau -Date: Mon, 17 Feb 2025 12:21:08 +0100 -Subject: [PATCH] net: bridge: locally receive all multicast packets if - IFF_ALLMULTI is set - -If multicast snooping is enabled, multicast packets may not always end up on -the local bridge interface, if the host is not a member of the multicast -group. Similar to how IFF_PROMISC allows all packets to be received locally, -let IFF_ALLMULTI allow all multicast packets to be received. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/bridge/br_input.c -+++ b/net/bridge/br_input.c -@@ -152,6 +152,8 @@ int br_handle_frame_finish(struct net *n - pkt_type = BR_PKT_MULTICAST; - if (br_multicast_rcv(&brmctx, &pmctx, vlan, skb, vid)) - goto drop; -+ if (br->dev->flags & IFF_ALLMULTI) -+ local_rcv = true; - } - } - diff --git a/lede/target/linux/generic/pending-6.12/650-net-pppoe-implement-GRO-support.patch b/lede/target/linux/generic/pending-6.12/650-net-pppoe-implement-GRO-support.patch index 11d0f03fba..2aa55f84b9 100644 --- a/lede/target/linux/generic/pending-6.12/650-net-pppoe-implement-GRO-support.patch +++ b/lede/target/linux/generic/pending-6.12/650-net-pppoe-implement-GRO-support.patch @@ -23,7 +23,7 @@ Signed-off-by: Felix Fietkau #include -@@ -435,7 +436,7 @@ static int pppoe_rcv(struct sk_buff *skb +@@ -434,7 +435,7 @@ static int pppoe_rcv(struct sk_buff *skb if (skb->len < len) goto drop; @@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau goto drop; ph = pppoe_hdr(skb); -@@ -1173,6 +1174,161 @@ static struct pernet_operations pppoe_ne +@@ -1176,6 +1177,161 @@ static struct pernet_operations pppoe_ne .size = sizeof(struct pppoe_net), }; @@ -194,7 +194,7 @@ Signed-off-by: Felix Fietkau static int __init pppoe_init(void) { int err; -@@ -1189,6 +1345,7 @@ static int __init pppoe_init(void) +@@ -1192,6 +1348,7 @@ static int __init pppoe_init(void) if (err) goto out_unregister_pppoe_proto; @@ -202,7 +202,7 @@ Signed-off-by: Felix Fietkau dev_add_pack(&pppoes_ptype); dev_add_pack(&pppoed_ptype); register_netdevice_notifier(&pppoe_notifier); -@@ -1208,6 +1365,7 @@ static void __exit pppoe_exit(void) +@@ -1211,6 +1368,7 @@ static void __exit pppoe_exit(void) unregister_netdevice_notifier(&pppoe_notifier); dev_remove_pack(&pppoed_ptype); dev_remove_pack(&pppoes_ptype); diff --git a/lede/target/linux/generic/pending-6.12/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch b/lede/target/linux/generic/pending-6.12/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch index 8c7fab9462..951e7f7e24 100644 --- a/lede/target/linux/generic/pending-6.12/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch +++ b/lede/target/linux/generic/pending-6.12/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch @@ -311,7 +311,7 @@ Signed-off-by: Steven Barth /** * ip6_tnl_addr_conflict - compare packet addresses to tunnel's own * @t: the outgoing tunnel device -@@ -1294,6 +1442,7 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str +@@ -1293,6 +1441,7 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str u8 protocol) { struct ip6_tnl *t = netdev_priv(dev); @@ -319,7 +319,7 @@ Signed-off-by: Steven Barth struct ipv6hdr *ipv6h; const struct iphdr *iph; int encap_limit = -1; -@@ -1393,6 +1542,18 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str +@@ -1392,6 +1541,18 @@ ipxip6_tnl_xmit(struct sk_buff *skb, str fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); dsfield = INET_ECN_encapsulate(dsfield, orig_dsfield); @@ -338,7 +338,7 @@ Signed-off-by: Steven Barth if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) return -1; -@@ -1546,6 +1707,14 @@ ip6_tnl_change(struct ip6_tnl *t, const +@@ -1545,6 +1706,14 @@ ip6_tnl_change(struct ip6_tnl *t, const t->parms.link = p->link; t->parms.proto = p->proto; t->parms.fwmark = p->fwmark; @@ -353,7 +353,7 @@ Signed-off-by: Steven Barth dst_cache_reset(&t->dst_cache); ip6_tnl_link_config(t); } -@@ -1580,6 +1749,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ +@@ -1579,6 +1748,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ p->flowinfo = u->flowinfo; p->link = u->link; p->proto = u->proto; @@ -361,7 +361,7 @@ Signed-off-by: Steven Barth memcpy(p->name, u->name, sizeof(u->name)); } -@@ -1963,6 +2133,15 @@ static int ip6_tnl_validate(struct nlatt +@@ -1962,6 +2132,15 @@ static int ip6_tnl_validate(struct nlatt return 0; } @@ -377,7 +377,7 @@ Signed-off-by: Steven Barth static void ip6_tnl_netlink_parms(struct nlattr *data[], struct __ip6_tnl_parm *parms) { -@@ -2000,6 +2179,46 @@ static void ip6_tnl_netlink_parms(struct +@@ -1999,6 +2178,46 @@ static void ip6_tnl_netlink_parms(struct if (data[IFLA_IPTUN_FWMARK]) parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); @@ -424,7 +424,7 @@ Signed-off-by: Steven Barth } static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev, -@@ -2084,6 +2303,12 @@ static void ip6_tnl_dellink(struct net_d +@@ -2083,6 +2302,12 @@ static void ip6_tnl_dellink(struct net_d static size_t ip6_tnl_get_size(const struct net_device *dev) { @@ -437,7 +437,7 @@ Signed-off-by: Steven Barth return /* IFLA_IPTUN_LINK */ nla_total_size(4) + -@@ -2113,6 +2338,24 @@ static size_t ip6_tnl_get_size(const str +@@ -2112,6 +2337,24 @@ static size_t ip6_tnl_get_size(const str nla_total_size(0) + /* IFLA_IPTUN_FWMARK */ nla_total_size(4) + @@ -462,7 +462,7 @@ Signed-off-by: Steven Barth 0; } -@@ -2120,6 +2363,9 @@ static int ip6_tnl_fill_info(struct sk_b +@@ -2119,6 +2362,9 @@ static int ip6_tnl_fill_info(struct sk_b { struct ip6_tnl *tunnel = netdev_priv(dev); struct __ip6_tnl_parm *parm = &tunnel->parms; @@ -472,7 +472,7 @@ Signed-off-by: Steven Barth if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || nla_put_in6_addr(skb, IFLA_IPTUN_LOCAL, &parm->laddr) || -@@ -2129,9 +2375,27 @@ static int ip6_tnl_fill_info(struct sk_b +@@ -2128,9 +2374,27 @@ static int ip6_tnl_fill_info(struct sk_b nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) || nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->proto) || @@ -501,7 +501,7 @@ Signed-off-by: Steven Barth if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, tunnel->encap.type) || nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT, tunnel->encap.sport) || nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT, tunnel->encap.dport) || -@@ -2171,6 +2435,7 @@ static const struct nla_policy ip6_tnl_p +@@ -2170,6 +2434,7 @@ static const struct nla_policy ip6_tnl_p [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 }, [IFLA_IPTUN_COLLECT_METADATA] = { .type = NLA_FLAG }, [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 }, diff --git a/lede/target/linux/generic/pending-6.12/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/lede/target/linux/generic/pending-6.12/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index f0cdd65766..c8693afbba 100644 --- a/lede/target/linux/generic/pending-6.12/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/lede/target/linux/generic/pending-6.12/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -66,7 +66,7 @@ Signed-off-by: Jonas Gorski static void rt_fibinfo_free(struct rtable __rcu **rtp) --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c -@@ -2762,6 +2762,7 @@ static const char *const rtn_type_names[ +@@ -2763,6 +2763,7 @@ static const char *const rtn_type_names[ [RTN_THROW] = "THROW", [RTN_NAT] = "NAT", [RTN_XRESOLVE] = "XRESOLVE", @@ -157,7 +157,7 @@ Signed-off-by: Jonas Gorski case RTN_THROW: case RTN_UNREACHABLE: default: -@@ -4598,6 +4617,17 @@ static int ip6_pkt_prohibit_out(struct n +@@ -4610,6 +4629,17 @@ static int ip6_pkt_prohibit_out(struct n return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); } @@ -175,7 +175,7 @@ Signed-off-by: Jonas Gorski /* * Allocate a dst for local (unicast / anycast) address. */ -@@ -5089,7 +5119,8 @@ static int rtm_to_fib6_config(struct sk_ +@@ -5101,7 +5131,8 @@ static int rtm_to_fib6_config(struct sk_ if (rtm->rtm_type == RTN_UNREACHABLE || rtm->rtm_type == RTN_BLACKHOLE || rtm->rtm_type == RTN_PROHIBIT || @@ -185,7 +185,7 @@ Signed-off-by: Jonas Gorski cfg->fc_flags |= RTF_REJECT; if (rtm->rtm_type == RTN_LOCAL) -@@ -6357,6 +6388,8 @@ static int ip6_route_dev_notify(struct n +@@ -6372,6 +6403,8 @@ static int ip6_route_dev_notify(struct n #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.ip6_prohibit_entry->dst.dev = dev; net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); @@ -194,7 +194,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.dev = dev; net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); #endif -@@ -6368,6 +6401,7 @@ static int ip6_route_dev_notify(struct n +@@ -6383,6 +6416,7 @@ static int ip6_route_dev_notify(struct n in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev); #ifdef CONFIG_IPV6_MULTIPLE_TABLES in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev); @@ -202,7 +202,7 @@ Signed-off-by: Jonas Gorski in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev); #endif } -@@ -6563,6 +6597,8 @@ static int __net_init ip6_route_net_init +@@ -6578,6 +6612,8 @@ static int __net_init ip6_route_net_init #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.fib6_has_custom_rules = false; @@ -211,7 +211,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, sizeof(*net->ipv6.ip6_prohibit_entry), GFP_KERNEL); -@@ -6573,11 +6609,21 @@ static int __net_init ip6_route_net_init +@@ -6588,11 +6624,21 @@ static int __net_init ip6_route_net_init ip6_template_metrics, true); INIT_LIST_HEAD(&net->ipv6.ip6_prohibit_entry->dst.rt_uncached); @@ -234,7 +234,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, ip6_template_metrics, true); -@@ -6604,6 +6650,8 @@ out: +@@ -6619,6 +6665,8 @@ out: return ret; #ifdef CONFIG_IPV6_MULTIPLE_TABLES @@ -243,7 +243,7 @@ Signed-off-by: Jonas Gorski out_ip6_prohibit_entry: kfree(net->ipv6.ip6_prohibit_entry); out_ip6_null_entry: -@@ -6623,6 +6671,7 @@ static void __net_exit ip6_route_net_exi +@@ -6638,6 +6686,7 @@ static void __net_exit ip6_route_net_exi kfree(net->ipv6.ip6_null_entry); #ifdef CONFIG_IPV6_MULTIPLE_TABLES kfree(net->ipv6.ip6_prohibit_entry); @@ -251,7 +251,7 @@ Signed-off-by: Jonas Gorski kfree(net->ipv6.ip6_blk_hole_entry); #endif dst_entries_destroy(&net->ipv6.ip6_dst_ops); -@@ -6706,6 +6755,9 @@ void __init ip6_route_init_special_entri +@@ -6721,6 +6770,9 @@ void __init ip6_route_init_special_entri init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); diff --git a/lede/target/linux/generic/pending-6.12/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch b/lede/target/linux/generic/pending-6.12/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch index 66926bd5fb..fdfacd8dee 100644 --- a/lede/target/linux/generic/pending-6.12/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch +++ b/lede/target/linux/generic/pending-6.12/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch @@ -35,7 +35,7 @@ Signed-off-by: Felix Fietkau | NETIF_F_HW_CSUM --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c -@@ -897,7 +897,7 @@ static int macvlan_hwtstamp_set(struct n +@@ -903,7 +903,7 @@ static int macvlan_hwtstamp_set(struct n static struct lock_class_key macvlan_netdev_addr_lock_key; #define ALWAYS_ON_OFFLOADS \ @@ -96,7 +96,7 @@ Signed-off-by: Felix Fietkau } --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -2554,7 +2554,7 @@ void sk_setup_caps(struct sock *sk, stru +@@ -2557,7 +2557,7 @@ void sk_setup_caps(struct sock *sk, stru icsk->icsk_ack.dst_quick_ack = dst_metric(dst, RTAX_QUICKACK); } if (sk->sk_route_caps & NETIF_F_GSO) diff --git a/lede/target/linux/generic/pending-6.12/690-net-add-missing-check-for-TCP-fraglist-GRO.patch b/lede/target/linux/generic/pending-6.12/690-net-add-missing-check-for-TCP-fraglist-GRO.patch index 2cf8cf159f..4684e045d2 100644 --- a/lede/target/linux/generic/pending-6.12/690-net-add-missing-check-for-TCP-fraglist-GRO.patch +++ b/lede/target/linux/generic/pending-6.12/690-net-add-missing-check-for-TCP-fraglist-GRO.patch @@ -16,7 +16,7 @@ Signed-off-by: Felix Fietkau --- a/net/ipv4/tcp_offload.c +++ b/net/ipv4/tcp_offload.c -@@ -354,6 +354,7 @@ struct sk_buff *tcp_gro_receive(struct l +@@ -355,6 +355,7 @@ struct sk_buff *tcp_gro_receive(struct l flush |= (__force int)(flags ^ tcp_flag_word(th2)); flush |= skb->ip_summed != p->ip_summed; flush |= skb->csum_level != p->csum_level; diff --git a/lede/target/linux/generic/pending-6.12/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch b/lede/target/linux/generic/pending-6.12/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch index 2ab483d6c4..360168ab23 100644 --- a/lede/target/linux/generic/pending-6.12/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch +++ b/lede/target/linux/generic/pending-6.12/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch @@ -18,7 +18,7 @@ Signed-off-by: Felix Fietkau --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c -@@ -8638,7 +8638,7 @@ static int nft_register_flowtable_net_ho +@@ -8718,7 +8718,7 @@ static int nft_register_flowtable_net_ho err = flowtable->data.type->setup(&flowtable->data, hook->ops.dev, FLOW_BLOCK_BIND); diff --git a/lede/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch b/lede/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch index ed6c9070b2..4e00118e53 100644 --- a/lede/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/lede/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -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 -@@ -996,6 +996,12 @@ struct phy_driver { +@@ -1037,6 +1037,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.12/704-net-phy-register-phy-led_triggers-during-probe-to-av.patch b/lede/target/linux/generic/pending-6.12/704-net-phy-register-phy-led_triggers-during-probe-to-av.patch new file mode 100644 index 0000000000..126275c7ec --- /dev/null +++ b/lede/target/linux/generic/pending-6.12/704-net-phy-register-phy-led_triggers-during-probe-to-av.patch @@ -0,0 +1,116 @@ +From 5225349f1e750dfd107a4c5dc97d91fa212dc1ed Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Sat, 21 Feb 2026 14:51:54 -0600 +Subject: [PATCH] net: phy: register phy led_triggers during probe to avoid + AB-BA deadlock + +There is an AB-BA deadlock when both LEDS_TRIGGER_NETDEV and +LED_TRIGGER_PHY are enabled: + +[ 1362.049207] [<8054e4b8>] led_trigger_register+0x5c/0x1fc <-- Trying to get lock "triggers_list_lock" via down_write(&triggers_list_lock); +[ 1362.054536] [<80662830>] phy_led_triggers_register+0xd0/0x234 +[ 1362.060329] [<8065e200>] phy_attach_direct+0x33c/0x40c +[ 1362.065489] [<80651fc4>] phylink_fwnode_phy_connect+0x15c/0x23c +[ 1362.071480] [<8066ee18>] mtk_open+0x7c/0xba0 +[ 1362.075849] [<806d714c>] __dev_open+0x280/0x2b0 +[ 1362.080384] [<806d7668>] __dev_change_flags+0x244/0x24c +[ 1362.085598] [<806d7698>] dev_change_flags+0x28/0x78 +[ 1362.090528] [<807150e4>] dev_ioctl+0x4c0/0x654 <-- Hold lock "rtnl_mutex" by calling rtnl_lock(); +[ 1362.094985] [<80694360>] sock_ioctl+0x2f4/0x4e0 +[ 1362.099567] [<802e9c4c>] sys_ioctl+0x32c/0xd8c +[ 1362.104022] [<80014504>] syscall_common+0x34/0x58 + +Here LED_TRIGGER_PHY is registering LED triggers during phy_attach +while holding RTNL and then taking triggers_list_lock. + +[ 1362.191101] [<806c2640>] register_netdevice_notifier+0x60/0x168 <-- Trying to get lock "rtnl_mutex" via rtnl_lock(); +[ 1362.197073] [<805504ac>] netdev_trig_activate+0x194/0x1e4 +[ 1362.202490] [<8054e28c>] led_trigger_set+0x1d4/0x360 <-- Hold lock "triggers_list_lock" by down_read(&triggers_list_lock); +[ 1362.207511] [<8054eb38>] led_trigger_write+0xd8/0x14c +[ 1362.212566] [<80381d98>] sysfs_kf_bin_write+0x80/0xbc +[ 1362.217688] [<8037fcd8>] kernfs_fop_write_iter+0x17c/0x28c +[ 1362.223174] [<802cbd70>] vfs_write+0x21c/0x3c4 +[ 1362.227712] [<802cc0c4>] ksys_write+0x78/0x12c +[ 1362.232164] [<80014504>] syscall_common+0x34/0x58 + +Here LEDS_TRIGGER_NETDEV is being enabled on an LED. It first takes +triggers_list_lock and then RTNL. A classical AB-BA deadlock. + +phy_led_triggers_registers() does not require the RTNL, it does not +make any calls into the network stack which require protection. There +is also no requirement the PHY has been attached to a MAC, the +triggers only make use of phydev state. This allows the call to +phy_led_triggers_registers() to be placed elsewhere. PHY probe() and +release() don't hold RTNL, so solving the AB-BA deadlock. + +Reported-by: Shiji Yang +Closes: https://lore.kernel.org/all/OS7PR01MB13602B128BA1AD3FA38B6D1FFBC69A@OS7PR01MB13602.jpnprd01.prod.outlook.com/ +Fixes: 06f502f57d0d ("leds: trigger: Introduce a NETDEV trigger") +Signed-off-by: Andrew Lunn +--- + drivers/net/phy/phy_device.c | 25 +++++++++++++++++-------- + 1 file changed, 17 insertions(+), 8 deletions(-) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1684,8 +1684,6 @@ int phy_attach_direct(struct net_device + goto error; + + phy_resume(phydev); +- if (!phydev->is_on_sfp_module) +- phy_led_triggers_register(phydev); + + /** + * If the external phy used by current mac interface is managed by +@@ -2058,9 +2056,6 @@ void phy_detach(struct phy_device *phyde + } + phydev->phylink = NULL; + +- if (!phydev->is_on_sfp_module) +- phy_led_triggers_unregister(phydev); +- + if (phydev->mdio.dev.driver) + module_put(phydev->mdio.dev.driver->owner); + +@@ -3691,17 +3686,28 @@ static int phy_probe(struct device *dev) + /* Set the state to READY by default */ + phydev->state = PHY_READY; + ++ /* Register the PHY LED triggers */ ++ if (!phydev->is_on_sfp_module) ++ phy_led_triggers_register(phydev); ++ + /* Get the LEDs from the device tree, and instantiate standard + * LEDs for them. + */ + if (IS_ENABLED(CONFIG_PHYLIB_LEDS) && !phy_driver_is_genphy(phydev) && +- !phy_driver_is_genphy_10g(phydev)) ++ !phy_driver_is_genphy_10g(phydev)) { + err = of_phy_leds(phydev); ++ if (err) ++ goto out; ++ } ++ ++ return 0; + + out: ++ if (!phydev->is_on_sfp_module) ++ phy_led_triggers_unregister(phydev); ++ + /* Re-assert the reset signal on error */ +- if (err) +- phy_device_reset(phydev, 1); ++ phy_device_reset(phydev, 1); + + return err; + } +@@ -3716,6 +3722,9 @@ static int phy_remove(struct device *dev + !phy_driver_is_genphy_10g(phydev)) + phy_leds_unregister(phydev); + ++ if (!phydev->is_on_sfp_module) ++ phy_led_triggers_unregister(phydev); ++ + phydev->state = PHY_DOWN; + + sfp_bus_del_upstream(phydev->sfp_bus); diff --git a/lede/target/linux/generic/pending-6.12/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch b/lede/target/linux/generic/pending-6.12/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch index 6b2b016881..dea84c7079 100644 --- a/lede/target/linux/generic/pending-6.12/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch +++ b/lede/target/linux/generic/pending-6.12/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch @@ -20,7 +20,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -2086,7 +2086,7 @@ int phylink_fwnode_phy_connect(struct ph +@@ -2273,7 +2273,7 @@ int phylink_fwnode_phy_connect(struct ph { struct fwnode_handle *phy_fwnode; struct phy_device *phy_dev; @@ -29,7 +29,7 @@ Signed-off-by: Daniel Golle /* Fixed links and 802.3z are handled without needing a PHY */ if (pl->cfg_link_an_mode == MLO_AN_FIXED || -@@ -2116,6 +2116,25 @@ int phylink_fwnode_phy_connect(struct ph +@@ -2303,6 +2303,25 @@ int phylink_fwnode_phy_connect(struct ph if (pl->config->mac_requires_rxc) flags |= PHY_F_RXC_ALWAYS_ON; diff --git a/lede/target/linux/generic/pending-6.12/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch b/lede/target/linux/generic/pending-6.12/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch index c44d2cf736..2f90df6013 100644 --- a/lede/target/linux/generic/pending-6.12/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch +++ b/lede/target/linux/generic/pending-6.12/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch @@ -24,7 +24,7 @@ Signed-off-by: Felix Fietkau --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c -@@ -201,6 +201,7 @@ void br_flood(struct net_bridge *br, str +@@ -202,6 +202,7 @@ void br_flood(struct net_bridge *br, str enum br_pkt_type pkt_type, bool local_rcv, bool local_orig, u16 vid) { @@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau struct net_bridge_port *prev = NULL; struct net_bridge_port *p; -@@ -218,6 +219,10 @@ void br_flood(struct net_bridge *br, str +@@ -219,6 +220,10 @@ void br_flood(struct net_bridge *br, str case BR_PKT_MULTICAST: if (!(p->flags & BR_MCAST_FLOOD) && skb->dev != br->dev) continue; @@ -45,7 +45,7 @@ Signed-off-by: Felix Fietkau if (!(p->flags & BR_BCAST_FLOOD) && skb->dev != br->dev) --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c -@@ -369,6 +369,8 @@ static rx_handler_result_t br_handle_fra +@@ -368,6 +368,8 @@ static rx_handler_result_t br_handle_fra fwd_mask |= p->group_fwd_mask; switch (dest[5]) { case 0x00: /* Bridge Group Address */ @@ -161,7 +161,7 @@ Signed-off-by: Felix Fietkau struct rtnl_link { rtnl_doit_func doit; -@@ -5012,7 +5012,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu +@@ -5009,7 +5009,9 @@ int ndo_dflt_bridge_getlink(struct sk_bu brport_nla_put_flag(skb, flags, mask, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD) || brport_nla_put_flag(skb, flags, mask, diff --git a/lede/target/linux/generic/pending-6.12/720-01-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch b/lede/target/linux/generic/pending-6.12/720-01-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch index 1becba6da6..ce4fd03115 100644 --- a/lede/target/linux/generic/pending-6.12/720-01-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch +++ b/lede/target/linux/generic/pending-6.12/720-01-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch @@ -15,7 +15,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c -@@ -1638,6 +1638,7 @@ static struct phy_driver realtek_drvs[] +@@ -2090,6 +2090,7 @@ static struct phy_driver realtek_drvs[] }, { .name = "RTL8226 2.5Gbps PHY", .match_phy_device = rtl8226_match_phy_device, @@ -23,7 +23,7 @@ Signed-off-by: Daniel Golle .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .read_status = rtl822x_read_status, -@@ -1648,6 +1649,7 @@ static struct phy_driver realtek_drvs[] +@@ -2100,6 +2101,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_match_phy_device, .name = "RTL8226B_RTL8221B 2.5Gbps PHY", @@ -31,15 +31,7 @@ Signed-off-by: Daniel Golle .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .config_init = rtl822xb_config_init, -@@ -1660,6 +1662,7 @@ static struct phy_driver realtek_drvs[] - }, { - PHY_ID_MATCH_EXACT(0x001cc838), - .name = "RTL8226-CG 2.5Gbps PHY", -+ .soft_reset = genphy_soft_reset, - .get_features = rtl822x_get_features, - .config_aneg = rtl822x_config_aneg, - .read_status = rtl822x_read_status, -@@ -1670,6 +1673,7 @@ static struct phy_driver realtek_drvs[] +@@ -2122,6 +2124,7 @@ static struct phy_driver realtek_drvs[] }, { PHY_ID_MATCH_EXACT(0x001cc848), .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", @@ -47,7 +39,7 @@ Signed-off-by: Daniel Golle .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .config_init = rtl822xb_config_init, -@@ -1682,6 +1686,7 @@ static struct phy_driver realtek_drvs[] +@@ -2134,6 +2137,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", @@ -55,27 +47,27 @@ Signed-off-by: Daniel Golle .probe = rtl822x_probe, .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, -@@ -1695,6 +1700,7 @@ static struct phy_driver realtek_drvs[] - }, { - .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, +@@ -2149,6 +2153,7 @@ static struct phy_driver realtek_drvs[] .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", -+ .soft_reset = genphy_soft_reset, + .config_intr = rtl8221b_config_intr, + .handle_interrupt = rtl8221b_handle_interrupt, ++ .soft_reset = rtl822x_c45_soft_reset, .probe = rtl822x_probe, .config_init = rtl822xb_config_init, .get_rate_matching = rtl822xb_get_rate_matching, -@@ -1706,6 +1712,7 @@ static struct phy_driver realtek_drvs[] +@@ -2160,6 +2165,7 @@ static struct phy_driver realtek_drvs[] }, { - .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, + .match_phy_device = rtl8221b_vm_cg_c22_match_phy_device, .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", + .soft_reset = genphy_soft_reset, .probe = rtl822x_probe, .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, -@@ -1719,6 +1726,7 @@ static struct phy_driver realtek_drvs[] - }, { - .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, - .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", -+ .soft_reset = genphy_soft_reset, +@@ -2175,6 +2181,7 @@ static struct phy_driver realtek_drvs[] + .name = "RTL8221B-VM-CG 2.5Gbps PHY (C45)", + .config_intr = rtl8221b_config_intr, + .handle_interrupt = rtl8221b_handle_interrupt, ++ .soft_reset = rtl822x_c45_soft_reset, .probe = rtl822x_probe, .config_init = rtl822xb_config_init, .get_rate_matching = rtl822xb_get_rate_matching, diff --git a/lede/target/linux/generic/pending-6.12/720-02-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch b/lede/target/linux/generic/pending-6.12/720-02-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch index a20c45fc65..85b2dbd8c6 100644 --- a/lede/target/linux/generic/pending-6.12/720-02-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch +++ b/lede/target/linux/generic/pending-6.12/720-02-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch @@ -10,6 +10,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 @@ -19,8 +20,8 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c -@@ -1035,8 +1035,8 @@ static int rtl822x_probe(struct phy_devi - static int rtl822xb_config_init(struct phy_device *phydev) +@@ -1241,8 +1241,8 @@ static int rtl822x_probe(struct phy_devi + static int rtl822x_set_serdes_option_mode(struct phy_device *phydev, bool gen1) { bool has_2500, has_sgmii; + int ret, val; @@ -29,15 +30,28 @@ Signed-off-by: Daniel Golle has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->host_interfaces) || -@@ -1086,7 +1086,29 @@ static int rtl822xb_config_init(struct p - if (ret < 0) - return ret; - -- return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020); -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020); +@@ -1284,18 +1284,42 @@ static int rtl822x_set_serdes_option_mod + RTL822X_VND1_SERDES_OPTION, + RTL822X_VND1_SERDES_OPTION_MODE_MASK, + mode); +- if (gen1 || ret < 0) + if (ret < 0) + return ret; + ++ if (!gen1) { ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6a04, 0x0503); ++ if (ret < 0) ++ return ret; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f10, 0xd455); ++ if (ret < 0) ++ return ret; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020); ++ if (ret < 0) ++ return ret; ++ } ++ + /* Disable SGMII AN */ + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x7588, 0x2); + if (ret < 0) @@ -45,18 +59,21 @@ Signed-off-by: Daniel Golle + + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x7589, 0x71d0); + if (ret < 0) -+ return ret; -+ + return ret; + +- ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6a04, 0x0503); + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x7587, 0x3); -+ if (ret < 0) -+ return ret; -+ + if (ret < 0) + return ret; + +- ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f10, 0xd455); + ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, 0x7587, + val, !(val & BIT(0)), 500, 100000, false); -+ if (ret < 0) -+ return ret; -+ + if (ret < 0) + return ret; + +- return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020); + return 0; } - static int rtl822xb_get_rate_matching(struct phy_device *phydev, + static int rtl822x_config_init(struct phy_device *phydev) diff --git a/lede/target/linux/generic/pending-6.12/720-03-net-phy-realtek-make-sure-paged-read-is-protected-by.patch b/lede/target/linux/generic/pending-6.12/720-03-net-phy-realtek-make-sure-paged-read-is-protected-by.patch index e6656445db..d603be802e 100644 --- a/lede/target/linux/generic/pending-6.12/720-03-net-phy-realtek-make-sure-paged-read-is-protected-by.patch +++ b/lede/target/linux/generic/pending-6.12/720-03-net-phy-realtek-make-sure-paged-read-is-protected-by.patch @@ -18,7 +18,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c -@@ -1313,9 +1313,11 @@ static bool rtlgen_supports_2_5gbps(stru +@@ -1711,9 +1711,11 @@ static bool rtlgen_supports_2_5gbps(stru { int val; diff --git a/lede/target/linux/generic/pending-6.12/720-04-net-phy-realtek-setup-aldps.patch b/lede/target/linux/generic/pending-6.12/720-04-net-phy-realtek-setup-aldps.patch index 3d3f7f5deb..e65dc43cba 100644 --- a/lede/target/linux/generic/pending-6.12/720-04-net-phy-realtek-setup-aldps.patch +++ b/lede/target/linux/generic/pending-6.12/720-04-net-phy-realtek-setup-aldps.patch @@ -13,9 +13,9 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c -@@ -129,6 +129,10 @@ - */ - #define RTL822X_VND2_C22_REG(reg) (0xa400 + 2 * (reg)) +@@ -162,6 +162,10 @@ + + #define RTL8224_SRAM_RTCT_LEN(pair) (0x8028 + (pair) * 4) +#define RTL8221B_PHYCR1 0xa430 +#define RTL8221B_PHYCR1_ALDPS_EN BIT(2) @@ -24,68 +24,19 @@ Signed-off-by: Daniel Golle #define RTL8366RB_POWER_SAVE 0x15 #define RTL8366RB_POWER_SAVE_ON BIT(12) -@@ -175,6 +179,10 @@ struct rtl821x_priv { - u32 saved_wolopts; - }; +@@ -1301,6 +1305,15 @@ static int rtl822x_set_serdes_option_mod + return ret; + } -+struct rtl822x_priv { -+ bool enable_aldps; -+}; ++ if (of_property_read_bool(phydev->mdio.dev.of_node, "realtek,aldps-enable")) ++ ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, RTL8221B_PHYCR1, ++ RTL8221B_PHYCR1_ALDPS_EN | RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN); ++ else ++ ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, RTL8221B_PHYCR1, ++ RTL8221B_PHYCR1_ALDPS_EN | RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN); ++ if (ret < 0) ++ return ret; + - static int rtl821x_read_page(struct phy_device *phydev) - { - return __phy_read(phydev, RTL821x_PAGE_SELECT); -@@ -1025,6 +1033,18 @@ static int rtl822x_write_mmd(struct phy_ - - static int rtl822x_probe(struct phy_device *phydev) - { -+ struct device *dev = &phydev->mdio.dev; -+ struct rtl822x_priv *priv; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->enable_aldps = of_property_read_bool(dev->of_node, -+ "realtek,aldps-enable"); -+ -+ phydev->priv = priv; -+ - if (IS_ENABLED(CONFIG_REALTEK_PHY_HWMON) && - phydev->phy_id != RTL_GENERIC_PHYID) - return rtl822x_hwmon_init(phydev); -@@ -1032,6 +1052,19 @@ static int rtl822x_probe(struct phy_devi - return 0; - } - -+static int rtl822x_init_phycr1(struct phy_device *phydev, bool no_aldps) -+{ -+ struct rtl822x_priv *priv = phydev->priv; -+ u16 val = 0; -+ -+ if (priv->enable_aldps && !no_aldps) -+ val = RTL8221B_PHYCR1_ALDPS_EN | RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN; -+ -+ return phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL8221B_PHYCR1, -+ RTL8221B_PHYCR1_ALDPS_EN | -+ RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN, val); -+} -+ - static int rtl822xb_config_init(struct phy_device *phydev) - { - bool has_2500, has_sgmii; -@@ -1108,6 +1141,14 @@ static int rtl822xb_config_init(struct p + /* Disable SGMII AN */ + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x7588, 0x2); if (ret < 0) - return ret; - -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020); -+ if (ret < 0) -+ return ret; -+ -+ ret = rtl822x_init_phycr1(phydev, false); -+ if (ret < 0) -+ return ret; -+ - return 0; - } - diff --git a/lede/target/linux/generic/pending-6.12/720-05-net-phy-realtek-detect-early-version-of-RTL8221B.patch b/lede/target/linux/generic/pending-6.12/720-05-net-phy-realtek-detect-early-version-of-RTL8221B.patch index 67e81a38a7..80023a0a51 100644 --- a/lede/target/linux/generic/pending-6.12/720-05-net-phy-realtek-detect-early-version-of-RTL8221B.patch +++ b/lede/target/linux/generic/pending-6.12/720-05-net-phy-realtek-detect-early-version-of-RTL8221B.patch @@ -14,7 +14,7 @@ Signed-off-by: Daniel Golle Signed-off-by: Mieczyslaw Nalewaj --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c -@@ -1368,10 +1368,32 @@ static int rtl8226_match_phy_device(stru +@@ -1768,10 +1768,32 @@ static int rtl8226_match_phy_device(stru static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id, bool is_c45) { diff --git a/lede/target/linux/generic/pending-6.12/720-06-net-phy-realtek-support-interrupt-of-RTL8221B.patch b/lede/target/linux/generic/pending-6.12/720-06-net-phy-realtek-support-interrupt-of-RTL8221B.patch deleted file mode 100644 index 9afe8baca6..0000000000 --- a/lede/target/linux/generic/pending-6.12/720-06-net-phy-realtek-support-interrupt-of-RTL8221B.patch +++ /dev/null @@ -1,102 +0,0 @@ -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/realtek_main.c | 47 +++++++++++++++++++++++++++++++++++++++ - 1 file changed, 47 insertions(+) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -1580,6 +1580,51 @@ static irqreturn_t rtl9000a_handle_inter - return IRQ_HANDLED; - } - -+static int rtl8221b_ack_interrupt(struct phy_device *phydev) -+{ -+ int err; -+ -+ err = phy_read_mmd(phydev, MDIO_MMD_VEND2, 0xa4d4); -+ -+ return (err < 0) ? err : 0; -+} -+ -+static int rtl8221b_config_intr(struct phy_device *phydev) -+{ -+ int err; -+ -+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { -+ err = rtl8221b_ack_interrupt(phydev); -+ if (err) -+ return err; -+ -+ err = phy_write_mmd(phydev, MDIO_MMD_VEND2, 0xa4d2, 0x7ff); -+ } else { -+ err = phy_write_mmd(phydev, MDIO_MMD_VEND2, 0xa4d2, 0x0); -+ if (err) -+ return err; -+ -+ err = rtl8221b_ack_interrupt(phydev); -+ } -+ -+ return err; -+} -+ -+static irqreturn_t rtl8221b_handle_interrupt(struct phy_device *phydev) -+{ -+ int err; -+ -+ err = rtl8221b_ack_interrupt(phydev); -+ if (err) { -+ phy_error(phydev); -+ return IRQ_NONE; -+ } -+ -+ phy_trigger_machine(phydev); -+ -+ return IRQ_HANDLED; -+} -+ - static struct phy_driver realtek_drvs[] = { - { - PHY_ID_MATCH_EXACT(0x00008201), -@@ -1745,6 +1790,8 @@ static struct phy_driver realtek_drvs[] - }, { - .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, - .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", -+ .config_intr = rtl8221b_config_intr, -+ .handle_interrupt = rtl8221b_handle_interrupt, - .soft_reset = genphy_soft_reset, - .probe = rtl822x_probe, - .get_features = rtl822x_get_features, -@@ -1759,6 +1806,8 @@ static struct phy_driver realtek_drvs[] - }, { - .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, - .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", -+ .config_intr = rtl8221b_config_intr, -+ .handle_interrupt = rtl8221b_handle_interrupt, - .soft_reset = genphy_soft_reset, - .probe = rtl822x_probe, - .config_init = rtl822xb_config_init, -@@ -1771,6 +1820,8 @@ static struct phy_driver realtek_drvs[] - }, { - .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, - .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", -+ .config_intr = rtl8221b_config_intr, -+ .handle_interrupt = rtl8221b_handle_interrupt, - .soft_reset = genphy_soft_reset, - .probe = rtl822x_probe, - .get_features = rtl822x_get_features, -@@ -1785,6 +1836,8 @@ static struct phy_driver realtek_drvs[] - }, { - .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, - .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", -+ .config_intr = rtl8221b_config_intr, -+ .handle_interrupt = rtl8221b_handle_interrupt, - .soft_reset = genphy_soft_reset, - .probe = rtl822x_probe, - .config_init = rtl822xb_config_init, diff --git a/lede/target/linux/generic/pending-6.12/720-07-net-phy-realtek-mark-existing-MMDs-as-present.patch b/lede/target/linux/generic/pending-6.12/720-07-net-phy-realtek-mark-existing-MMDs-as-present.patch index 20bd666fd2..b06ddb09e2 100644 --- a/lede/target/linux/generic/pending-6.12/720-07-net-phy-realtek-mark-existing-MMDs-as-present.patch +++ b/lede/target/linux/generic/pending-6.12/720-07-net-phy-realtek-mark-existing-MMDs-as-present.patch @@ -15,7 +15,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c -@@ -1244,6 +1244,9 @@ static int rtl822x_c45_get_features(stru +@@ -1465,6 +1465,9 @@ static int rtl822x_c45_get_features(stru linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, phydev->supported); diff --git a/lede/target/linux/generic/pending-6.12/720-08-net-phy-realtek-work-around-broken-serdes.patch b/lede/target/linux/generic/pending-6.12/720-08-net-phy-realtek-work-around-broken-serdes.patch new file mode 100644 index 0000000000..5bde9d157d --- /dev/null +++ b/lede/target/linux/generic/pending-6.12/720-08-net-phy-realtek-work-around-broken-serdes.patch @@ -0,0 +1,58 @@ +From: Daniel Golle +Date: Thu, 30 Jan 2025 05:33:12 +0000 +Subject: [PATCH] net: phy: realtek: work around broken SerDes + +For still unknown reasons the SerDes init sequence may sometimes +time out because a self-clearing bit never clears, indicating the +PHY has entered an unrecoverable error state. + +Work-around the issue by triggering a hardware reset and retry the +setup sequence while warning the user that this has happened. +This is really more of a work-around than a fix, and should be +replaced by a better actual fix in future (hopefully). + +Signed-off-by: Daniel Golle +--- +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -1345,6 +1345,22 @@ static int rtl822xb_config_init(struct p + return rtl822x_set_serdes_option_mode(phydev, false); + } + ++static int rtl822xb_config_init_war(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = rtl822xb_config_init(phydev); ++ ++ if (ret == -ETIMEDOUT) { ++ phydev_warn(phydev, "SerDes setup timed out, retrying\n"); ++ phy_device_reset(phydev, 1); ++ phy_device_reset(phydev, 0); ++ ret = rtl822xb_config_init(phydev); ++ } ++ ++ return ret; ++} ++ + static int rtl822xb_get_rate_matching(struct phy_device *phydev, + phy_interface_t iface) + { +@@ -2219,7 +2235,7 @@ static struct phy_driver realtek_drvs[] + .handle_interrupt = rtl8221b_handle_interrupt, + .soft_reset = rtl822x_c45_soft_reset, + .probe = rtl822x_probe, +- .config_init = rtl822xb_config_init, ++ .config_init = rtl822xb_config_init_war, + .get_rate_matching = rtl822xb_get_rate_matching, + .get_features = rtl822x_c45_get_features, + .config_aneg = rtl822x_c45_config_aneg, +@@ -2247,7 +2263,7 @@ static struct phy_driver realtek_drvs[] + .handle_interrupt = rtl8221b_handle_interrupt, + .soft_reset = rtl822x_c45_soft_reset, + .probe = rtl822x_probe, +- .config_init = rtl822xb_config_init, ++ .config_init = rtl822xb_config_init_war, + .get_rate_matching = rtl822xb_get_rate_matching, + .get_features = rtl822x_c45_get_features, + .config_aneg = rtl822x_c45_config_aneg, diff --git a/lede/target/linux/generic/pending-6.12/720-09-net-phy-realtek-disable-MDIO-broadcast.patch b/lede/target/linux/generic/pending-6.12/720-09-net-phy-realtek-disable-MDIO-broadcast.patch index 5281e07d48..4462e4b274 100644 --- a/lede/target/linux/generic/pending-6.12/720-09-net-phy-realtek-disable-MDIO-broadcast.patch +++ b/lede/target/linux/generic/pending-6.12/720-09-net-phy-realtek-disable-MDIO-broadcast.patch @@ -13,21 +13,15 @@ Signed-off-by: Daniel Golle --- --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c -@@ -132,6 +132,7 @@ - #define RTL8221B_PHYCR1 0xa430 - #define RTL8221B_PHYCR1_ALDPS_EN BIT(2) - #define RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN BIT(12) -+#define RTL8221B_PHYCR1_PHYAD_0_EN BIT(13) +@@ -1256,6 +1256,11 @@ static int rtl822x_set_serdes_option_mod + phydev->host_interfaces) || + phydev->interface == PHY_INTERFACE_MODE_SGMII; - #define RTL8366RB_POWER_SAVE 0x15 - #define RTL8366RB_POWER_SAVE_ON BIT(12) -@@ -1062,7 +1063,8 @@ static int rtl822x_init_phycr1(struct ph - - return phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL8221B_PHYCR1, - RTL8221B_PHYCR1_ALDPS_EN | -- RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN, val); -+ RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN | -+ RTL8221B_PHYCR1_PHYAD_0_EN, val); - } - - static int rtl822xb_config_init(struct phy_device *phydev) ++ /* disable listening on MDIO broadcast address (0) */ ++ ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, 0xa430, BIT(13)); ++ if (ret < 0) ++ return ret; ++ + /* fill in possible interfaces */ + __assign_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->possible_interfaces, + has_2500); diff --git a/lede/target/linux/generic/pending-6.12/732-02-net-ethernet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch b/lede/target/linux/generic/pending-6.12/732-02-net-ethernet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch deleted file mode 100644 index bd7a1b96f2..0000000000 --- a/lede/target/linux/generic/pending-6.12/732-02-net-ethernet-mtk_eth_soc-set-NETIF_F_ALL_TSO.patch +++ /dev/null @@ -1,21 +0,0 @@ -From: Felix Fietkau -Date: Fri, 28 Oct 2022 12:54:48 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: set NETIF_F_ALL_TSO - -Significantly improves performance by avoiding unnecessary segmentation - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -49,8 +49,7 @@ - #define MTK_HW_FEATURES (NETIF_F_IP_CSUM | \ - NETIF_F_RXCSUM | \ - NETIF_F_HW_VLAN_CTAG_TX | \ -- NETIF_F_SG | NETIF_F_TSO | \ -- NETIF_F_TSO6 | \ -+ NETIF_F_SG | NETIF_F_ALL_TSO | \ - NETIF_F_IPV6_CSUM |\ - NETIF_F_HW_TC) - #define MTK_HW_FEATURES_MT7628 (NETIF_F_SG | NETIF_F_RXCSUM) diff --git a/lede/target/linux/generic/pending-6.12/732-03-net-ethernet-mtk_eth_soc-optimize-dma-ring-address-i.patch b/lede/target/linux/generic/pending-6.12/732-03-net-ethernet-mtk_eth_soc-optimize-dma-ring-address-i.patch new file mode 100644 index 0000000000..ef46691878 --- /dev/null +++ b/lede/target/linux/generic/pending-6.12/732-03-net-ethernet-mtk_eth_soc-optimize-dma-ring-address-i.patch @@ -0,0 +1,486 @@ +From: Felix Fietkau +Date: Tue, 15 Oct 2024 12:52:56 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: optimize dma ring address/index + calculation + +Since DMA descriptor sizes are all power of 2, we can avoid costly integer +division in favor or simple shifts. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -43,6 +43,11 @@ MODULE_PARM_DESC(msg_level, "Message lev + offsetof(struct mtk_hw_stats, xdp_stats.x) / \ + sizeof(u64) } + ++#define RX_DESC_OFS(eth, i) \ ++ ((i) << (eth)->soc->rx.desc_shift) ++#define TX_DESC_OFS(eth, i) \ ++ ((i) << (eth)->soc->tx.desc_shift) ++ + static const struct mtk_reg_map mtk_reg_map = { + .tx_irq_mask = 0x1a1c, + .tx_irq_status = 0x1a18, +@@ -1160,14 +1165,14 @@ static int mtk_init_fq_dma(struct mtk_et + eth->scratch_ring = eth->sram_base; + else + eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, +- cnt * soc->tx.desc_size, ++ TX_DESC_OFS(eth, cnt), + ð->phy_scratch_ring, + GFP_KERNEL); + + if (unlikely(!eth->scratch_ring)) + return -ENOMEM; + +- phy_ring_tail = eth->phy_scratch_ring + soc->tx.desc_size * (cnt - 1); ++ phy_ring_tail = eth->phy_scratch_ring + TX_DESC_OFS(eth, cnt - 1); + + for (j = 0; j < DIV_ROUND_UP(soc->tx.fq_dma_size, MTK_FQ_DMA_LENGTH); j++) { + len = min_t(int, cnt - j * MTK_FQ_DMA_LENGTH, MTK_FQ_DMA_LENGTH); +@@ -1186,11 +1191,11 @@ static int mtk_init_fq_dma(struct mtk_et + for (i = 0; i < len; i++) { + struct mtk_tx_dma_v2 *txd; + +- txd = eth->scratch_ring + (j * MTK_FQ_DMA_LENGTH + i) * soc->tx.desc_size; ++ txd = eth->scratch_ring + TX_DESC_OFS(eth, j * MTK_FQ_DMA_LENGTH + i); + txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE; + if (j * MTK_FQ_DMA_LENGTH + i < cnt) + txd->txd2 = eth->phy_scratch_ring + +- (j * MTK_FQ_DMA_LENGTH + i + 1) * soc->tx.desc_size; ++ TX_DESC_OFS(eth, j * MTK_FQ_DMA_LENGTH + i + 1); + + txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE); + if (MTK_HAS_CAPS(soc->caps, MTK_36BIT_DMA)) +@@ -1220,9 +1225,9 @@ static void *mtk_qdma_phys_to_virt(struc + } + + static struct mtk_tx_buf *mtk_desc_to_tx_buf(struct mtk_tx_ring *ring, +- void *txd, u32 txd_size) ++ void *txd, u32 txd_shift) + { +- int idx = (txd - ring->dma) / txd_size; ++ int idx = (txd - ring->dma) >> txd_shift; + + return &ring->buf[idx]; + } +@@ -1233,9 +1238,9 @@ static struct mtk_tx_dma *qdma_to_pdma(s + return ring->dma_pdma - (struct mtk_tx_dma *)ring->dma + dma; + } + +-static int txd_to_idx(struct mtk_tx_ring *ring, void *dma, u32 txd_size) ++static int txd_to_idx(struct mtk_tx_ring *ring, void *dma, u32 txd_shift) + { +- return (dma - ring->dma) / txd_size; ++ return (dma - ring->dma) >> txd_shift; + } + + static void mtk_tx_unmap(struct mtk_eth *eth, struct mtk_tx_buf *tx_buf, +@@ -1443,7 +1448,7 @@ static int mtk_tx_map(struct sk_buff *sk + if (itxd == ring->last_free) + return -ENOMEM; + +- itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size); ++ itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift); + memset(itx_buf, 0, sizeof(*itx_buf)); + + txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size, +@@ -1497,7 +1502,7 @@ static int mtk_tx_map(struct sk_buff *sk + mtk_tx_set_dma_desc(dev, txd, &txd_info); + + tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->tx.desc_size); ++ soc->tx.desc_shift); + if (new_desc) + memset(tx_buf, 0, sizeof(*tx_buf)); + tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; +@@ -1540,7 +1545,7 @@ static int mtk_tx_map(struct sk_buff *sk + } else { + int next_idx; + +- next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_size), ++ next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_shift), + ring->dma_size); + mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0); + } +@@ -1549,7 +1554,7 @@ static int mtk_tx_map(struct sk_buff *sk + + err_dma: + do { +- tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift); + + /* unmap dma */ + mtk_tx_unmap(eth, tx_buf, NULL, false); +@@ -1723,7 +1728,7 @@ static struct mtk_rx_ring *mtk_get_rx_ri + + ring = ð->rx_ring[i]; + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->rx.desc_size; ++ rxd = ring->dma + RX_DESC_OFS(eth, idx); + if (rxd->rxd2 & RX_DMA_DONE) { + ring->calc_idx_update = true; + return ring; +@@ -1891,7 +1896,7 @@ static int mtk_xdp_submit_frame(struct m + } + htxd = txd; + +- tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_shift); + memset(tx_buf, 0, sizeof(*tx_buf)); + htx_buf = tx_buf; + +@@ -1910,7 +1915,7 @@ static int mtk_xdp_submit_frame(struct m + goto unmap; + + tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->tx.desc_size); ++ soc->tx.desc_shift); + memset(tx_buf, 0, sizeof(*tx_buf)); + n_desc++; + } +@@ -1948,7 +1953,7 @@ static int mtk_xdp_submit_frame(struct m + } else { + int idx; + +- idx = txd_to_idx(ring, txd, soc->tx.desc_size); ++ idx = txd_to_idx(ring, txd, soc->tx.desc_shift); + mtk_w32(eth, NEXT_DESP_IDX(idx, ring->dma_size), + MT7628_TX_CTX_IDX0); + } +@@ -1959,7 +1964,7 @@ static int mtk_xdp_submit_frame(struct m + + unmap: + while (htxd != txd) { +- tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->tx.desc_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->tx.desc_shift); + mtk_tx_unmap(eth, tx_buf, NULL, false); + + htxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; +@@ -2091,7 +2096,7 @@ static int mtk_poll_rx(struct napi_struc + goto rx_done; + + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->rx.desc_size; ++ rxd = ring->dma + RX_DESC_OFS(eth, idx); + data = ring->data[idx]; + + if (!mtk_rx_get_desc(eth, &trxd, rxd)) +@@ -2355,7 +2360,7 @@ static int mtk_poll_tx_qdma(struct mtk_e + break; + + tx_buf = mtk_desc_to_tx_buf(ring, desc, +- eth->soc->tx.desc_size); ++ eth->soc->tx.desc_shift); + if (!tx_buf->data) + break; + +@@ -2406,7 +2411,7 @@ static int mtk_poll_tx_pdma(struct mtk_e + } + mtk_tx_unmap(eth, tx_buf, &bq, true); + +- desc = ring->dma + cpu * eth->soc->tx.desc_size; ++ desc = ring->dma + TX_DESC_OFS(eth, cpu); + ring->last_free = desc; + atomic_inc(&ring->free_count); + +@@ -2524,7 +2529,7 @@ static int mtk_tx_alloc(struct mtk_eth * + { + const struct mtk_soc_data *soc = eth->soc; + struct mtk_tx_ring *ring = ð->tx_ring; +- int i, sz = soc->tx.desc_size; ++ int i, sz = TX_DESC_OFS(eth, 1); + struct mtk_tx_dma_v2 *txd; + int ring_size; + u32 ofs, val; +@@ -2571,7 +2576,7 @@ static int mtk_tx_alloc(struct mtk_eth * + * descriptors in ring->dma_pdma. + */ + if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) { +- ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, ++ ring->dma_pdma = dma_alloc_coherent(eth->dma_dev, TX_DESC_OFS(eth, ring_size), + &ring->phys_pdma, GFP_KERNEL); + if (!ring->dma_pdma) + goto no_tx_mem; +@@ -2586,7 +2591,7 @@ static int mtk_tx_alloc(struct mtk_eth * + atomic_set(&ring->free_count, ring_size - 2); + ring->next_free = ring->dma; + ring->last_free = (void *)txd; +- ring->last_free_ptr = (u32)(ring->phys + ((ring_size - 1) * sz)); ++ ring->last_free_ptr = (u32)(ring->phys + TX_DESC_OFS(eth, ring_size - 1)); + ring->thresh = MAX_SKB_FRAGS; + + /* make sure that all changes to the dma ring are flushed before we +@@ -2598,7 +2603,7 @@ 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, +- ring->phys + ((ring_size - 1) * sz), ++ ring->phys + TX_DESC_OFS(eth, ring_size - 1), + soc->reg_map->qdma.crx_ptr); + mtk_w32(eth, ring->last_free_ptr, soc->reg_map->qdma.drx_ptr); + +@@ -2647,14 +2652,14 @@ static void mtk_tx_clean(struct mtk_eth + } + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->tx.desc_size, ++ TX_DESC_OFS(eth, ring->dma_size), + ring->dma, ring->phys); + ring->dma = NULL; + } + + if (ring->dma_pdma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->tx.desc_size, ++ TX_DESC_OFS(eth, ring->dma_size), + ring->dma_pdma, ring->phys_pdma); + ring->dma_pdma = NULL; + } +@@ -2710,15 +2715,13 @@ static int mtk_rx_alloc(struct mtk_eth * + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) || + rx_flag != MTK_RX_FLAGS_NORMAL) { + ring->dma = dma_alloc_coherent(eth->dma_dev, +- rx_dma_size * eth->soc->rx.desc_size, ++ RX_DESC_OFS(eth, rx_dma_size), + &ring->phys, GFP_KERNEL); + } else { + struct mtk_tx_ring *tx_ring = ð->tx_ring; + +- ring->dma = tx_ring->dma + tx_ring_size * +- eth->soc->tx.desc_size * (ring_no + 1); +- ring->phys = tx_ring->phys + tx_ring_size * +- eth->soc->tx.desc_size * (ring_no + 1); ++ ring->dma = tx_ring->dma + TX_DESC_OFS(eth, tx_ring_size * (ring_no + 1)); ++ ring->phys = tx_ring->phys + TX_DESC_OFS(eth, tx_ring_size * (ring_no + 1)); + } + + if (!ring->dma) +@@ -2729,7 +2732,7 @@ static int mtk_rx_alloc(struct mtk_eth * + dma_addr_t dma_addr; + void *data; + +- rxd = ring->dma + i * eth->soc->rx.desc_size; ++ rxd = ring->dma + RX_DESC_OFS(eth, i); + if (ring->page_pool) { + data = mtk_page_pool_get_buff(ring->page_pool, + &dma_addr, GFP_KERNEL); +@@ -2820,7 +2823,7 @@ static void mtk_rx_clean(struct mtk_eth + if (!ring->data[i]) + continue; + +- rxd = ring->dma + i * eth->soc->rx.desc_size; ++ rxd = ring->dma + RX_DESC_OFS(eth, i); + if (!rxd->rxd1) + continue; + +@@ -2837,7 +2840,7 @@ static void mtk_rx_clean(struct mtk_eth + + if (!in_sram && ring->dma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * eth->soc->rx.desc_size, ++ RX_DESC_OFS(eth, ring->dma_size), + ring->dma, ring->phys); + ring->dma = NULL; + } +@@ -3208,7 +3211,7 @@ static void mtk_dma_free(struct mtk_eth + + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) { + dma_free_coherent(eth->dma_dev, +- MTK_QDMA_RING_SIZE * soc->tx.desc_size, ++ TX_DESC_OFS(eth, MTK_QDMA_RING_SIZE), + eth->scratch_ring, eth->phy_scratch_ring); + eth->scratch_ring = NULL; + eth->phy_scratch_ring = 0; +@@ -5236,6 +5239,9 @@ static void mtk_remove(struct platform_d + mtk_mdio_cleanup(eth); + } + ++#define DESC_SIZE(struct_name) \ ++ .desc_shift = const_ilog2(sizeof(struct_name)) ++ + static const struct mtk_soc_data mt2701_data = { + .reg_map = &mtk_reg_map, + .caps = MT7623_CAPS | MTK_HWLRO, +@@ -5244,14 +5250,14 @@ static const struct mtk_soc_data mt2701_ + .required_pctl = true, + .version = 1, + .tx = { +- .desc_size = sizeof(struct mtk_tx_dma), ++ DESC_SIZE(struct mtk_tx_dma), + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + .dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(2K), + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma), ++ DESC_SIZE(struct mtk_rx_dma), + .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID, + .dma_size = MTK_DMA_SIZE(2K), +@@ -5272,14 +5278,14 @@ static const struct mtk_soc_data mt7621_ + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, + .tx = { +- .desc_size = sizeof(struct mtk_tx_dma), ++ DESC_SIZE(struct mtk_tx_dma), + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + .dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(2K), + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma), ++ DESC_SIZE(struct mtk_rx_dma), + .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID, + .dma_size = MTK_DMA_SIZE(2K), +@@ -5302,14 +5308,14 @@ static const struct mtk_soc_data mt7622_ + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, + .tx = { +- .desc_size = sizeof(struct mtk_tx_dma), ++ DESC_SIZE(struct mtk_tx_dma), + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + .dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(2K), + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma), ++ DESC_SIZE(struct mtk_rx_dma), + .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID, + .dma_size = MTK_DMA_SIZE(2K), +@@ -5331,14 +5337,14 @@ static const struct mtk_soc_data mt7623_ + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, + .disable_pll_modes = true, + .tx = { +- .desc_size = sizeof(struct mtk_tx_dma), ++ DESC_SIZE(struct mtk_tx_dma), + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + .dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(2K), + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma), ++ DESC_SIZE(struct mtk_rx_dma), + .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID, + .dma_size = MTK_DMA_SIZE(2K), +@@ -5357,14 +5363,14 @@ static const struct mtk_soc_data mt7629_ + .has_accounting = true, + .version = 1, + .tx = { +- .desc_size = sizeof(struct mtk_tx_dma), ++ DESC_SIZE(struct mtk_tx_dma), + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + .dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(2K), + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma), ++ DESC_SIZE(struct mtk_rx_dma), + .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID, + .dma_size = MTK_DMA_SIZE(2K), +@@ -5387,14 +5393,14 @@ static const struct mtk_soc_data mt7981_ + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, + .tx = { +- .desc_size = sizeof(struct mtk_tx_dma_v2), ++ DESC_SIZE(struct mtk_tx_dma_v2), + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + .dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(2K), + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma), ++ DESC_SIZE(struct mtk_rx_dma), + .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN, +@@ -5417,14 +5423,14 @@ static const struct mtk_soc_data mt7986_ + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, + .tx = { +- .desc_size = sizeof(struct mtk_tx_dma_v2), ++ DESC_SIZE(struct mtk_tx_dma_v2), + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + .dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(2K), + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma), ++ DESC_SIZE(struct mtk_rx_dma), + .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN, +@@ -5447,14 +5453,14 @@ static const struct mtk_soc_data mt7988_ + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, + .tx = { +- .desc_size = sizeof(struct mtk_tx_dma_v2), ++ DESC_SIZE(struct mtk_tx_dma_v2), + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + .dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(4K), + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma_v2), ++ DESC_SIZE(struct mtk_rx_dma_v2), + .irq_done_mask = MTK_RX_DONE_INT_V2, + .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, +@@ -5471,13 +5477,13 @@ static const struct mtk_soc_data rt5350_ + .required_pctl = false, + .version = 1, + .tx = { +- .desc_size = sizeof(struct mtk_tx_dma), ++ DESC_SIZE(struct mtk_tx_dma), + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + .dma_size = MTK_DMA_SIZE(2K), + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma), ++ DESC_SIZE(struct mtk_rx_dma), + .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_PDMA, + .dma_max_len = MTK_TX_DMA_BUF_LEN, +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1160,7 +1160,7 @@ struct mtk_reg_map { + * @foe_entry_size Foe table entry size. + * @has_accounting Bool indicating support for accounting of + * offloaded flows. +- * @desc_size Tx/Rx DMA descriptor size. ++ * @desc_shift Tx/Rx DMA descriptor size (in power-of-2). + * @irq_done_mask Rx irq done register mask. + * @dma_l4_valid Rx DMA valid register mask. + * @dma_max_len Max DMA tx/rx buffer length. +@@ -1181,14 +1181,14 @@ struct mtk_soc_data { + bool has_accounting; + bool disable_pll_modes; + struct { +- u32 desc_size; ++ u32 desc_shift; + u32 dma_max_len; + u32 dma_len_offset; + u32 dma_size; + u32 fq_dma_size; + } tx; + struct { +- u32 desc_size; ++ u32 desc_shift; + u32 irq_done_mask; + u32 dma_l4_valid; + u32 dma_max_len; diff --git a/lede/target/linux/generic/pending-6.12/732-04-net-ethernet-mtk_eth_soc-shrink-struct-mtk_tx_buf.patch b/lede/target/linux/generic/pending-6.12/732-04-net-ethernet-mtk_eth_soc-shrink-struct-mtk_tx_buf.patch new file mode 100644 index 0000000000..a2dd04b378 --- /dev/null +++ b/lede/target/linux/generic/pending-6.12/732-04-net-ethernet-mtk_eth_soc-shrink-struct-mtk_tx_buf.patch @@ -0,0 +1,124 @@ +From: Felix Fietkau +Date: Mon, 14 Jul 2025 10:52:59 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: shrink struct mtk_tx_buf + +There is no need to track the difference between dma_map_page +and dma_map_single, since they're unmapped in exactly the same way. +Also reorder fields in order to avoid padding. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1246,32 +1246,19 @@ static int txd_to_idx(struct mtk_tx_ring + static void mtk_tx_unmap(struct mtk_eth *eth, struct mtk_tx_buf *tx_buf, + struct xdp_frame_bulk *bq, bool napi) + { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { +- if (tx_buf->flags & MTK_TX_FLAGS_SINGLE0) { +- dma_unmap_single(eth->dma_dev, +- dma_unmap_addr(tx_buf, dma_addr0), +- dma_unmap_len(tx_buf, dma_len0), +- DMA_TO_DEVICE); +- } else if (tx_buf->flags & MTK_TX_FLAGS_PAGE0) { +- dma_unmap_page(eth->dma_dev, +- dma_unmap_addr(tx_buf, dma_addr0), +- dma_unmap_len(tx_buf, dma_len0), +- DMA_TO_DEVICE); +- } +- } else { +- if (dma_unmap_len(tx_buf, dma_len0)) { +- dma_unmap_page(eth->dma_dev, +- dma_unmap_addr(tx_buf, dma_addr0), +- dma_unmap_len(tx_buf, dma_len0), +- DMA_TO_DEVICE); +- } ++ if (dma_unmap_len(tx_buf, dma_len0)) { ++ dma_unmap_page(eth->dma_dev, ++ dma_unmap_addr(tx_buf, dma_addr0), ++ dma_unmap_len(tx_buf, dma_len0), ++ DMA_TO_DEVICE); ++ } + +- if (dma_unmap_len(tx_buf, dma_len1)) { +- dma_unmap_page(eth->dma_dev, +- dma_unmap_addr(tx_buf, dma_addr1), +- dma_unmap_len(tx_buf, dma_len1), +- DMA_TO_DEVICE); +- } ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA) && ++ dma_unmap_len(tx_buf, dma_len1)) { ++ dma_unmap_page(eth->dma_dev, ++ dma_unmap_addr(tx_buf, dma_addr1), ++ dma_unmap_len(tx_buf, dma_len1), ++ DMA_TO_DEVICE); + } + + if (tx_buf->data && tx_buf->data != (void *)MTK_DMA_DUMMY_DESC) { +@@ -1293,7 +1280,6 @@ static void mtk_tx_unmap(struct mtk_eth + xdp_return_frame(xdpf); + } + } +- tx_buf->flags = 0; + tx_buf->data = NULL; + } + +@@ -1458,7 +1444,6 @@ 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; + itx_buf->mac_id = mac->id; + setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size, + k++); +@@ -1506,7 +1491,6 @@ static int mtk_tx_map(struct sk_buff *sk + if (new_desc) + memset(tx_buf, 0, sizeof(*tx_buf)); + tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; +- tx_buf->flags |= MTK_TX_FLAGS_PAGE0; + tx_buf->mac_id = mac->id; + + setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr, +@@ -1839,8 +1823,6 @@ static int mtk_xdp_frame_map(struct mtk_ + txd_info->size, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(eth->dma_dev, txd_info->addr))) + return -ENOMEM; +- +- tx_buf->flags |= MTK_TX_FLAGS_SINGLE0; + } else { + struct page *page = virt_to_head_page(data); + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -701,14 +701,6 @@ struct mtk_hw_stats { + struct u64_stats_sync syncp; + }; + +-enum mtk_tx_flags { +- /* PDMA descriptor can point at 1-2 segments. This enum allows us to +- * track how memory was allocated so that it can be freed properly. +- */ +- MTK_TX_FLAGS_SINGLE0 = 0x01, +- MTK_TX_FLAGS_PAGE0 = 0x02, +-}; +- + /* This enum allows us to identify how the clock is defined on the array of the + * clock in the order + */ +@@ -881,13 +873,12 @@ enum mtk_tx_buf_type { + */ + struct mtk_tx_buf { + enum mtk_tx_buf_type type; ++ u16 mac_id; + void *data; + +- u16 mac_id; +- u16 flags; + DEFINE_DMA_UNMAP_ADDR(dma_addr0); +- DEFINE_DMA_UNMAP_LEN(dma_len0); + DEFINE_DMA_UNMAP_ADDR(dma_addr1); ++ DEFINE_DMA_UNMAP_LEN(dma_len0); + DEFINE_DMA_UNMAP_LEN(dma_len1); + }; + diff --git a/lede/target/linux/generic/pending-6.12/732-05-net-ethernet-mtk_eth_soc-add-support-for-sending-fra.patch b/lede/target/linux/generic/pending-6.12/732-05-net-ethernet-mtk_eth_soc-add-support-for-sending-fra.patch new file mode 100644 index 0000000000..8dad080fa6 --- /dev/null +++ b/lede/target/linux/generic/pending-6.12/732-05-net-ethernet-mtk_eth_soc-add-support-for-sending-fra.patch @@ -0,0 +1,519 @@ +From: Felix Fietkau +Date: Mon, 14 Jul 2025 10:41:27 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for sending + fraglist GSO packets + +When primarily forwarding traffic, TCP fraglist GRO can be noticeably more +efficient than regular TCP GRO. In order to avoid the overhead of +unnecessary segmentation on ethernet tx, add support for sending fraglist +GRO packets. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -18,6 +18,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -27,6 +29,7 @@ + #include + #include + #include ++#include + #include + + #include "mtk_eth_soc.h" +@@ -1404,119 +1407,251 @@ static void mtk_tx_set_dma_desc(struct n + mtk_tx_set_dma_desc_v1(dev, txd, info); + } + ++struct mtk_tx_map_state { ++ struct mtk_tx_dma *txd, *txd_pdma; ++ struct mtk_tx_buf *tx_buf; ++ int nbuf; ++ int ndesc; ++}; ++ ++static void ++mtk_tx_map_set_txd(struct mtk_tx_map_state *state, struct mtk_tx_ring *ring, ++ const struct mtk_soc_data *soc, struct mtk_tx_dma *txd) ++{ ++ state->txd = txd; ++ state->txd_pdma = qdma_to_pdma(ring, txd); ++ state->tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_shift); ++ memset(state->tx_buf, 0, sizeof(*state->tx_buf)); ++} ++ ++static int ++mtk_tx_map_info(struct mtk_eth *eth, struct mtk_tx_ring *ring, ++ struct net_device *dev, struct mtk_tx_map_state *state, ++ struct mtk_tx_dma_desc_info *txd_info) ++{ ++ const struct mtk_soc_data *soc = eth->soc; ++ struct mtk_tx_buf *tx_buf = state->tx_buf; ++ struct mtk_tx_dma *txd = state->txd; ++ struct mtk_mac *mac = netdev_priv(dev); ++ ++ if (state->nbuf && ++ (MTK_HAS_CAPS(soc->caps, MTK_QDMA) || (state->nbuf & 1) == 0)) { ++ txd = mtk_qdma_phys_to_virt(ring, txd->txd2); ++ if (txd == ring->last_free) ++ return -1; ++ ++ mtk_tx_map_set_txd(state, ring, soc, txd); ++ state->ndesc++; ++ } ++ ++ mtk_tx_set_dma_desc(dev, txd, txd_info); ++ tx_buf = state->tx_buf; ++ tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; ++ tx_buf->mac_id = mac->id; ++ ++ setup_tx_buf(eth, tx_buf, state->txd_pdma, txd_info->addr, ++ txd_info->size, state->nbuf++); ++ return 0; ++} ++ ++static void ++mtk_tx_update_ipaddr(struct sk_buff *skb, ++ struct iphdr *iph, struct tcphdr *th, ++ __be32 *old_ip, __be32 new_ip) ++{ ++ if (*old_ip == new_ip) ++ return; ++ ++ inet_proto_csum_replace4(&th->check, skb, *old_ip, new_ip, true); ++ csum_replace4(&iph->check, *old_ip, new_ip); ++ *old_ip = new_ip; ++} ++ ++static void ++mtk_tx_update_ip6addr(struct sk_buff *skb, struct ipv6hdr *iph, ++ struct tcphdr *th, struct in6_addr *old_ip, ++ const struct in6_addr *new_ip) ++{ ++ if (ipv6_addr_equal(old_ip, new_ip)) ++ return; ++ ++ inet_proto_csum_replace16(&th->check, skb, old_ip->s6_addr32, ++ new_ip->s6_addr32, true); ++ *old_ip = *new_ip; ++} ++ ++static void ++mtk_tx_update_port(struct sk_buff *skb, struct tcphdr *th, ++ __be16 *old_port, __be16 new_port) ++{ ++ if (*old_port == new_port) ++ return; ++ ++ inet_proto_csum_replace2(&th->check, skb, *old_port, new_port, false); ++ *old_port = new_port; ++} ++ + static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, +- int tx_num, struct mtk_tx_ring *ring, bool gso) ++ int tx_num, struct mtk_tx_ring *ring, bool gso, ++ unsigned int header_len) + { +- struct mtk_tx_dma_desc_info txd_info = { +- .size = skb_headlen(skb), +- .gso = gso, +- .csum = skb->ip_summed == CHECKSUM_PARTIAL, +- .vlan = skb_vlan_tag_present(skb), +- .qid = skb_get_queue_mapping(skb), +- .vlan_tci = skb_vlan_tag_get(skb), +- .first = true, +- .last = !skb_is_nonlinear(skb), ++ struct mtk_tx_dma_desc_info txd_info; ++ struct mtk_tx_map_state state = { ++ .ndesc = 1, + }; + struct netdev_queue *txq; + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; + const struct mtk_soc_data *soc = eth->soc; +- struct mtk_tx_dma *itxd, *txd; +- struct mtk_tx_dma *itxd_pdma, *txd_pdma; +- struct mtk_tx_buf *itx_buf, *tx_buf; +- int i, n_desc = 1; ++ struct mtk_tx_dma *itxd; ++ struct sk_buff *cur_skb, *next_skb; + int queue = skb_get_queue_mapping(skb); +- int k = 0; ++ int i, frag_size = skb_headlen(skb); ++ bool gso_v4, gso_fraglist; ++ int offset = 0; + + txq = netdev_get_tx_queue(dev, queue); + itxd = ring->next_free; +- itxd_pdma = qdma_to_pdma(ring, itxd); + if (itxd == ring->last_free) + return -ENOMEM; + +- itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift); +- memset(itx_buf, 0, sizeof(*itx_buf)); ++ cur_skb = skb; ++ next_skb = skb_shinfo(skb)->frag_list; ++ mtk_tx_map_set_txd(&state, ring, soc, itxd); ++ gso_v4 = skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4; ++ gso_fraglist = skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST; + +- txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size, +- DMA_TO_DEVICE); +- if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr))) +- return -ENOMEM; ++next: ++ txd_info = (struct mtk_tx_dma_desc_info){ ++ .gso = gso, ++ .qid = queue, ++ .csum = cur_skb->ip_summed == CHECKSUM_PARTIAL || gso, ++ .vlan = skb_vlan_tag_present(skb), ++ .vlan_tci = skb_vlan_tag_get(skb), ++ .first = true, ++ }; + +- mtk_tx_set_dma_desc(dev, itxd, &txd_info); ++ if (cur_skb != skb) { ++ struct tcphdr *th, *th2; + +- itx_buf->mac_id = mac->id; +- setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size, +- k++); +- +- /* TX SG offload */ +- txd = itxd; +- txd_pdma = qdma_to_pdma(ring, txd); +- +- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { +- skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; +- unsigned int offset = 0; +- int frag_size = skb_frag_size(frag); ++ if (skb_cow_head(cur_skb, header_len)) ++ goto err_dma; + +- while (frag_size) { +- bool new_desc = true; ++ memcpy(cur_skb->data - header_len, skb->data, ++ skb_network_offset(skb)); + +- if (MTK_HAS_CAPS(soc->caps, MTK_QDMA) || +- (i & 0x1)) { +- txd = mtk_qdma_phys_to_virt(ring, txd->txd2); +- txd_pdma = qdma_to_pdma(ring, txd); +- if (txd == ring->last_free) +- goto err_dma; ++ th = tcp_hdr(cur_skb); ++ th2 = tcp_hdr(skb); ++ if (gso_v4) { ++ struct iphdr *iph = ip_hdr(cur_skb); ++ struct iphdr *iph2 = ip_hdr(skb); ++ ++ mtk_tx_update_ipaddr(skb, iph, th, &iph->saddr, ++ iph2->saddr); ++ mtk_tx_update_ipaddr(skb, iph, th, &iph->daddr, ++ iph2->daddr); ++ } else { ++ struct ipv6hdr *iph = ipv6_hdr(cur_skb); ++ struct ipv6hdr *iph2 = ipv6_hdr(skb); + +- n_desc++; +- } else { +- new_desc = false; +- } ++ mtk_tx_update_ip6addr(skb, iph, th, &iph->saddr, ++ &iph2->saddr); ++ mtk_tx_update_ip6addr(skb, iph, th, &iph->daddr, ++ &iph2->daddr); ++ } ++ ++ mtk_tx_update_port(skb, th, &th->source, th2->source); ++ mtk_tx_update_port(skb, th, &th->dest, th2->dest); ++ ++ offset = -header_len; ++ frag_size += header_len; ++ } else if (next_skb && gso_fraglist) { ++ unsigned int ip_len = skb_pagelen(skb) - skb_network_offset(skb); ++ if (gso_v4) { ++ struct iphdr *iph = ip_hdr(cur_skb); ++ __be16 ip_len_val = cpu_to_be16(ip_len); + +- memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); ++ csum_replace2(&iph->check, iph->tot_len, ip_len_val); ++ iph->tot_len = ip_len_val; ++ } else { ++ struct ipv6hdr *iph = ipv6_hdr(cur_skb); ++ __be16 ip_len_val = cpu_to_be16(ip_len - sizeof(*iph)); ++ ++ iph->payload_len = ip_len_val; ++ } ++ } ++ ++next_frag: ++ while (frag_size) { ++ txd_info.size = min_t(unsigned int, frag_size, ++ soc->tx.dma_max_len); ++ txd_info.addr = dma_map_single(eth->dma_dev, cur_skb->data + offset, ++ txd_info.size, DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr))) ++ goto err_dma; ++ ++ frag_size -= txd_info.size; ++ offset += txd_info.size; ++ txd_info.last = !frag_size && !skb_shinfo(cur_skb)->nr_frags && ++ (gso_fraglist || !next_skb); ++ if (mtk_tx_map_info(eth, ring, dev, &state, &txd_info) < 0) ++ goto err_dma; ++ } ++ ++ for (i = 0; i < skb_shinfo(cur_skb)->nr_frags; i++) { ++ skb_frag_t *frag = &skb_shinfo(cur_skb)->frags[i]; ++ ++ frag_size = skb_frag_size(frag); ++ memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); ++ txd_info.qid = queue; ++ offset = 0; ++ while (frag_size) { + txd_info.size = min_t(unsigned int, frag_size, + soc->tx.dma_max_len); +- txd_info.qid = queue; +- 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, +- offset, txd_info.size, +- DMA_TO_DEVICE); ++ txd_info.addr = skb_frag_dma_map(eth->dma_dev, frag, offset, ++ txd_info.size, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr))) + goto err_dma; + +- mtk_tx_set_dma_desc(dev, txd, &txd_info); +- +- tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->tx.desc_shift); +- if (new_desc) +- memset(tx_buf, 0, sizeof(*tx_buf)); +- tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; +- tx_buf->mac_id = mac->id; +- +- setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr, +- txd_info.size, k++); +- + frag_size -= txd_info.size; + offset += txd_info.size; ++ txd_info.last = i == skb_shinfo(cur_skb)->nr_frags - 1 && ++ !frag_size && (gso_fraglist || !next_skb); ++ if (mtk_tx_map_info(eth, ring, dev, &state, &txd_info) < 0) ++ goto err_dma; + } + } + +- /* store skb to cleanup */ +- itx_buf->type = MTK_TYPE_SKB; +- itx_buf->data = skb; ++ if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA) && ++ (gso_fraglist || !next_skb)) { ++ if (state.nbuf & 0x1) { ++ state.txd_pdma->txd2 |= TX_DMA_LS0; ++ state.nbuf++; ++ } else { ++ state.txd_pdma->txd2 |= TX_DMA_LS1; ++ } ++ } ++ ++ if (next_skb) { ++ cur_skb = next_skb; ++ next_skb = cur_skb->next; ++ offset = 0; ++ frag_size = skb_headlen(cur_skb); ++ if (!gso_fraglist) ++ goto next_frag; + +- if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) { +- if (k & 0x1) +- txd_pdma->txd2 |= TX_DMA_LS0; +- else +- txd_pdma->txd2 |= TX_DMA_LS1; ++ goto next; + } + ++ /* store skb to cleanup */ ++ state.tx_buf->type = MTK_TYPE_SKB; ++ state.tx_buf->data = skb; ++ + netdev_tx_sent_queue(txq, skb->len); + skb_tx_timestamp(skb); + +- ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2); +- atomic_sub(n_desc, &ring->free_count); ++ ring->next_free = mtk_qdma_phys_to_virt(ring, state.txd->txd2); ++ atomic_sub(state.ndesc, &ring->free_count); + + /* make sure that all changes to the dma ring are flushed before we + * continue +@@ -1525,11 +1660,11 @@ static int mtk_tx_map(struct sk_buff *sk + + if (MTK_HAS_CAPS(soc->caps, MTK_QDMA)) { + if (netif_xmit_stopped(txq) || !netdev_xmit_more()) +- mtk_w32(eth, txd->txd2, soc->reg_map->qdma.ctx_ptr); ++ mtk_w32(eth, state.txd->txd2, soc->reg_map->qdma.ctx_ptr); + } else { + int next_idx; + +- next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_shift), ++ next_idx = NEXT_DESP_IDX(txd_to_idx(ring, state.txd, soc->tx.desc_shift), + ring->dma_size); + mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0); + } +@@ -1538,18 +1673,20 @@ static int mtk_tx_map(struct sk_buff *sk + + err_dma: + do { +- tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift); ++ struct mtk_tx_dma *itxd_pdma = qdma_to_pdma(ring, itxd); ++ struct mtk_tx_buf *itx_buf; ++ ++ itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_shift); + + /* unmap dma */ +- mtk_tx_unmap(eth, tx_buf, NULL, false); ++ mtk_tx_unmap(eth, itx_buf, NULL, false); + + itxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; + if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) + itxd_pdma->txd2 = TX_DMA_DESP2_DEF; + + itxd = mtk_qdma_phys_to_virt(ring, itxd->txd2); +- itxd_pdma = qdma_to_pdma(ring, itxd); +- } while (itxd != txd); ++ } while (itxd != state.txd); + + return -ENOMEM; + } +@@ -1569,6 +1706,9 @@ static int mtk_cal_txd_req(struct mtk_et + nfrags += skb_shinfo(skb)->nr_frags; + } + ++ for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next) ++ nfrags += mtk_cal_txd_req(eth, skb) + 1; ++ + return nfrags; + } + +@@ -1609,9 +1749,29 @@ static bool mtk_skb_has_small_frag(struc + if (skb_frag_size(&skb_shinfo(skb)->frags[i]) < min_size) + return true; + ++ for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next) ++ if (mtk_skb_has_small_frag(skb)) ++ return true; ++ + return false; + } + ++static bool mtk_skb_valid_gso(struct mtk_eth *eth, struct sk_buff *skb, ++ unsigned int header_len) ++{ ++ if (mtk_is_netsys_v1(eth) && mtk_skb_has_small_frag(skb)) ++ return false; ++ ++ if (!(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST)) ++ return true; ++ ++ if (skb->encapsulation) ++ return false; ++ ++ return skb_pagelen(skb) - header_len == skb_shinfo(skb)->gso_size && ++ skb_headlen(skb) > header_len; ++} ++ + static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct mtk_mac *mac = netdev_priv(dev); +@@ -1619,6 +1779,7 @@ static netdev_tx_t mtk_start_xmit(struct + struct mtk_tx_ring *ring = ð->tx_ring; + struct net_device_stats *stats = &dev->stats; + struct sk_buff *segs, *next; ++ unsigned int header_len = 0; + bool gso = false; + int tx_num; + +@@ -1647,37 +1808,42 @@ static netdev_tx_t mtk_start_xmit(struct + return NETDEV_TX_BUSY; + } + +- if (mtk_is_netsys_v1(eth) && +- skb_is_gso(skb) && mtk_skb_has_small_frag(skb)) { +- segs = skb_gso_segment(skb, dev->features & ~NETIF_F_ALL_TSO); +- if (IS_ERR(segs)) +- goto drop; +- +- if (segs) { +- consume_skb(skb); +- skb = segs; +- } +- } +- +- /* TSO: fill MSS info in tcp checksum field */ + if (skb_is_gso(skb)) { +- if (skb_cow_head(skb, 0)) { +- netif_warn(eth, tx_err, dev, +- "GSO expand head fail.\n"); +- goto drop; ++ header_len = skb_tcp_all_headers(skb); ++ if (!mtk_skb_valid_gso(eth, skb, header_len)) { ++ segs = skb_gso_segment(skb, dev->features & ~NETIF_F_ALL_TSO); ++ if (IS_ERR(segs)) ++ goto drop; ++ ++ if (segs) { ++ consume_skb(skb); ++ skb = segs; ++ } ++ goto send; + } + ++ if ((skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST)) ++ goto send; ++ + if (skb_shinfo(skb)->gso_type & + (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { ++ /* TSO: fill MSS info in tcp checksum field */ + gso = true; ++ if (skb_cow_head(skb, 0)) { ++ netif_warn(eth, tx_err, dev, ++ "GSO expand head fail.\n"); ++ goto drop; ++ } ++ + tcp_hdr(skb)->check = htons(skb_shinfo(skb)->gso_size); + } + } + ++send: + skb_list_walk_safe(skb, skb, next) { + if ((mtk_is_netsys_v1(eth) && + mtk_skb_has_small_frag(skb) && skb_linearize(skb)) || +- mtk_tx_map(skb, dev, tx_num, ring, gso) < 0) { ++ mtk_tx_map(skb, dev, tx_num, ring, gso, header_len) < 0) { + stats->tx_dropped++; + dev_kfree_skb_any(skb); + } +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -51,6 +51,8 @@ + NETIF_F_HW_VLAN_CTAG_TX | \ + NETIF_F_SG | NETIF_F_TSO | \ + NETIF_F_TSO6 | \ ++ NETIF_F_FRAGLIST | \ ++ NETIF_F_GSO_FRAGLIST | \ + NETIF_F_IPV6_CSUM |\ + NETIF_F_HW_TC) + #define MTK_HW_FEATURES_MT7628 (NETIF_F_SG | NETIF_F_RXCSUM) diff --git a/lede/target/linux/generic/pending-6.12/733-01-net-ethernet-mtk_eth_soc-use-napi_build_skb.patch b/lede/target/linux/generic/pending-6.12/733-01-net-ethernet-mtk_eth_soc-use-napi_build_skb.patch index 36c1d499d3..f87315ac95 100644 --- a/lede/target/linux/generic/pending-6.12/733-01-net-ethernet-mtk_eth_soc-use-napi_build_skb.patch +++ b/lede/target/linux/generic/pending-6.12/733-01-net-ethernet-mtk_eth_soc-use-napi_build_skb.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 -@@ -2151,7 +2151,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -2312,7 +2312,7 @@ static int mtk_poll_rx(struct napi_struc if (ret != XDP_PASS) goto skip_rx; @@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau if (unlikely(!skb)) { page_pool_put_full_page(ring->page_pool, page, true); -@@ -2189,7 +2189,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -2350,7 +2350,7 @@ static int mtk_poll_rx(struct napi_struc dma_unmap_single(eth->dma_dev, ((u64)trxd.rxd1 | addr64), ring->buf_size, DMA_FROM_DEVICE); diff --git a/lede/target/linux/generic/pending-6.12/734-net-ethernet-mediatek-enlarge-DMA-reserve-buffer.patch b/lede/target/linux/generic/pending-6.12/734-net-ethernet-mediatek-enlarge-DMA-reserve-buffer.patch index d9e2873262..8d0f0b9802 100644 --- a/lede/target/linux/generic/pending-6.12/734-net-ethernet-mediatek-enlarge-DMA-reserve-buffer.patch +++ b/lede/target/linux/generic/pending-6.12/734-net-ethernet-mediatek-enlarge-DMA-reserve-buffer.patch @@ -15,7 +15,7 @@ Signed-off-by: Chad Monroe --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -279,6 +279,7 @@ +@@ -282,6 +282,7 @@ #define MTK_WCOMP_EN BIT(24) #define MTK_RESV_BUF (0x80 << 16) #define MTK_MUTLI_CNT (0x4 << 12) @@ -25,7 +25,7 @@ Signed-off-by: Chad Monroe /* QDMA Flow Control Register */ --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3324,12 +3324,14 @@ static int mtk_start_dma(struct mtk_eth +@@ -3483,12 +3483,14 @@ static int mtk_start_dma(struct mtk_eth MTK_TX_BT_32DWORDS | MTK_NDP_CO_PRO | MTK_RX_2B_OFFSET | MTK_TX_WB_DDONE; diff --git a/lede/target/linux/generic/pending-6.12/736-05-net-ethernet-mtk_eth_soc-zero-initialize-PPE-flow-ta.patch b/lede/target/linux/generic/pending-6.12/736-05-net-ethernet-mtk_eth_soc-zero-initialize-PPE-flow-ta.patch new file mode 100644 index 0000000000..2ca5ace367 --- /dev/null +++ b/lede/target/linux/generic/pending-6.12/736-05-net-ethernet-mtk_eth_soc-zero-initialize-PPE-flow-ta.patch @@ -0,0 +1,27 @@ +From: Felix Fietkau +Date: Fri, 12 Sep 2025 14:18:14 +0200 +Subject: [PATCH] net: ethernet: mtk_eth_soc: zero initialize PPE flow table + +Avoid picking up flows from last boot or other invalid data + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -914,6 +914,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ + if (!foe) + goto err_free_l2_flows; + ++ memset(foe, 0, MTK_PPE_ENTRIES * soc->foe_entry_size); + ppe->foe_table = foe; + + foe_flow_size = (MTK_PPE_ENTRIES / soc->hash_offset) * +@@ -928,6 +929,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ + if (!mib) + return NULL; + ++ memset(mib, 0, MTK_PPE_ENTRIES * sizeof(*mib)); + ppe->mib_table = mib; + + acct = devm_kzalloc(dev, MTK_PPE_ENTRIES * sizeof(*acct), diff --git a/lede/target/linux/generic/pending-6.12/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch b/lede/target/linux/generic/pending-6.12/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch index 4c2c1a3308..93ceb9819a 100644 --- a/lede/target/linux/generic/pending-6.12/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch +++ b/lede/target/linux/generic/pending-6.12/737-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch @@ -205,7 +205,7 @@ Signed-off-by: Daniel Golle 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 -@@ -22,6 +22,8 @@ +@@ -24,6 +24,8 @@ #include #include #include @@ -214,7 +214,7 @@ Signed-off-by: Daniel Golle #include #include #include -@@ -514,6 +516,30 @@ static void mtk_setup_bridge_switch(stru +@@ -522,6 +524,30 @@ static void mtk_setup_bridge_switch(stru MTK_GSW_CFG); } @@ -245,7 +245,7 @@ Signed-off-by: Daniel Golle static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, phy_interface_t interface) { -@@ -522,6 +548,21 @@ static struct phylink_pcs *mtk_mac_selec +@@ -530,6 +556,21 @@ static struct phylink_pcs *mtk_mac_selec struct mtk_eth *eth = mac->hw; unsigned int sid; @@ -267,7 +267,7 @@ Signed-off-by: Daniel Golle if (interface == PHY_INTERFACE_MODE_SGMII || phy_interface_mode_is_8023z(interface)) { sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? -@@ -573,7 +614,22 @@ static void mtk_mac_config(struct phylin +@@ -581,7 +622,22 @@ static void mtk_mac_config(struct phylin goto init_err; } break; @@ -290,7 +290,7 @@ Signed-off-by: Daniel Golle break; default: goto err_phy; -@@ -620,8 +676,6 @@ static void mtk_mac_config(struct phylin +@@ -628,8 +684,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); @@ -299,7 +299,7 @@ Signed-off-by: Daniel Golle } /* SGMII */ -@@ -638,21 +692,40 @@ static void mtk_mac_config(struct phylin +@@ -646,21 +700,40 @@ static void mtk_mac_config(struct phylin /* Save the syscfg0 value for mac_finish */ mac->syscfg0 = val; @@ -347,7 +347,7 @@ Signed-off-by: Daniel Golle return; err_phy: -@@ -665,6 +738,18 @@ init_err: +@@ -673,6 +746,18 @@ init_err: mac->id, phy_modes(state->interface), err); } @@ -366,7 +366,7 @@ Signed-off-by: Daniel Golle static int mtk_mac_finish(struct phylink_config *config, unsigned int mode, phy_interface_t interface) { -@@ -673,6 +758,10 @@ static int mtk_mac_finish(struct phylink +@@ -681,6 +766,10 @@ static int mtk_mac_finish(struct phylink struct mtk_eth *eth = mac->hw; u32 mcr_cur, mcr_new; @@ -377,7 +377,7 @@ Signed-off-by: Daniel Golle /* Enable SGMII */ if (interface == PHY_INTERFACE_MODE_SGMII || phy_interface_mode_is_8023z(interface)) -@@ -697,10 +786,14 @@ static void mtk_mac_link_down(struct phy +@@ -705,10 +794,14 @@ static void mtk_mac_link_down(struct phy { struct mtk_mac *mac = container_of(config, struct mtk_mac, phylink_config); @@ -395,7 +395,7 @@ Signed-off-by: Daniel Golle } static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, -@@ -772,13 +865,11 @@ static void mtk_set_queue_speed(struct m +@@ -780,13 +873,11 @@ static void mtk_set_queue_speed(struct m mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); } @@ -413,7 +413,7 @@ Signed-off-by: Daniel Golle u32 mcr; mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); -@@ -822,9 +913,63 @@ static void mtk_mac_link_up(struct phyli +@@ -830,9 +921,63 @@ static void mtk_mac_link_up(struct phyli mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); } @@ -477,7 +477,7 @@ Signed-off-by: Daniel Golle .mac_finish = mtk_mac_finish, .mac_link_down = mtk_mac_link_down, .mac_link_up = mtk_mac_link_up, -@@ -3432,6 +3577,9 @@ static int mtk_open(struct net_device *d +@@ -3591,6 +3736,9 @@ static int mtk_open(struct net_device *d ppe_num = eth->soc->ppe_num; @@ -487,7 +487,7 @@ Signed-off-by: Daniel Golle err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); if (err) { netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, -@@ -3579,6 +3727,9 @@ static int mtk_stop(struct net_device *d +@@ -3738,6 +3886,9 @@ static int mtk_stop(struct net_device *d for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) mtk_ppe_stop(eth->ppe[i]); @@ -497,7 +497,7 @@ Signed-off-by: Daniel Golle return 0; } -@@ -4669,6 +4820,7 @@ static const struct net_device_ops mtk_n +@@ -4828,6 +4979,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); @@ -505,7 +505,7 @@ Signed-off-by: Daniel Golle phy_interface_t phy_mode; struct phylink *phylink; struct mtk_mac *mac; -@@ -4707,16 +4859,44 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4866,16 +5018,44 @@ static int mtk_add_mac(struct mtk_eth *e mac->id = id; mac->hw = eth; mac->of_node = np; @@ -558,7 +558,7 @@ Signed-off-by: Daniel Golle } memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip)); -@@ -4799,8 +4979,21 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4958,8 +5138,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); @@ -580,7 +580,7 @@ Signed-off-by: Daniel Golle phylink = phylink_create(&mac->phylink_config, of_fwnode_handle(mac->of_node), phy_mode, &mtk_phylink_ops); -@@ -4851,6 +5044,26 @@ free_netdev: +@@ -5010,6 +5203,26 @@ free_netdev: return err; } @@ -607,7 +607,7 @@ Signed-off-by: Daniel Golle void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev) { struct net_device *dev, *tmp; -@@ -4997,7 +5210,8 @@ static int mtk_probe(struct platform_dev +@@ -5156,7 +5369,8 @@ static int mtk_probe(struct platform_dev regmap_write(cci, 0, 3); } @@ -617,7 +617,7 @@ Signed-off-by: Daniel Golle err = mtk_sgmii_init(eth); if (err) -@@ -5108,6 +5322,24 @@ static int mtk_probe(struct platform_dev +@@ -5267,6 +5481,24 @@ static int mtk_probe(struct platform_dev } } @@ -642,7 +642,7 @@ Signed-off-by: Daniel Golle if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) { err = devm_request_irq(eth->dev, eth->irq[0], mtk_handle_irq, 0, -@@ -5218,6 +5450,11 @@ static void mtk_remove(struct platform_d +@@ -5377,6 +5609,11 @@ static void mtk_remove(struct platform_d mtk_stop(eth->netdev[i]); mac = netdev_priv(eth->netdev[i]); phylink_disconnect_phy(mac->phylink); @@ -664,7 +664,7 @@ Signed-off-by: Daniel Golle #include #include #include -@@ -524,6 +525,21 @@ +@@ -527,6 +528,21 @@ #define INTF_MODE_RGMII_1000 (TRGMII_MODE | TRGMII_CENTRAL_ALIGNED) #define INTF_MODE_RGMII_10_100 0 @@ -686,7 +686,7 @@ Signed-off-by: Daniel Golle /* GPIO port control registers for GMAC 2*/ #define GPIO_OD33_CTRL8 0x4c0 #define GPIO_BIAS_CTRL 0xed0 -@@ -549,6 +565,7 @@ +@@ -552,6 +568,7 @@ #define SYSCFG0_SGMII_GMAC2 ((3 << 8) & SYSCFG0_SGMII_MASK) #define SYSCFG0_SGMII_GMAC1_V2 BIT(9) #define SYSCFG0_SGMII_GMAC2_V2 BIT(8) @@ -694,7 +694,7 @@ Signed-off-by: Daniel Golle /* ethernet subsystem clock register */ -@@ -587,6 +604,11 @@ +@@ -590,6 +607,11 @@ #define GEPHY_MAC_SEL BIT(1) /* Top misc registers */ @@ -706,7 +706,7 @@ Signed-off-by: Daniel Golle #define USB_PHY_SWITCH_REG 0x218 #define QPHY_SEL_MASK GENMASK(1, 0) #define SGMII_QPHY_SEL 0x2 -@@ -611,6 +633,8 @@ +@@ -614,6 +636,8 @@ #define MT7628_SDM_RBCNT (MT7628_SDM_OFFSET + 0x10c) #define MT7628_SDM_CS_ERR (MT7628_SDM_OFFSET + 0x110) @@ -715,7 +715,7 @@ Signed-off-by: Daniel Golle #define MTK_FE_CDM1_FSM 0x220 #define MTK_FE_CDM2_FSM 0x224 #define MTK_FE_CDM3_FSM 0x238 -@@ -619,6 +643,11 @@ +@@ -622,6 +646,11 @@ #define MTK_FE_CDM6_FSM 0x328 #define MTK_FE_GDM1_FSM 0x228 #define MTK_FE_GDM2_FSM 0x22C @@ -727,7 +727,7 @@ Signed-off-by: Daniel Golle #define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100)) -@@ -951,6 +980,8 @@ enum mkt_eth_capabilities { +@@ -945,6 +974,8 @@ enum mkt_eth_capabilities { MTK_RGMII_BIT = 0, MTK_TRGMII_BIT, MTK_SGMII_BIT, @@ -736,7 +736,7 @@ Signed-off-by: Daniel Golle MTK_ESW_BIT, MTK_GEPHY_BIT, MTK_MUX_BIT, -@@ -971,8 +1002,11 @@ enum mkt_eth_capabilities { +@@ -965,8 +996,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, @@ -748,7 +748,7 @@ Signed-off-by: Daniel Golle /* PATH BITS */ MTK_ETH_PATH_GMAC1_RGMII_BIT, -@@ -980,14 +1014,21 @@ enum mkt_eth_capabilities { +@@ -974,14 +1008,21 @@ enum mkt_eth_capabilities { MTK_ETH_PATH_GMAC1_SGMII_BIT, MTK_ETH_PATH_GMAC2_RGMII_BIT, MTK_ETH_PATH_GMAC2_SGMII_BIT, @@ -770,7 +770,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) -@@ -1010,10 +1051,16 @@ enum mkt_eth_capabilities { +@@ -1004,10 +1045,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) @@ -787,7 +787,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) -@@ -1021,8 +1068,13 @@ enum mkt_eth_capabilities { +@@ -1015,8 +1062,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) @@ -801,7 +801,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) -@@ -1030,7 +1082,12 @@ enum mkt_eth_capabilities { +@@ -1024,7 +1076,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) @@ -814,7 +814,7 @@ Signed-off-by: Daniel Golle /* MUXes present on SoCs */ /* 0: GDM1 -> GMAC1, 1: GDM1 -> ESW */ -@@ -1049,10 +1106,20 @@ enum mkt_eth_capabilities { +@@ -1043,10 +1100,20 @@ enum mkt_eth_capabilities { (MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_MUX | \ MTK_SHARED_SGMII) @@ -835,7 +835,7 @@ Signed-off-by: Daniel Golle #define MTK_HAS_CAPS(caps, _x) (((caps) & (_x)) == (_x)) #define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \ -@@ -1084,8 +1151,12 @@ enum mkt_eth_capabilities { +@@ -1078,8 +1145,12 @@ enum mkt_eth_capabilities { MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ MTK_RSTCTRL_PPE1 | MTK_SRAM) @@ -850,7 +850,7 @@ Signed-off-by: Daniel Golle struct mtk_tx_dma_desc_info { dma_addr_t addr; -@@ -1333,6 +1404,9 @@ struct mtk_mac { +@@ -1327,6 +1398,9 @@ struct mtk_mac { struct device_node *of_node; struct phylink *phylink; struct phylink_config phylink_config; @@ -860,7 +860,7 @@ Signed-off-by: Daniel Golle struct mtk_eth *hw; struct mtk_hw_stats *hw_stats; __be32 hwlro_ip[MTK_MAX_LRO_IP_CNT]; -@@ -1456,6 +1530,19 @@ static inline u32 mtk_get_ib2_multicast_ +@@ -1450,6 +1524,19 @@ static inline u32 mtk_get_ib2_multicast_ return MTK_FOE_IB2_MULTICAST; } @@ -880,7 +880,7 @@ Signed-off-by: Daniel Golle /* read the hardware status register */ void mtk_stats_update_mac(struct mtk_mac *mac); -@@ -1464,8 +1551,10 @@ u32 mtk_r32(struct mtk_eth *eth, unsigne +@@ -1458,8 +1545,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); diff --git a/lede/target/linux/generic/pending-6.12/738-01-net-ethernet-mtk_eth_soc-reduce-rx-ring-size-for-older.patch b/lede/target/linux/generic/pending-6.12/738-01-net-ethernet-mtk_eth_soc-reduce-rx-ring-size-for-older.patch index 7ec342a20f..1ba5433466 100644 --- a/lede/target/linux/generic/pending-6.12/738-01-net-ethernet-mtk_eth_soc-reduce-rx-ring-size-for-older.patch +++ b/lede/target/linux/generic/pending-6.12/738-01-net-ethernet-mtk_eth_soc-reduce-rx-ring-size-for-older.patch @@ -30,8 +30,8 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -5482,7 +5482,7 @@ static const struct mtk_soc_data mt2701_ - .desc_size = sizeof(struct mtk_rx_dma), +@@ -5647,7 +5647,7 @@ static const struct mtk_soc_data mt2701_ + DESC_SIZE(struct mtk_rx_dma), .irq_done_mask = MTK_RX_DONE_INT, .dma_l4_valid = RX_DMA_L4_VALID, - .dma_size = MTK_DMA_SIZE(2K), @@ -39,8 +39,8 @@ Signed-off-by: Felix Fietkau .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5510,7 +5510,7 @@ static const struct mtk_soc_data mt7621_ - .desc_size = sizeof(struct mtk_rx_dma), +@@ -5675,7 +5675,7 @@ static const struct mtk_soc_data mt7621_ + DESC_SIZE(struct mtk_rx_dma), .irq_done_mask = MTK_RX_DONE_INT, .dma_l4_valid = RX_DMA_L4_VALID, - .dma_size = MTK_DMA_SIZE(2K), @@ -48,8 +48,8 @@ Signed-off-by: Felix Fietkau .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5540,7 +5540,7 @@ static const struct mtk_soc_data mt7622_ - .desc_size = sizeof(struct mtk_rx_dma), +@@ -5705,7 +5705,7 @@ static const struct mtk_soc_data mt7622_ + DESC_SIZE(struct mtk_rx_dma), .irq_done_mask = MTK_RX_DONE_INT, .dma_l4_valid = RX_DMA_L4_VALID, - .dma_size = MTK_DMA_SIZE(2K), @@ -57,8 +57,8 @@ Signed-off-by: Felix Fietkau .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5569,7 +5569,7 @@ static const struct mtk_soc_data mt7623_ - .desc_size = sizeof(struct mtk_rx_dma), +@@ -5734,7 +5734,7 @@ static const struct mtk_soc_data mt7623_ + DESC_SIZE(struct mtk_rx_dma), .irq_done_mask = MTK_RX_DONE_INT, .dma_l4_valid = RX_DMA_L4_VALID, - .dma_size = MTK_DMA_SIZE(2K), @@ -66,8 +66,8 @@ Signed-off-by: Felix Fietkau .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5595,7 +5595,7 @@ static const struct mtk_soc_data mt7629_ - .desc_size = sizeof(struct mtk_rx_dma), +@@ -5760,7 +5760,7 @@ static const struct mtk_soc_data mt7629_ + DESC_SIZE(struct mtk_rx_dma), .irq_done_mask = MTK_RX_DONE_INT, .dma_l4_valid = RX_DMA_L4_VALID, - .dma_size = MTK_DMA_SIZE(2K), @@ -75,7 +75,7 @@ Signed-off-by: Felix Fietkau .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5627,7 +5627,7 @@ static const struct mtk_soc_data mt7981_ +@@ -5792,7 +5792,7 @@ static const struct mtk_soc_data mt7981_ .dma_l4_valid = RX_DMA_L4_VALID_V2, .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, @@ -84,7 +84,7 @@ Signed-off-by: Felix Fietkau }, }; -@@ -5657,7 +5657,7 @@ static const struct mtk_soc_data mt7986_ +@@ -5822,7 +5822,7 @@ static const struct mtk_soc_data mt7986_ .dma_l4_valid = RX_DMA_L4_VALID_V2, .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, @@ -93,7 +93,7 @@ Signed-off-by: Felix Fietkau }, }; -@@ -5710,7 +5710,7 @@ static const struct mtk_soc_data rt5350_ +@@ -5875,7 +5875,7 @@ static const struct mtk_soc_data rt5350_ .dma_l4_valid = RX_DMA_L4_VALID_PDMA, .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, diff --git a/lede/target/linux/generic/pending-6.12/738-02-net-ethernet-mtk_eth_soc-do-not-enable-page-pool-sta.patch b/lede/target/linux/generic/pending-6.12/738-02-net-ethernet-mtk_eth_soc-do-not-enable-page-pool-sta.patch index 26706de6ad..10712eb4fa 100644 --- a/lede/target/linux/generic/pending-6.12/738-02-net-ethernet-mtk_eth_soc-do-not-enable-page-pool-sta.patch +++ b/lede/target/linux/generic/pending-6.12/738-02-net-ethernet-mtk_eth_soc-do-not-enable-page-pool-sta.patch @@ -25,7 +25,7 @@ Signed-off-by: Felix Fietkau help --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4588,6 +4588,7 @@ static int mtk_get_sset_count(struct net +@@ -4747,6 +4747,7 @@ static int mtk_get_sset_count(struct net static void mtk_ethtool_pp_stats(struct mtk_eth *eth, u64 *data) { @@ -33,7 +33,7 @@ Signed-off-by: Felix Fietkau struct page_pool_stats stats = {}; int i; -@@ -4600,6 +4601,7 @@ static void mtk_ethtool_pp_stats(struct +@@ -4759,6 +4760,7 @@ static void mtk_ethtool_pp_stats(struct page_pool_get_stats(ring->page_pool, &stats); } page_pool_ethtool_stats_get(data, &stats); diff --git a/lede/target/linux/generic/pending-6.12/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch b/lede/target/linux/generic/pending-6.12/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch index 8eb9d35b58..0e4a63ec7f 100644 --- a/lede/target/linux/generic/pending-6.12/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch +++ b/lede/target/linux/generic/pending-6.12/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch @@ -79,7 +79,7 @@ Signed-off-by: Daniel Golle 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 +@@ -117,6 +139,17 @@ static void mtk_pcs_lynxi_get_state(stru FIELD_GET(SGMII_LPA, adv)); } @@ -97,7 +97,7 @@ Signed-off-by: Daniel Golle static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, const unsigned long *advertising, -@@ -147,6 +180,7 @@ static int mtk_pcs_lynxi_config(struct p +@@ -162,6 +195,7 @@ static int mtk_pcs_lynxi_config(struct p SGMII_PHYA_PWD); /* Reset SGMII PCS state */ @@ -105,7 +105,7 @@ Signed-off-by: Daniel Golle regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0, SGMII_SW_RESET); -@@ -233,10 +267,29 @@ static void mtk_pcs_lynxi_link_up(struct +@@ -248,10 +282,29 @@ static void mtk_pcs_lynxi_link_up(struct } } @@ -135,7 +135,7 @@ Signed-off-by: Daniel Golle mpcs->interface = PHY_INTERFACE_MODE_NA; } -@@ -246,11 +299,12 @@ static const struct phylink_pcs_ops mtk_ +@@ -262,11 +315,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, @@ -151,7 +151,7 @@ Signed-off-by: Daniel Golle { struct mtk_pcs_lynxi *mpcs; u32 id, ver; -@@ -258,29 +312,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create +@@ -274,29 +328,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id); if (ret < 0) @@ -192,7 +192,7 @@ Signed-off-by: Daniel Golle mpcs->ana_rgc3 = ana_rgc3; mpcs->regmap = regmap; -@@ -291,6 +349,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create +@@ -307,6 +365,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create mpcs->interface = PHY_INTERFACE_MODE_NA; return &mpcs->pcs; @@ -206,7 +206,7 @@ Signed-off-by: Daniel Golle } EXPORT_SYMBOL(mtk_pcs_lynxi_create); -@@ -303,5 +368,142 @@ void mtk_pcs_lynxi_destroy(struct phylin +@@ -319,5 +384,142 @@ void mtk_pcs_lynxi_destroy(struct phylin } EXPORT_SYMBOL(mtk_pcs_lynxi_destroy); diff --git a/lede/target/linux/generic/pending-6.12/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch b/lede/target/linux/generic/pending-6.12/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch index 381b3a98cd..318d6216d8 100644 --- a/lede/target/linux/generic/pending-6.12/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch +++ b/lede/target/linux/generic/pending-6.12/739-05-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch @@ -19,7 +19,7 @@ Signed-off-by: Daniel Golle --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -14419,7 +14419,9 @@ M: Daniel Golle +@@ -14425,7 +14425,9 @@ M: Daniel Golle L: netdev@vger.kernel.org S: Maintained F: drivers/net/pcs/pcs-mtk-lynxi.c diff --git a/lede/target/linux/generic/pending-6.12/750-net-sfp-add-quirk-for-FlyPro-10Gbase-T-module.patch b/lede/target/linux/generic/pending-6.12/750-net-sfp-add-quirk-for-FlyPro-10Gbase-T-module.patch deleted file mode 100644 index b7d3af572d..0000000000 --- a/lede/target/linux/generic/pending-6.12/750-net-sfp-add-quirk-for-FlyPro-10Gbase-T-module.patch +++ /dev/null @@ -1,28 +0,0 @@ -From ddbf0e78a8b20ec18d314d31336a0230fdc9b394 Mon Sep 17 00:00:00 2001 -From: Aleksander Jan Bajkowski -Date: Sun, 31 Aug 2025 12:59:07 +0200 -Subject: net: sfp: add quirk for FLYPRO copper SFP+ module - -Add quirk for a copper SFP that identifies itself as "FLYPRO" -"SFP-10GT-CS-30M". It uses RollBall protocol to talk to the PHY. - -Signed-off-by: Aleksander Jan Bajkowski -Reviewed-by: Russell King (Oracle) -Link: https://patch.msgid.link/20250831105910.3174-1-olek2@wp.pl -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/sfp.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/net/phy/sfp.c -+++ b/drivers/net/phy/sfp.c -@@ -494,6 +494,9 @@ static const struct sfp_quirk sfp_quirks - // FLYPRO SFP-10GT-CS-30M uses Rollball protocol to talk to the PHY. - SFP_QUIRK_F("FLYPRO", "SFP-10GT-CS-30M", sfp_fixup_rollball), - -+ // FLYPRO SFP-10GT-CS-30M uses Rollball protocol to talk to the PHY. -+ SFP_QUIRK_F("FLYPRO", "SFP-10GT-CS-30M", sfp_fixup_rollball), -+ - // Fiberstore SFP-10G-T doesn't identify as copper, uses the Rollball - // protocol to talk to the PHY and needs 4 sec wait before probing the - // PHY. diff --git a/lede/target/linux/generic/pending-6.12/791-tg3-Fix-DMA-allocations-on-57766-devices.patch b/lede/target/linux/generic/pending-6.12/791-tg3-Fix-DMA-allocations-on-57766-devices.patch index bc29761445..5181041ec0 100644 --- a/lede/target/linux/generic/pending-6.12/791-tg3-Fix-DMA-allocations-on-57766-devices.patch +++ b/lede/target/linux/generic/pending-6.12/791-tg3-Fix-DMA-allocations-on-57766-devices.patch @@ -17,7 +17,7 @@ Signed-off-by: Pavan Chebbi --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c -@@ -17802,8 +17802,10 @@ static int tg3_init_one(struct pci_dev * +@@ -17799,8 +17799,10 @@ static int tg3_init_one(struct pci_dev * } else persist_dma_mask = dma_mask = DMA_BIT_MASK(64); diff --git a/lede/target/linux/generic/pending-6.12/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch b/lede/target/linux/generic/pending-6.12/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch index e3b37eecc1..8121901c66 100644 --- a/lede/target/linux/generic/pending-6.12/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch +++ b/lede/target/linux/generic/pending-6.12/801-gpio-gpio-cascade-add-generic-GPIO-cascade.patch @@ -92,7 +92,7 @@ v1 -> v2: endif --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile -@@ -45,6 +45,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd +@@ -46,6 +46,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o diff --git a/lede/target/linux/generic/pending-6.12/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch b/lede/target/linux/generic/pending-6.12/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch index aedeeb4e9f..042afdc391 100644 --- a/lede/target/linux/generic/pending-6.12/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch +++ b/lede/target/linux/generic/pending-6.12/802-OPP-Provide-old-opp-to-config_clks-on-_set_opp.patch @@ -72,6 +72,19 @@ Signed-off-by: Christian Marangi &target_freq, false); goto put_opp_table; } +--- a/drivers/ufs/core/ufshcd.c ++++ b/drivers/ufs/core/ufshcd.c +@@ -1122,8 +1122,8 @@ out: + } + + int ufshcd_opp_config_clks(struct device *dev, struct opp_table *opp_table, +- struct dev_pm_opp *opp, void *data, +- bool scaling_down) ++ struct dev_pm_opp *old_opp, struct dev_pm_opp *opp, ++ void *data, bool scaling_down) + { + struct ufs_hba *hba = dev_get_drvdata(dev); + struct list_head *head = &hba->clk_list_head; --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -50,7 +50,8 @@ typedef int (*config_regulators_t)(struc @@ -106,3 +119,16 @@ Signed-off-by: Christian Marangi { return -EOPNOTSUPP; } +--- a/include/ufs/ufshcd.h ++++ b/include/ufs/ufshcd.h +@@ -1333,8 +1333,8 @@ void ufshcd_mcq_enable(struct ufs_hba *h + void ufshcd_mcq_config_esi(struct ufs_hba *hba, struct msi_msg *msg); + + int ufshcd_opp_config_clks(struct device *dev, struct opp_table *opp_table, +- struct dev_pm_opp *opp, void *data, +- bool scaling_down); ++ struct dev_pm_opp *old_opp, struct dev_pm_opp *opp, ++ void *data, bool scaling_down); + /** + * ufshcd_set_variant - set variant specific data to the hba + * @hba: per adapter instance diff --git a/lede/target/linux/generic/pending-6.12/810-pci_disable_common_quirks.patch b/lede/target/linux/generic/pending-6.12/810-pci_disable_common_quirks.patch index 559348332f..89dcbc2786 100644 --- a/lede/target/linux/generic/pending-6.12/810-pci_disable_common_quirks.patch +++ b/lede/target/linux/generic/pending-6.12/810-pci_disable_common_quirks.patch @@ -33,7 +33,7 @@ Signed-off-by: Gabor Juhos /* * The Mellanox Tavor device gives false positive parity errors. Disable * parity error reporting. -@@ -3508,6 +3509,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I +@@ -3509,6 +3510,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata); @@ -42,7 +42,7 @@ Signed-off-by: Gabor Juhos /* * Ivytown NTB BAR sizes are misreported by the hardware due to an erratum. * To work around this, query the size it should be configured to by the -@@ -3533,6 +3536,8 @@ static void quirk_intel_ntb(struct pci_d +@@ -3534,6 +3537,8 @@ static void quirk_intel_ntb(struct pci_d DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e08, quirk_intel_ntb); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e0d, quirk_intel_ntb); @@ -51,7 +51,7 @@ Signed-off-by: Gabor Juhos /* * Some BIOS implementations leave the Intel GPU interrupts enabled, even * though no one is handling them (e.g., if the i915 driver is never -@@ -3571,6 +3576,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN +@@ -3572,6 +3577,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0152, disable_igfx_irq); diff --git a/lede/target/linux/generic/pending-6.12/812-PCI-sysfs-enforce-single-creation-of-sysfs-entry-for.patch b/lede/target/linux/generic/pending-6.12/812-PCI-sysfs-enforce-single-creation-of-sysfs-entry-for.patch new file mode 100644 index 0000000000..e5f54d7214 --- /dev/null +++ b/lede/target/linux/generic/pending-6.12/812-PCI-sysfs-enforce-single-creation-of-sysfs-entry-for.patch @@ -0,0 +1,142 @@ +From d33941523a8379e30070374b133b28a2077dcef8 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 13 Oct 2025 20:45:25 +0200 +Subject: [PATCH] PCI/sysfs: enforce single creation of sysfs entry for pdev +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In some specific scenario it's possible that the +pci_create_resource_files() gets called multiple times and the created +entry actually gets wrongly deleted with extreme case of having a NULL +pointer dereference when the PCI is removed. + +This mainly happen due to bad timing where the PCI bus is adding PCI +devices and at the same time the sysfs code is adding the entry causing +double execution of the pci_create_resource_files function and kernel +WARNING. + +To be more precise there is a race between the late_initcall of +pci-sysfs with pci_sysfs_init and PCI bus.c pci_bus_add_device that also +call pci_create_sysfs_dev_files. + +With correct amount of ""luck"" (or better say bad luck) +pci_create_sysfs_dev_files in bus.c might be called with pci_sysfs_init +is executing the loop. + +This has been reported multiple times and on multiple system, like imx6 +system, ipq806x systems... + +To address this, imlement multiple improvement to the implementation: +1. Add a bool to pci_dev to flag when sysfs entry are created + (sysfs_init) +2. Implement a simple completion to wait pci_sysfs_init execution. +3. Permit additional call of pci_create_sysfs_dev_files only after + pci_sysfs_init has finished. + +With such logic in place, we address al kind of timing problem with +minimal change to any driver. + +A notice worth to mention is that the remove function are not affected +by this as the pci_remove_resource_files have enough check in place to +always work and it's always called by pci_stop_dev. + +Cc: stable@vger.kernel.org +Reported-by: Krzysztof Hałasa +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=215515 +Signed-off-by: Christian Marangi +--- + drivers/pci/pci-sysfs.c | 34 +++++++++++++++++++++++++++++----- + include/linux/pci.h | 1 + + 2 files changed, 30 insertions(+), 5 deletions(-) + +--- a/drivers/pci/pci-sysfs.c ++++ b/drivers/pci/pci-sysfs.c +@@ -13,6 +13,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -36,6 +37,7 @@ + #endif + + static int sysfs_initialized; /* = 0 */ ++static DECLARE_COMPLETION(sysfs_init_completion); + + /* show configuration fields */ + #define pci_config_attr(field, format_string) \ +@@ -1551,12 +1553,32 @@ static const struct attribute_group pci_ + .is_visible = resource_resize_is_visible, + }; + ++static int __pci_create_sysfs_dev_files(struct pci_dev *pdev) ++{ ++ int ret; ++ ++ ret = pci_create_resource_files(pdev); ++ if (ret) ++ return ret; ++ ++ /* on success set sysfs correctly created */ ++ pdev->sysfs_init = true; ++ return 0; ++} ++ + int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev) + { + if (!sysfs_initialized) + return -EACCES; + +- return pci_create_resource_files(pdev); ++ /* sysfs entry already created */ ++ if (pdev->sysfs_init) ++ return 0; ++ ++ /* wait for pci_sysfs_init */ ++ wait_for_completion(&sysfs_init_completion); ++ ++ return __pci_create_sysfs_dev_files(pdev); + } + + /** +@@ -1577,21 +1599,23 @@ static int __init pci_sysfs_init(void) + { + struct pci_dev *pdev = NULL; + struct pci_bus *pbus = NULL; +- int retval; ++ int retval = 0; + + sysfs_initialized = 1; + for_each_pci_dev(pdev) { +- retval = pci_create_sysfs_dev_files(pdev); ++ retval = __pci_create_sysfs_dev_files(pdev); + if (retval) { + pci_dev_put(pdev); +- return retval; ++ goto exit; + } + } + + while ((pbus = pci_find_next_bus(pbus))) + pci_create_legacy_files(pbus); + +- return 0; ++exit: ++ complete_all(&sysfs_init_completion); ++ return retval; + } + late_initcall(pci_sysfs_init); + +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -484,6 +484,7 @@ struct pci_dev { + unsigned int rom_attr_enabled:1; /* Display of ROM attribute enabled? */ + pci_dev_flags_t dev_flags; + atomic_t enable_cnt; /* pci_enable_device has been called */ ++ bool sysfs_init; /* sysfs entry has been created */ + + spinlock_t pcie_cap_lock; /* Protects RMW ops in capability accessors */ + u32 saved_config_space[16]; /* Config space saved at suspend time */ diff --git a/lede/target/linux/generic/pending-6.12/834-ledtrig-libata.patch b/lede/target/linux/generic/pending-6.12/834-ledtrig-libata.patch index 09c53ee875..373e2ec575 100644 --- a/lede/target/linux/generic/pending-6.12/834-ledtrig-libata.patch +++ b/lede/target/linux/generic/pending-6.12/834-ledtrig-libata.patch @@ -63,7 +63,7 @@ Signed-off-by: Daniel Golle /** * ata_build_rw_tf - Build ATA taskfile for given read/write request * @qc: Metadata associated with the taskfile to build -@@ -4767,6 +4778,9 @@ void __ata_qc_complete(struct ata_queued +@@ -4800,6 +4811,9 @@ void __ata_qc_complete(struct ata_queued link->active_tag = ATA_TAG_POISON; ap->nr_active_links--; } @@ -73,7 +73,7 @@ Signed-off-by: Daniel Golle /* clear exclusive status */ if (unlikely(qc->flags & ATA_QCFLAG_CLEAR_EXCL && -@@ -5489,6 +5503,9 @@ struct ata_port *ata_port_alloc(struct a +@@ -5522,6 +5536,9 @@ struct ata_port *ata_port_alloc(struct a ap->stats.unhandled_irq = 1; ap->stats.idle_irq = 1; #endif @@ -83,7 +83,7 @@ Signed-off-by: Daniel Golle ata_sff_port_init(ap); ata_force_pflags(ap); -@@ -5505,6 +5522,12 @@ void ata_port_free(struct ata_port *ap) +@@ -5538,6 +5555,12 @@ void ata_port_free(struct ata_port *ap) kfree(ap->pmp_link); kfree(ap->slave_link); ida_free(&ata_ida, ap->print_id); @@ -96,7 +96,7 @@ Signed-off-by: Daniel Golle kfree(ap); } EXPORT_SYMBOL_GPL(ata_port_free); -@@ -5909,7 +5932,23 @@ int ata_host_register(struct ata_host *h +@@ -5942,7 +5965,23 @@ int ata_host_register(struct ata_host *h WARN_ON(1); return -EINVAL; } diff --git a/lede/target/linux/generic/pending-6.12/920-mangle_bootargs.patch b/lede/target/linux/generic/pending-6.12/920-mangle_bootargs.patch index 04f5be3f74..3bf2fce4fb 100644 --- a/lede/target/linux/generic/pending-6.12/920-mangle_bootargs.patch +++ b/lede/target/linux/generic/pending-6.12/920-mangle_bootargs.patch @@ -13,7 +13,7 @@ Signed-off-by: Imre Kaloz --- a/init/Kconfig +++ b/init/Kconfig -@@ -1887,6 +1887,15 @@ config ARCH_HAS_MEMBARRIER_CALLBACKS +@@ -1888,6 +1888,15 @@ config ARCH_HAS_MEMBARRIER_CALLBACKS config ARCH_HAS_MEMBARRIER_SYNC_CORE bool @@ -31,7 +31,7 @@ Signed-off-by: Imre Kaloz help --- a/init/main.c +++ b/init/main.c -@@ -621,6 +621,29 @@ static inline void setup_nr_cpu_ids(void +@@ -633,6 +633,29 @@ static inline void setup_nr_cpu_ids(void static inline void smp_prepare_cpus(unsigned int maxcpus) { } #endif @@ -61,7 +61,7 @@ Signed-off-by: Imre Kaloz /* * We need to store the untouched command line for future reference. * We also need to store the touched command line since the parameter -@@ -927,6 +950,7 @@ void start_kernel(void) +@@ -939,6 +962,7 @@ void start_kernel(void) jump_label_init(); static_call_init(); early_security_init(); diff --git a/lede/target/linux/mediatek/patches-6.12/051-v6.16-hwrng-mtk-Add-struct-device-pointer-to-device-contex.patch b/lede/target/linux/mediatek/patches-6.12/051-v6.16-hwrng-mtk-Add-struct-device-pointer-to-device-contex.patch new file mode 100644 index 0000000000..70c771d2df --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/051-v6.16-hwrng-mtk-Add-struct-device-pointer-to-device-contex.patch @@ -0,0 +1,60 @@ +From f9c0c36eefaa8c6ee224634bf9c0b8b4ed87b43a Mon Sep 17 00:00:00 2001 +From: Sakari Ailus +Date: Thu, 10 Apr 2025 18:22:38 +0300 +Subject: [PATCH] hwrng: mtk - Add struct device pointer to device context struct + +Add a struct device pointer field to the device's context struct. This +makes using the unsigned long priv pointer in struct hwrng unnecessary, so +remove that one as well. + +Signed-off-by: Sakari Ailus +Signed-off-by: Herbert Xu +--- + drivers/char/hw_random/mtk-rng.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/char/hw_random/mtk-rng.c ++++ b/drivers/char/hw_random/mtk-rng.c +@@ -36,6 +36,7 @@ struct mtk_rng { + void __iomem *base; + struct clk *clk; + struct hwrng rng; ++ struct device *dev; + }; + + static int mtk_rng_init(struct hwrng *rng) +@@ -85,7 +86,7 @@ static int mtk_rng_read(struct hwrng *rn + struct mtk_rng *priv = to_mtk_rng(rng); + int retval = 0; + +- pm_runtime_get_sync((struct device *)priv->rng.priv); ++ pm_runtime_get_sync(priv->dev); + + while (max >= sizeof(u32)) { + if (!mtk_rng_wait_ready(rng, wait)) +@@ -97,8 +98,8 @@ static int mtk_rng_read(struct hwrng *rn + max -= sizeof(u32); + } + +- pm_runtime_mark_last_busy((struct device *)priv->rng.priv); +- pm_runtime_put_sync_autosuspend((struct device *)priv->rng.priv); ++ pm_runtime_mark_last_busy(priv->dev); ++ pm_runtime_put_sync_autosuspend(priv->dev); + + return retval || !wait ? retval : -EIO; + } +@@ -112,13 +113,13 @@ static int mtk_rng_probe(struct platform + if (!priv) + return -ENOMEM; + ++ priv->dev = &pdev->dev; + priv->rng.name = pdev->name; + #ifndef CONFIG_PM + priv->rng.init = mtk_rng_init; + priv->rng.cleanup = mtk_rng_cleanup; + #endif + priv->rng.read = mtk_rng_read; +- priv->rng.priv = (unsigned long)&pdev->dev; + priv->rng.quality = 900; + + priv->clk = devm_clk_get(&pdev->dev, "rng"); diff --git a/lede/target/linux/mediatek/patches-6.12/061-v6.19-arm64-dts-mediatek-mt7986-bpi-r3-Change-fan-PWM-valu.patch b/lede/target/linux/mediatek/patches-6.12/061-v6.19-arm64-dts-mediatek-mt7986-bpi-r3-Change-fan-PWM-valu.patch new file mode 100644 index 0000000000..4b27031d11 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/061-v6.19-arm64-dts-mediatek-mt7986-bpi-r3-Change-fan-PWM-valu.patch @@ -0,0 +1,72 @@ +From 5f271fe1365b63f67fc384ca8d50d473d09de0d1 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Tue, 3 Dec 2024 07:33:55 +0300 +Subject: [PATCH] arm64: dts: mediatek: mt7986-bpi-r3: Change fan PWM value for + mid speed + +Popular cheap PWM fans for this machine, like the ones coming in +heatsink+fan combos will not work properly at the currently defined +medium speed. Trying different pwm setting using a command + + echo $value > /sys/devices/platform/pwm-fan/hwmon/hwmon1/pwm1 + +I found: + + pwm1 value fan rotation speed cpu temperature notes + ----------------------------------------------------------------- + 0 maximal 31.5 Celsius too noisy + 40 optimal 35.2 Celsius no noise hearable + 95 minimal + above 95 does not rotate 55.5 Celsius + ----------------------------------------------------------------- + +Thus only cpu-active-high and cpu-active-low modes are usable. +I think this is wrong. + +This patch fixes cpu-active-medium settings for bpi-r3 board. + +I know, the patch is not ideal as it can break pwm fan for some users. +Likely this is the only official mt7986-bpi-r3 heatsink+fan solution +available on the market. + +This patch may not be enough. Users may wants to tweak their thermal_zone0 +trip points, thus tuning fan rotation speed depending on cpu temperature. +That can be done on the base of the following example: + + === example ========= + # cpu temperature below 25 Celsius degrees, no rotation + echo 25000 > /sys/class/thermal/thermal_zone0/trip_point_4_temp + # cpu temperature in [25..32] Celsius degrees, normal rotation speed + echo 32000 > /sys/class/thermal/thermal_zone0/trip_point_3_temp + # cpu temperature above 50 Celsius degrees, max rotation speed + echo 50000 > /sys/class/thermal/thermal_zone0/trip_point_2_temp + ===================== + +Signed-off-by: Mikhail Kshevetskiy +Acked-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno + +--- +Changes from v1 to v2: + * improve patch description + +Changes from v2 to v3: + * added question to Frank Wunderlich + +Changes from v3 to v4: + * Acked by Frank Wunderlich +--- + arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts +@@ -42,7 +42,7 @@ + compatible = "pwm-fan"; + #cooling-cells = <2>; + /* cooling level (0, 1, 2) - pwm inverted */ +- cooling-levels = <255 96 0>; ++ cooling-levels = <255 40 0>; + pwms = <&pwm 0 10000>; + status = "okay"; + }; diff --git a/lede/target/linux/mediatek/patches-6.12/070-v7.0-pinctrl-mediatek-enable-ies_present-flag-for-MT798x.patch b/lede/target/linux/mediatek/patches-6.12/070-v7.0-pinctrl-mediatek-enable-ies_present-flag-for-MT798x.patch new file mode 100644 index 0000000000..47263733ac --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/070-v7.0-pinctrl-mediatek-enable-ies_present-flag-for-MT798x.patch @@ -0,0 +1,59 @@ +From 6da9f0cc2717158857f8b8b9369523d0d6770c07 Mon Sep 17 00:00:00 2001 +From: Shiji Yang +Date: Sat, 17 Jan 2026 11:04:37 +0800 +Subject: [PATCH] pinctrl: mediatek: enable ies_present flag for MT798x + +The MT798x series SoCs have IES regiter definitions. I think we +must enable the ies_present flag to correctly configure the pin +input mode. + +Signed-off-by: Shiji Yang +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/pinctrl-mt7981.c | 2 +- + drivers/pinctrl/mediatek/pinctrl-mt7986.c | 4 ++-- + drivers/pinctrl/mediatek/pinctrl-mt7988.c | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c +@@ -1019,7 +1019,7 @@ static struct mtk_pin_soc mt7981_data = + .nfuncs = ARRAY_SIZE(mt7981_functions), + .eint_hw = &mt7981_eint_hw, + .gpio_m = 0, +- .ies_present = false, ++ .ies_present = true, + .base_names = mt7981_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt7981_pinctrl_register_base_names), + .bias_disable_set = mtk_pinconf_bias_disable_set, +--- a/drivers/pinctrl/mediatek/pinctrl-mt7986.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c +@@ -919,7 +919,7 @@ static struct mtk_pin_soc mt7986a_data = + .nfuncs = ARRAY_SIZE(mt7986_functions), + .eint_hw = &mt7986a_eint_hw, + .gpio_m = 0, +- .ies_present = false, ++ .ies_present = true, + .base_names = mt7986_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), + .bias_disable_set = mtk_pinconf_bias_disable_set, +@@ -945,7 +945,7 @@ static struct mtk_pin_soc mt7986b_data = + .nfuncs = ARRAY_SIZE(mt7986_functions), + .eint_hw = &mt7986b_eint_hw, + .gpio_m = 0, +- .ies_present = false, ++ .ies_present = true, + .base_names = mt7986_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), + .bias_disable_set = mtk_pinconf_bias_disable_set, +--- a/drivers/pinctrl/mediatek/pinctrl-mt7988.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7988.c +@@ -1515,7 +1515,7 @@ static const struct mtk_pin_soc mt7988_d + .nfuncs = ARRAY_SIZE(mt7988_functions), + .eint_hw = &mt7988_eint_hw, + .gpio_m = 0, +- .ies_present = false, ++ .ies_present = true, + .base_names = mt7988_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt7988_pinctrl_register_base_names), + .bias_disable_set = mtk_pinconf_bias_disable_set, diff --git a/lede/target/linux/mediatek/patches-6.12/119-pinctrl-mediatek-MT7981-some-register-map-fixes.patch b/lede/target/linux/mediatek/patches-6.12/119-pinctrl-mediatek-MT7981-some-register-map-fixes.patch new file mode 100644 index 0000000000..fce45298aa --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/119-pinctrl-mediatek-MT7981-some-register-map-fixes.patch @@ -0,0 +1,76 @@ +From 2b4d8df6054acb13cae20889c40102c93df2edd6 Mon Sep 17 00:00:00 2001 +From: developer +Date: Tue, 6 Jan 2026 19:52:11 +0800 +Subject: [PATCH] pinctrl: mediatek: MT7981: some register map fixes + +Fix mt7981 pinctrl setting mistake including: +1) Wrong pinctrl bits length +2) Wrong pinctrl register offset + +Link: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/52579dd19e62df5aff784462e133e14bfe4a7726 +Signed-off-by: Shiji Yang +--- + drivers/pinctrl/mediatek/pinctrl-mt7981.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c +@@ -48,7 +48,7 @@ static const struct mtk_pin_field_calc m + + PIN_FIELD_BASE(9, 9, 5, 0x20, 0x10, 9, 1), + PIN_FIELD_BASE(10, 10, 5, 0x20, 0x10, 8, 1), +- PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1), ++ PIN_FIELD_BASE(11, 11, 5, 0x20, 0x10, 10, 1), + PIN_FIELD_BASE(12, 12, 5, 0x20, 0x10, 7, 1), + PIN_FIELD_BASE(13, 13, 5, 0x20, 0x10, 11, 1), + +@@ -157,7 +157,7 @@ static const struct mtk_pin_field_calc m + PIN_FIELD_BASE(41, 41, 7, 0x70, 0x10, 0, 1), + PIN_FIELD_BASE(42, 42, 7, 0x70, 0x10, 9, 1), + PIN_FIELD_BASE(43, 43, 7, 0x70, 0x10, 7, 1), +- PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1), ++ PIN_FIELD_BASE(44, 44, 7, 0x70, 0x10, 8, 1), + PIN_FIELD_BASE(45, 45, 7, 0x70, 0x10, 3, 1), + PIN_FIELD_BASE(46, 46, 7, 0x70, 0x10, 4, 1), + PIN_FIELD_BASE(47, 47, 7, 0x70, 0x10, 5, 1), +@@ -221,8 +221,8 @@ static const struct mtk_pin_field_calc m + + PIN_FIELD_BASE(2, 2, 5, 0x00, 0x10, 18, 3), + +- PIN_FIELD_BASE(3, 3, 4, 0x00, 0x10, 18, 1), +- PIN_FIELD_BASE(4, 4, 4, 0x00, 0x10, 6, 1), ++ PIN_FIELD_BASE(3, 3, 4, 0x00, 0x10, 18, 3), ++ PIN_FIELD_BASE(4, 4, 4, 0x00, 0x10, 6, 3), + PIN_FIELD_BASE(5, 5, 4, 0x00, 0x10, 3, 3), + PIN_FIELD_BASE(6, 6, 4, 0x00, 0x10, 9, 3), + PIN_FIELD_BASE(7, 7, 4, 0x00, 0x10, 0, 3), +@@ -230,9 +230,9 @@ static const struct mtk_pin_field_calc m + + PIN_FIELD_BASE(9, 9, 5, 0x00, 0x10, 27, 3), + PIN_FIELD_BASE(10, 10, 5, 0x00, 0x10, 24, 3), +- PIN_FIELD_BASE(11, 11, 5, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(11, 11, 5, 0x10, 0x10, 0, 3), + PIN_FIELD_BASE(12, 12, 5, 0x00, 0x10, 21, 3), +- PIN_FIELD_BASE(13, 13, 5, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(13, 13, 5, 0x10, 0x10, 3, 3), + + PIN_FIELD_BASE(14, 14, 4, 0x00, 0x10, 27, 3), + +@@ -244,7 +244,7 @@ static const struct mtk_pin_field_calc m + PIN_FIELD_BASE(20, 20, 2, 0x00, 0x10, 9, 3), + PIN_FIELD_BASE(21, 21, 2, 0x00, 0x10, 18, 3), + PIN_FIELD_BASE(22, 22, 2, 0x00, 0x10, 21, 3), +- PIN_FIELD_BASE(23, 23, 2, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(23, 23, 2, 0x10, 0x10, 0, 3), + PIN_FIELD_BASE(24, 24, 2, 0x00, 0x10, 27, 3), + PIN_FIELD_BASE(25, 25, 2, 0x00, 0x10, 24, 3), + +@@ -310,7 +310,7 @@ static const struct mtk_pin_field_calc m + PIN_FIELD_BASE(17, 17, 2, 0x30, 0x10, 5, 1), + PIN_FIELD_BASE(18, 18, 2, 0x30, 0x10, 4, 1), + PIN_FIELD_BASE(19, 19, 2, 0x30, 0x10, 2, 1), +- PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1), ++ PIN_FIELD_BASE(20, 20, 2, 0x30, 0x10, 3, 1), + PIN_FIELD_BASE(21, 21, 2, 0x30, 0x10, 6, 1), + PIN_FIELD_BASE(22, 22, 2, 0x30, 0x10, 7, 1), + PIN_FIELD_BASE(23, 23, 2, 0x30, 0x10, 10, 1), diff --git a/lede/target/linux/mediatek/patches-6.12/171-arm64-dts-mediatek-mt7988a-Add-xsphy-for-ssusb0-pcie2.patch b/lede/target/linux/mediatek/patches-6.12/171-v6.16-arm64-dts-mediatek-mt7988-Add-xsphy-for-ssusb0-pcie2.patch similarity index 89% rename from lede/target/linux/mediatek/patches-6.12/171-arm64-dts-mediatek-mt7988a-Add-xsphy-for-ssusb0-pcie2.patch rename to lede/target/linux/mediatek/patches-6.12/171-v6.16-arm64-dts-mediatek-mt7988-Add-xsphy-for-ssusb0-pcie2.patch index fac060ef16..18f1ddc5bf 100644 --- a/lede/target/linux/mediatek/patches-6.12/171-arm64-dts-mediatek-mt7988a-Add-xsphy-for-ssusb0-pcie2.patch +++ b/lede/target/linux/mediatek/patches-6.12/171-v6.16-arm64-dts-mediatek-mt7988-Add-xsphy-for-ssusb0-pcie2.patch @@ -1,14 +1,15 @@ -From 1861c63ba7bb7f8a5145d4ceabcf346f274da61f Mon Sep 17 00:00:00 2001 +From 2400b24dfecea9a628f63089bf7eeb9a43b91021 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Tue, 22 Apr 2025 15:24:30 +0200 -Subject: [PATCH 28/32] arm64: dts: mediatek: mt7988: Add xsphy for - ssusb0/pcie2 +Subject: [PATCH 28/32] arm64: dts: mediatek: mt7988: Add xsphy for ssusb0/pcie2 First usb and third pcie controller on mt7988 need a xs-phy to work properly. Signed-off-by: Frank Wunderlich Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20250422132438.15735-8-linux@fw-web.de +Signed-off-by: AngeloGioacchino Del Regno --- arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/lede/target/linux/mediatek/patches-6.12/172-arm64-dts-mediatek-mt7988a-bpi-r4-enable-xsphy.patch b/lede/target/linux/mediatek/patches-6.12/172-v6.16-arm64-dts-mediatek-mt7988a-bpi-r4-enable-xsphy.patch similarity index 82% rename from lede/target/linux/mediatek/patches-6.12/172-arm64-dts-mediatek-mt7988a-bpi-r4-enable-xsphy.patch rename to lede/target/linux/mediatek/patches-6.12/172-v6.16-arm64-dts-mediatek-mt7988a-bpi-r4-enable-xsphy.patch index da26a93eb7..d02bca2b4e 100644 --- a/lede/target/linux/mediatek/patches-6.12/172-arm64-dts-mediatek-mt7988a-bpi-r4-enable-xsphy.patch +++ b/lede/target/linux/mediatek/patches-6.12/172-v6.16-arm64-dts-mediatek-mt7988a-bpi-r4-enable-xsphy.patch @@ -1,4 +1,4 @@ -From d326d21a44fbc48663840316c35524002029fbb1 Mon Sep 17 00:00:00 2001 +From bb5872c4b6cb0a8687b424b9970b2c3cca2ededd Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Tue, 22 Apr 2025 15:24:31 +0200 Subject: [PATCH 29/32] arm64: dts: mediatek: mt7988a-bpi-r4: enable xsphy @@ -7,6 +7,8 @@ Enable XS-Phy on Bananapi R4 for pcie2. Signed-off-by: Frank Wunderlich Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20250422132438.15735-9-linux@fw-web.de +Signed-off-by: AngeloGioacchino Del Regno --- arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 4 ++++ arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 2 +- diff --git a/lede/target/linux/mediatek/patches-6.12/174-arm64-dts-mediatek-mt7988-add-spi-controllers.patch b/lede/target/linux/mediatek/patches-6.12/174-arm64-dts-mediatek-mt7988-add-spi-controllers.patch deleted file mode 100644 index a0557ab966..0000000000 --- a/lede/target/linux/mediatek/patches-6.12/174-arm64-dts-mediatek-mt7988-add-spi-controllers.patch +++ /dev/null @@ -1,112 +0,0 @@ -From patchwork Sun May 11 14:19:20 2025 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Frank Wunderlich -X-Patchwork-Id: 14084127 -From: Frank Wunderlich -To: Andrew Lunn , - Vladimir Oltean , - "David S. Miller" , - Eric Dumazet , - Jakub Kicinski , - Paolo Abeni , - Rob Herring , - Krzysztof Kozlowski , - Conor Dooley , - Matthias Brugger , - AngeloGioacchino Del Regno -Subject: [PATCH v1 04/14] arm64: dts: mediatek: mt7988: add spi controllers -Date: Sun, 11 May 2025 16:19:20 +0200 -Message-ID: <20250511141942.10284-5-linux@fw-web.de> -X-Mailer: git-send-email 2.43.0 -In-Reply-To: <20250511141942.10284-1-linux@fw-web.de> -References: <20250511141942.10284-1-linux@fw-web.de> -MIME-Version: 1.0 -X-Mail-ID: 5110cbfc-28b8-49e4-b9da-560d0bd630a5 -X-BeenThere: linux-mediatek@lists.infradead.org -X-Mailman-Version: 2.1.34 -Precedence: list -List-Id: -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Cc: devicetree@vger.kernel.org, Landen Chao , - =?utf-8?b?QXLEsW7DpyDDnE5BTA==?= , - netdev@vger.kernel.org, Sean Wang , - Daniel Golle , linux-kernel@vger.kernel.org, - DENG Qingfang , linux-mediatek@lists.infradead.org, - Lorenzo Bianconi , linux-arm-kernel@lists.infradead.org, - Felix Fietkau -Sender: "Linux-mediatek" -Errors-To: - linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org - -From: Frank Wunderlich - -Add SPI controllers for mt7988. - -Signed-off-by: Daniel Golle -Signed-off-by: Frank Wunderlich ---- - arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 45 +++++++++++++++++++++++ - 1 file changed, 45 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi -@@ -311,6 +311,51 @@ - status = "disabled"; - }; - -+ spi0: spi@11007000 { -+ compatible = "mediatek,mt7988-spi-quad", "mediatek,spi-ipm"; -+ reg = <0 0x11007000 0 0x100>; -+ interrupts = ; -+ clocks = <&topckgen CLK_TOP_MPLL_D2>, -+ <&topckgen CLK_TOP_SPI_SEL>, -+ <&infracfg CLK_INFRA_104M_SPI0>, -+ <&infracfg CLK_INFRA_66M_SPI0_HCK>; -+ clock-names = "parent-clk", "sel-clk", "spi-clk", -+ "hclk"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ spi1: spi@11008000 { -+ compatible = "mediatek,mt7988-spi-single", "mediatek,spi-ipm"; -+ reg = <0 0x11008000 0 0x100>; -+ interrupts = ; -+ clocks = <&topckgen CLK_TOP_MPLL_D2>, -+ <&topckgen CLK_TOP_SPIM_MST_SEL>, -+ <&infracfg CLK_INFRA_104M_SPI1>, -+ <&infracfg CLK_INFRA_66M_SPI1_HCK>; -+ clock-names = "parent-clk", "sel-clk", "spi-clk", -+ "hclk"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ spi2: spi@11009000 { -+ compatible = "mediatek,mt7988-spi-quad", "mediatek,spi-ipm"; -+ reg = <0 0x11009000 0 0x100>; -+ interrupts = ; -+ clocks = <&topckgen CLK_TOP_MPLL_D2>, -+ <&topckgen CLK_TOP_SPI_SEL>, -+ <&infracfg CLK_INFRA_104M_SPI2_BCK>, -+ <&infracfg CLK_INFRA_66M_SPI2_HCK>; -+ clock-names = "parent-clk", "sel-clk", "spi-clk", -+ "hclk"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ - lvts: lvts@1100a000 { - compatible = "mediatek,mt7988-lvts-ap"; - #thermal-sensor-cells = <1>; diff --git a/lede/target/linux/mediatek/patches-6.12/174-v6.16-arm64-dts-mediatek-mt7988-add-spi-controllers.patch b/lede/target/linux/mediatek/patches-6.12/174-v6.16-arm64-dts-mediatek-mt7988-add-spi-controllers.patch new file mode 100644 index 0000000000..d634671ab5 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/174-v6.16-arm64-dts-mediatek-mt7988-add-spi-controllers.patch @@ -0,0 +1,69 @@ +From bf7c2ce439ca811dc1697b4bc19ab57bd8f13be3 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 16 May 2025 20:01:35 +0200 +Subject: [PATCH] arm64: dts: mediatek: mt7988: add spi controllers + +Add SPI controllers for mt7988. + +Signed-off-by: Daniel Golle +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20250516180147.10416-6-linux@fw-web.de +Signed-off-by: AngeloGioacchino Del Regno +--- + arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 45 +++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +@@ -311,6 +311,51 @@ + status = "disabled"; + }; + ++ spi0: spi@11007000 { ++ compatible = "mediatek,mt7988-spi-quad", "mediatek,spi-ipm"; ++ reg = <0 0x11007000 0 0x100>; ++ interrupts = ; ++ clocks = <&topckgen CLK_TOP_MPLL_D2>, ++ <&topckgen CLK_TOP_SPI_SEL>, ++ <&infracfg CLK_INFRA_104M_SPI0>, ++ <&infracfg CLK_INFRA_66M_SPI0_HCK>; ++ clock-names = "parent-clk", "sel-clk", "spi-clk", ++ "hclk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi1: spi@11008000 { ++ compatible = "mediatek,mt7988-spi-single", "mediatek,spi-ipm"; ++ reg = <0 0x11008000 0 0x100>; ++ interrupts = ; ++ clocks = <&topckgen CLK_TOP_MPLL_D2>, ++ <&topckgen CLK_TOP_SPIM_MST_SEL>, ++ <&infracfg CLK_INFRA_104M_SPI1>, ++ <&infracfg CLK_INFRA_66M_SPI1_HCK>; ++ clock-names = "parent-clk", "sel-clk", "spi-clk", ++ "hclk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi2: spi@11009000 { ++ compatible = "mediatek,mt7988-spi-quad", "mediatek,spi-ipm"; ++ reg = <0 0x11009000 0 0x100>; ++ interrupts = ; ++ clocks = <&topckgen CLK_TOP_MPLL_D2>, ++ <&topckgen CLK_TOP_SPI_SEL>, ++ <&infracfg CLK_INFRA_104M_SPI2_BCK>, ++ <&infracfg CLK_INFRA_66M_SPI2_HCK>; ++ clock-names = "parent-clk", "sel-clk", "spi-clk", ++ "hclk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + lvts: lvts@1100a000 { + compatible = "mediatek,mt7988-lvts-ap"; + #thermal-sensor-cells = <1>; diff --git a/lede/target/linux/mediatek/patches-6.12/175-arm64-dts-mediatek-mt7988-move-uart0-and-spi1-pins-to-soc-dtsi.patch b/lede/target/linux/mediatek/patches-6.12/175-arm64-dts-mediatek-mt7988-move-uart0-and-spi1-pins-to-soc-dtsi.patch deleted file mode 100644 index 7dbc1e4286..0000000000 --- a/lede/target/linux/mediatek/patches-6.12/175-arm64-dts-mediatek-mt7988-move-uart0-and-spi1-pins-to-soc-dtsi.patch +++ /dev/null @@ -1,133 +0,0 @@ -From patchwork Sun May 11 14:19:21 2025 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Frank Wunderlich -X-Patchwork-Id: 14084155 -From: Frank Wunderlich -To: Andrew Lunn , - Vladimir Oltean , - "David S. Miller" , - Eric Dumazet , - Jakub Kicinski , - Paolo Abeni , - Rob Herring , - Krzysztof Kozlowski , - Conor Dooley , - Matthias Brugger , - AngeloGioacchino Del Regno -Subject: [PATCH v1 05/14] arm64: dts: mediatek: mt7988: move uart0 and spi1 - pins to soc dtsi -Date: Sun, 11 May 2025 16:19:21 +0200 -Message-ID: <20250511141942.10284-6-linux@fw-web.de> -X-Mailer: git-send-email 2.43.0 -In-Reply-To: <20250511141942.10284-1-linux@fw-web.de> -References: <20250511141942.10284-1-linux@fw-web.de> -MIME-Version: 1.0 -X-Mail-ID: 730e5bd4-362e-4c00-a35e-0ec77e8f4691 -X-BeenThere: linux-mediatek@lists.infradead.org -X-Mailman-Version: 2.1.34 -Precedence: list -List-Id: -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Cc: devicetree@vger.kernel.org, Landen Chao , - =?utf-8?b?QXLEsW7DpyDDnE5BTA==?= , - netdev@vger.kernel.org, Sean Wang , - Daniel Golle , linux-kernel@vger.kernel.org, - DENG Qingfang , linux-mediatek@lists.infradead.org, - Lorenzo Bianconi , linux-arm-kernel@lists.infradead.org, - Felix Fietkau -Sender: "Linux-mediatek" -Errors-To: - linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org - -From: Frank Wunderlich - -In order to use uart0 or spi1 there is only 1 possible pin definition -so move them to soc dtsi to reuse them in other boards and avoiding -conflict if defined twice. - -Suggested-by: Daniel Golle -Signed-off-by: Frank Wunderlich ---- - .../dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 14 -------------- - arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 18 ++++++++++++++++++ - 2 files changed, 18 insertions(+), 14 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi -@@ -328,13 +328,6 @@ - }; - }; - -- uart0_pins: uart0-pins { -- mux { -- function = "uart"; -- groups = "uart0"; -- }; -- }; -- - snfi_pins: snfi-pins { - mux { - function = "flash"; -@@ -356,13 +349,6 @@ - }; - }; - -- spi1_pins: spi1-pins { -- mux { -- function = "spi"; -- groups = "spi1"; -- }; -- }; -- - spi2_pins: spi2-pins { - mux { - function = "spi"; ---- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi -@@ -209,6 +209,20 @@ - "pcie_wake_n3_0"; - }; - }; -+ -+ spi1_pins: spi1-pins { -+ mux { -+ function = "spi"; -+ groups = "spi1"; -+ }; -+ }; -+ -+ uart0_pins: uart0-pins { -+ mux { -+ function = "uart"; -+ groups = "uart0"; -+ }; -+ }; - }; - - pwm: pwm@10048000 { -@@ -244,6 +258,8 @@ - clocks = <&topckgen CLK_TOP_UART_SEL>, - <&infracfg CLK_INFRA_52M_UART0_CK>; - clock-names = "baud", "bus"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart0_pins>; - status = "disabled"; - }; - -@@ -338,6 +354,8 @@ - "hclk"; - #address-cells = <1>; - #size-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi1_pins>; - status = "disabled"; - }; - diff --git a/lede/target/linux/mediatek/patches-6.12/175-v6.16-arm64-dts-mediatek-mt7988-move-uart0-and-spi1-pins-t.patch b/lede/target/linux/mediatek/patches-6.12/175-v6.16-arm64-dts-mediatek-mt7988-move-uart0-and-spi1-pins-t.patch new file mode 100644 index 0000000000..54d829c7d9 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/175-v6.16-arm64-dts-mediatek-mt7988-move-uart0-and-spi1-pins-t.patch @@ -0,0 +1,90 @@ +From b9ebd166b006f77cef4530b4bf4a291a112da4f2 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 16 May 2025 20:01:36 +0200 +Subject: [PATCH] arm64: dts: mediatek: mt7988: move uart0 and spi1 pins to soc + dtsi + +In order to use uart0 or spi1 there is only 1 possible pin definition +so move them to soc dtsi to reuse them in other boards and avoiding +conflict if defined twice. + +Suggested-by: Daniel Golle +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20250516180147.10416-7-linux@fw-web.de +Signed-off-by: AngeloGioacchino Del Regno +--- + .../dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 14 -------------- + arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 18 ++++++++++++++++++ + 2 files changed, 18 insertions(+), 14 deletions(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +@@ -328,13 +328,6 @@ + }; + }; + +- uart0_pins: uart0-pins { +- mux { +- function = "uart"; +- groups = "uart0"; +- }; +- }; +- + snfi_pins: snfi-pins { + mux { + function = "flash"; +@@ -356,13 +349,6 @@ + }; + }; + +- spi1_pins: spi1-pins { +- mux { +- function = "spi"; +- groups = "spi1"; +- }; +- }; +- + spi2_pins: spi2-pins { + mux { + function = "spi"; +--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +@@ -209,6 +209,20 @@ + "pcie_wake_n3_0"; + }; + }; ++ ++ spi1_pins: spi1-pins { ++ mux { ++ function = "spi"; ++ groups = "spi1"; ++ }; ++ }; ++ ++ uart0_pins: uart0-pins { ++ mux { ++ function = "uart"; ++ groups = "uart0"; ++ }; ++ }; + }; + + pwm: pwm@10048000 { +@@ -244,6 +258,8 @@ + clocks = <&topckgen CLK_TOP_UART_SEL>, + <&infracfg CLK_INFRA_52M_UART0_CK>; + clock-names = "baud", "bus"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins>; + status = "disabled"; + }; + +@@ -338,6 +354,8 @@ + "hclk"; + #address-cells = <1>; + #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi1_pins>; + status = "disabled"; + }; + diff --git a/lede/target/linux/mediatek/patches-6.12/176-arm64-dts-mediatek-mt7988-add-cci-node.patch b/lede/target/linux/mediatek/patches-6.12/176-arm64-dts-mediatek-mt7988-add-cci-node.patch deleted file mode 100644 index 915c45caeb..0000000000 --- a/lede/target/linux/mediatek/patches-6.12/176-arm64-dts-mediatek-mt7988-add-cci-node.patch +++ /dev/null @@ -1,128 +0,0 @@ -From patchwork Sun May 11 14:19:22 2025 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Frank Wunderlich -X-Patchwork-Id: 14084106 -From: Frank Wunderlich -To: Andrew Lunn , - Vladimir Oltean , - "David S. Miller" , - Eric Dumazet , - Jakub Kicinski , - Paolo Abeni , - Rob Herring , - Krzysztof Kozlowski , - Conor Dooley , - Matthias Brugger , - AngeloGioacchino Del Regno -Subject: [PATCH v1 06/14] arm64: dts: mediatek: mt7988: add cci node -Date: Sun, 11 May 2025 16:19:22 +0200 -Message-ID: <20250511141942.10284-7-linux@fw-web.de> -X-Mailer: git-send-email 2.43.0 -In-Reply-To: <20250511141942.10284-1-linux@fw-web.de> -References: <20250511141942.10284-1-linux@fw-web.de> -MIME-Version: 1.0 -X-Mail-ID: beeb7784-23fa-410f-9e58-cc51116d869e -X-BeenThere: linux-mediatek@lists.infradead.org -X-Mailman-Version: 2.1.34 -Precedence: list -List-Id: -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Cc: devicetree@vger.kernel.org, Landen Chao , - =?utf-8?b?QXLEsW7DpyDDnE5BTA==?= , - netdev@vger.kernel.org, Sean Wang , - Daniel Golle , linux-kernel@vger.kernel.org, - DENG Qingfang , linux-mediatek@lists.infradead.org, - Lorenzo Bianconi , linux-arm-kernel@lists.infradead.org, - Felix Fietkau -Sender: "Linux-mediatek" -Errors-To: - linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org - -From: Frank Wunderlich - -Add cci devicetree node for cpu frequency scaling. - -Signed-off-by: Daniel Golle -Signed-off-by: Frank Wunderlich ---- - arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 33 +++++++++++++++++++++++ - 1 file changed, 33 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi -@@ -12,6 +12,35 @@ - #address-cells = <2>; - #size-cells = <2>; - -+ cci: cci { -+ compatible = "mediatek,mt8183-cci"; -+ clocks = <&mcusys CLK_MCU_BUS_DIV_SEL>, -+ <&topckgen CLK_TOP_XTAL>; -+ clock-names = "cci", "intermediate"; -+ operating-points-v2 = <&cci_opp>; -+ }; -+ -+ cci_opp: opp-table-cci { -+ compatible = "operating-points-v2"; -+ opp-shared; -+ opp-480000000 { -+ opp-hz = /bits/ 64 <480000000>; -+ opp-microvolt = <850000>; -+ }; -+ opp-660000000 { -+ opp-hz = /bits/ 64 <660000000>; -+ opp-microvolt = <850000>; -+ }; -+ opp-900000000 { -+ opp-hz = /bits/ 64 <900000000>; -+ opp-microvolt = <850000>; -+ }; -+ opp-1080000000 { -+ opp-hz = /bits/ 64 <1080000000>; -+ opp-microvolt = <900000>; -+ }; -+ }; -+ - cpus { - #address-cells = <1>; - #size-cells = <0>; -@@ -25,6 +54,7 @@ - <&topckgen CLK_TOP_XTAL>; - clock-names = "cpu", "intermediate"; - operating-points-v2 = <&cluster0_opp>; -+ mediatek,cci = <&cci>; - }; - - cpu1: cpu@1 { -@@ -36,6 +66,7 @@ - <&topckgen CLK_TOP_XTAL>; - clock-names = "cpu", "intermediate"; - operating-points-v2 = <&cluster0_opp>; -+ mediatek,cci = <&cci>; - }; - - cpu2: cpu@2 { -@@ -47,6 +78,7 @@ - <&topckgen CLK_TOP_XTAL>; - clock-names = "cpu", "intermediate"; - operating-points-v2 = <&cluster0_opp>; -+ mediatek,cci = <&cci>; - }; - - cpu3: cpu@3 { -@@ -58,6 +90,7 @@ - <&topckgen CLK_TOP_XTAL>; - clock-names = "cpu", "intermediate"; - operating-points-v2 = <&cluster0_opp>; -+ mediatek,cci = <&cci>; - }; - - cluster0_opp: opp-table-0 { diff --git a/lede/target/linux/mediatek/patches-6.12/176-v6.17-arm64-dts-mediatek-mt7988-add-cci-node.patch b/lede/target/linux/mediatek/patches-6.12/176-v6.17-arm64-dts-mediatek-mt7988-add-cci-node.patch new file mode 100644 index 0000000000..42a4aed2e2 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/176-v6.17-arm64-dts-mediatek-mt7988-add-cci-node.patch @@ -0,0 +1,86 @@ +From 0cbdb6d04689f8c05074e348c8e0a42b229ef9a3 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 6 Jul 2025 15:22:03 +0200 +Subject: [PATCH] arm64: dts: mediatek: mt7988: add cci node + +Add cci devicetree node for cpu frequency scaling. + +Signed-off-by: Daniel Golle +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20250706132213.20412-9-linux@fw-web.de +Signed-off-by: AngeloGioacchino Del Regno +--- + arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 33 +++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +@@ -12,6 +12,35 @@ + #address-cells = <2>; + #size-cells = <2>; + ++ cci: cci { ++ compatible = "mediatek,mt7988-cci", "mediatek,mt8183-cci"; ++ clocks = <&mcusys CLK_MCU_BUS_DIV_SEL>, ++ <&topckgen CLK_TOP_XTAL>; ++ clock-names = "cci", "intermediate"; ++ operating-points-v2 = <&cci_opp>; ++ }; ++ ++ cci_opp: opp-table-cci { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ opp-480000000 { ++ opp-hz = /bits/ 64 <480000000>; ++ opp-microvolt = <850000>; ++ }; ++ opp-660000000 { ++ opp-hz = /bits/ 64 <660000000>; ++ opp-microvolt = <850000>; ++ }; ++ opp-900000000 { ++ opp-hz = /bits/ 64 <900000000>; ++ opp-microvolt = <850000>; ++ }; ++ opp-1080000000 { ++ opp-hz = /bits/ 64 <1080000000>; ++ opp-microvolt = <900000>; ++ }; ++ }; ++ + cpus { + #address-cells = <1>; + #size-cells = <0>; +@@ -25,6 +54,7 @@ + <&topckgen CLK_TOP_XTAL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; ++ mediatek,cci = <&cci>; + }; + + cpu1: cpu@1 { +@@ -36,6 +66,7 @@ + <&topckgen CLK_TOP_XTAL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; ++ mediatek,cci = <&cci>; + }; + + cpu2: cpu@2 { +@@ -47,6 +78,7 @@ + <&topckgen CLK_TOP_XTAL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; ++ mediatek,cci = <&cci>; + }; + + cpu3: cpu@3 { +@@ -58,6 +90,7 @@ + <&topckgen CLK_TOP_XTAL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; ++ mediatek,cci = <&cci>; + }; + + cluster0_opp: opp-table-0 { diff --git a/lede/target/linux/mediatek/patches-6.12/177-arm64-dts-mediatek-mt7988-add-phy-calibration-efuse-subnodes.patch b/lede/target/linux/mediatek/patches-6.12/177-arm64-dts-mediatek-mt7988-add-phy-calibration-efuse-subnodes.patch deleted file mode 100644 index dc6df8ee57..0000000000 --- a/lede/target/linux/mediatek/patches-6.12/177-arm64-dts-mediatek-mt7988-add-phy-calibration-efuse-subnodes.patch +++ /dev/null @@ -1,85 +0,0 @@ -From patchwork Sun May 11 14:19:23 2025 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Frank Wunderlich -X-Patchwork-Id: 14084124 -From: Frank Wunderlich -To: Andrew Lunn , - Vladimir Oltean , - "David S. Miller" , - Eric Dumazet , - Jakub Kicinski , - Paolo Abeni , - Rob Herring , - Krzysztof Kozlowski , - Conor Dooley , - Matthias Brugger , - AngeloGioacchino Del Regno -Subject: [PATCH v1 07/14] arm64: dts: mediatek: mt7988: add phy calibration - efuse subnodes -Date: Sun, 11 May 2025 16:19:23 +0200 -Message-ID: <20250511141942.10284-8-linux@fw-web.de> -X-Mailer: git-send-email 2.43.0 -In-Reply-To: <20250511141942.10284-1-linux@fw-web.de> -References: <20250511141942.10284-1-linux@fw-web.de> -MIME-Version: 1.0 -X-Mail-ID: b7327c0d-db13-43b6-8ec5-709b71d19c3b -X-BeenThere: linux-mediatek@lists.infradead.org -X-Mailman-Version: 2.1.34 -Precedence: list -List-Id: -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Cc: devicetree@vger.kernel.org, Landen Chao , - =?utf-8?b?QXLEsW7DpyDDnE5BTA==?= , - netdev@vger.kernel.org, Sean Wang , - Daniel Golle , linux-kernel@vger.kernel.org, - DENG Qingfang , linux-mediatek@lists.infradead.org, - Lorenzo Bianconi , linux-arm-kernel@lists.infradead.org, - Felix Fietkau -Sender: "Linux-mediatek" -Errors-To: - linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org - -From: Frank Wunderlich - -MT7988 contains buildin mt753x switch which needs calibration data from -efuse. - -Signed-off-by: Daniel Golle -Signed-off-by: Frank Wunderlich ---- - arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi -@@ -702,6 +702,22 @@ - lvts_calibration: calib@918 { - reg = <0x918 0x28>; - }; -+ -+ phy_calibration_p0: calib@940 { -+ reg = <0x940 0x10>; -+ }; -+ -+ phy_calibration_p1: calib@954 { -+ reg = <0x954 0x10>; -+ }; -+ -+ phy_calibration_p2: calib@968 { -+ reg = <0x968 0x10>; -+ }; -+ -+ phy_calibration_p3: calib@97c { -+ reg = <0x97c 0x10>; -+ }; - }; - - clock-controller@15000000 { diff --git a/lede/target/linux/mediatek/patches-6.12/177-v6.16-arm64-dts-mediatek-mt7988-add-phy-calibration-efuse-.patch b/lede/target/linux/mediatek/patches-6.12/177-v6.16-arm64-dts-mediatek-mt7988-add-phy-calibration-efuse-.patch new file mode 100644 index 0000000000..b657e221f6 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/177-v6.16-arm64-dts-mediatek-mt7988-add-phy-calibration-efuse-.patch @@ -0,0 +1,42 @@ +From e4950b016c727feb0c39ad12cfcb6182c9ef3814 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 16 May 2025 20:01:38 +0200 +Subject: [PATCH] arm64: dts: mediatek: mt7988: add phy calibration efuse + subnodes + +MT7988 contains buildin mt753x switch which needs calibration data from +efuse. + +Signed-off-by: Daniel Golle +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20250516180147.10416-9-linux@fw-web.de +Signed-off-by: AngeloGioacchino Del Regno +--- + arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +@@ -702,6 +702,22 @@ + lvts_calibration: calib@918 { + reg = <0x918 0x28>; + }; ++ ++ phy_calibration_p0: calib@940 { ++ reg = <0x940 0x10>; ++ }; ++ ++ phy_calibration_p1: calib@954 { ++ reg = <0x954 0x10>; ++ }; ++ ++ phy_calibration_p2: calib@968 { ++ reg = <0x968 0x10>; ++ }; ++ ++ phy_calibration_p3: calib@97c { ++ reg = <0x97c 0x10>; ++ }; + }; + + clock-controller@15000000 { diff --git a/lede/target/linux/mediatek/patches-6.12/180-arm64-dts-mediatek-mt7988a-bpi-r4-Add-fan-and-coolingmaps.patch b/lede/target/linux/mediatek/patches-6.12/180-arm64-dts-mediatek-mt7988a-bpi-r4-Add-fan-and-coolingmaps.patch deleted file mode 100644 index 4e3d4ae8c0..0000000000 --- a/lede/target/linux/mediatek/patches-6.12/180-arm64-dts-mediatek-mt7988a-bpi-r4-Add-fan-and-coolingmaps.patch +++ /dev/null @@ -1,98 +0,0 @@ -From patchwork Sun May 11 14:26:50 2025 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Frank Wunderlich -X-Patchwork-Id: 14084133 -From: Frank Wunderlich -To: Andrew Lunn , - Vladimir Oltean , - "David S. Miller" , - Eric Dumazet , - Jakub Kicinski , - Paolo Abeni , - Rob Herring , - Krzysztof Kozlowski , - Conor Dooley , - Matthias Brugger , - AngeloGioacchino Del Regno -Subject: [PATCH v1 10/14] arm64: dts: mediatek: mt7988a-bpi-r4: Add fan and - coolingmaps -Date: Sun, 11 May 2025 16:26:50 +0200 -Message-ID: <20250511142655.11007-1-frank-w@public-files.de> -X-Mailer: git-send-email 2.43.0 -MIME-Version: 1.0 -X-BeenThere: linux-mediatek@lists.infradead.org -X-Mailman-Version: 2.1.34 -Precedence: list -List-Id: -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Cc: devicetree@vger.kernel.org, Landen Chao , - =?utf-8?b?QXLEsW7DpyDDnE5BTA==?= , - netdev@vger.kernel.org, Sean Wang , - Daniel Golle , linux-kernel@vger.kernel.org, - DENG Qingfang , linux-mediatek@lists.infradead.org, - Lorenzo Bianconi , linux-arm-kernel@lists.infradead.org, - Felix Fietkau -Sender: "Linux-mediatek" -Errors-To: - linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org - -Add Fan and cooling maps for Bananpi-R4 board. - -Signed-off-by: Frank Wunderlich ---- - .../dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 29 +++++++++++++++++++ - 1 file changed, 29 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi -@@ -12,6 +12,15 @@ - stdout-path = "serial0:115200n8"; - }; - -+ fan: pwm-fan { -+ compatible = "pwm-fan"; -+ /* cooling level (0, 1, 2, 3) : (0% duty, 30% duty, 50% duty, 100% duty) */ -+ cooling-levels = <0 80 128 255>; -+ #cooling-cells = <2>; -+ pwms = <&pwm 0 50000>; -+ status = "okay"; -+ }; -+ - reg_1p8v: regulator-1p8v { - compatible = "regulator-fixed"; - regulator-name = "fixed-1.8V"; -@@ -73,6 +82,26 @@ - type = "active"; - }; - }; -+ -+ cooling-maps { -+ map-cpu-active-high { -+ /* active: set fan to cooling level 2 */ -+ cooling-device = <&fan 3 3>; -+ trip = <&cpu_trip_active_high>; -+ }; -+ -+ map-cpu-active-med { -+ /* active: set fan to cooling level 1 */ -+ cooling-device = <&fan 2 2>; -+ trip = <&cpu_trip_active_med>; -+ }; -+ -+ map-cpu-active-low { -+ /* active: set fan to cooling level 0 */ -+ cooling-device = <&fan 1 1>; -+ trip = <&cpu_trip_active_low>; -+ }; -+ }; - }; - - &i2c0 { diff --git a/lede/target/linux/mediatek/patches-6.12/180-v6.16-arm64-dts-mediatek-mt7988a-bpi-r4-Add-fan-and-coolin.patch b/lede/target/linux/mediatek/patches-6.12/180-v6.16-arm64-dts-mediatek-mt7988a-bpi-r4-Add-fan-and-coolin.patch new file mode 100644 index 0000000000..9b616cebd1 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/180-v6.16-arm64-dts-mediatek-mt7988a-bpi-r4-Add-fan-and-coolin.patch @@ -0,0 +1,59 @@ +From 0f63e96e2ab422d1d35def1da75d3df299bf503e Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 16 May 2025 20:01:41 +0200 +Subject: [PATCH] arm64: dts: mediatek: mt7988a-bpi-r4: Add fan and coolingmaps + +Add Fan and cooling maps for Bananapi-R4 board. + +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20250516180147.10416-12-linux@fw-web.de +Signed-off-by: AngeloGioacchino Del Regno +--- + .../dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 29 +++++++++++++++++++ + 1 file changed, 29 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +@@ -12,6 +12,15 @@ + stdout-path = "serial0:115200n8"; + }; + ++ fan: pwm-fan { ++ compatible = "pwm-fan"; ++ /* cooling level (0, 1, 2, 3) : (0% duty, 30% duty, 50% duty, 100% duty) */ ++ cooling-levels = <0 80 128 255>; ++ #cooling-cells = <2>; ++ pwms = <&pwm 0 50000>; ++ status = "okay"; ++ }; ++ + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; +@@ -73,6 +82,26 @@ + type = "active"; + }; + }; ++ ++ cooling-maps { ++ map-cpu-active-high { ++ /* active: set fan to cooling level 2 */ ++ cooling-device = <&fan 3 3>; ++ trip = <&cpu_trip_active_high>; ++ }; ++ ++ map-cpu-active-med { ++ /* active: set fan to cooling level 1 */ ++ cooling-device = <&fan 2 2>; ++ trip = <&cpu_trip_active_med>; ++ }; ++ ++ map-cpu-active-low { ++ /* active: set fan to cooling level 0 */ ++ cooling-device = <&fan 1 1>; ++ trip = <&cpu_trip_active_low>; ++ }; ++ }; + }; + + &i2c0 { diff --git a/lede/target/linux/mediatek/patches-6.12/181-arm64-dts-mediatek-mt7988a-bpi-r4-configure-spi-nodes.patch b/lede/target/linux/mediatek/patches-6.12/181-arm64-dts-mediatek-mt7988a-bpi-r4-configure-spi-nodes.patch deleted file mode 100644 index c5c5e83e92..0000000000 --- a/lede/target/linux/mediatek/patches-6.12/181-arm64-dts-mediatek-mt7988a-bpi-r4-configure-spi-nodes.patch +++ /dev/null @@ -1,99 +0,0 @@ -From patchwork Sun May 11 14:26:51 2025 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Frank Wunderlich -X-Patchwork-Id: 14084136 -Received: from frank-u24 ([194.15.84.99]) by mail.gmx.net (mrgmx104 - [212.227.17.168]) with ESMTPSA (Nemesis) id 1MD9XF-1u5YvB0cIj-00FOt5; Sun, 11 - May 2025 16:27:04 +0200 -From: Frank Wunderlich -To: Andrew Lunn , - Vladimir Oltean , - "David S. Miller" , - Eric Dumazet , - Jakub Kicinski , - Paolo Abeni , - Rob Herring , - Krzysztof Kozlowski , - Conor Dooley , - Matthias Brugger , - AngeloGioacchino Del Regno -Subject: [PATCH v1 11/14] arm64: dts: mediatek: mt7988a-bpi-r4: configure - spi-nodes -Date: Sun, 11 May 2025 16:26:51 +0200 -Message-ID: <20250511142655.11007-2-frank-w@public-files.de> -X-Mailer: git-send-email 2.43.0 -In-Reply-To: <20250511142655.11007-1-frank-w@public-files.de> -References: <20250511142655.11007-1-frank-w@public-files.de> -MIME-Version: 1.0 -X-BeenThere: linux-mediatek@lists.infradead.org -X-Mailman-Version: 2.1.34 -Precedence: list -List-Id: -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Cc: devicetree@vger.kernel.org, Landen Chao , - =?utf-8?b?QXLEsW7DpyDDnE5BTA==?= , - netdev@vger.kernel.org, Sean Wang , - Daniel Golle , linux-kernel@vger.kernel.org, - DENG Qingfang , linux-mediatek@lists.infradead.org, - Lorenzo Bianconi , linux-arm-kernel@lists.infradead.org, - Felix Fietkau -Sender: "Linux-mediatek" -Errors-To: - linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org - -Configure and enable SPI nodes on Bananapi R4 board. - -Signed-off-by: Frank Wunderlich ---- - .../dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 32 +++++++++++++++++++ - 1 file changed, 32 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi -@@ -401,6 +401,38 @@ - status = "okay"; - }; - -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_flash_pins>; -+ status = "okay"; -+ -+ spi_nand: flash@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ spi-max-frequency = <52000000>; -+ spi-tx-bus-width = <4>; -+ spi-rx-bus-width = <4>; -+ }; -+}; -+ -+&spi1 { -+ status = "okay"; -+}; -+ -+&spi_nand { -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "bl2"; -+ reg = <0x0 0x200000>; -+ read-only; -+ }; -+ }; -+}; -+ - &ssusb1 { - status = "okay"; - }; diff --git a/lede/target/linux/mediatek/patches-6.12/181-v6.16-arm64-dts-mediatek-mt7988a-bpi-r4-configure-spi-node.patc b/lede/target/linux/mediatek/patches-6.12/181-v6.16-arm64-dts-mediatek-mt7988a-bpi-r4-configure-spi-node.patc new file mode 100644 index 0000000000..cffc02226b --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/181-v6.16-arm64-dts-mediatek-mt7988a-bpi-r4-configure-spi-node.patc @@ -0,0 +1,55 @@ +From 6b7642e9d095d33d8034b8b396a2de9e5ecb25a7 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 16 May 2025 20:01:42 +0200 +Subject: [PATCH] arm64: dts: mediatek: mt7988a-bpi-r4: configure spi-nodes + +Configure and enable SPI nodes on Bananapi R4 board. + +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20250516180147.10416-13-linux@fw-web.de +Signed-off-by: AngeloGioacchino Del Regno +--- + .../dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 32 +++++++++++++++++++ + 1 file changed, 32 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +@@ -401,6 +401,38 @@ + status = "okay"; + }; + ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_flash_pins>; ++ status = "okay"; ++ ++ spi_nand: flash@0 { ++ compatible = "spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <52000000>; ++ spi-tx-bus-width = <4>; ++ spi-rx-bus-width = <4>; ++ }; ++}; ++ ++&spi1 { ++ status = "okay"; ++}; ++ ++&spi_nand { ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "bl2"; ++ reg = <0x0 0x200000>; ++ read-only; ++ }; ++ }; ++}; ++ + &ssusb1 { + status = "okay"; + }; diff --git a/lede/target/linux/mediatek/patches-6.12/182-arm64-dts-mediatek-mt7988a-bpi-r4-add-proc-supply-for-cci.patch b/lede/target/linux/mediatek/patches-6.12/182-arm64-dts-mediatek-mt7988a-bpi-r4-add-proc-supply-for-cci.patch deleted file mode 100644 index f692a6f1c4..0000000000 --- a/lede/target/linux/mediatek/patches-6.12/182-arm64-dts-mediatek-mt7988a-bpi-r4-add-proc-supply-for-cci.patch +++ /dev/null @@ -1,68 +0,0 @@ -From patchwork Sun May 11 14:26:52 2025 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Frank Wunderlich -X-Patchwork-Id: 14084137 -From: Frank Wunderlich -To: Andrew Lunn , - Vladimir Oltean , - "David S. Miller" , - Eric Dumazet , - Jakub Kicinski , - Paolo Abeni , - Rob Herring , - Krzysztof Kozlowski , - Conor Dooley , - Matthias Brugger , - AngeloGioacchino Del Regno -Subject: [PATCH v1 12/14] arm64: dts: mediatek: mt7988a-bpi-r4: add - proc-supply for cci -Date: Sun, 11 May 2025 16:26:52 +0200 -Message-ID: <20250511142655.11007-3-frank-w@public-files.de> -X-Mailer: git-send-email 2.43.0 -In-Reply-To: <20250511142655.11007-1-frank-w@public-files.de> -References: <20250511142655.11007-1-frank-w@public-files.de> -MIME-Version: 1.0 -X-BeenThere: linux-mediatek@lists.infradead.org -X-Mailman-Version: 2.1.34 -Precedence: list -List-Id: -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Cc: devicetree@vger.kernel.org, Landen Chao , - =?utf-8?b?QXLEsW7DpyDDnE5BTA==?= , - netdev@vger.kernel.org, Sean Wang , - Daniel Golle , linux-kernel@vger.kernel.org, - DENG Qingfang , linux-mediatek@lists.infradead.org, - Lorenzo Bianconi , linux-arm-kernel@lists.infradead.org, - Felix Fietkau -Sender: "Linux-mediatek" -Errors-To: - linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org - -CCI requires proc-supply. Add it on board level. - -Signed-off-by: Frank Wunderlich ---- - arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi -@@ -40,6 +40,10 @@ - }; - }; - -+&cci { -+ proc-supply = <&rt5190_buck3>; -+}; -+ - &cpu0 { - proc-supply = <&rt5190_buck3>; - }; diff --git a/lede/target/linux/mediatek/patches-6.12/182-v6.17-arm64-dts-mediatek-mt7988a-bpi-r4-add-proc-supply-fo.patch b/lede/target/linux/mediatek/patches-6.12/182-v6.17-arm64-dts-mediatek-mt7988a-bpi-r4-add-proc-supply-fo.patch new file mode 100644 index 0000000000..68858e76b0 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/182-v6.17-arm64-dts-mediatek-mt7988a-bpi-r4-add-proc-supply-fo.patch @@ -0,0 +1,28 @@ +From b5a4ad957114b59a74b3e3f598ae0785dd86cd32 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 6 Jul 2025 15:22:06 +0200 +Subject: [PATCH] arm64: dts: mediatek: mt7988a-bpi-r4: add proc-supply for cci + +CCI requires proc-supply. Add it on board level. + +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20250706132213.20412-12-linux@fw-web.de +Signed-off-by: AngeloGioacchino Del Regno +--- + arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +@@ -40,6 +40,10 @@ + }; + }; + ++&cci { ++ proc-supply = <&rt5190_buck3>; ++}; ++ + &cpu0 { + proc-supply = <&rt5190_buck3>; + }; diff --git a/lede/target/linux/mediatek/patches-6.12/187-arm64-dts-mediatek-fix-mt7981-spim-clock.patch b/lede/target/linux/mediatek/patches-6.12/187-arm64-dts-mediatek-fix-mt7981-spim-clock.patch new file mode 100644 index 0000000000..d75f7dd12f --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/187-arm64-dts-mediatek-fix-mt7981-spim-clock.patch @@ -0,0 +1,53 @@ +From 0c74ae06ed6b6c9627712a74ecee4e61bbd4092d Mon Sep 17 00:00:00 2001 +From: developer +Date: Mon, 19 Jan 2026 21:42:29 +0800 +Subject: [PATCH] arm64: dts: mediatek: fix mt7981 spim clock + +1) Add spi0/1/2 clock parent setting +2) Fix spi1 clock_sel to CLK_TOP_SPIM_MST_SEL + +Link: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/836034ca0baad57e4c287a62ccc5677c60be0e18 +Signed-off-by: Shiji Yang +--- + arch/arm64/boot/dts/mediatek/mt7981b.dtsi | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7981b.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7981b.dtsi +@@ -248,6 +248,10 @@ + <&topckgen CLK_TOP_SPI_SEL>, + <&infracfg CLK_INFRA_SPI2_CK>, + <&infracfg CLK_INFRA_SPI2_HCK_CK>; ++ assigned-clocks = <&topckgen CLK_TOP_SPI_SEL>, ++ <&infracfg CLK_INFRA_SPI2_SEL>; ++ assigned-clock-parents = <&topckgen CLK_TOP_CB_M_D2>, ++ <&topckgen CLK_TOP_SPI_SEL>; + clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; + #address-cells = <1>; + #size-cells = <0>; +@@ -262,6 +266,10 @@ + <&topckgen CLK_TOP_SPI_SEL>, + <&infracfg CLK_INFRA_SPI0_CK>, + <&infracfg CLK_INFRA_SPI0_HCK_CK>; ++ assigned-clocks = <&topckgen CLK_TOP_SPI_SEL>, ++ <&infracfg CLK_INFRA_SPI0_SEL>; ++ assigned-clock-parents = <&topckgen CLK_TOP_CB_M_D2>, ++ <&topckgen CLK_TOP_SPI_SEL>; + clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; + #address-cells = <1>; + #size-cells = <0>; +@@ -273,9 +281,13 @@ + reg = <0 0x1100b000 0 0x1000>; + interrupts = ; + clocks = <&topckgen CLK_TOP_CB_M_D2>, +- <&topckgen CLK_TOP_SPI_SEL>, ++ <&topckgen CLK_TOP_SPIM_MST_SEL>, + <&infracfg CLK_INFRA_SPI1_CK>, + <&infracfg CLK_INFRA_SPI1_HCK_CK>; ++ assigned-clocks = <&topckgen CLK_TOP_SPIM_MST_SEL>, ++ <&infracfg CLK_INFRA_SPI1_SEL>; ++ assigned-clock-parents = <&topckgen CLK_TOP_CB_M_D2>, ++ <&topckgen CLK_TOP_SPIM_MST_SEL>; + clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; + #address-cells = <1>; + #size-cells = <0>; diff --git a/lede/target/linux/mediatek/patches-6.12/188-arm64-dts-mediatek-add-MT7988A-reference-board-devic.patch b/lede/target/linux/mediatek/patches-6.12/188-arm64-dts-mediatek-add-MT7988A-reference-board-devic.patch index 204a2cb434..0e0236c5fc 100644 --- a/lede/target/linux/mediatek/patches-6.12/188-arm64-dts-mediatek-add-MT7988A-reference-board-devic.patch +++ b/lede/target/linux/mediatek/patches-6.12/188-arm64-dts-mediatek-add-MT7988A-reference-board-devic.patch @@ -56,7 +56,7 @@ Signed-off-by: Daniel Golle dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm-hana.dtb --- /dev/null +++ b/arch/arm64/boot/dts/mediatek/mt7988a-rfb-emmc.dtso -@@ -0,0 +1,60 @@ +@@ -0,0 +1,62 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. @@ -72,6 +72,8 @@ Signed-off-by: Daniel Golle + fragment@0 { + target = <&mmc0>; + __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_emmc_51>; + pinctrl-1 = <&mmc0_pins_emmc_51>; @@ -424,7 +426,7 @@ Signed-off-by: Daniel Golle +}; --- /dev/null +++ b/arch/arm64/boot/dts/mediatek/mt7988a-rfb-sd.dtso -@@ -0,0 +1,58 @@ +@@ -0,0 +1,60 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2023 MediaTek Inc. @@ -442,6 +444,8 @@ Signed-off-by: Daniel Golle + fragment@0 { + target-path = <&mmc0>; + __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_sdcard>; + pinctrl-1 = <&mmc0_pins_sdcard>; @@ -485,7 +489,7 @@ Signed-off-by: Daniel Golle +}; --- /dev/null +++ b/arch/arm64/boot/dts/mediatek/mt7988a-rfb-snfi-nand.dtso -@@ -0,0 +1,81 @@ +@@ -0,0 +1,85 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. @@ -512,6 +516,10 @@ Signed-off-by: Daniel Golle + spi-rx-bus-width = <4>; + + partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ + partition@0 { + label = "BL2"; + reg = <0x00000 0x0200000>; @@ -811,7 +819,7 @@ Signed-off-by: Daniel Golle +}; --- /dev/null +++ b/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dts -@@ -0,0 +1,470 @@ +@@ -0,0 +1,471 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. @@ -831,13 +839,14 @@ Signed-off-by: Daniel Golle + "mediatek,mt7988a"; + + chosen { -+ bootargs = "console=ttyS0,115200n1 loglevel=8 \ ++ bootargs = "console=ttyS0,115200n1 \ + earlycon=uart8250,mmio32,0x11000000 \ + pci=pcie_bus_perf"; + }; + -+ memory { ++ memory@40000000 { + reg = <0 0x40000000 0 0x40000000>; ++ device_type = "memory"; + }; + + reg_1p8v: regulator-1p8v { diff --git a/lede/target/linux/mediatek/patches-6.12/189-arm64-dts-mediatek-mt7988a-complete-bpi-r4.patch b/lede/target/linux/mediatek/patches-6.12/189-arm64-dts-mediatek-mt7988a-complete-bpi-r4.patch index e43d0f6633..8eccb6f8f1 100644 --- a/lede/target/linux/mediatek/patches-6.12/189-arm64-dts-mediatek-mt7988a-complete-bpi-r4.patch +++ b/lede/target/linux/mediatek/patches-6.12/189-arm64-dts-mediatek-mt7988a-complete-bpi-r4.patch @@ -5,7 +5,7 @@ Subject: [PATCH 32/32] WIP: add BPi-R4 --- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-2g5.dts +++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-2g5.dts -@@ -20,3 +20,15 @@ +@@ -20,3 +20,16 @@ pinctrl-names = "i2p5gbe-led"; pinctrl-0 = <&i2p5gbe_led0_pins>; }; @@ -14,6 +14,7 @@ Subject: [PATCH 32/32] WIP: add BPi-R4 + phy-mode = "internal"; + phy-connection-type = "internal"; + phy = <&int_2p5g_phy>; ++ openwrt,netdev-name = "lan4"; + status = "okay"; +}; + @@ -161,7 +162,7 @@ Subject: [PATCH 32/32] WIP: add BPi-R4 +}; --- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts +++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts -@@ -35,3 +35,10 @@ +@@ -35,3 +35,11 @@ reg = <2>; }; }; @@ -170,6 +171,7 @@ Subject: [PATCH 32/32] WIP: add BPi-R4 + sfp = <&sfp2>; + managed = "in-band-status"; + phy-mode = "usxgmii"; ++ openwrt,netdev-name = "sfp-lan"; + status = "okay"; +}; --- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi @@ -187,12 +189,12 @@ Subject: [PATCH 32/32] WIP: add BPi-R4 / { chosen { stdout-path = "serial0:115200n8"; -+ bootargs = "console=ttyS0,115200n1 loglevel=8 pci=pcie_bus_perf ubi.block=0,fit root=/dev/fit0"; ++ bootargs = "console=ttyS0,115200n1 pci=pcie_bus_perf ubi.block=0,fit root=/dev/fit0"; + rootdisk-spim-nand = <&ubi_rootfs>; }; fan: pwm-fan { -@@ -50,6 +54,140 @@ +@@ -50,6 +54,142 @@ rate-select0-gpios = <&pio 21 GPIO_ACTIVE_LOW>; maximum-power-milliwatt = <3000>; }; @@ -208,8 +210,9 @@ Subject: [PATCH 32/32] WIP: add BPi-R4 + led-upgrade = &led_green; + }; + -+ memory { ++ memory@40000000 { + reg = <0x00 0x40000000 0x00 0x10000000>; ++ device_type = "memory"; + }; + + /* SFP1 cage (WAN) */ @@ -265,6 +268,7 @@ Subject: [PATCH 32/32] WIP: add BPi-R4 + sfp = <&sfp1>; + managed = "in-band-status"; + phy-mode = "usxgmii"; ++ openwrt,netdev-name = "sfp-wan"; + status = "okay"; +}; + @@ -333,7 +337,7 @@ Subject: [PATCH 32/32] WIP: add BPi-R4 }; &cci { -@@ -174,6 +313,10 @@ +@@ -174,6 +314,10 @@ color = ; }; @@ -344,7 +348,7 @@ Subject: [PATCH 32/32] WIP: add BPi-R4 &i2c0 { pinctrl-names = "default"; pinctrl-0 = <&i2c0_pins>; -@@ -265,6 +407,14 @@ +@@ -265,6 +409,14 @@ #size-cells = <0>; reg = <1>; }; @@ -359,7 +363,7 @@ Subject: [PATCH 32/32] WIP: add BPi-R4 }; }; -@@ -364,34 +514,6 @@ +@@ -364,34 +516,6 @@ }; }; @@ -394,7 +398,7 @@ Subject: [PATCH 32/32] WIP: add BPi-R4 i2p5gbe_led0_pins: 2p5gbe-led0-pins { mux { function = "led"; -@@ -399,13 +521,6 @@ +@@ -399,13 +523,6 @@ }; }; @@ -408,7 +412,7 @@ Subject: [PATCH 32/32] WIP: add BPi-R4 mmc0_pins_emmc_45: mmc0-emmc-45-pins { mux { function = "flash"; -@@ -427,40 +542,12 @@ +@@ -427,40 +544,12 @@ }; }; @@ -449,7 +453,7 @@ Subject: [PATCH 32/32] WIP: add BPi-R4 }; &pwm { -@@ -500,6 +587,32 @@ +@@ -500,6 +589,32 @@ reg = <0x0 0x200000>; read-only; }; diff --git a/lede/target/linux/mediatek/patches-6.12/197-dts-mt7986a-bpi-r3-mini-wifi-eeprom.patch b/lede/target/linux/mediatek/patches-6.12/197-dts-mt7986a-bpi-r3-mini-wifi-eeprom.patch deleted file mode 100644 index 298de57364..0000000000 --- a/lede/target/linux/mediatek/patches-6.12/197-dts-mt7986a-bpi-r3-mini-wifi-eeprom.patch +++ /dev/null @@ -1,136 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-mini.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-mini.dts -@@ -495,4 +495,133 @@ - pinctrl-names = "dbdc"; - pinctrl-0 = <&wf_dbdc_pins>, <&wf_led_pins>; - status = "okay"; -+ -+ mediatek,eeprom-data = <0x86790200 0x000c4326 0x60000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x125b486c 0x00280000 0x05d00000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x0c000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000012 0x12120000 0x00000000 0x00000000 0x00002222 0x22223333 0x33333333 -+ 0x33333333 0x33333333 0x33333333 0x33333333 0x33333333 0x33330000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00292929 0x29282828 0x28282828 0x28282828 0x28282828 0x28282828 0x28000000 0x00000000 -+ 0x00000000 0x00242424 0x24222222 0x22242424 0x24222222 0x22242424 0x24222222 0x22242424 -+ 0x24222222 0x22000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x007f7f7f 0xd1d1dddd 0xe9e9f5f5 0x01010909 0x1515d1d1 0xdddde9e9 0xf5f5fdfd -+ 0x09091515 0xd1d1dddd 0xe9e9f5f5 0xfdfd0909 0x1515d1d1 0xdddde9e9 0xf5f5fdfd 0x09091515 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x0efefc00 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x021e021e 0x02000200 0x02370237 0x02370237 -+ 0x02370237 0x02370237 0x02370237 0x02370237 0x02370237 0x02370237 0x02370237 0x02370237 -+ 0x02370237 0x02370237 0x02370237 0x02370237 0x002200c6 0xc6c4c4c3 0x0000c1c2 0xc1838383 -+ 0x838686c1 0xc1838383 0x838686c2 0xc1c18181 0x82838585 0x8686c1c1 0x81818283 0x85858686 -+ 0xc1c18181 0x82838585 0x8686c1c1 0x81818283 0x85858686 0xc1c18181 0x82838585 0x8686c5c5 -+ 0xc3c100c2 0xc3c2c200 0x81828383 0xc2c2c200 0x81828383 0xc3c1c1c1 0x81828384 0x84c2c2c2 -+ 0xc2008182 0x83838585 0xc2c2c200 0x81828383 0x8585c1c1 0xc1818283 0x84848686 0x82828484 -+ 0x85868787 0x8989c2c2 0xc2008182 0x83838585 0xc2c2c200 0x81828383 0x8585c2c2 0xc2008182 -+ 0x83838585 0xc4c4c2c1 0x00c3c3c3 0xc1008183 0x838686c3 0xc3c3c100 0x81838386 0x86c2c2c2 -+ 0x00818284 0x84868682 0x82828485 0x8688888b 0x8bc3c3c3 0xc1008183 0x838686c3 0xc3c3c100 -+ 0x81838386 0x86c3c3c3 0xc1008183 0x83868600 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00bd0000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00c50000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00495256 0x55555555 0x004a5251 0x51515151 0x004a5355 0x56565656 0x0049504e 0x51515151 -+ 0x00495150 0x54545454 0x00495051 0x51515151 0x00495251 0x50505050 0x00495251 0x51515151 -+ 0x00495251 0x54545454 0x00495150 0x54545454 0x00495352 0x51515151 0x00495353 0x52525252 -+ 0x00495150 0x50505050 0x00495152 0x54545454 0x00495251 0x53535353 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0xd1d1dddd 0xe9e9f5f5 0xfdfd1414 0x1d1d0000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x85840000 0xc3c4c382 0x828281c1 0xc4c5c400 0x0000c1c3 0xc4c4c481 0x8181c1c2 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0xc0bbc0bb 0xc0bbc0bb 0x40c5c0c4 0xc0c3c0c3 0x40c340c5 0x40c4c0c3 0x40c3c0c2 0xc0c5c0c4 -+ 0x40c440c4 0xc0c3c0c5 0xc0c440c4 0x40c4c0c3 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 -+ 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 -+ 0x40c640c6 0x40c640c6 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000>; - }; diff --git a/lede/target/linux/mediatek/patches-6.12/198-dts-mt7988a-enable-wed.patch b/lede/target/linux/mediatek/patches-6.12/198-dts-mt7988a-enable-wed.patch new file mode 100644 index 0000000000..a78aba3cee --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/198-dts-mt7988a-enable-wed.patch @@ -0,0 +1,167 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +@@ -145,6 +145,32 @@ + reg = <0 0x43000000 0 0x50000>; + no-map; + }; ++ ++ wmcpu_emi: wmcpu-reserved@47cc0000 { ++ reg = <0 0x47cc0000 0 0x00100000>; ++ no-map; ++ }; ++ ++ wo_emi0: wo-emi@4f600000 { ++ reg = <0 0x4f600000 0 0x40000>; ++ no-map; ++ }; ++ ++ wo_emi1: wo-emi@4f640000 { ++ reg = <0 0x4f640000 0 0x40000>; ++ no-map; ++ }; ++ ++ wo_emi2: wo-emi@4f680000 { ++ reg = <0 0x4f680000 0 0x40000>; ++ no-map; ++ }; ++ ++ wo_data: wo-data@4f700000 { ++ reg = <0 0x4f700000 0 0x800000>; ++ no-map; ++ shared = <1>; ++ }; + }; + + soc { +@@ -867,6 +893,50 @@ + reg = <0 0x15000000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ }; ++ ++ wed0: wed@15010000 { ++ compatible = "mediatek,mt7988-wed", ++ "syscon"; ++ reg = <0 0x15010000 0 0x2000>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ memory-region = <&wo_emi0>, <&wo_data>; ++ memory-region-names = "wo-emi", "wo-data"; ++ mediatek,wo-ccif = <&wo_ccif0>; ++ mediatek,wo-ilm = <&wo_ilm0>; ++ mediatek,wo-dlm = <&wo_dlm0>; ++ mediatek,wo-cpuboot = <&wo_cpuboot0>; ++ }; ++ ++ wed1: wed@15012000 { ++ compatible = "mediatek,mt7988-wed", ++ "syscon"; ++ reg = <0 0x15012000 0 0x2000>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ memory-region = <&wo_emi1>, <&wo_data>; ++ memory-region-names = "wo-emi", "wo-data"; ++ mediatek,wo-ccif = <&wo_ccif1>; ++ mediatek,wo-ilm = <&wo_ilm1>; ++ mediatek,wo-dlm = <&wo_dlm1>; ++ mediatek,wo-cpuboot = <&wo_cpuboot1>; ++ }; ++ ++ wed2: wed@15014000 { ++ compatible = "mediatek,mt7988-wed", ++ "syscon"; ++ reg = <0 0x15014000 0 0x2000>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ memory-region = <&wo_emi2>, <&wo_data>; ++ memory-region-names = "wo-emi", "wo-data"; ++ mediatek,wo-ccif = <&wo_ccif2>; ++ mediatek,wo-ilm = <&wo_ilm2>; ++ mediatek,wo-dlm = <&wo_dlm2>; ++ mediatek,wo-cpuboot = <&wo_cpuboot2>; + }; + + switch: switch@15020000 { +@@ -1086,6 +1156,7 @@ + <&apmixedsys CLK_APMIXED_SGMPLL>; + mediatek,ethsys = <ðsys>; + mediatek,infracfg = <&topmisc>; ++ mediatek,wed = <&wed0>, <&wed1>, <&wed2>; + #address-cells = <1>; + #size-cells = <0>; + +@@ -1147,6 +1218,72 @@ + }; + }; + ++ wo_ccif0: syscon@151a5000 { ++ compatible = "mediatek,mt7988-wo-ccif", "syscon"; ++ reg = <0 0x151a5000 0 0x1000>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ ++ wo_ccif1: syscon@152a5000 { ++ compatible = "mediatek,mt7988-wo-ccif", "syscon"; ++ reg = <0 0x152a5000 0 0x1000>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ ++ wo_ccif2: syscon@153a5000 { ++ compatible = "mediatek,mt7988-wo-ccif", "syscon"; ++ reg = <0 0x153a5000 0 0x1000>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ ++ wo_ilm0: syscon@151e0000 { ++ compatible = "mediatek,mt7988-wo-ilm", "syscon"; ++ reg = <0 0x151e0000 0 0x8000>; ++ }; ++ ++ wo_ilm1: syscon@152e0000 { ++ compatible = "mediatek,mt7988-wo-ilm", "syscon"; ++ reg = <0 0x152e0000 0 0x8000>; ++ }; ++ ++ wo_ilm2: syscon@153e0000 { ++ compatible = "mediatek,mt7988-wo-ilm", "syscon"; ++ reg = <0 0x153e0000 0 0x8000>; ++ }; ++ ++ wo_dlm0: syscon@151e8000 { ++ compatible = "mediatek,mt7988-wo-dlm", "syscon"; ++ reg = <0 0x151e8000 0 0x2000>; ++ }; ++ ++ wo_dlm1: syscon@152e8000 { ++ compatible = "mediatek,mt7988-wo-dlm", "syscon"; ++ reg = <0 0x152e8000 0 0x2000>; ++ }; ++ ++ wo_dlm2: syscon@153e8000 { ++ compatible = "mediatek,mt7988-wo-dlm", "syscon"; ++ reg = <0 0x153e8000 0 0x2000>; ++ }; ++ ++ wo_cpuboot0: syscon@15194000 { ++ compatible = "mediatek,mt7988-wo-cpuboot", "syscon"; ++ reg = <0 0x15194000 0 0x1000>; ++ }; ++ ++ wo_cpuboot1: syscon@15294000 { ++ compatible = "mediatek,mt7988-wo-cpuboot", "syscon"; ++ reg = <0 0x15294000 0 0x1000>; ++ }; ++ ++ wo_cpuboot2: syscon@15394000 { ++ compatible = "mediatek,mt7988-wo-cpuboot", "syscon"; ++ reg = <0 0x15394000 0 0x1000>; ++ }; ++ + crypto: crypto@15600000 { + compatible = "inside-secure,safexcel-eip197b"; + reg = <0 0x15600000 0 0x180000>; diff --git a/lede/target/linux/mediatek/patches-6.12/199-arm64-dts-mediatek-mt7986-increase-ATF-reserved-memo.patch b/lede/target/linux/mediatek/patches-6.12/199-arm64-dts-mediatek-mt7986-increase-ATF-reserved-memo.patch new file mode 100644 index 0000000000..8cef5ba442 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/199-arm64-dts-mediatek-mt7986-increase-ATF-reserved-memo.patch @@ -0,0 +1,29 @@ +From 236317dd4e55512933dcdaec3d0b4a0824f5e5bd Mon Sep 17 00:00:00 2001 +From: Shiji Yang +Date: Sun, 10 Aug 2025 18:11:01 +0800 +Subject: [PATCH] arm64: dts: mediatek: mt7986: increase ATF reserved memory to + 256 kiB + +The latest Mediatek open-source Trusted Firmware-A project has +reserved 256 KiB for BL2 and BL31. It is better to increase the +reserved memory region in the Linux kernel to protect the data. + +Signed-off-by: Shiji Yang +--- + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -76,9 +76,9 @@ + record-size = <0x1000>; + }; + +- /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ ++ /* 256 KiB reserved for ARM Trusted Firmware (BL31 + BL32) */ + secmon_reserved: secmon@43000000 { +- reg = <0 0x43000000 0 0x30000>; ++ reg = <0 0x43000000 0 0x40000>; + no-map; + }; + diff --git a/lede/target/linux/mediatek/patches-6.12/200-phy-phy-mtk-tphy-Add-hifsys-support.patch b/lede/target/linux/mediatek/patches-6.12/200-phy-phy-mtk-tphy-Add-hifsys-support.patch index b3db243a97..5c482f6358 100644 --- a/lede/target/linux/mediatek/patches-6.12/200-phy-phy-mtk-tphy-Add-hifsys-support.patch +++ b/lede/target/linux/mediatek/patches-6.12/200-phy-phy-mtk-tphy-Add-hifsys-support.patch @@ -51,7 +51,7 @@ Subject: [PATCH] phy: phy-mtk-tphy: Add hifsys-support &tphy->src_coef); } -+ if (of_find_property(np, "mediatek,phy-switch", NULL)) { ++ if (of_property_present(np, "mediatek,phy-switch")) { + tphy->hif = syscon_regmap_lookup_by_phandle(np, + "mediatek,phy-switch"); + if (IS_ERR(tphy->hif)) { diff --git a/lede/target/linux/mediatek/patches-6.12/320-hwrng-add-driver-for-MediaTek-TRNG-SMC.patch b/lede/target/linux/mediatek/patches-6.12/320-hwrng-add-driver-for-MediaTek-TRNG-SMC.patch deleted file mode 100644 index e738883800..0000000000 --- a/lede/target/linux/mediatek/patches-6.12/320-hwrng-add-driver-for-MediaTek-TRNG-SMC.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 9837930d6738e9fdc323ad887ace7c236a61d70c Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 25 Jan 2023 00:27:49 +0000 -Subject: [PATCH] hwrng: add driver for MediaTek TRNG SMC - -Add driver providing kernel-side support for the Random Number -Generator hardware found on Mediatek SoCs which have a driver in ARM -TrustedFirmware-A allowing Linux to read random numbers using a -non-standard vendor-defined Secure Monitor Call. - -Signed-off-by: Daniel Golle ---- - drivers/char/hw_random/Kconfig | 16 +++++++ - drivers/char/hw_random/Makefile | 1 + - drivers/char/hw_random/mtk-rng-v2.c | 74 +++++++++++++++++++++++++++++ - 3 files changed, 91 insertions(+) - create mode 100644 drivers/char/hw_random/mtk-rng-v2.c - ---- a/drivers/char/hw_random/Kconfig -+++ b/drivers/char/hw_random/Kconfig -@@ -451,6 +451,23 @@ config HW_RANDOM_MTK - - If unsure, say Y. - -+config HW_RANDOM_MTK_V2 -+ tristate "Mediatek Random Number Generator support (v2/SMC)" -+ depends on HAVE_ARM_SMCCC -+ depends on HW_RANDOM -+ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST -+ default y -+ help -+ This driver provides kernel-side support for the Random Number -+ Generator hardware found on Mediatek SoCs which have a driver -+ in ARM TrustedFirmware-A allowing Linux to read using a non- -+ standard vendor-defined Secure Monitor Call. -+ -+ To compile this driver as a module, choose M here. the -+ module will be called mtk-rng-v2. -+ -+ If unsure, say Y. -+ - config HW_RANDOM_S390 - tristate "S390 True Random Number Generator support" - depends on S390 ---- a/drivers/char/hw_random/Makefile -+++ b/drivers/char/hw_random/Makefile -@@ -39,6 +39,7 @@ obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-r - obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o - obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o - obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o -+obj-$(CONFIG_HW_RANDOM_MTK_V2) += mtk-rng-v2.o - obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o - obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o - obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o ---- /dev/null -+++ b/drivers/char/hw_random/mtk-rng-v2.c -@@ -0,0 +1,76 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * Driver for Mediatek Hardware Random Number Generator (v2/SMCC) -+ * -+ * Copyright (C) 2023 Daniel Golle -+ * based on patch from Mingming Su -+ */ -+#define MTK_RNG_DEV KBUILD_MODNAME -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MTK_SIP_KERNEL_GET_RND MTK_SIP_SMC_CMD(0x550) -+ -+static int mtk_rng_v2_read(struct hwrng *rng, void *buf, size_t max, bool wait) -+{ -+ struct arm_smccc_res res; -+ int retval = 0; -+ -+ while (max >= sizeof(u32)) { -+ arm_smccc_smc(MTK_SIP_KERNEL_GET_RND, 0, 0, 0, 0, 0, 0, 0, -+ &res); -+ if (res.a0) -+ break; -+ -+ *(u32 *)buf = res.a1; -+ retval += sizeof(u32); -+ buf += sizeof(u32); -+ max -= sizeof(u32); -+ } -+ -+ return retval || !wait ? retval : -EIO; -+} -+ -+static int mtk_rng_v2_probe(struct platform_device *pdev) -+{ -+ struct hwrng *trng; -+ -+ trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL); -+ if (!trng) -+ return -ENOMEM; -+ -+ trng->name = pdev->name; -+ trng->read = mtk_rng_v2_read; -+ trng->quality = 900; -+ -+ return devm_hwrng_register(&pdev->dev, trng); -+} -+ -+static const struct of_device_id mtk_rng_v2_match[] = { -+ { .compatible = "mediatek,mt7981-rng" }, -+ { .compatible = "mediatek,mt7987-rng" }, -+ { .compatible = "mediatek,mt7988-rng" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, mtk_rng_v2_match); -+ -+static struct platform_driver mtk_rng_v2_driver = { -+ .probe = mtk_rng_v2_probe, -+ .driver = { -+ .name = KBUILD_MODNAME, -+ .of_match_table = mtk_rng_v2_match, -+ }, -+}; -+module_platform_driver(mtk_rng_v2_driver); -+ -+MODULE_DESCRIPTION("Mediatek Random Number Generator Driver (v2/SMC)"); -+MODULE_AUTHOR("Daniel Golle "); -+MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/mediatek/patches-6.12/320-hwrng-mtk-add-support-for-hw-access-via-SMCC.patch b/lede/target/linux/mediatek/patches-6.12/320-hwrng-mtk-add-support-for-hw-access-via-SMCC.patch new file mode 100644 index 0000000000..9bd9d0ab31 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/320-hwrng-mtk-add-support-for-hw-access-via-SMCC.patch @@ -0,0 +1,212 @@ +From d211e2184d820207d14f5e8f84938c639875bf0d Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 3 Mar 2026 23:45:46 +0000 +Subject: [PATCH] hwrng: mtk - add support for hw access via SMCC + +Newer versions of ARM TrustedFirmware-A on MediaTek's ARMv8 SoCs no longer +allow accessing the TRNG from outside of the trusted firmware. +Instead, a vendor-defined custom Secure Monitor Call can be used to +acquire random bytes. +Add support for newer SoCs (MT7981, MT7987, MT7988). On MT7986 the best bet +is to test if firmware blocks direct access to the hwrng and if so, expect +the SMCC interface to be usable. + +Signed-off-by: Daniel Golle +--- + drivers/char/hw_random/mtk-rng.c | 128 ++++++++++++++++++++++++++----- + 1 file changed, 107 insertions(+), 21 deletions(-) + +--- a/drivers/char/hw_random/mtk-rng.c ++++ b/drivers/char/hw_random/mtk-rng.c +@@ -3,6 +3,7 @@ + * Driver for Mediatek Hardware Random Number Generator + * + * Copyright (C) 2017 Sean Wang ++ * Copyright (C) 2026 Daniel Golle + */ + #define MTK_RNG_DEV KBUILD_MODNAME + +@@ -17,6 +18,8 @@ + #include + #include + #include ++#include ++#include + + /* Runtime PM autosuspend timeout: */ + #define RNG_AUTOSUSPEND_TIMEOUT 100 +@@ -30,6 +33,11 @@ + + #define RNG_DATA 0x08 + ++/* Driver feature flags */ ++#define MTK_RNG_SMC BIT(0) ++ ++#define MTK_SIP_KERNEL_GET_RND MTK_SIP_SMC_CMD(0x550) ++ + #define to_mtk_rng(p) container_of(p, struct mtk_rng, rng) + + struct mtk_rng { +@@ -37,6 +45,7 @@ struct mtk_rng { + struct clk *clk; + struct hwrng rng; + struct device *dev; ++ unsigned long flags; + }; + + static int mtk_rng_init(struct hwrng *rng) +@@ -104,6 +113,56 @@ static int mtk_rng_read(struct hwrng *rn + return retval || !wait ? retval : -EIO; + } + ++static int mtk_rng_read_smc(struct hwrng *rng, void *buf, size_t max, ++ bool wait) ++{ ++ struct arm_smccc_res res; ++ int retval = 0; ++ ++ while (max >= sizeof(u32)) { ++ arm_smccc_smc(MTK_SIP_KERNEL_GET_RND, 0, 0, 0, 0, 0, 0, 0, ++ &res); ++ if (res.a0) ++ break; ++ ++ *(u32 *)buf = res.a1; ++ retval += sizeof(u32); ++ buf += sizeof(u32); ++ max -= sizeof(u32); ++ } ++ ++ return retval || !wait ? retval : -EIO; ++} ++ ++static bool mtk_rng_hw_accessible(struct mtk_rng *priv) ++{ ++ u32 val; ++ int err; ++ ++ err = clk_prepare_enable(priv->clk); ++ if (err) ++ return false; ++ ++ val = readl(priv->base + RNG_CTRL); ++ val |= RNG_EN; ++ writel(val, priv->base + RNG_CTRL); ++ ++ val = readl(priv->base + RNG_CTRL); ++ ++ if (val & RNG_EN) { ++ /* HW is accessible, clean up: disable RNG and clock */ ++ writel(val & ~RNG_EN, priv->base + RNG_CTRL); ++ clk_disable_unprepare(priv->clk); ++ return true; ++ } ++ ++ /* ++ * If TF-A blocks direct access, the register reads back as 0. ++ * Leave the clock enabled as TF-A's SMC handler needs it. ++ */ ++ return false; ++} ++ + static int mtk_rng_probe(struct platform_device *pdev) + { + int ret; +@@ -115,23 +174,42 @@ static int mtk_rng_probe(struct platform + + priv->dev = &pdev->dev; + priv->rng.name = pdev->name; +-#ifndef CONFIG_PM +- priv->rng.init = mtk_rng_init; +- priv->rng.cleanup = mtk_rng_cleanup; +-#endif +- priv->rng.read = mtk_rng_read; + priv->rng.quality = 900; ++ priv->flags = (unsigned long)device_get_match_data(&pdev->dev); + +- priv->clk = devm_clk_get(&pdev->dev, "rng"); +- if (IS_ERR(priv->clk)) { +- ret = PTR_ERR(priv->clk); +- dev_err(&pdev->dev, "no clock for device: %d\n", ret); +- return ret; ++ if (!(priv->flags & MTK_RNG_SMC)) { ++ priv->clk = devm_clk_get(&pdev->dev, "rng"); ++ if (IS_ERR(priv->clk)) { ++ ret = PTR_ERR(priv->clk); ++ dev_err(&pdev->dev, "no clock for device: %d\n", ret); ++ return ret; ++ } ++ ++ priv->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ if (IS_ENABLED(CONFIG_HAVE_ARM_SMCCC) && ++ of_device_is_compatible(pdev->dev.of_node, ++ "mediatek,mt7986-rng") && ++ !mtk_rng_hw_accessible(priv)) { ++ priv->flags |= MTK_RNG_SMC; ++ dev_info(&pdev->dev, ++ "HW RNG not MMIO accessible, using SMC\n"); ++ } + } + +- priv->base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(priv->base)) +- return PTR_ERR(priv->base); ++ if (priv->flags & MTK_RNG_SMC) { ++ if (!IS_ENABLED(CONFIG_HAVE_ARM_SMCCC)) ++ return -ENODEV; ++ priv->rng.read = mtk_rng_read_smc; ++ } else { ++#ifndef CONFIG_PM ++ priv->rng.init = mtk_rng_init; ++ priv->rng.cleanup = mtk_rng_cleanup; ++#endif ++ priv->rng.read = mtk_rng_read; ++ } + + ret = devm_hwrng_register(&pdev->dev, &priv->rng); + if (ret) { +@@ -140,12 +218,15 @@ static int mtk_rng_probe(struct platform + return ret; + } + +- dev_set_drvdata(&pdev->dev, priv); +- pm_runtime_set_autosuspend_delay(&pdev->dev, RNG_AUTOSUSPEND_TIMEOUT); +- pm_runtime_use_autosuspend(&pdev->dev); +- ret = devm_pm_runtime_enable(&pdev->dev); +- if (ret) +- return ret; ++ if (!(priv->flags & MTK_RNG_SMC)) { ++ dev_set_drvdata(&pdev->dev, priv); ++ pm_runtime_set_autosuspend_delay(&pdev->dev, ++ RNG_AUTOSUSPEND_TIMEOUT); ++ pm_runtime_use_autosuspend(&pdev->dev); ++ ret = devm_pm_runtime_enable(&pdev->dev); ++ if (ret) ++ return ret; ++ } + + dev_info(&pdev->dev, "registered RNG driver\n"); + +@@ -182,8 +263,12 @@ static const struct dev_pm_ops mtk_rng_p + #endif /* CONFIG_PM */ + + static const struct of_device_id mtk_rng_match[] = { +- { .compatible = "mediatek,mt7986-rng" }, + { .compatible = "mediatek,mt7623-rng" }, ++ { .compatible = "mediatek,mt7622-rng" }, ++ { .compatible = "mediatek,mt7981-rng", .data = (void *)MTK_RNG_SMC }, ++ { .compatible = "mediatek,mt7986-rng" }, ++ { .compatible = "mediatek,mt7987-rng", .data = (void *)MTK_RNG_SMC }, ++ { .compatible = "mediatek,mt7988-rng", .data = (void *)MTK_RNG_SMC }, + {}, + }; + MODULE_DEVICE_TABLE(of, mtk_rng_match); +@@ -201,4 +286,5 @@ module_platform_driver(mtk_rng_driver); + + MODULE_DESCRIPTION("Mediatek Random Number Generator Driver"); + MODULE_AUTHOR("Sean Wang "); ++MODULE_AUTHOR("Daniel Golle "); + MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/mediatek/patches-6.12/330-snand-mtk-bmt-support.patch b/lede/target/linux/mediatek/patches-6.12/330-snand-mtk-bmt-support.patch index 0a8f80c1e0..a077544061 100644 --- a/lede/target/linux/mediatek/patches-6.12/330-snand-mtk-bmt-support.patch +++ b/lede/target/linux/mediatek/patches-6.12/330-snand-mtk-bmt-support.patch @@ -8,7 +8,7 @@ static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) { -@@ -1529,6 +1530,7 @@ static int spinand_probe(struct spi_mem +@@ -1596,6 +1597,7 @@ static int spinand_probe(struct spi_mem if (ret) return ret; @@ -16,7 +16,7 @@ ret = mtd_device_register(mtd, NULL, 0); if (ret) goto err_spinand_cleanup; -@@ -1536,6 +1538,7 @@ static int spinand_probe(struct spi_mem +@@ -1603,6 +1605,7 @@ static int spinand_probe(struct spi_mem return 0; err_spinand_cleanup: @@ -24,7 +24,7 @@ spinand_cleanup(spinand); return ret; -@@ -1554,6 +1557,7 @@ static int spinand_remove(struct spi_mem +@@ -1621,6 +1624,7 @@ static int spinand_remove(struct spi_mem if (ret) return ret; diff --git a/lede/target/linux/mediatek/patches-6.12/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch b/lede/target/linux/mediatek/patches-6.12/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch index cb3e425c46..a5cb1176d1 100644 --- a/lede/target/linux/mediatek/patches-6.12/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch +++ b/lede/target/linux/mediatek/patches-6.12/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch @@ -18,16 +18,16 @@ Signed-off-by: Davide Fioravanti +++ b/drivers/mtd/nand/spi/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 --spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o foresee.o gigadevice.o -+spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o fidelix.o foresee.o gigadevice.o - spinand-objs += macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o +-spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o fmsh.o foresee.o gigadevice.o ++spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o fidelix.o fmsh.o foresee.o gigadevice.o + spinand-objs += macronix.o micron.o paragon.o skyhigh.o toshiba.o winbond.o xtx.o obj-$(CONFIG_MTD_SPI_NAND) += spinand.o --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c -@@ -1117,6 +1117,7 @@ static const struct spinand_manufacturer - &ato_spinand_manufacturer, +@@ -1181,6 +1181,7 @@ static const struct spinand_manufacturer &esmt_c8_spinand_manufacturer, &etron_spinand_manufacturer, + &fmsh_spinand_manufacturer, + &fidelix_spinand_manufacturer, &foresee_spinand_manufacturer, &gigadevice_spinand_manufacturer, @@ -113,10 +113,10 @@ Signed-off-by: Davide Fioravanti +}; --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h -@@ -264,6 +264,7 @@ extern const struct spinand_manufacturer - extern const struct spinand_manufacturer ato_spinand_manufacturer; +@@ -266,6 +266,7 @@ extern const struct spinand_manufacturer extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; extern const struct spinand_manufacturer etron_spinand_manufacturer; + extern const struct spinand_manufacturer fmsh_spinand_manufacturer; +extern const struct spinand_manufacturer fidelix_spinand_manufacturer; extern const struct spinand_manufacturer foresee_spinand_manufacturer; extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; diff --git a/lede/target/linux/mediatek/patches-6.12/360-pinctrl-mediatek-add-mt7987-pinctrl-support.patch b/lede/target/linux/mediatek/patches-6.12/360-pinctrl-mediatek-add-mt7987-pinctrl-support.patch index c22be8cd1d..061a14c5f6 100644 --- a/lede/target/linux/mediatek/patches-6.12/360-pinctrl-mediatek-add-mt7987-pinctrl-support.patch +++ b/lede/target/linux/mediatek/patches-6.12/360-pinctrl-mediatek-add-mt7987-pinctrl-support.patch @@ -750,7 +750,7 @@ Signed-off-by: Daniel Golle + .nfuncs = ARRAY_SIZE(mt7987_functions), + .eint_hw = &mt7987_eint_hw, + .gpio_m = 0, -+ .ies_present = false, ++ .ies_present = true, + .base_names = mt7987_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt7987_pinctrl_register_base_names), + .bias_disable_set = mtk_pinconf_bias_disable_set, diff --git a/lede/target/linux/mediatek/patches-6.12/411-mtd-spinand-fix-support-for-FORESEE.patch b/lede/target/linux/mediatek/patches-6.12/411-mtd-spinand-fix-support-for-FORESEE.patch new file mode 100644 index 0000000000..48a6515b56 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/411-mtd-spinand-fix-support-for-FORESEE.patch @@ -0,0 +1,19 @@ +Force update_cache_variants to use reset for Foresee NAND with bad blocks + +Tested on Xiaomi AX3000T + F35SQA001G with bad blocks and without bad blocks + +Signed-off-by: Dim Fish + +--- a/drivers/mtd/nand/spi/foresee.c ++++ b/drivers/mtd/nand/spi/foresee.c +@@ -22,8 +22,8 @@ static SPINAND_OP_VARIANTS(write_cache_v + SPINAND_PROG_LOAD(true, 0, NULL, 0)); + + static SPINAND_OP_VARIANTS(update_cache_variants, +- SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), +- SPINAND_PROG_LOAD(false, 0, NULL, 0)); ++ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), ++ SPINAND_PROG_LOAD(true, 0, NULL, 0)); + + static int f35sqa002g_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) diff --git a/lede/target/linux/mediatek/patches-6.12/433-drivers-spi-mem-Add-spi-calibration-hook.patch b/lede/target/linux/mediatek/patches-6.12/433-drivers-spi-mem-Add-spi-calibration-hook.patch index e8377f5c4c..731d911296 100644 --- a/lede/target/linux/mediatek/patches-6.12/433-drivers-spi-mem-Add-spi-calibration-hook.patch +++ b/lede/target/linux/mediatek/patches-6.12/433-drivers-spi-mem-Add-spi-calibration-hook.patch @@ -11,7 +11,7 @@ Signed-off-by: SkyLake.Huang --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c -@@ -466,6 +466,14 @@ int spi_mem_exec_op(struct spi_mem *mem, +@@ -486,6 +486,14 @@ int spi_mem_exec_op(struct spi_mem *mem, } EXPORT_SYMBOL_GPL(spi_mem_exec_op); @@ -28,7 +28,7 @@ Signed-off-by: SkyLake.Huang * upper layer if necessary --- a/include/linux/spi/spi-mem.h +++ b/include/linux/spi/spi-mem.h -@@ -372,6 +372,10 @@ bool spi_mem_supports_op(struct spi_mem +@@ -390,6 +390,10 @@ bool spi_mem_supports_op(struct spi_mem int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op); diff --git a/lede/target/linux/mediatek/patches-6.12/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch b/lede/target/linux/mediatek/patches-6.12/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch index 6f58346bfa..76764963ce 100644 --- a/lede/target/linux/mediatek/patches-6.12/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch +++ b/lede/target/linux/mediatek/patches-6.12/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch @@ -11,7 +11,7 @@ Signed-off-by: SkyLake.Huang --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c -@@ -1155,6 +1155,56 @@ static int spinand_manufacturer_match(st +@@ -1220,6 +1220,56 @@ static int spinand_manufacturer_match(st return -EOPNOTSUPP; } @@ -68,7 +68,7 @@ Signed-off-by: SkyLake.Huang static int spinand_id_detect(struct spinand_device *spinand) { u8 *id = spinand->id.data; -@@ -1406,6 +1456,10 @@ static int spinand_init(struct spinand_d +@@ -1473,6 +1523,10 @@ static int spinand_init(struct spinand_d if (!spinand->scratchbuf) return -ENOMEM; diff --git a/lede/target/linux/mediatek/patches-6.12/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch b/lede/target/linux/mediatek/patches-6.12/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch index 39a4d3759d..8b505e20bc 100644 --- a/lede/target/linux/mediatek/patches-6.12/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch +++ b/lede/target/linux/mediatek/patches-6.12/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch @@ -12,7 +12,7 @@ Signed-off-by: SkyLake.Huang --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c -@@ -1196,7 +1196,10 @@ static int spinand_cal_read(void *priv, +@@ -1261,7 +1261,10 @@ static int spinand_cal_read(void *priv, if (ret) return ret; diff --git a/lede/target/linux/mediatek/patches-6.12/500-gsw-rtl8367s-mt7622-support.patch b/lede/target/linux/mediatek/patches-6.12/500-gsw-rtl8367s-mt7622-support.patch index 8f911f6fd8..60643e2657 100644 --- a/lede/target/linux/mediatek/patches-6.12/500-gsw-rtl8367s-mt7622-support.patch +++ b/lede/target/linux/mediatek/patches-6.12/500-gsw-rtl8367s-mt7622-support.patch @@ -15,7 +15,7 @@ select CRC16 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -114,6 +114,7 @@ obj-$(CONFIG_REALTEK_PHY) += realtek/ +@@ -113,6 +113,7 @@ obj-$(CONFIG_REALTEK_PHY) += realtek/ obj-y += rtl8261n/ obj-$(CONFIG_RENESAS_PHY) += uPD60620.o obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o diff --git a/lede/target/linux/mediatek/patches-6.12/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch b/lede/target/linux/mediatek/patches-6.12/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch deleted file mode 100644 index 1b18679fb3..0000000000 --- a/lede/target/linux/mediatek/patches-6.12/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch +++ /dev/null @@ -1,34 +0,0 @@ -From: qizhong cheng -Date: Mon, 27 Dec 2021 21:31:10 +0800 -Subject: [PATCH] PCI: mediatek: Assert PERST# for 100ms for power and clock to - stabilize -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Described in PCIe CEM specification sections 2.2 (PERST# Signal) and -2.2.1 (Initial Power-Up (G3 to S0)). The deassertion of PERST# should -be delayed 100ms (TPVPERL) for the power and clock to become stable. - -Link: https://lore.kernel.org/r/20211227133110.14500-1-qizhong.cheng@mediatek.com -Signed-off-by: qizhong cheng -Signed-off-by: Lorenzo Pieralisi -Acked-by: Pali Rohár ---- - ---- a/drivers/pci/controller/pcie-mediatek.c -+++ b/drivers/pci/controller/pcie-mediatek.c -@@ -700,6 +700,13 @@ static int mtk_pcie_startup_port_v2(stru - */ - msleep(100); - -+ /* -+ * Described in PCIe CEM specification sections 2.2 (PERST# Signal) and -+ * 2.2.1 (Initial Power-Up (G3 to S0)). The deassertion of PERST# should -+ * be delayed 100ms (TPVPERL) for the power and clock to become stable. -+ */ -+ msleep(100); -+ - /* De-assert PHY, PE, PIPE, MAC and configuration reset */ - val = readl(port->base + PCIE_RST_CTRL); - val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB | diff --git a/lede/target/linux/mediatek/patches-6.12/700-net-phy-mediatek-Add-2.5Gphy-firmware-dt-bindings-an.patch b/lede/target/linux/mediatek/patches-6.12/700-net-phy-mediatek-Add-2.5Gphy-firmware-dt-bindings-an.patch index 8c0ded2b37..9996501427 100644 --- a/lede/target/linux/mediatek/patches-6.12/700-net-phy-mediatek-Add-2.5Gphy-firmware-dt-bindings-an.patch +++ b/lede/target/linux/mediatek/patches-6.12/700-net-phy-mediatek-Add-2.5Gphy-firmware-dt-bindings-an.patch @@ -57,7 +57,7 @@ Signed-off-by: Sky Huang + }; --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -14426,9 +14426,10 @@ F: include/linux/pcs/pcs-mtk-usxgmii.h +@@ -14439,9 +14439,10 @@ F: include/linux/pcs/pcs-mtk-usxgmii.h MEDIATEK ETHERNET PHY DRIVERS M: Daniel Golle M: Qingfang Deng diff --git a/lede/target/linux/mediatek/patches-6.12/701-net-phy-mediatek-add-driver-for-built-in-2.5G-ethern.patch b/lede/target/linux/mediatek/patches-6.12/701-net-phy-mediatek-add-driver-for-built-in-2.5G-ethern.patch index 0bb8ba00a3..ff7aa40f53 100644 --- a/lede/target/linux/mediatek/patches-6.12/701-net-phy-mediatek-add-driver-for-built-in-2.5G-ethern.patch +++ b/lede/target/linux/mediatek/patches-6.12/701-net-phy-mediatek-add-driver-for-built-in-2.5G-ethern.patch @@ -20,7 +20,7 @@ Signed-off-by: Sky Huang --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -14430,6 +14430,7 @@ M: Sky Huang +#include +#include +#include -+#include ++#include +#include +#include +#include @@ -386,7 +386,7 @@ Signed-off-by: Sky Huang + +module_phy_driver(mtk_2p5gephy_driver); + -+static struct mdio_device_id __maybe_unused mtk_2p5ge_phy_tbl[] = { ++static const struct mdio_device_id __maybe_unused mtk_2p5ge_phy_tbl[] = { + { PHY_ID_MATCH_VENDOR(0x00339c00) }, + { } +}; diff --git a/lede/target/linux/mediatek/patches-6.12/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch b/lede/target/linux/mediatek/patches-6.12/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch index d85e505d45..5b8707a89a 100644 --- a/lede/target/linux/mediatek/patches-6.12/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch +++ b/lede/target/linux/mediatek/patches-6.12/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch @@ -61,7 +61,7 @@ Signed-off-by: Felix Fietkau struct mtk_pcie_port; /** -@@ -1052,6 +1058,27 @@ static int mtk_pcie_setup(struct mtk_pci +@@ -1045,6 +1051,27 @@ static int mtk_pcie_setup(struct mtk_pci struct mtk_pcie_port *port, *tmp; int err, slot; diff --git a/lede/target/linux/mediatek/patches-6.12/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch b/lede/target/linux/mediatek/patches-6.12/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch deleted file mode 100644 index d1ac132ac5..0000000000 --- a/lede/target/linux/mediatek/patches-6.12/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch +++ /dev/null @@ -1,63 +0,0 @@ -From a969b663c866129ed9eb217785a6574fbe826f1d Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 6 Apr 2023 23:36:50 +0100 -Subject: [PATCH] net: phy: mxl-gpy: don't use SGMII AN if using phylink - -MAC drivers using phylink expect SGMII in-band-status to be switched off -when attached to a PHY. Make sure this is the case also for mxl-gpy which -keeps SGMII in-band-status in case of SGMII interface mode is used. - -Signed-off-by: Daniel Golle ---- - drivers/net/phy/mxl-gpy.c | 19 ++++++++++++++++--- - 1 file changed, 16 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/mxl-gpy.c -+++ b/drivers/net/phy/mxl-gpy.c -@@ -380,8 +380,11 @@ static bool gpy_2500basex_chk(struct phy - - phydev->speed = SPEED_2500; - phydev->interface = PHY_INTERFACE_MODE_2500BASEX; -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, -- VSPEC1_SGMII_CTRL_ANEN, 0); -+ -+ if (!phydev->phylink) -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, -+ VSPEC1_SGMII_CTRL_ANEN, 0); -+ - return true; - } - -@@ -432,6 +435,14 @@ static int gpy_config_aneg(struct phy_de - u32 adv; - int ret; - -+ /* Disable SGMII auto-negotiation if using phylink */ -+ if (phydev->phylink) { -+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, -+ VSPEC1_SGMII_CTRL_ANEN, 0); -+ if (ret < 0) -+ return ret; -+ } -+ - if (phydev->autoneg == AUTONEG_DISABLE) { - /* Configure half duplex with genphy_setup_forced, - * because genphy_c45_pma_setup_forced does not support. -@@ -554,6 +565,8 @@ static int gpy_update_interface(struct p - switch (phydev->speed) { - case SPEED_2500: - phydev->interface = PHY_INTERFACE_MODE_2500BASEX; -+ if (phydev->phylink) -+ break; - ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, - VSPEC1_SGMII_CTRL_ANEN, 0); - if (ret < 0) { -@@ -567,7 +580,7 @@ static int gpy_update_interface(struct p - case SPEED_100: - case SPEED_10: - phydev->interface = PHY_INTERFACE_MODE_SGMII; -- if (gpy_sgmii_aneg_en(phydev)) -+ if (phydev->phylink || gpy_sgmii_aneg_en(phydev)) - break; - /* Enable and restart SGMII ANEG for 10/100/1000Mbps link speed - * if ANEG is disabled (in 2500-BaseX mode). diff --git a/lede/target/linux/mediatek/patches-6.12/737-net-dsa-add-Airoha-AN8855.patch b/lede/target/linux/mediatek/patches-6.12/737-net-dsa-add-Airoha-AN8855.patch index d31215ec27..188540591e 100644 --- a/lede/target/linux/mediatek/patches-6.12/737-net-dsa-add-Airoha-AN8855.patch +++ b/lede/target/linux/mediatek/patches-6.12/737-net-dsa-add-Airoha-AN8855.patch @@ -216,10 +216,10 @@ Christian Marangi (9): config NET_DSA_LANTIQ_GSWIP --- a/drivers/net/dsa/Makefile +++ b/drivers/net/dsa/Makefile -@@ -5,6 +5,7 @@ obj-$(CONFIG_NET_DSA_LOOP) += dsa_loop.o - ifdef CONFIG_NET_DSA_LOOP +@@ -6,6 +6,7 @@ ifdef CONFIG_NET_DSA_LOOP obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdinfo.o endif + obj-$(CONFIG_NET_DSA_KS8995) += ks8995.o +obj-$(CONFIG_NET_DSA_AN8855) += an8855.o obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o diff --git a/lede/target/linux/mediatek/patches-6.12/739-net-add-negotiation-of-in-band-capabilities.patch b/lede/target/linux/mediatek/patches-6.12/739-net-add-negotiation-of-in-band-capabilities.patch deleted file mode 100644 index 12638978b3..0000000000 --- a/lede/target/linux/mediatek/patches-6.12/739-net-add-negotiation-of-in-band-capabilities.patch +++ /dev/null @@ -1,1242 +0,0 @@ -From: "Russell King (Oracle)" -To: Andrew Lunn , Heiner Kallweit -Cc: Alexander Couzens , - Andrew Lunn , - AngeloGioacchino Del Regno - , - Broadcom internal kernel review list - , - Daniel Golle , - "David S. Miller" , - Eric Dumazet , - Florian Fainelli , - Ioana Ciornei , - Jakub Kicinski , - Jose Abreu , - linux-arm-kernel@lists.infradead.org, - linux-mediatek@lists.infradead.org, - Marcin Wojtas , - Matthias Brugger , - netdev@vger.kernel.org, Paolo Abeni -Subject: [PATCH RFC net-next 00/16] net: add negotiation of in-band capabilities -Date: Tue, 26 Nov 2024 09:23:48 +0000 [thread overview] -Message-ID: (raw) - -Hi, - -Yes, this is one patch over the limit of 15 for netdev - but I think it's -important to include the last patch to head off review comments like "why -don't you remove phylink_phy_no_inband() in this series?" - -Phylink's handling of in-band has been deficient for a long time, and -people keep hitting problems with it. Notably, situations with the way- -to-late standardized 2500Base-X and whether that should or should not -have in-band enabled. We have also been carrying a hack in the form of -phylink_phy_no_inband() for a PHY that has been used on a SFP module, -but has no in-band capabilities, not even for SGMII. - -When phylink is trying to operate in in-band mode, this series will look -at the capabilities of the MAC-side PCS and PHY, and work out whether -in-band can or should be used, programming the PHY as appropriate. This -includes in-band bypass mode at the PHY. - -We don't... yet... support that on the MAC side PCS, because that -requires yet more complexity. - -Patch 1 passes struct phylink and struct phylink_pcs into -phylink_pcs_neg_mode() so we can look at more state in this function in -a future patch. - -Patch 2 splits "cur_link_an_mode" (the MLO_AN_* mode) into two separate -purposes - a requested and an active mode. The active mode is the one -we will be using for the MAC, which becomes dependent on the result of -in-band negotiation. - -Patch 3 adds debug to phylink_major_config() so we can see what is going -on with the requested and active AN modes. - -Patch 4 adds to phylib a method to get the in-band capabilities of the -PHY from phylib. Patches 5 and 6 add implementations for BCM84881 and -some Marvell PHYs found on SFPs. - -Patch 7 adds to phylib a method to configure the PHY in-band signalling, -and patch 8 implements it for those Marvell PHYs that support the method -in patch 4. - -Patch 9 does the same as patch 4 but for the MAC-side PCS, with patches -10 through 14 adding support to several PCS. - -Patch 15 adds the code to phylink_pcs_neg_mode() which looks at the -capabilities, and works out whether to use in-band or out-band mode for -driving the link between the MAC PCS and PHY. - -Patch 16 removes the phylink_phy_no_inband() hack now that we are -publishing the in-band capabilities from the BCM84881 PHY driver. - - drivers/net/ethernet/marvell/mvneta.c | 27 +- - drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 25 +- - drivers/net/pcs/pcs-lynx.c | 22 ++ - drivers/net/pcs/pcs-mtk-lynxi.c | 16 ++ - drivers/net/pcs/pcs-xpcs.c | 28 ++ - drivers/net/phy/bcm84881.c | 10 + - drivers/net/phy/marvell.c | 48 ++++ - drivers/net/phy/phy.c | 52 ++++ - drivers/net/phy/phylink.c | 352 +++++++++++++++++++----- - include/linux/phy.h | 34 +++ - include/linux/phylink.h | 17 ++ - 11 files changed, 539 insertions(+), 92 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -56,7 +56,8 @@ struct phylink { - struct phy_device *phydev; - phy_interface_t link_interface; /* PHY_INTERFACE_xxx */ - u8 cfg_link_an_mode; /* MLO_AN_xxx */ -- u8 cur_link_an_mode; -+ u8 req_link_an_mode; /* Requested MLO_AN_xxx mode */ -+ u8 act_link_an_mode; /* Active MLO_AN_xxx mode */ - u8 link_port; /* The current non-phy ethtool port */ - __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); - -@@ -74,6 +75,7 @@ struct phylink { - - struct mutex state_mutex; - struct phylink_link_state phy_state; -+ unsigned int phy_ib_mode; - struct work_struct resolve; - unsigned int pcs_neg_mode; - unsigned int pcs_state; -@@ -175,6 +177,24 @@ static const char *phylink_an_mode_str(u - return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown"; - } - -+static const char *phylink_pcs_mode_str(unsigned int mode) -+{ -+ if (!mode) -+ return "none"; -+ -+ if (mode & PHYLINK_PCS_NEG_OUTBAND) -+ return "outband"; -+ -+ if (mode & PHYLINK_PCS_NEG_INBAND) { -+ if (mode & PHYLINK_PCS_NEG_ENABLED) -+ return "inband,an-enabled"; -+ else -+ return "inband,an-disabled"; -+ } -+ -+ return "unknown"; -+} -+ - static unsigned int phylink_interface_signal_rate(phy_interface_t interface) - { - switch (interface) { -@@ -988,6 +1008,15 @@ static void phylink_resolve_an_pause(str - } - } - -+static unsigned int phylink_pcs_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface) -+{ -+ if (pcs && pcs->ops->pcs_inband_caps) -+ return pcs->ops->pcs_inband_caps(pcs, interface); -+ -+ return 0; -+} -+ - static void phylink_pcs_pre_config(struct phylink_pcs *pcs, - phy_interface_t interface) - { -@@ -1041,6 +1070,24 @@ static void phylink_pcs_link_up(struct p - pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex); - } - -+/* Query inband for a specific interface mode, asking the MAC for the -+ * PCS which will be used to handle the interface mode. -+ */ -+static unsigned int phylink_inband_caps(struct phylink *pl, -+ phy_interface_t interface) -+{ -+ struct phylink_pcs *pcs; -+ -+ if (!pl->mac_ops->mac_select_pcs) -+ return 0; -+ -+ pcs = pl->mac_ops->mac_select_pcs(pl->config, interface); -+ if (!pcs) -+ return 0; -+ -+ return phylink_pcs_inband_caps(pcs, interface); -+} -+ - static void phylink_pcs_poll_stop(struct phylink *pl) - { - if (pl->cfg_link_an_mode == MLO_AN_INBAND) -@@ -1082,13 +1129,13 @@ static void phylink_mac_config(struct ph - - phylink_dbg(pl, - "%s: mode=%s/%s/%s adv=%*pb pause=%02x\n", -- __func__, phylink_an_mode_str(pl->cur_link_an_mode), -+ __func__, phylink_an_mode_str(pl->act_link_an_mode), - phy_modes(st.interface), - phy_rate_matching_to_str(st.rate_matching), - __ETHTOOL_LINK_MODE_MASK_NBITS, st.advertising, - st.pause); - -- pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, &st); -+ pl->mac_ops->mac_config(pl->config, pl->act_link_an_mode, &st); - } - - static void phylink_pcs_an_restart(struct phylink *pl) -@@ -1096,13 +1143,14 @@ static void phylink_pcs_an_restart(struc - if (pl->pcs && 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)) -+ phylink_autoneg_inband(pl->act_link_an_mode)) - pl->pcs->ops->pcs_an_restart(pl->pcs); - } - - /** - * phylink_pcs_neg_mode() - helper to determine PCS inband mode -- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. -+ * @pl: a pointer to a &struct phylink returned from phylink_create() -+ * @pcs: a pointer to &struct phylink_pcs - * @interface: interface mode to be used - * @advertising: adertisement ethtool link mode mask - * -@@ -1119,11 +1167,21 @@ static void phylink_pcs_an_restart(struc - * Note: this is for cases where the PCS itself is involved in negotiation - * (e.g. Clause 37, SGMII and similar) not Clause 73. - */ --static unsigned int phylink_pcs_neg_mode(unsigned int mode, -- phy_interface_t interface, -- const unsigned long *advertising) -+static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs, -+ phy_interface_t interface, -+ const unsigned long *advertising) - { -- unsigned int neg_mode; -+ unsigned int pcs_ib_caps = 0; -+ unsigned int phy_ib_caps = 0; -+ unsigned int neg_mode, mode; -+ enum { -+ INBAND_CISCO_SGMII, -+ INBAND_BASEX, -+ } type; -+ -+ mode = pl->req_link_an_mode; -+ -+ pl->phy_ib_mode = 0; - - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: -@@ -1136,10 +1194,7 @@ static unsigned int phylink_pcs_neg_mode - * 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; -+ type = INBAND_CISCO_SGMII; - break; - - case PHY_INTERFACE_MODE_1000BASEX: -@@ -1150,21 +1205,143 @@ static unsigned int phylink_pcs_neg_mode - * as well, but drivers may not support this, so may - * need to override this. - */ -- if (!phylink_autoneg_inband(mode)) -+ type = INBAND_BASEX; -+ break; -+ -+ default: -+ pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE; -+ pl->act_link_an_mode = mode; -+ return; -+ } -+ -+ if (pcs) -+ pcs_ib_caps = phylink_pcs_inband_caps(pcs, interface); -+ -+ if (pl->phydev) -+ phy_ib_caps = phy_inband_caps(pl->phydev, interface); -+ -+ phylink_dbg(pl, "interface %s inband modes: pcs=%02x phy=%02x\n", -+ phy_modes(interface), pcs_ib_caps, phy_ib_caps); -+ -+ if (!phylink_autoneg_inband(mode)) { -+ bool pcs_ib_only = false; -+ bool phy_ib_only = false; -+ -+ if (pcs_ib_caps && pcs_ib_caps != LINK_INBAND_DISABLE) { -+ /* PCS supports reporting in-band capabilities, and -+ * supports more than disable mode. -+ */ -+ if (pcs_ib_caps & LINK_INBAND_DISABLE) -+ neg_mode = PHYLINK_PCS_NEG_OUTBAND; -+ else if (pcs_ib_caps & LINK_INBAND_ENABLE) -+ pcs_ib_only = true; -+ } -+ -+ if (phy_ib_caps && phy_ib_caps != LINK_INBAND_DISABLE) { -+ /* PHY supports in-band capabilities, and supports -+ * more than disable mode. -+ */ -+ if (phy_ib_caps & LINK_INBAND_DISABLE) -+ pl->phy_ib_mode = LINK_INBAND_DISABLE; -+ else if (phy_ib_caps & LINK_INBAND_BYPASS) -+ pl->phy_ib_mode = LINK_INBAND_BYPASS; -+ else if (phy_ib_caps & LINK_INBAND_ENABLE) -+ phy_ib_only = true; -+ } -+ -+ /* If either the PCS or PHY requires inband to be enabled, -+ * this is an invalid configuration. Provide a diagnostic -+ * message for this case, but don't try to force the issue. -+ */ -+ if (pcs_ib_only || phy_ib_only) -+ phylink_warn(pl, -+ "firmware wants %s mode, but %s%s%s requires inband\n", -+ phylink_an_mode_str(mode), -+ pcs_ib_only ? "PCS" : "", -+ pcs_ib_only && phy_ib_only ? " and " : "", -+ phy_ib_only ? "PHY" : ""); -+ -+ neg_mode = PHYLINK_PCS_NEG_OUTBAND; -+ } else if (type == INBAND_CISCO_SGMII || pl->phydev) { -+ /* For SGMII modes which are designed to be used with PHYs, or -+ * Base-X with a PHY, we try to use in-band mode where-ever -+ * possible. However, there are some PHYs e.g. BCM84881 which -+ * do not support in-band. -+ */ -+ const unsigned int inband_ok = LINK_INBAND_ENABLE | -+ LINK_INBAND_BYPASS; -+ const unsigned int outband_ok = LINK_INBAND_DISABLE | -+ LINK_INBAND_BYPASS; -+ /* PCS PHY -+ * D E D E -+ * 0 0 0 0 no information inband enabled -+ * 1 0 0 0 pcs doesn't support outband -+ * 0 1 0 0 pcs required inband enabled -+ * 1 1 0 0 pcs optional inband enabled -+ * 0 0 1 0 phy doesn't support outband -+ * 1 0 1 0 pcs+phy doesn't support outband -+ * 0 1 1 0 pcs required, phy doesn't support, invalid -+ * 1 1 1 0 pcs optional, phy doesn't support, outband -+ * 0 0 0 1 phy required inband enabled -+ * 1 0 0 1 pcs doesn't support, phy required, invalid -+ * 0 1 0 1 pcs+phy required inband enabled -+ * 1 1 0 1 pcs optional, phy required inband enabled -+ * 0 0 1 1 phy optional inband enabled -+ * 1 0 1 1 pcs doesn't support, phy optional, outband -+ * 0 1 1 1 pcs required, phy optional inband enabled -+ * 1 1 1 1 pcs+phy optional inband enabled -+ */ -+ if ((!pcs_ib_caps || pcs_ib_caps & inband_ok) && -+ (!phy_ib_caps || phy_ib_caps & inband_ok)) { -+ /* In-band supported or unknown at both ends. Enable -+ * in-band mode with or without bypass at the PHY. -+ */ -+ if (phy_ib_caps & LINK_INBAND_ENABLE) -+ pl->phy_ib_mode = LINK_INBAND_ENABLE; -+ else if (phy_ib_caps & LINK_INBAND_BYPASS) -+ pl->phy_ib_mode = LINK_INBAND_BYPASS; -+ -+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; -+ } else if ((!pcs_ib_caps || pcs_ib_caps & outband_ok) && -+ (!phy_ib_caps || phy_ib_caps & outband_ok)) { -+ /* Either in-band not supported at at least one end. -+ * In-band bypass at the other end is possible. -+ */ -+ if (phy_ib_caps & LINK_INBAND_DISABLE) -+ pl->phy_ib_mode = LINK_INBAND_DISABLE; -+ else if (phy_ib_caps & LINK_INBAND_BYPASS) -+ pl->phy_ib_mode = LINK_INBAND_BYPASS; -+ - neg_mode = PHYLINK_PCS_NEG_OUTBAND; -+ if (pl->phydev) -+ mode = MLO_AN_PHY; -+ } else { -+ /* invalid */ -+ phylink_warn(pl, "%s: incompatible in-band capabilities, trying in-band", -+ phy_modes(interface)); -+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; -+ } -+ } else { -+ /* For Base-X without a PHY */ -+ if (pcs_ib_caps == LINK_INBAND_DISABLE) -+ /* If the PCS doesn't support inband, then inband must -+ * be disabled. -+ */ -+ neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED; -+ else if (pcs_ib_caps == LINK_INBAND_ENABLE) -+ /* If the PCS requires inband, then inband must always -+ * be enabled. -+ */ -+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; - 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; -+ pl->pcs_neg_mode = neg_mode; -+ pl->act_link_an_mode = mode; - } - - static void phylink_major_config(struct phylink *pl, bool restart, -@@ -1176,11 +1353,9 @@ static void phylink_major_config(struct - 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); -+ phylink_dbg(pl, "major config, requested %s/%s\n", -+ phylink_an_mode_str(pl->req_link_an_mode), -+ phy_modes(state->interface)); - - if (pl->using_mac_select_pcs) { - pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); -@@ -1194,10 +1369,17 @@ static void phylink_major_config(struct - pcs_changed = pcs && pl->pcs != pcs; - } - -+ phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising); -+ -+ phylink_dbg(pl, "major config, active %s/%s/%s\n", -+ phylink_an_mode_str(pl->act_link_an_mode), -+ phylink_pcs_mode_str(pl->pcs_neg_mode), -+ phy_modes(state->interface)); -+ - phylink_pcs_poll_stop(pl); - - if (pl->mac_ops->mac_prepare) { -- err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode, -+ err = pl->mac_ops->mac_prepare(pl->config, pl->act_link_an_mode, - state->interface); - if (err < 0) { - phylink_err(pl, "mac_prepare failed: %pe\n", -@@ -1231,7 +1413,7 @@ static void phylink_major_config(struct - if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed) - phylink_pcs_enable(pl->pcs); - -- neg_mode = pl->cur_link_an_mode; -+ neg_mode = pl->act_link_an_mode; - if (pl->pcs && pl->pcs->neg_mode) - neg_mode = pl->pcs_neg_mode; - -@@ -1247,13 +1429,20 @@ static void phylink_major_config(struct - phylink_pcs_an_restart(pl); - - if (pl->mac_ops->mac_finish) { -- err = pl->mac_ops->mac_finish(pl->config, pl->cur_link_an_mode, -+ err = pl->mac_ops->mac_finish(pl->config, pl->act_link_an_mode, - state->interface); - if (err < 0) - phylink_err(pl, "mac_finish failed: %pe\n", - ERR_PTR(err)); - } - -+ if (pl->phydev && pl->phy_ib_mode) { -+ err = phy_config_inband(pl->phydev, pl->phy_ib_mode); -+ if (err < 0) -+ phylink_err(pl, "phy_config_inband: %pe\n", -+ ERR_PTR(err)); -+ } -+ - if (pl->sfp_bus) { - rate_kbd = phylink_interface_signal_rate(state->interface); - if (rate_kbd) -@@ -1278,17 +1467,16 @@ static int phylink_change_inband_advert( - return 0; - - phylink_dbg(pl, "%s: mode=%s/%s adv=%*pb pause=%02x\n", __func__, -- phylink_an_mode_str(pl->cur_link_an_mode), -+ phylink_an_mode_str(pl->req_link_an_mode), - phy_modes(pl->link_config.interface), - __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); -+ phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface, -+ pl->link_config.advertising); - -- neg_mode = pl->cur_link_an_mode; -+ neg_mode = pl->act_link_an_mode; - if (pl->pcs->neg_mode) - neg_mode = pl->pcs_neg_mode; - -@@ -1353,7 +1541,7 @@ static void phylink_mac_initial_config(s - { - struct phylink_link_state link_state; - -- switch (pl->cur_link_an_mode) { -+ switch (pl->req_link_an_mode) { - case MLO_AN_PHY: - link_state = pl->phy_state; - break; -@@ -1427,14 +1615,14 @@ static void phylink_link_up(struct phyli - - pl->cur_interface = link_state.interface; - -- neg_mode = pl->cur_link_an_mode; -+ neg_mode = pl->act_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->mac_ops->mac_link_up(pl->config, pl->phydev, pl->act_link_an_mode, - pl->cur_interface, speed, duplex, - !!(link_state.pause & MLO_PAUSE_TX), rx_pause); - -@@ -1454,7 +1642,7 @@ static void phylink_link_down(struct phy - - if (ndev) - netif_carrier_off(ndev); -- pl->mac_ops->mac_link_down(pl->config, pl->cur_link_an_mode, -+ pl->mac_ops->mac_link_down(pl->config, pl->act_link_an_mode, - pl->cur_interface); - phylink_info(pl, "Link is Down\n"); - } -@@ -1481,7 +1669,7 @@ static void phylink_resolve(struct work_ - link_state.link = false; - retrigger = true; - } else { -- switch (pl->cur_link_an_mode) { -+ switch (pl->act_link_an_mode) { - case MLO_AN_PHY: - link_state = pl->phy_state; - phylink_apply_manual_flow(pl, &link_state); -@@ -1671,7 +1859,7 @@ int phylink_set_fixed_link(struct phylin - pl->link_config.an_complete = 1; - - pl->cfg_link_an_mode = MLO_AN_FIXED; -- pl->cur_link_an_mode = pl->cfg_link_an_mode; -+ pl->req_link_an_mode = pl->cfg_link_an_mode; - - return 0; - } -@@ -1766,7 +1954,7 @@ struct phylink *phylink_create(struct ph - } - } - -- pl->cur_link_an_mode = pl->cfg_link_an_mode; -+ pl->req_link_an_mode = pl->cfg_link_an_mode; - - ret = phylink_register_sfp(pl, fwnode); - if (ret < 0) { -@@ -2242,7 +2430,7 @@ void phylink_start(struct phylink *pl) - ASSERT_RTNL(); - - phylink_info(pl, "configuring for %s/%s link mode\n", -- phylink_an_mode_str(pl->cur_link_an_mode), -+ phylink_an_mode_str(pl->req_link_an_mode), - phy_modes(pl->link_config.interface)); - - /* Always set the carrier off */ -@@ -2501,7 +2689,7 @@ int phylink_ethtool_ksettings_get(struct - - linkmode_copy(kset->link_modes.supported, pl->supported); - -- switch (pl->cur_link_an_mode) { -+ switch (pl->act_link_an_mode) { - case MLO_AN_FIXED: - /* We are using fixed settings. Report these as the - * current link settings - and note that these also -@@ -2532,6 +2720,26 @@ int phylink_ethtool_ksettings_get(struct - } - EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_get); - -+static bool phylink_validate_pcs_inband_autoneg(struct phylink *pl, -+ phy_interface_t interface, -+ unsigned long *adv) -+{ -+ unsigned int inband = phylink_inband_caps(pl, interface); -+ unsigned int mask; -+ -+ /* If the PCS doesn't implement inband support, be permissive. */ -+ if (!inband) -+ return true; -+ -+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, adv)) -+ mask = LINK_INBAND_ENABLE; -+ else -+ mask = LINK_INBAND_DISABLE; -+ -+ /* Check whether the PCS implements the required mode */ -+ return !!(inband & mask); -+} -+ - /** - * phylink_ethtool_ksettings_set() - set the link settings - * @pl: a pointer to a &struct phylink returned from phylink_create() -@@ -2593,7 +2801,7 @@ int phylink_ethtool_ksettings_set(struct - /* If we have a fixed link, refuse to change link parameters. - * If the link parameters match, accept them but do nothing. - */ -- if (pl->cur_link_an_mode == MLO_AN_FIXED) { -+ if (pl->req_link_an_mode == MLO_AN_FIXED) { - if (s->speed != pl->link_config.speed || - s->duplex != pl->link_config.duplex) - return -EINVAL; -@@ -2609,7 +2817,7 @@ int phylink_ethtool_ksettings_set(struct - * is our default case) but do not allow the advertisement to - * be changed. If the advertisement matches, simply return. - */ -- if (pl->cur_link_an_mode == MLO_AN_FIXED) { -+ if (pl->req_link_an_mode == MLO_AN_FIXED) { - if (!linkmode_equal(config.advertising, - pl->link_config.advertising)) - return -EINVAL; -@@ -2649,7 +2857,7 @@ int phylink_ethtool_ksettings_set(struct - linkmode_copy(support, pl->supported); - if (phylink_validate(pl, support, &config)) { - phylink_err(pl, "validation of %s/%s with support %*pb failed\n", -- phylink_an_mode_str(pl->cur_link_an_mode), -+ phylink_an_mode_str(pl->req_link_an_mode), - phy_modes(config.interface), - __ETHTOOL_LINK_MODE_MASK_NBITS, support); - return -EINVAL; -@@ -2667,6 +2875,13 @@ int phylink_ethtool_ksettings_set(struct - phylink_is_empty_linkmode(config.advertising)) - return -EINVAL; - -+ /* Validate the autonegotiation state. We don't have a PHY in this -+ * situation, so the PCS is the media-facing entity. -+ */ -+ if (!phylink_validate_pcs_inband_autoneg(pl, config.interface, -+ config.advertising)) -+ return -EINVAL; -+ - mutex_lock(&pl->state_mutex); - pl->link_config.speed = config.speed; - pl->link_config.duplex = config.duplex; -@@ -2749,7 +2964,7 @@ int phylink_ethtool_set_pauseparam(struc - - ASSERT_RTNL(); - -- if (pl->cur_link_an_mode == MLO_AN_FIXED) -+ if (pl->req_link_an_mode == MLO_AN_FIXED) - return -EOPNOTSUPP; - - if (!phylink_test(pl->supported, Pause) && -@@ -3013,7 +3228,7 @@ static int phylink_mii_read(struct phyli - struct phylink_link_state state; - int val = 0xffff; - -- switch (pl->cur_link_an_mode) { -+ switch (pl->act_link_an_mode) { - case MLO_AN_FIXED: - if (phy_id == 0) { - phylink_get_fixed_state(pl, &state); -@@ -3038,7 +3253,7 @@ static int phylink_mii_read(struct phyli - static int phylink_mii_write(struct phylink *pl, unsigned int phy_id, - unsigned int reg, unsigned int val) - { -- switch (pl->cur_link_an_mode) { -+ switch (pl->act_link_an_mode) { - case MLO_AN_FIXED: - break; - -@@ -3208,10 +3423,11 @@ static phy_interface_t phylink_choose_sf - return interface; - } - --static void phylink_sfp_set_config(struct phylink *pl, u8 mode, -+static void phylink_sfp_set_config(struct phylink *pl, - unsigned long *supported, - struct phylink_link_state *state) - { -+ u8 mode = MLO_AN_INBAND; - bool changed = false; - - phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n", -@@ -3228,9 +3444,9 @@ static void phylink_sfp_set_config(struc - changed = true; - } - -- if (pl->cur_link_an_mode != mode || -+ if (pl->req_link_an_mode != mode || - pl->link_config.interface != state->interface) { -- pl->cur_link_an_mode = mode; -+ pl->req_link_an_mode = mode; - pl->link_config.interface = state->interface; - - changed = true; -@@ -3245,8 +3461,7 @@ static void phylink_sfp_set_config(struc - phylink_mac_initial_config(pl, false); - } - --static int phylink_sfp_config_phy(struct phylink *pl, u8 mode, -- struct phy_device *phy) -+static int phylink_sfp_config_phy(struct phylink *pl, struct phy_device *phy) - { - __ETHTOOL_DECLARE_LINK_MODE_MASK(support1); - __ETHTOOL_DECLARE_LINK_MODE_MASK(support); -@@ -3285,8 +3500,7 @@ static int phylink_sfp_config_phy(struct - ret = phylink_validate(pl, support1, &config); - if (ret) { - phylink_err(pl, -- "validation of %s/%s with support %*pb failed: %pe\n", -- phylink_an_mode_str(mode), -+ "validation of %s with support %*pb failed: %pe\n", - phy_modes(config.interface), - __ETHTOOL_LINK_MODE_MASK_NBITS, support, - ERR_PTR(ret)); -@@ -3295,7 +3509,7 @@ static int phylink_sfp_config_phy(struct - - pl->link_port = pl->sfp_port; - -- phylink_sfp_set_config(pl, mode, support, &config); -+ phylink_sfp_set_config(pl, support, &config); - - return 0; - } -@@ -3351,6 +3565,12 @@ static int phylink_sfp_config_optical(st - phylink_dbg(pl, "optical SFP: chosen %s interface\n", - phy_modes(interface)); - -+ if (!phylink_validate_pcs_inband_autoneg(pl, interface, -+ config.advertising)) { -+ phylink_err(pl, "autoneg setting not compatible with PCS"); -+ return -EINVAL; -+ } -+ - config.interface = interface; - - /* Ignore errors if we're expecting a PHY to attach later */ -@@ -3364,7 +3584,7 @@ static int phylink_sfp_config_optical(st - - pl->link_port = pl->sfp_port; - -- phylink_sfp_set_config(pl, MLO_AN_INBAND, pl->sfp_support, &config); -+ phylink_sfp_set_config(pl, pl->sfp_support, &config); - - return 0; - } -@@ -3435,20 +3655,10 @@ static void phylink_sfp_link_up(void *up - phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_LINK); - } - --/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII -- * or 802.3z control word, so inband will not work. -- */ --static bool phylink_phy_no_inband(struct phy_device *phy) --{ -- 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) - { - struct phylink *pl = upstream; - phy_interface_t interface; -- u8 mode; - int ret; - - /* -@@ -3460,17 +3670,12 @@ static int phylink_sfp_connect_phy(void - */ - phy_support_asym_pause(phy); - -- if (phylink_phy_no_inband(phy)) -- mode = MLO_AN_PHY; -- else -- mode = MLO_AN_INBAND; -- - /* Set the PHY's host supported interfaces */ - phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces, - pl->config->supported_interfaces); - - /* Do the initial configuration */ -- ret = phylink_sfp_config_phy(pl, mode, phy); -+ ret = phylink_sfp_config_phy(pl, phy); - if (ret < 0) - return ret; - ---- a/drivers/net/phy/phy.c -+++ b/drivers/net/phy/phy.c -@@ -1049,6 +1049,58 @@ static int phy_check_link_status(struct - } - - /** -+ * phy_inband_caps - query which in-band signalling modes are supported -+ * @phydev: a pointer to a &struct phy_device -+ * @interface: the interface mode for the PHY -+ * -+ * Returns zero if it is unknown what in-band signalling is supported by the -+ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise, -+ * returns a bit mask of the LINK_INBAND_* values from -+ * &enum link_inband_signalling to describe which inband modes are supported -+ * by the PHY for this interface mode. -+ */ -+unsigned int phy_inband_caps(struct phy_device *phydev, -+ phy_interface_t interface) -+{ -+ if (phydev->drv && phydev->drv->inband_caps) -+ return phydev->drv->inband_caps(phydev, interface); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(phy_inband_caps); -+ -+/** -+ * phy_config_inband - configure the desired PHY in-band mode -+ * @phydev: the phy_device struct -+ * @modes: in-band modes to configure -+ * -+ * Description: disables, enables or enables-with-bypass in-band signalling -+ * between the PHY and host system. -+ * -+ * Returns: zero on success, or negative errno value. -+ */ -+int phy_config_inband(struct phy_device *phydev, unsigned int modes) -+{ -+ int err; -+ -+ if (!!(modes & LINK_INBAND_DISABLE) + -+ !!(modes & LINK_INBAND_ENABLE) + -+ !!(modes & LINK_INBAND_BYPASS) != 1) -+ return -EINVAL; -+ -+ mutex_lock(&phydev->lock); -+ if (!phydev->drv) -+ err = -EIO; -+ else if (!phydev->drv->config_inband) -+ err = -EOPNOTSUPP; -+ else -+ err = phydev->drv->config_inband(phydev, modes); -+ mutex_unlock(&phydev->lock); -+ -+ return err; -+} -+ -+/** - * _phy_start_aneg - start auto-negotiation for this PHY device - * @phydev: the phy_device struct - * ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -816,6 +816,24 @@ struct phy_tdr_config { - #define PHY_PAIR_ALL -1 - - /** -+ * enum link_inband_signalling - in-band signalling modes that are supported -+ * -+ * @LINK_INBAND_DISABLE: in-band signalling can be disabled -+ * @LINK_INBAND_ENABLE: in-band signalling can be enabled without bypass -+ * @LINK_INBAND_BYPASS: in-band signalling can be enabled with bypass -+ * -+ * The possible and required bits can only be used if the valid bit is set. -+ * If possible is clear, that means inband signalling can not be used. -+ * Required is only valid when possible is set, and means that inband -+ * signalling must be used. -+ */ -+enum link_inband_signalling { -+ LINK_INBAND_DISABLE = BIT(0), -+ LINK_INBAND_ENABLE = BIT(1), -+ LINK_INBAND_BYPASS = BIT(2), -+}; -+ -+/** - * struct phy_plca_cfg - Configuration of the PLCA (Physical Layer Collision - * Avoidance) Reconciliation Sublayer. - * -@@ -955,6 +973,19 @@ struct phy_driver { - int (*get_features)(struct phy_device *phydev); - - /** -+ * @inband_caps: query whether in-band is supported for the given PHY -+ * interface mode. Returns a bitmask of bits defined by enum -+ * link_inband_signalling. -+ */ -+ unsigned int (*inband_caps)(struct phy_device *phydev, -+ phy_interface_t interface); -+ -+ /** -+ * @config_inband: configure in-band mode for the PHY -+ */ -+ int (*config_inband)(struct phy_device *phydev, unsigned int modes); -+ -+ /** - * @get_rate_matching: Get the supported type of rate matching for a - * particular phy interface. This is used by phy consumers to determine - * whether to advertise lower-speed modes for that interface. It is -@@ -1840,6 +1871,9 @@ int phy_config_aneg(struct phy_device *p - int _phy_start_aneg(struct phy_device *phydev); - int phy_start_aneg(struct phy_device *phydev); - int phy_aneg_done(struct phy_device *phydev); -+unsigned int phy_inband_caps(struct phy_device *phydev, -+ phy_interface_t interface); -+int phy_config_inband(struct phy_device *phydev, unsigned int modes); - int phy_speed_down(struct phy_device *phydev, bool sync); - int phy_speed_up(struct phy_device *phydev); - bool phy_check_valid(int speed, int duplex, unsigned long *features); ---- a/drivers/net/phy/bcm84881.c -+++ b/drivers/net/phy/bcm84881.c -@@ -235,11 +235,21 @@ static int bcm84881_read_status(struct p - return genphy_c45_read_mdix(phydev); - } - -+/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII -+ * or 802.3z control word, so inband will not work. -+ */ -+static unsigned int bcm84881_inband_caps(struct phy_device *phydev, -+ phy_interface_t interface) -+{ -+ return LINK_INBAND_DISABLE; -+} -+ - static struct phy_driver bcm84881_drivers[] = { - { - .phy_id = 0xae025150, - .phy_id_mask = 0xfffffff0, - .name = "Broadcom BCM84881", -+ .inband_caps = bcm84881_inband_caps, - .config_init = bcm84881_config_init, - .probe = bcm84881_probe, - .get_features = bcm84881_get_features, ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -716,6 +716,48 @@ static int marvell_config_aneg_fiber(str - return genphy_check_and_restart_aneg(phydev, changed); - } - -+static unsigned int m88e1111_inband_caps(struct phy_device *phydev, -+ phy_interface_t interface) -+{ -+ /* In 1000base-X and SGMII modes, the inband mode can be changed -+ * through the Fibre page BMCR ANENABLE bit. -+ */ -+ if (interface == PHY_INTERFACE_MODE_1000BASEX || -+ interface == PHY_INTERFACE_MODE_SGMII) -+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE | -+ LINK_INBAND_BYPASS; -+ -+ return 0; -+} -+ -+static int m88e1111_config_inband(struct phy_device *phydev, unsigned int modes) -+{ -+ u16 extsr, bmcr; -+ int err; -+ -+ if (phydev->interface != PHY_INTERFACE_MODE_1000BASEX && -+ phydev->interface != PHY_INTERFACE_MODE_SGMII) -+ return -EINVAL; -+ -+ if (modes == LINK_INBAND_BYPASS) -+ extsr = MII_M1111_HWCFG_SERIAL_AN_BYPASS; -+ else -+ extsr = 0; -+ -+ if (modes == LINK_INBAND_DISABLE) -+ bmcr = 0; -+ else -+ bmcr = BMCR_ANENABLE; -+ -+ err = phy_modify(phydev, MII_M1111_PHY_EXT_SR, -+ MII_M1111_HWCFG_SERIAL_AN_BYPASS, extsr); -+ if (err < 0) -+ return extsr; -+ -+ return phy_modify_paged(phydev, MII_MARVELL_FIBER_PAGE, MII_BMCR, -+ BMCR_ANENABLE, bmcr); -+} -+ - static int m88e1111_config_aneg(struct phy_device *phydev) - { - int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR); -@@ -3667,6 +3709,8 @@ static struct phy_driver marvell_drivers - .name = "Marvell 88E1112", - /* PHY_GBIT_FEATURES */ - .probe = marvell_probe, -+ .inband_caps = m88e1111_inband_caps, -+ .config_inband = m88e1111_config_inband, - .config_init = m88e1112_config_init, - .config_aneg = marvell_config_aneg, - .config_intr = marvell_config_intr, -@@ -3688,6 +3732,8 @@ static struct phy_driver marvell_drivers - /* PHY_GBIT_FEATURES */ - .flags = PHY_POLL_CABLE_TEST, - .probe = marvell_probe, -+ .inband_caps = m88e1111_inband_caps, -+ .config_inband = m88e1111_config_inband, - .config_init = m88e1111gbe_config_init, - .config_aneg = m88e1111_config_aneg, - .read_status = marvell_read_status, -@@ -3711,6 +3757,8 @@ static struct phy_driver marvell_drivers - .name = "Marvell 88E1111 (Finisar)", - /* PHY_GBIT_FEATURES */ - .probe = marvell_probe, -+ .inband_caps = m88e1111_inband_caps, -+ .config_inband = m88e1111_config_inband, - .config_init = m88e1111gbe_config_init, - .config_aneg = m88e1111_config_aneg, - .read_status = marvell_read_status, ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -419,6 +419,7 @@ struct phylink_pcs { - /** - * struct phylink_pcs_ops - MAC PCS operations structure. - * @pcs_validate: validate the link configuration. -+ * @pcs_inband_caps: query inband support for interface mode. - * @pcs_enable: enable the PCS. - * @pcs_disable: disable the PCS. - * @pcs_pre_config: pre-mac_config method (for errata) -@@ -434,6 +435,8 @@ struct phylink_pcs { - struct phylink_pcs_ops { - int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported, - const struct phylink_link_state *state); -+ unsigned int (*pcs_inband_caps)(struct phylink_pcs *pcs, -+ phy_interface_t interface); - int (*pcs_enable)(struct phylink_pcs *pcs); - void (*pcs_disable)(struct phylink_pcs *pcs); - void (*pcs_pre_config)(struct phylink_pcs *pcs, -@@ -471,6 +474,20 @@ int pcs_validate(struct phylink_pcs *pcs - const struct phylink_link_state *state); - - /** -+ * pcs_inband_caps - query PCS in-band capabilities for interface mode. -+ * @pcs: a pointer to a &struct phylink_pcs. -+ * @interface: interface mode to be queried -+ * -+ * Returns zero if it is unknown what in-band signalling is supported by the -+ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise, -+ * returns a bit mask of the LINK_INBAND_* values from -+ * &enum link_inband_signalling to describe which inband modes are supported -+ * for this interface mode. -+ */ -+unsigned int pcs_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface); -+ -+/** - * pcs_enable() - enable the PCS. - * @pcs: a pointer to a &struct phylink_pcs. - */ ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -3960,20 +3960,27 @@ static struct mvneta_port *mvneta_pcs_to - return container_of(pcs, struct mvneta_port, phylink_pcs); - } - --static int mvneta_pcs_validate(struct phylink_pcs *pcs, -- unsigned long *supported, -- const struct phylink_link_state *state) -+static unsigned int mvneta_pcs_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface) - { -- /* We only support QSGMII, SGMII, 802.3z and RGMII modes. -- * When in 802.3z mode, we must have AN enabled: -+ /* When operating in an 802.3z mode, we must have AN enabled: - * "Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ... - * When = 1 (1000BASE-X) this field must be set to 1." -+ * Therefore, inband is "required". - */ -- if (phy_interface_mode_is_8023z(state->interface) && -- !phylink_test(state->advertising, Autoneg)) -- return -EINVAL; -+ if (phy_interface_mode_is_8023z(interface)) -+ return LINK_INBAND_ENABLE; - -- return 0; -+ /* QSGMII, SGMII and RGMII can be configured to use inband -+ * signalling of the AN result. Indicate these as "possible". -+ */ -+ if (interface == PHY_INTERFACE_MODE_SGMII || -+ interface == PHY_INTERFACE_MODE_QSGMII || -+ phy_interface_mode_is_rgmii(interface)) -+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ -+ /* For any other modes, indicate that inband is not supported. */ -+ return LINK_INBAND_DISABLE; - } - - static void mvneta_pcs_get_state(struct phylink_pcs *pcs, -@@ -4071,7 +4078,7 @@ static void mvneta_pcs_an_restart(struct - } - - static const struct phylink_pcs_ops mvneta_phylink_pcs_ops = { -- .pcs_validate = mvneta_pcs_validate, -+ .pcs_inband_caps = mvneta_pcs_inband_caps, - .pcs_get_state = mvneta_pcs_get_state, - .pcs_config = mvneta_pcs_config, - .pcs_an_restart = mvneta_pcs_an_restart, ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -6237,19 +6237,26 @@ static const struct phylink_pcs_ops mvpp - .pcs_config = mvpp2_xlg_pcs_config, - }; - --static int mvpp2_gmac_pcs_validate(struct phylink_pcs *pcs, -- unsigned long *supported, -- const struct phylink_link_state *state) -+static unsigned int mvpp2_gmac_pcs_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface) - { -- /* When in 802.3z mode, we must have AN enabled: -+ /* When operating in an 802.3z mode, we must have AN enabled: - * Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ... - * When = 1 (1000BASE-X) this field must be set to 1. -+ * Therefore, inband is "required". - */ -- if (phy_interface_mode_is_8023z(state->interface) && -- !phylink_test(state->advertising, Autoneg)) -- return -EINVAL; -+ if (phy_interface_mode_is_8023z(interface)) -+ return LINK_INBAND_ENABLE; - -- return 0; -+ /* SGMII and RGMII can be configured to use inband signalling of the -+ * AN result. Indicate these as "possible". -+ */ -+ if (interface == PHY_INTERFACE_MODE_SGMII || -+ phy_interface_mode_is_rgmii(interface)) -+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ -+ /* For any other modes, indicate that inband is not supported. */ -+ return LINK_INBAND_DISABLE; - } - - static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs, -@@ -6356,7 +6363,7 @@ static void mvpp2_gmac_pcs_an_restart(st - } - - static const struct phylink_pcs_ops mvpp2_phylink_gmac_pcs_ops = { -- .pcs_validate = mvpp2_gmac_pcs_validate, -+ .pcs_inband_caps = mvpp2_gmac_pcs_inband_caps, - .pcs_get_state = mvpp2_gmac_pcs_get_state, - .pcs_config = mvpp2_gmac_pcs_config, - .pcs_an_restart = mvpp2_gmac_pcs_an_restart, ---- a/drivers/net/pcs/pcs-lynx.c -+++ b/drivers/net/pcs/pcs-lynx.c -@@ -35,6 +35,27 @@ enum sgmii_speed { - #define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs) - #define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs) - -+static unsigned int lynx_pcs_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface) -+{ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ -+ case PHY_INTERFACE_MODE_10GBASER: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ return LINK_INBAND_DISABLE; -+ -+ case PHY_INTERFACE_MODE_USXGMII: -+ return LINK_INBAND_ENABLE; -+ -+ default: -+ return 0; -+ } -+} -+ - static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs, - struct phylink_link_state *state) - { -@@ -306,6 +327,7 @@ static void lynx_pcs_link_up(struct phyl - } - - static const struct phylink_pcs_ops lynx_pcs_phylink_ops = { -+ .pcs_inband_caps = lynx_pcs_inband_caps, - .pcs_get_state = lynx_pcs_get_state, - .pcs_config = lynx_pcs_config, - .pcs_an_restart = lynx_pcs_an_restart, ---- a/drivers/net/pcs/pcs-mtk-lynxi.c -+++ b/drivers/net/pcs/pcs-mtk-lynxi.c -@@ -110,6 +110,21 @@ static struct mtk_pcs_lynxi *pcs_to_mtk_ - return container_of(pcs, struct mtk_pcs_lynxi, pcs); - } - -+static unsigned int mtk_pcs_lynxi_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface) -+{ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ -+ default: -+ return 0; -+ } -+} -+ - static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs, - struct phylink_link_state *state) - { -@@ -302,6 +317,7 @@ static void mtk_pcs_lynxi_disable(struct - } - - static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = { -+ .pcs_inband_caps = mtk_pcs_lynxi_inband_caps, - .pcs_get_state = mtk_pcs_lynxi_get_state, - .pcs_config = mtk_pcs_lynxi_config, - .pcs_an_restart = mtk_pcs_lynxi_restart_an, ---- a/drivers/net/pcs/pcs-xpcs.c -+++ b/drivers/net/pcs/pcs-xpcs.c -@@ -608,6 +608,33 @@ static int xpcs_validate(struct phylink_ - return 0; - } - -+static unsigned int xpcs_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface) -+{ -+ struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs); -+ const struct dw_xpcs_compat *compat; -+ -+ compat = xpcs_find_compat(xpcs, interface); -+ if (!compat) -+ return 0; -+ -+ switch (compat->an_mode) { -+ case DW_AN_C73: -+ return LINK_INBAND_ENABLE; -+ -+ case DW_AN_C37_SGMII: -+ case DW_AN_C37_1000BASEX: -+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ -+ case DW_10GBASER: -+ case DW_2500BASEX: -+ return LINK_INBAND_DISABLE; -+ -+ default: -+ return 0; -+ } -+} -+ - void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces) - { - int i, j; -@@ -1365,6 +1392,7 @@ static const struct dw_xpcs_desc xpcs_de - - static const struct phylink_pcs_ops xpcs_phylink_ops = { - .pcs_validate = xpcs_validate, -+ .pcs_inband_caps = xpcs_inband_caps, - .pcs_config = xpcs_config, - .pcs_get_state = xpcs_get_state, - .pcs_an_restart = xpcs_an_restart, diff --git a/lede/target/linux/mediatek/patches-6.12/750-net-ethernet-mtk_eth_soc-add-mt7987-support.patch b/lede/target/linux/mediatek/patches-6.12/750-net-ethernet-mtk_eth_soc-add-mt7987-support.patch index dcd815cec3..e4a46f0323 100644 --- a/lede/target/linux/mediatek/patches-6.12/750-net-ethernet-mtk_eth_soc-add-mt7987-support.patch +++ b/lede/target/linux/mediatek/patches-6.12/750-net-ethernet-mtk_eth_soc-add-mt7987-support.patch @@ -106,7 +106,7 @@ Signed-off-by: Bo-Cun Chen mdelay(20); mtk_m32(mac->hw, XMAC_GLB_CNTCLR, XMAC_GLB_CNTCLR, MTK_XMAC_CNT_CTRL(mac->id)); -@@ -2901,10 +2931,16 @@ static int mtk_tx_alloc(struct mtk_eth * +@@ -2908,10 +2938,16 @@ static int mtk_tx_alloc(struct mtk_eth * mtk_w32(eth, val, soc->reg_map->qdma.qtx_cfg + ofs); val = MTK_QTX_SCH_MIN_RATE_EN | @@ -126,7 +126,7 @@ Signed-off-by: Bo-Cun Chen if (mtk_is_netsys_v1(eth)) val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); -@@ -5873,6 +5909,36 @@ static const struct mtk_soc_data mt7986_ +@@ -5883,6 +5919,36 @@ static const struct mtk_soc_data mt7986_ }, }; @@ -144,14 +144,14 @@ Signed-off-by: Bo-Cun Chen + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, + .tx = { -+ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ DESC_SIZE(struct mtk_tx_dma_v2), + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + .dma_size = MTK_DMA_SIZE(2K), + .fq_dma_size = MTK_DMA_SIZE(4K), + }, + .rx = { -+ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ DESC_SIZE(struct mtk_rx_dma_v2), + .irq_done_mask = MTK_RX_DONE_INT_V2, + .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, @@ -163,7 +163,7 @@ Signed-off-by: Bo-Cun Chen static const struct mtk_soc_data mt7988_data = { .reg_map = &mt7988_reg_map, .ana_rgc3 = 0x128, -@@ -5934,6 +6000,7 @@ const struct of_device_id of_mtk_match[] +@@ -5944,6 +6010,7 @@ const struct of_device_id of_mtk_match[] { .compatible = "mediatek,mt7629-eth", .data = &mt7629_data }, { .compatible = "mediatek,mt7981-eth", .data = &mt7981_data }, { .compatible = "mediatek,mt7986-eth", .data = &mt7986_data }, diff --git a/lede/target/linux/mediatek/patches-6.12/751-net-ethernet-mtk_eth_soc-revise-hardware-configuration-for-mt7987.patch b/lede/target/linux/mediatek/patches-6.12/751-net-ethernet-mtk_eth_soc-revise-hardware-configuration-for-mt7987.patch index 56dd3257c6..3510ee529e 100644 --- a/lede/target/linux/mediatek/patches-6.12/751-net-ethernet-mtk_eth_soc-revise-hardware-configuration-for-mt7987.patch +++ b/lede/target/linux/mediatek/patches-6.12/751-net-ethernet-mtk_eth_soc-revise-hardware-configuration-for-mt7987.patch @@ -15,7 +15,7 @@ Signed-off-by: Bo-Cun Chen --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4445,27 +4445,40 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -4452,27 +4452,40 @@ static int mtk_hw_init(struct mtk_eth *e mtk_w32(eth, PSE_DUMMY_WORK_GDM(1) | PSE_DUMMY_WORK_GDM(2) | PSE_DUMMY_WORK_GDM(3) | DUMMY_PAGE_THR, PSE_DUMY_REQ); diff --git a/lede/target/linux/mediatek/patches-6.12/863-arm64-dts-mt7986-add-sound-wm8960.patch b/lede/target/linux/mediatek/patches-6.12/863-arm64-dts-mt7986-add-sound-wm8960.patch index b16a63ada9..db51bf1779 100644 --- a/lede/target/linux/mediatek/patches-6.12/863-arm64-dts-mt7986-add-sound-wm8960.patch +++ b/lede/target/linux/mediatek/patches-6.12/863-arm64-dts-mt7986-add-sound-wm8960.patch @@ -46,7 +46,7 @@ Subject: [PATCH] arm64: dts: mt7986: add sound wm8960 }; &spi0 { -@@ -50,3 +80,13 @@ +@@ -48,3 +78,13 @@ &wifi { mediatek,mtd-eeprom = <&factory 0>; }; diff --git a/lede/target/linux/mediatek/patches-6.12/901-arm-add-cmdline-override.patch b/lede/target/linux/mediatek/patches-6.12/901-arm-add-cmdline-override.patch index 001c7bf2f0..a3f31473c5 100644 --- a/lede/target/linux/mediatek/patches-6.12/901-arm-add-cmdline-override.patch +++ b/lede/target/linux/mediatek/patches-6.12/901-arm-add-cmdline-override.patch @@ -37,7 +37,7 @@ * CONFIG_CMDLINE is meant to be a default in case nothing else --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig -@@ -2380,6 +2380,14 @@ config CMDLINE_FORCE +@@ -2381,6 +2381,14 @@ config CMDLINE_FORCE endchoice diff --git a/lede/target/linux/mediatek/patches-6.12/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch b/lede/target/linux/mediatek/patches-6.12/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch index abb6591b7d..a7a854dd6e 100644 --- a/lede/target/linux/mediatek/patches-6.12/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch +++ b/lede/target/linux/mediatek/patches-6.12/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch @@ -22,7 +22,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -1322,6 +1322,24 @@ mtk_wed_rro_alloc(struct mtk_wed_device +@@ -1333,6 +1333,24 @@ mtk_wed_rro_alloc(struct mtk_wed_device struct device_node *np; int index; @@ -47,7 +47,7 @@ Signed-off-by: Lorenzo Bianconi index = of_property_match_string(dev->hw->node, "memory-region-names", "wo-dlm"); if (index < 0) -@@ -1338,6 +1356,7 @@ mtk_wed_rro_alloc(struct mtk_wed_device +@@ -1349,6 +1367,7 @@ mtk_wed_rro_alloc(struct mtk_wed_device return -ENODEV; dev->rro.miod_phys = rmem->base; diff --git a/lede/target/linux/mediatek/patches-6.12/950-smartrg-i2c-led-driver.patch b/lede/target/linux/mediatek/patches-6.12/950-smartrg-i2c-led-driver.patch index faa801fc82..95f39f1a2a 100644 --- a/lede/target/linux/mediatek/patches-6.12/950-smartrg-i2c-led-driver.patch +++ b/lede/target/linux/mediatek/patches-6.12/950-smartrg-i2c-led-driver.patch @@ -29,6 +29,6 @@ obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o +obj-$(CONFIG_LEDS_SMARTRG_LED) += leds-smartrg-system.o - obj-$(CONFIG_LEDS_SUN50I_A100) += leds-sun50i-a100.o obj-$(CONFIG_LEDS_ST1202) += leds-st1202.o + obj-$(CONFIG_LEDS_SUN50I_A100) += leds-sun50i-a100.o obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o diff --git a/lede/target/linux/mediatek/patches-6.12/955-dts-mt7968a-bpi-r3-add-label-to-gmac-for-sfp1-port.patch b/lede/target/linux/mediatek/patches-6.12/955-dts-mt7968a-bpi-r3-add-label-to-gmac-for-sfp1-port.patch new file mode 100644 index 0000000000..f11cf01686 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/955-dts-mt7968a-bpi-r3-add-label-to-gmac-for-sfp1-port.patch @@ -0,0 +1,10 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts +@@ -195,6 +195,7 @@ + phy-mode = "2500base-x"; + sfp = <&sfp1>; + managed = "in-band-status"; ++ openwrt,netdev-name = "sfp1"; + }; + + mdio: mdio-bus { diff --git a/lede/target/linux/mediatek/patches-6.12/960-asus-hack-u-boot-ignore-mtdparts.patch b/lede/target/linux/mediatek/patches-6.12/960-asus-hack-u-boot-ignore-mtdparts.patch new file mode 100644 index 0000000000..84ec9338b5 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/960-asus-hack-u-boot-ignore-mtdparts.patch @@ -0,0 +1,47 @@ +From 30a04cf5b6ffa1249df72ccd98cef05f37890f89 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Thu, 6 Feb 2025 05:07:20 +0000 +Subject: [PATCH] mtd: spinand: add work-around to prevent bootloader wiping + mtdparts + +ASUS makes use of U-Boot's fdt_fixup_mtdparts() function which applies +the partitions defined in U-Boot's mtdparts and mtdids environment +variables to the devicetree passed over to Linux. + +The undesired side-effect is that in this way also all additional +properties and child nodes get wiped, preventing NVMEM cells to be +defined for MTD partitions or UBI volumes. + +To work-around this issue, add an additional compatible string +'u-boot-dont-touch-spi-nand' which can be used instead of 'spi-nand' in +case the replacement of the MTD partitions by U-Boot should be skipped +alltogether. + +In practise this is mostly relevant for SPI-NAND which anyway comes only +with two partitions nowadays: 'Bootloader' and 'UBI_DEV'. Hence this +work-around is applicable for SPI-NAND only. Similar work-arounds for +other MTD devices can be created as well should they actually be needed. + +Signed-off-by: Daniel Golle +--- + drivers/mtd/nand/spi/core.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -1690,6 +1690,7 @@ static int spinand_remove(struct spi_mem + + static const struct spi_device_id spinand_ids[] = { + { .name = "spi-nand" }, ++ { .name = "u-boot-dont-touch-spi-nand" }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(spi, spinand_ids); +@@ -1697,6 +1698,7 @@ MODULE_DEVICE_TABLE(spi, spinand_ids); + #ifdef CONFIG_OF + static const struct of_device_id spinand_of_ids[] = { + { .compatible = "spi-nand" }, ++ { .compatible = "u-boot-dont-touch-spi-nand" }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, spinand_of_ids); diff --git a/lede/target/linux/mediatek/patches-6.12/966-pcie-mediatek-gen3-Add-WIFI-HW-reset-flow.patch b/lede/target/linux/mediatek/patches-6.12/966-pcie-mediatek-gen3-Add-WIFI-HW-reset-flow.patch new file mode 100644 index 0000000000..ae60a9645f --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.12/966-pcie-mediatek-gen3-Add-WIFI-HW-reset-flow.patch @@ -0,0 +1,88 @@ +From f566462daef92eb0074013e32d0332116fc3a2eb Mon Sep 17 00:00:00 2001 +From: Jianguo Zhang +Date: Tue, 14 Oct 2025 16:00:03 +0800 +Subject: [PATCH] pcie: mediatek-gen3: Add WIFI HW reset flow + +[Description] +Add WIFI HW reset before PCIe host detects EP device for reboot. + +[Release-log] +NA + +Signed-off-by: Jianguo Zhang +--- + drivers/pci/controller/pcie-mediatek-gen3.c | 29 +++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -10,6 +10,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -18,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -160,6 +163,8 @@ struct mtk_msi_set { + * @phy: PHY controller block + * @clks: PCIe clocks + * @num_clks: PCIe clocks count for this port ++ * @wifi_reset: reset pin for WIFI chip ++ * @wifi_reset_delay_ms: delay time for WIFI chip reset + * @irq: PCIe controller interrupt number + * @saved_irq_state: IRQ enable state saved at suspend time + * @irq_lock: lock protecting IRQ register access +@@ -181,6 +186,9 @@ struct mtk_gen3_pcie { + struct clk_bulk_data *clks; + int num_clks; + ++ struct gpio_desc *wifi_reset; ++ u32 wifi_reset_delay_ms; ++ + int irq; + u32 saved_irq_state; + raw_spinlock_t irq_lock; +@@ -402,6 +410,12 @@ static int mtk_pcie_startup_port(struct + val |= PCIE_DISABLE_DVFSRC_VLT_REQ; + writel_relaxed(val, pcie->base + PCIE_MISC_CTRL_REG); + ++ if (pcie->wifi_reset) { ++ gpiod_set_value_cansleep(pcie->wifi_reset, 1); ++ msleep(pcie->wifi_reset_delay_ms); ++ gpiod_set_value_cansleep(pcie->wifi_reset, 0); ++ } ++ + /* Assert all reset signals */ + val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG); + val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB; +@@ -864,6 +878,20 @@ static int mtk_pcie_parse_port(struct mt + return pcie->num_clks; + } + ++ ret = of_property_read_u32(dev->of_node, "wifi-reset-msleep", ++ &pcie->wifi_reset_delay_ms); ++ if (!ret) { ++ pcie->wifi_reset = devm_gpiod_get_optional(dev, "wifi-reset", ++ GPIOD_OUT_LOW); ++ if (IS_ERR(pcie->wifi_reset)) { ++ ret = PTR_ERR(pcie->wifi_reset); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, ++ "failed to request WIFI reset gpio\n"); ++ return ret; ++ } ++ } ++ + return 0; + } + diff --git a/mieru/.github/workflows/mihomo.yaml b/mieru/.github/workflows/mihomo.yaml index 293080fd1b..1aed4bf7cc 100644 --- a/mieru/.github/workflows/mihomo.yaml +++ b/mieru/.github/workflows/mihomo.yaml @@ -1,5 +1,15 @@ name: 'mihomo test' -on: [workflow_dispatch] +on: + workflow_dispatch: + inputs: + repository: + description: 'mihomo repository (e.g. MetaCubeX/mihomo)' + required: true + default: 'MetaCubeX/mihomo' + branch: + description: 'Branch to checkout' + required: true + default: 'Alpha' jobs: mihomo-test: runs-on: ubuntu-latest @@ -12,8 +22,8 @@ jobs: - name: Check out mihomo repository code uses: actions/checkout@v6 with: - repository: MetaCubeX/mihomo - ref: Alpha + repository: ${{ inputs.repository }} + ref: ${{ inputs.branch }} path: mihomo - name: Set up Go uses: actions/setup-go@v6 diff --git a/mihomo/dns/util.go b/mihomo/dns/util.go index ef57a7c24f..de0f65e2db 100644 --- a/mihomo/dns/util.go +++ b/mihomo/dns/util.go @@ -64,6 +64,13 @@ func putMsgToCache(c dnsCache, q D.Question, msg *D.Msg) { return } + msg = msg.Copy() // never modify the original msg + + // OPT RRs MUST NOT be cached, forwarded, or stored in or loaded from master files. + msg.Extra = lo.Filter(msg.Extra, func(rr D.RR, index int) bool { + return rr.Header().Rrtype != D.TypeOPT + }) + var ttl uint32 if msg.Rcode == D.RcodeServerFailure { // [...] a resolver MAY cache a server failure response. @@ -76,13 +83,6 @@ func putMsgToCache(c dnsCache, q D.Question, msg *D.Msg) { return } - msg = msg.Copy() // never modify the original msg - - // OPT RRs MUST NOT be cached, forwarded, or stored in or loaded from master files. - msg.Extra = lo.Filter(msg.Extra, func(rr D.RR, index int) bool { - return rr.Header().Rrtype != D.TypeOPT - }) - c.SetWithExpire(q.String(), msg, time.Now().Add(time.Duration(ttl)*time.Second)) } diff --git a/openwrt-packages/adguardhome/Makefile b/openwrt-packages/adguardhome/Makefile index f86b0a465c..5009da9ab0 100644 --- a/openwrt-packages/adguardhome/Makefile +++ b/openwrt-packages/adguardhome/Makefile @@ -1,22 +1,24 @@ -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# +# SPDX-License-Identifier: GPL-2.0-only include $(TOPDIR)/rules.mk PKG_NAME:=adguardhome PKG_VERSION:=0.107.73 -PKG_RELEASE:=1 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/AdguardTeam/AdGuardHome/tar.gz/v$(PKG_VERSION)? PKG_HASH:=f5f2c97dc1425ba1445d0c4050911e6924f153bd64926f27c677087586f9a4fb PKG_BUILD_DIR:=$(BUILD_DIR)/AdGuardHome-$(PKG_VERSION) +FRONTEND_DEST:=$(PKG_NAME)-frontend-$(PKG_VERSION).tar.gz +FRONTEND_URL:=https://github.com/AdguardTeam/AdGuardHome/releases/download/v$(PKG_VERSION)/ +FRONTEND_HASH:=a69c540fe6959575330bdea150e31eee0c0c204985bf50e3522ce6d292e3c64e + PKG_LICENSE:=GPL-3.0-only PKG_LICENSE_FILES:=LICENSE.txt -PKG_MAINTAINER:=Dobroslaw Kijowski +PKG_CPE_ID:=cpe:/a:adguard:adguardhome +PKG_MAINTAINER:=Dobroslaw Kijowski , George Sapkin PKG_BUILD_DEPENDS:=golang/host PKG_BUILD_PARALLEL:=1 @@ -25,11 +27,10 @@ PKG_BUILD_FLAGS:=no-mips16 GO_PKG:=github.com/AdguardTeam/AdGuardHome GO_PKG_BUILD_PKG:=$(GO_PKG) -AGH_BUILD_TIME:=$(shell date -d @$(SOURCE_DATE_EPOCH) +%FT%TZ%z) GO_PKG_LDFLAGS_X:= \ $(GO_PKG)/internal/version.channel=release \ $(GO_PKG)/internal/version.version=v$(PKG_VERSION) \ - $(GO_PKG)/internal/version.buildtime=$(AGH_BUILD_TIME) \ + $(GO_PKG)/internal/version.committime=$(SOURCE_DATE_EPOCH) \ $(GO_PKG)/internal/version.goarm=$(GO_ARM) \ $(GO_PKG)/internal/version.gomips=$(GO_MIPS) @@ -42,10 +43,11 @@ define Package/adguardhome TITLE:=Network-wide ads and trackers blocking DNS server URL:=https://github.com/AdguardTeam/AdGuardHome DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle + USERID:=adguardhome=853:adguardhome=853 endef define Package/adguardhome/conffiles -/etc/adguardhome.yaml +/etc/adguardhome/adguardhome.yaml /etc/config/adguardhome endef @@ -53,27 +55,35 @@ define Package/adguardhome/description Free and open source, powerful network-wide ads and trackers blocking DNS server. endef -FRONTEND_FILE:=$(PKG_NAME)-frontend-$(PKG_VERSION).tar.gz define Download/adguardhome-frontend - URL:=https://github.com/AdguardTeam/AdGuardHome/releases/download/v$(PKG_VERSION)/ + URL:=$(FRONTEND_URL) URL_FILE:=AdGuardHome_frontend.tar.gz - FILE:=$(FRONTEND_FILE) - HASH:=a69c540fe6959575330bdea150e31eee0c0c204985bf50e3522ce6d292e3c64e + FILE:=$(FRONTEND_DEST) + HASH:=$(FRONTEND_HASH) endef define Build/Prepare $(call Build/Prepare/Default) - gzip -dc $(DL_DIR)/$(FRONTEND_FILE) | $(HOST_TAR) -C $(PKG_BUILD_DIR)/ $(TAR_OPTIONS) + gzip -dc $(DL_DIR)/$(FRONTEND_DEST) | $(HOST_TAR) -C $(PKG_BUILD_DIR)/ $(TAR_OPTIONS) endef define Package/adguardhome/install $(call GoPackage/Package/Install/Bin,$(1)) + $(INSTALL_DIR) $(1)/etc/capabilities + $(INSTALL_CONF) ./files/adguardhome.json $(1)/etc/capabilities/adguardhome.json + + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) ./files/adguardhome.conf $(1)/etc/config/adguardhome + $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_BIN) ./files/adguardhome.init $(1)/etc/init.d/adguardhome - $(INSTALL_DIR) $(1)/etc/config - $(INSTALL_DATA) ./files/adguardhome.config $(1)/etc/config/adguardhome + $(INSTALL_DIR) $(1)/etc/sysctl.d + $(INSTALL_CONF) ./files/adguardhome.sysctl $(1)/etc/sysctl.d/50-adguardhome.conf + + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_BIN) ./files/adguardhome.defaults $(1)/etc/uci-defaults/adguardhome endef $(eval $(call Download,adguardhome-frontend)) diff --git a/openwrt-packages/adguardhome/files/adguardhome.conf b/openwrt-packages/adguardhome/files/adguardhome.conf new file mode 100644 index 0000000000..41bb3644af --- /dev/null +++ b/openwrt-packages/adguardhome/files/adguardhome.conf @@ -0,0 +1,30 @@ + +config adguardhome 'config' + option enabled '0' + # All paths must be readable by the configured user + option config_file '/etc/adguardhome/adguardhome.yaml' + # Where to store persistent data by AdGuard Home + option work_dir '/var/lib/adguardhome' + option user 'adguardhome' + option group 'adguardhome' + option verbose '0' + + # Files and directories that AdGuard Home has read-only access to + # list jail_mount '/etc/ssl/adguardhome.crt' + # list jail_mount '/etc/ssl/adguardhome.key' + + # Files and directories that AdGuard Home has read-write access to + # list jail_mount_rw '/path/to/dir' + + # Advanced options. Modify at your own risk. + + # More info: https://go.dev/doc/gc-guide#GOGC + option gc '0' + + # Max number of OS threads to use + # 0 to match the number of CPUs (default) + # >0 to explicitly specify concurrency + option maxprocs '0' + + # Soft memory limit in MB, 0 to disable + option memlimit '0' diff --git a/openwrt-packages/adguardhome/files/adguardhome.config b/openwrt-packages/adguardhome/files/adguardhome.config deleted file mode 100644 index a9558020bb..0000000000 --- a/openwrt-packages/adguardhome/files/adguardhome.config +++ /dev/null @@ -1,4 +0,0 @@ -config adguardhome config - option enabled '0' - # Where to store persistent data by AdGuard Home - option workdir /var/adguardhome diff --git a/openwrt-packages/adguardhome/files/adguardhome.defaults b/openwrt-packages/adguardhome/files/adguardhome.defaults new file mode 100644 index 0000000000..d19d531eee --- /dev/null +++ b/openwrt-packages/adguardhome/files/adguardhome.defaults @@ -0,0 +1,109 @@ +#!/bin/sh +# +# SPDX-License-Identifier: GPL-2.0-only + +# Migrate old config format only +OLD_CONFIG_FILE=$(uci -q get adguardhome.config.config) +OLD_CONFIG_FILE=${OLD_CONFIG_FILE:-/etc/adguardhome.yaml} +OLD_CONFIG_NEW_OPT_FILE=$(uci -q get adguardhome.config.config_file) +NEW_CONFIG_DIR=/etc/adguardhome +NEW_CONFIG_FILE="$NEW_CONFIG_DIR/adguardhome.yaml" + +start_service() { + if ! /etc/init.d/adguardhome running; then + /etc/init.d/adguardhome start + fi +} + +stop_service() { + if /etc/init.d/adguardhome running; then + /etc/init.d/adguardhome stop + fi +} + +if [ -f "$OLD_CONFIG_NEW_OPT_FILE" ] && [ "$OLD_CONFIG_NEW_OPT_FILE" != "$NEW_CONFIG_FILE" ]; then + echo "Old AdGuard Home config found in '$OLD_CONFIG_NEW_OPT_FILE'" + + USER=$(uci -q get adguardhome.config.user) + USER=${USER:-adguardhome} + + echo "AdGuard Home config is stored in a non-default path." + echo "Ensure configured service user '$USER' can access it." + +elif [ -f "$OLD_CONFIG_FILE" ] && [ "$OLD_CONFIG_FILE" != "$NEW_CONFIG_FILE" ]; then + echo "Old AdGuard Home config found in '$OLD_CONFIG_FILE'" + OLD_CONFIG_DIR=$(dirname "$OLD_CONFIG_FILE") + + USER=$(uci -q get adguardhome.config.user) + USER=${USER:-adguardhome} + GROUP=$(uci -q get adguardhome.config.group) + GROUP=${GROUP:-adguardhome} + + CUR_CONFIG_FILE="$OLD_CONFIG_FILE" + if [ "$OLD_CONFIG_DIR" = "/etc" ]; then + echo "AdGuard Home config must be stored in its own directory. Migrating..." + stop_service + + echo "Using $USER:$GROUP for file ownership." + + [ -d "$NEW_CONFIG_DIR" ] || mkdir -m 0700 -p "$NEW_CONFIG_DIR" + mv "$OLD_CONFIG_FILE" "$NEW_CONFIG_FILE" + chown -R "$USER":"$GROUP" "$NEW_CONFIG_DIR" + CUR_CONFIG_FILE="$NEW_CONFIG_FILE" + + echo "Config migrated to '$NEW_CONFIG_FILE'" + + else + echo "AdGuard Home config is stored in a non-default path." + echo "Ensure configured service user '$USER' can access it." + fi + + uci set adguardhome.config.config_file="$CUR_CONFIG_FILE" + uci -q delete adguardhome.config.config + + # Use awk to split match on :, remove double quotes and trim leading and + # trailing spaces + cert_path=$(grep certificate_path: "$CUR_CONFIG_FILE" \ + | awk -F':' '{gsub(/"/, "", $2); gsub(/^ +| +$/, "", $2); print $2}') + if [ -n "$cert_path" ]; then + echo "Found custom 'certificate_path' pointing to '$cert_path'." \ + + "Ensure configured service user '$USER' can access it." + + stop_service + + if ! uci -q show adguardhome.config.jail_mount | grep -q "$cert_path"; then + uci add_list adguardhome.config.jail_mount="$cert_path" + fi + fi + + private_key_path=$(grep private_key_path: "$CUR_CONFIG_FILE" \ + | awk -F':' '{gsub(/"/, "", $2); gsub(/^ +| +$/, "", $2); print $2}') + if [ -n "$private_key_path" ]; then + echo "Found custom 'private_key_path' pointing to '$private_key_path'." \ + + "Ensure configured service user '$USER' can access it." + + stop_service + + if ! uci -q show adguardhome.config.jail_mount | grep -q "$private_key_path"; then + uci add_list adguardhome.config.jail_mount="$private_key_path" + fi + fi + + uci commit adguardhome + start_service + +elif [ -z "$OLD_CONFIG_NEW_OPT_FILE" ] && [ "$OLD_CONFIG_FILE" != "$NEW_CONFIG_FILE" ]; then + echo "Old AdGuard Home config not found in '$OLD_CONFIG_FILE'" + stop_service + + # Service script will create the new config directory + uci set adguardhome.config.config_file="$NEW_CONFIG_FILE" + uci -q delete adguardhome.config.config + echo "Config path changed to '$NEW_CONFIG_FILE'" + + uci commit adguardhome + start_service + +else + echo "AdGuard Home config is in its default path '$NEW_CONFIG_FILE'" +fi diff --git a/openwrt-packages/adguardhome/files/adguardhome.init b/openwrt-packages/adguardhome/files/adguardhome.init index 270353c3aa..43db94bbb4 100644 --- a/openwrt-packages/adguardhome/files/adguardhome.init +++ b/openwrt-packages/adguardhome/files/adguardhome.init @@ -1,25 +1,111 @@ #!/bin/sh /etc/rc.common +# +# SPDX-License-Identifier: GPL-2.0-only +# +# shellcheck disable=SC3043 # ash supports local -PROG=/usr/bin/AdGuardHome - -USE_PROCD=1 - -# starts just after network starts to avoid some network race conditions -START=25 +# matches dnsmasq +START=19 # stops before networking stops STOP=89 -start_service() { - config_load adguardhome - config_get_bool enabled config enabled - config_get WORK_DIR config workdir +PROG=/usr/bin/AdGuardHome +USE_PROCD=1 - [ "$enabled" -eq "1" ] || exit 2 - [ -d "$WORK_DIR" ] || mkdir -m 0755 -p "$WORK_DIR" - - procd_open_instance - procd_set_param command "$PROG" -c /etc/adguardhome.yaml -w "$WORK_DIR" --no-check-update - procd_set_param stdout 1 - procd_set_param stderr 1 - procd_close_instance +boot() { + ADGUARDHOME_BOOT=1 + start "$@" +} + +start_service() { + if [ -n "$ADGUARDHOME_BOOT" ]; then + # Do not start yet, wait for triggers + return 0 + fi + + config_load 'adguardhome' + + local config_name='config' + local config_file config group user verbose work_dir workdir + local enabled gc maxprocs memlimit + + uci_validate_section 'adguardhome' 'adguardhome' "$config_name" \ + 'enabled:bool:0' \ + 'gc:uinteger:0' \ + 'group:string:adguardhome' \ + 'config:string' \ + 'config_file:string:/etc/adguardhome/adguardhome.yaml' \ + 'jail_mount:list(string)' \ + 'jail_mount_rw:list(string)' \ + 'maxprocs:uinteger:0' \ + 'memlimit:uinteger:0' \ + 'user:string:adguardhome' \ + 'verbose:bool:0' \ + 'workdir:string' \ + 'work_dir:string:/var/lib/adguardhome' + + [ "$enabled" -eq "1" ] || return 1 + + # Compatibility with older configs + [ -n "$config" ] && config_file="$config" + [ -n "$workdir" ] && work_dir="$workdir" + + local config_dir + config_dir=$(dirname "$config_file") + if [ "$config_dir" = '/etc' ]; then + echo 'AdGuard Home config must be stored in its own directory, and not in /etc' >&2 + return 1 + fi + mkdir -m 0700 -p "$config_dir" + chown -R "$user":"$group" "$config_dir" + + mkdir -m 0700 -p "$work_dir" + chown -R "$user":"$group" "$work_dir" + + procd_open_instance adguardhome + + procd_set_param command "$PROG" + + [ "$gc" -le 0 ] || procd_append_param env GOGC="$gc" + [ "$maxprocs" -le 0 ] || procd_append_param env GOMAXPROCS="$maxprocs" + [ "$memlimit" -le 0 ] || procd_append_param env GOMEMLIMIT="$memlimit" + + procd_append_param command --config "$config_file" + procd_append_param command --logfile syslog + procd_append_param command --no-check-update + [ "$verbose" = 1 ] && procd_append_param command --verbose + procd_append_param command --work-dir "$work_dir" + + procd_set_param stdout 1 + procd_set_param stderr 1 + procd_set_param user "$user" + procd_set_param group "$group" + procd_set_param capabilities '/etc/capabilities/adguardhome.json' + procd_set_param no_new_privs 1 + procd_set_param respawn + + # log is needed for logging to syslog instead of stdout + # procfs is needed to readlink /proc/self/exe + procd_add_jail adguardhome log procfs + + # config directory must be writable to write new config files + procd_add_jail_mount_rw "$config_dir" + procd_add_jail_mount_rw "$work_dir" + + procd_add_jail_mount '/etc/hosts' + procd_add_jail_mount '/etc/ssl/certs' + config_list_foreach "$config_name" jail_mount procd_add_jail_mount + config_list_foreach "$config_name" jail_mount_rw procd_add_jail_mount_rw + + procd_close_instance +} + +service_triggers() { + procd_add_reload_trigger adguardhome + + if [ -n "$ADGUARDHOME_BOOT" ]; then + # Wait for interfaces to be up before starting AdGuard Home for real. + # Prevents issues like https://github.com/openwrt/packages/issues/21868. + procd_add_raw_trigger 'interface.*.up' 5000 /etc/init.d/adguardhome restart + fi } diff --git a/openwrt-packages/adguardhome/files/adguardhome.json b/openwrt-packages/adguardhome/files/adguardhome.json new file mode 100644 index 0000000000..3586a4ae9e --- /dev/null +++ b/openwrt-packages/adguardhome/files/adguardhome.json @@ -0,0 +1,22 @@ +{ + "bounding": [ + "CAP_NET_BIND_SERVICE", + "CAP_NET_RAW" + ], + "effective": [ + "CAP_NET_BIND_SERVICE", + "CAP_NET_RAW" + ], + "ambient": [ + "CAP_NET_BIND_SERVICE", + "CAP_NET_RAW" + ], + "permitted": [ + "CAP_NET_BIND_SERVICE", + "CAP_NET_RAW" + ], + "inheritable": [ + "CAP_NET_BIND_SERVICE", + "CAP_NET_RAW" + ] +} diff --git a/openwrt-packages/adguardhome/files/adguardhome.sysctl b/openwrt-packages/adguardhome/files/adguardhome.sysctl new file mode 100644 index 0000000000..dfc1698af1 --- /dev/null +++ b/openwrt-packages/adguardhome/files/adguardhome.sysctl @@ -0,0 +1,3 @@ +# quic-go expects larger UDP send/receive buffers +net.core.rmem_max = 7500000 +net.core.wmem_max = 7500000 diff --git a/openwrt-packages/luci-app-adguardhome/Makefile b/openwrt-packages/luci-app-adguardhome/Makefile index 62b2c5ad74..628ea93ec3 100644 --- a/openwrt-packages/luci-app-adguardhome/Makefile +++ b/openwrt-packages/luci-app-adguardhome/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 2018-2019 Lienol +# Copyright (C) 2018-2024 OpenWrt luci-app-adguardhome contributors # # This is free software, licensed under the Apache License, Version 2.0 . # @@ -6,7 +6,9 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-adguardhome -PKG_MAINTAINER:= +PKG_MAINTAINER:=kenzok8 +PKG_VERSION:=1.0 +PKG_RELEASE:=1 LUCI_TITLE:=LuCI app for AdGuardHome LUCI_PKGARCH:=all @@ -29,24 +31,26 @@ endef define Package/luci-app-adguardhome/postinst #!/bin/sh /etc/init.d/AdGuardHome enable >/dev/null 2>&1 - enable=$(uci get AdGuardHome.AdGuardHome.enabled 2>/dev/null) - if [ "$enable" == "1" ]; then - /etc/init.d/AdGuardHome reload - fi + enable="$(uci get AdGuardHome.AdGuardHome.enabled 2>/dev/null)" + [ "$enable" = "1" ] && /etc/init.d/AdGuardHome reload >/dev/null 2>&1 rm -f /tmp/luci-indexcache - rm -f /tmp/luci-modulecache/* + rm -f /tmp/luci-modulecache/* 2>/dev/null exit 0 endef define Package/luci-app-adguardhome/prerm #!/bin/sh if [ -z "$${IPKG_INSTROOT}" ]; then - /etc/init.d/AdGuardHome disable - /etc/init.d/AdGuardHome stop -uci -q batch <<-EOF >/dev/null 2>&1 - delete ucitrack.@AdGuardHome[-1] - commit ucitrack -EOF + /etc/init.d/AdGuardHome disable >/dev/null 2>&1 + /etc/init.d/AdGuardHome stop >/dev/null 2>&1 + ucitrack_del() { + local name="$1" + local track="$(uci show ucitrack 2>/dev/null | grep -F "$name\." | head -1)" + [ -n "$track" ] && uci -q del "$track" 2>/dev/null + } + ucitrack_del "AdGuardHome" + [ -n "$(uci show ucitrack 2>/dev/null | grep -c 'AdGuardHome')" ] || true + uci commit ucitrack 2>/dev/null fi exit 0 endef diff --git a/openwrt-packages/luci-app-adguardhome/README.md b/openwrt-packages/luci-app-adguardhome/README.md new file mode 100644 index 0000000000..a8b7939ec2 --- /dev/null +++ b/openwrt-packages/luci-app-adguardhome/README.md @@ -0,0 +1,145 @@ +# luci-app-adguardhome + +适用于 OpenWrt/Lede 的 AdGuard Home LuCI 控制面板插件。 + +## 功能特性 + +- **基础配置**: 核心路径、配置文件路径、工作目录、日志路径、Web 管理端口等 +- **多种重定向模式**: 无重定向、作为 dnsmasq 上游、重定向 53 端口、替换 dnsmasq +- **核心自动更新**: 支持从 GitHub releases 自动下载更新 +- **UPX 压缩**: 下载后可自动使用 UPX 压缩二进制文件节省空间 +- **GFW 列表管理**: 自动从 gfwlist 生成 AdGuard Home 规则 +- **IPv6 主机同步**: 自动同步 LAN 中的 IPv6 设备到 hosts +- **计划任务**: 自动更新核心、GFW 列表、清理日志 +- **备份与恢复**: 关机时自动备份工作目录文件 +- **Web 管理**: 实时状态监控、日志查看、配置编辑 + +## 依赖 + +- `luci` +- `luci-base` +- `ca-certs` +- `curl` +- `wget-ssl` + +## 安装 + +### OpenWrt Feed 方式 + +```bash +# 添加 feed +echo 'src-git adguardhome https://github.com/kenzok78/luci-app-adguardhome' >> feeds.conf.default +./scripts/feeds update -a +./scripts/feeds install -a -p adguardhome + +# 编译 +make package/luci-app-adguardhome/compile V=s +``` + +### 直接编译 + +```bash +# 克隆到 package 目录 +git clone https://github.com/kenzok78/luci-app-adguardhome.git package/luci-app-adguardhome +make menuconfig # 选择 LuCI -> Applications -> luci-app-adguardhome +make -j$(nproc) V=s +``` + +## 使用说明 + +### 基本配置 + +1. 访问 OpenWrt Web 管理界面 → 服务 → AdGuard Home +2. 启用插件 +3. 设置核心路径(默认 `/usr/bin/AdGuardHome`) +4. 配置重定向模式 + +### 重定向模式说明 + +| 模式 | 说明 | +|------|------| +| 无 | 仅运行 AdGuard Home,不拦截任何 DNS 请求 | +| 作为 dnsmasq 上游 | 将 dnsmasq 的上游 DNS 指向 AdGuard Home | +| 重定向 53 端口 | 通过 iptables 重定向本机 53 端口到 AdGuard Home | +| 替换 dnsmasq | 使用 AdGuard Home 的 53 端口替换 dnsmasq | + +### 更新核心 + +在基础设置页面点击"更新核心版本",或通过定时任务自动更新。 + +### GFW 列表 + +点击"添加 GFW 列表"自动从 gfwlist 生成 AdGuard Home 规则。 + +## 配置示例 + +### /etc/config/AdGuardHome + +``` +config AdGuardHome 'AdGuardHome' + option enabled '0' + option httpport '3000' + option redirect 'none' + option configpath '/etc/AdGuardHome.yaml' + option workdir '/etc/AdGuardHome' + option logfile '/tmp/AdGuardHome.log' + option binpath '/usr/bin/AdGuardHome' +``` + +### /etc/AdGuardHome.yaml + +```yaml +bind_host: 0.0.0.0 +bind_port: 3000 +dns: + bind_hosts: + - 0.0.0.0 + port: 53 + upstream_dns: + - 223.5.5.5 + - 119.29.29.29 +``` + +## 目录结构 + +``` +luci-app-adguardhome/ +├──luasrc/ +│ ├── controller/ # LuCI 控制器 +│ ├── model/cbi/ # CBI 模型 +│ └── view/ # HTML 视图模板 +├── po/ # 翻译文件 +├── root/ +│ ├── etc/ +│ │ ├── config/ # UCI 配置 +│ │ └── init.d/ # 启动脚本 +│ └── usr/share/ # 辅助脚本 +└── Makefile +``` + +## 常见问题 + +### Q: 更新核心失败怎么办? + +检查网络连接,确保可以访问 GitHub。也可以手动下载核心并放置到指定路径。 + +### Q: 如何查看实时日志? + +通过 LuCI 界面的日志页面查看,或: + +```bash +logread -e AdGuardHome +``` + +### Q: 开机后 AdGuard Home 不自动启动? + +检查"开机后网络就绪时重启"选项是否启用,或手动执行 `/etc/init.d/AdGuardHome enable`。 + +## 许可证 + +Apache-2.0 + +## 来源 + +- [AdGuard Home](https://github.com/AdguardTeam/AdGuardHome) +- 基于 [rufengsuixing/luci-app-adguardhome](https://github.com/rufengsuixing/luci-app-adguardhome) 维护 diff --git a/openwrt-packages/luci-app-adguardhome/luasrc/controller/AdGuardHome.lua b/openwrt-packages/luci-app-adguardhome/luasrc/controller/AdGuardHome.lua index e9d37a766b..62f3d4919c 100644 --- a/openwrt-packages/luci-app-adguardhome/luasrc/controller/AdGuardHome.lua +++ b/openwrt-packages/luci-app-adguardhome/luasrc/controller/AdGuardHome.lua @@ -1,130 +1,193 @@ -module("luci.controller.AdGuardHome",package.seeall) -local fs=require"nixio.fs" -local http=require"luci.http" -local uci=require"luci.model.uci".cursor() +module("luci.controller.AdGuardHome", package.seeall) + +local fs = require "nixio.fs" +local http = require "luci.http" +local uci = require "luci.model.uci".cursor() + function index() -local page = entry({"admin", "services", "AdGuardHome"},alias("admin", "services", "AdGuardHome", "base"),_("AdGuard Home")) -page.order = 10 -page.dependent = true -page.acl_depends = { "luci-app-adguardhome" } -entry({"admin","services","AdGuardHome","base"},cbi("AdGuardHome/base"),_("Base Setting"),1).leaf = true -entry({"admin","services","AdGuardHome","log"},form("AdGuardHome/log"),_("Log"),2).leaf = true -entry({"admin","services","AdGuardHome","manual"},cbi("AdGuardHome/manual"),_("Manual Config"),3).leaf = true -entry({"admin","services","AdGuardHome","status"},call("act_status")).leaf=true -entry({"admin", "services", "AdGuardHome", "check"}, call("check_update")) -entry({"admin", "services", "AdGuardHome", "doupdate"}, call("do_update")) -entry({"admin", "services", "AdGuardHome", "getlog"}, call("get_log")) -entry({"admin", "services", "AdGuardHome", "dodellog"}, call("do_dellog")) -entry({"admin", "services", "AdGuardHome", "reloadconfig"}, call("reload_config")) -entry({"admin", "services", "AdGuardHome", "gettemplateconfig"}, call("get_template_config")) + local page = entry({"admin", "services", "AdGuardHome"}, + alias("admin", "services", "AdGuardHome", "base"), + _("AdGuard Home"), 10) + page.dependent = true + page.acl_depends = { "luci-app-adguardhome" } + + entry({"admin", "services", "AdGuardHome", "base"}, + cbi("AdGuardHome/base"), _("Base Setting"), 1).leaf = true + entry({"admin", "services", "AdGuardHome", "log"}, + form("AdGuardHome/log"), _("Log"), 2).leaf = true + entry({"admin", "services", "AdGuardHome", "manual"}, + cbi("AdGuardHome/manual"), _("Manual Config"), 3).leaf = true + + entry({"admin", "services", "AdGuardHome", "status"}, + call("act_status"), nil).leaf = true + entry({"admin", "services", "AdGuardHome", "check"}, + call("check_update"), nil) + entry({"admin", "services", "AdGuardHome", "doupdate"}, + call("do_update"), nil) + entry({"admin", "services", "AdGuardHome", "getlog"}, + call("get_log"), nil) + entry({"admin", "services", "AdGuardHome", "dodellog"}, + call("do_dellog"), nil) + entry({"admin", "services", "AdGuardHome", "reloadconfig"}, + call("reload_config"), nil) + entry({"admin", "services", "AdGuardHome", "gettemplateconfig"}, + call("get_template_config"), nil) end -function get_template_config() - local b - local d="" - for cnt in io.lines("/tmp/resolv.conf.d/resolv.conf.auto") do - b=string.match (cnt,"^[^#]*nameserver%s+([^%s]+)$") - if (b~=nil) then - d=d.." - "..b.."\n" + +local function gen_template_config() + local dns_servers = "" + local resolv_auto = "/tmp/resolv.conf.d/resolv.conf.auto" + if fs.access(resolv_auto) then + for line in io.lines(resolv_auto) do + local ns = line:match("^[^#]*nameserver%s+([^%s]+)") + if ns then + dns_servers = dns_servers .. " - " .. ns .. "\n" + end end end - local f=io.open("/usr/share/AdGuardHome/AdGuardHome_template.yaml", "r+") - local tbl = {} - local a="" - while (1) do - a=f:read("*l") - if (a=="#bootstrap_dns") then - a=d - elseif (a=="#upstream_dns") then - a=d - elseif (a==nil) then - break + + local tmpl = "/usr/share/AdGuardHome/AdGuardHome_template.yaml" + local f = io.open(tmpl, "r") + if not f then return "" end + + local lines = {} + for line in f:lines() do + if line == "#bootstrap_dns" then + table.insert(lines, dns_servers) + elseif line == "#upstream_dns" then + table.insert(lines, dns_servers) + else + table.insert(lines, line) end - table.insert(tbl, a) end f:close() - http.prepare_content("text/plain; charset=utf-8") - http.write(table.concat(tbl, "\n")) + return table.concat(lines, "\n") end + +function get_template_config() + http.prepare_content("text/plain; charset=utf-8") + http.write(gen_template_config()) +end + function reload_config() fs.remove("/tmp/AdGuardHometmpconfig.yaml") http.prepare_content("application/json") - http.write('') + http.write('{}') end + function act_status() - local e={} - local binpath=uci:get("AdGuardHome","AdGuardHome","binpath") - e.running=luci.sys.call("pgrep "..binpath.." >/dev/null")==0 - e.redirect=(fs.readfile("/var/run/AdGredir")=="1") - http.prepare_content("application/json") - http.write_json(e) -end -function do_update() - fs.writefile("/var/run/lucilogpos","0") - http.prepare_content("application/json") - http.write('') - local arg - if luci.http.formvalue("force") == "1" then - arg="force" + local result = {} + local binpath = uci:get("AdGuardHome", "AdGuardHome", "binpath") or "/usr/bin/AdGuardHome" + + if fs.access(binpath) then + result.running = (luci.sys.call("pgrep -f '" .. binpath .. "' >/dev/null 2>&1") == 0) else - arg="" + result.running = false end + + local redir = fs.readfile("/var/run/AdGredir") + result.redirect = (redir == "1") + + http.prepare_content("application/json") + http.write_json(result) +end + +function do_update() + fs.writefile("/var/run/lucilogpos", "0") + http.prepare_content("application/json") + http.write('{}') + + local arg = "" + if luci.http.formvalue("force") == "1" then + arg = "force" + end + + local script = "/usr/share/AdGuardHome/update_core.sh" if fs.access("/var/run/update_core") then - if arg=="force" then - luci.sys.exec("kill $(pgrep /usr/share/AdGuardHome/update_core.sh) ; sh /usr/share/AdGuardHome/update_core.sh "..arg.." >/tmp/AdGuardHome_update.log 2>&1 &") + if arg == "force" then + luci.sys.exec("pkill -f '" .. script .. "' 2>/dev/null; " .. script .. " " .. arg .. " >/tmp/AdGuardHome_update.log 2>&1 &") end else - luci.sys.exec("sh /usr/share/AdGuardHome/update_core.sh "..arg.." >/tmp/AdGuardHome_update.log 2>&1 &") + luci.sys.exec(script .. " " .. arg .. " >/tmp/AdGuardHome_update.log 2>&1 &") end end + function get_log() - local logfile=uci:get("AdGuardHome","AdGuardHome","logfile") - if (logfile==nil) then + local logfile = uci:get("AdGuardHome", "AdGuardHome", "logfile") + + if not logfile or logfile == "" then http.write("no log available\n") return - elseif (logfile=="syslog") then + end + + if logfile == "syslog" then if not fs.access("/var/run/AdGuardHomesyslog") then luci.sys.exec("(/usr/share/AdGuardHome/getsyslog.sh &); sleep 1;") end - logfile="/tmp/AdGuardHometmp.log" - fs.writefile("/var/run/AdGuardHomesyslog","1") + logfile = "/tmp/AdGuardHometmp.log" + fs.writefile("/var/run/AdGuardHomesyslog", "1") elseif not fs.access(logfile) then http.write("") return end + http.prepare_content("text/plain; charset=utf-8") - local fdp + + local fdp = 0 if fs.access("/var/run/lucilogreload") then - fdp=0 + fdp = 0 fs.remove("/var/run/lucilogreload") else - fdp=tonumber(fs.readfile("/var/run/lucilogpos")) or 0 + local pos = fs.readfile("/var/run/lucilogpos") + fdp = tonumber(pos) or 0 end - local f=io.open(logfile, "r+") - f:seek("set",fdp) - local a=f:read(2048000) or "" - fdp=f:seek() - fs.writefile("/var/run/lucilogpos",tostring(fdp)) + + local f = io.open(logfile, "r") + if not f then + http.write("") + return + end + + f:seek("set", fdp) + local content = f:read(2048000) or "" + fdp = f:seek() f:close() - http.write(a) + + fs.writefile("/var/run/lucilogpos", tostring(fdp)) + http.write(content) end + function do_dellog() - local logfile=uci:get("AdGuardHome","AdGuardHome","logfile") - fs.writefile(logfile,"") + local logfile = uci:get("AdGuardHome", "AdGuardHome", "logfile") + if logfile and logfile ~= "" and logfile ~= "syslog" then + fs.writefile(logfile, "") + end http.prepare_content("application/json") - http.write('') + http.write('{}') end + function check_update() http.prepare_content("text/plain; charset=utf-8") - local fdp=tonumber(fs.readfile("/var/run/lucilogpos")) or 0 - local f=io.open("/tmp/AdGuardHome_update.log", "r+") - f:seek("set",fdp) - local a=f:read(2048000) or "" - fdp=f:seek() - fs.writefile("/var/run/lucilogpos",tostring(fdp)) + + local pos = fs.readfile("/var/run/lucilogpos") + local fdp = tonumber(pos) or 0 + + local f = io.open("/tmp/AdGuardHome_update.log", "r") + if not f then + http.write("") + return + end + + f:seek("set", fdp) + local content = f:read(2048000) or "" + fdp = f:seek() f:close() -if fs.access("/var/run/update_core") then - http.write(a) -else - http.write(a.."\0") -end + + fs.writefile("/var/run/lucilogpos", tostring(fdp)) + + if fs.access("/var/run/update_core") then + http.write(content) + else + http.write(content .. "\0") + end end diff --git a/openwrt-packages/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/base.lua b/openwrt-packages/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/base.lua index 6896b61eff..5120b0cd36 100644 --- a/openwrt-packages/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/base.lua +++ b/openwrt-packages/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/base.lua @@ -1,90 +1,96 @@ require("luci.sys") require("luci.util") require("io") -local m,s,o,o1 -local fs=require"nixio.fs" -local uci=require"luci.model.uci".cursor() -local configpath=uci:get("AdGuardHome","AdGuardHome","configpath") or "/etc/AdGuardHome.yaml" -local binpath=uci:get("AdGuardHome","AdGuardHome","binpath") or "/usr/bin/AdGuardHome" -httpport=uci:get("AdGuardHome","AdGuardHome","httpport") or "3000" + +local m, s, o, o1 +local fs = require "nixio.fs" +local uci = require "luci.model.uci".cursor() + +local configpath = uci:get("AdGuardHome", "AdGuardHome", "configpath") or "/etc/AdGuardHome.yaml" +local binpath = uci:get("AdGuardHome", "AdGuardHome", "binpath") or "/usr/bin/AdGuardHome" +local httpport = uci:get("AdGuardHome", "AdGuardHome", "httpport") or "3000" + m = Map("AdGuardHome", "AdGuard Home") m.description = translate("Free and open source, powerful network-wide ads & trackers blocking DNS server.") -m:section(SimpleSection).template = "AdGuardHome/AdGuardHome_status" +m:section(SimpleSection).template = "AdGuardHome/AdGuardHome_status" s = m:section(TypedSection, "AdGuardHome") -s.anonymous=true -s.addremove=false ----- enable +s.anonymous = true +s.addremove = false + o = s:option(Flag, "enabled", translate("Enable")) -o.default = 0 +o.default = "0" o.optional = false ----- httpport -o =s:option(Value,"httpport",translate("Browser management port")) -o.placeholder=3000 -o.default=3000 -o.datatype="port" + +o = s:option(Value, "httpport", translate("Browser management port")) +o.placeholder = "3000" +o.default = "3000" +o.datatype = "port" o.optional = false -o.description = translate("") ----- update warning not safe -local binmtime=uci:get("AdGuardHome","AdGuardHome","binmtime") or "0" -local e="" +o.description = translate("") + +local binmtime = uci:get("AdGuardHome", "AdGuardHome", "binmtime") or "0" +local version_info = "" + if not fs.access(configpath) then - e=e.." "..translate("no config") + version_info = translate("no config") end + if not fs.access(binpath) then - e=e.." "..translate("no core") + version_info = version_info .. " " .. translate("no core") else - local version=uci:get("AdGuardHome","AdGuardHome","version") - local testtime=fs.stat(binpath,"mtime") - if testtime~=tonumber(binmtime) or version==nil then - local tmp=luci.sys.exec(binpath.." --version | grep -m 1 -E 'v[0-9.]+' -o ") - version=string.sub(tmp, 1) - if version=="" then version="core error" end - uci:set("AdGuardHome","AdGuardHome","version",version) - uci:set("AdGuardHome","AdGuardHome","binmtime",testtime) + local version = uci:get("AdGuardHome", "AdGuardHome", "version") + local testtime = fs.stat(binpath, "mtime") + if testtime ~= tonumber(binmtime) or not version then + local tmp = luci.sys.exec(binpath .. " --version 2>/dev/null | grep -oE 'v[0-9.]+' | head -1") + version = tmp:match("v[0-9.]+") or "core error" + if version == "core error" or version == "" then + version = "core error" + end + uci:set("AdGuardHome", "AdGuardHome", "version", version) + uci:set("AdGuardHome", "AdGuardHome", "binmtime", testtime) uci:save("AdGuardHome") end - e=version..e + version_info = version .. version_info end -o=s:option(Button,"restart",translate("Update")) -o.inputtitle=translate("Update core version") + +o = s:option(Button, "restart", translate("Update")) +o.inputtitle = translate("Update core version") o.template = "AdGuardHome/AdGuardHome_check" -o.showfastconfig=(not fs.access(configpath)) -o.description=string.format(translate("core version:").."%s ",e) ----- port warning not safe -local port=luci.sys.exec("awk '/ port:/{printf($2);exit;}' "..configpath.." 2>nul") -if (port=="") then port="?" end ----- Redirect -o = s:option(ListValue, "redirect", port..translate("Redirect"), translate("AdGuardHome redirect mode")) +o.showfastconfig = not fs.access(configpath) +o.description = string.format(translate("core version:") .. "%s", version_info) + +local port = luci.sys.exec("awk '/^ port:/{print $2;exit}' " .. configpath .. " 2>/dev/null") +if not port or port == "" then + port = "?" +end + +o = s:option(ListValue, "redirect", port .. translate("Redirect"), translate("AdGuardHome redirect mode")) o.placeholder = "none" o:value("none", translate("none")) o:value("dnsmasq-upstream", translate("Run as dnsmasq upstream server")) o:value("redirect", translate("Redirect 53 port to AdGuardHome")) o:value("exchange", translate("Use port 53 replace dnsmasq")) -o.default = "none" +o.default = "none" o.optional = true ----- bin path + o = s:option(Value, "binpath", translate("Bin Path"), translate("AdGuardHome Bin path if no bin will auto download")) -o.default = "/usr/bin/AdGuardHome" -o.datatype = "string" +o.default = "/usr/bin/AdGuardHome" +o.datatype = "string" o.optional = false -o.rmempty=false -o.validate=function(self, value) -if value=="" then return nil end -if fs.stat(value,"type")=="dir" then - fs.rmdir(value) -end -if fs.stat(value,"type")=="dir" then - if (m.message) then - m.message =m.message.."\nerror!bin path is a dir" - else - m.message ="error!bin path is a dir" +o.rmempty = false +o.validate = function(self, value) + if value == "" then return nil end + if fs.stat(value, "type") == "dir" then + fs.rmdir(value) end - return nil + if fs.stat(value, "type") == "dir" then + m.message = (m.message or "") .. "\nerror: bin path is a directory" + return nil + end + return value end -return value -end ---- upx + o = s:option(ListValue, "upxflag", translate("use upx to compress bin after download")) o:value("", translate("none")) o:value("-1", translate("compress faster")) @@ -92,213 +98,209 @@ o:value("-9", translate("compress better")) o:value("--best", translate("compress best(can be slow for big files)")) o:value("--brute", translate("try all available compression methods & filters [slow]")) o:value("--ultra-brute", translate("try even more compression variants [very slow]")) -o.default = "" -o.description=translate("bin use less space,but may have compatibility issues") +o.default = "" +o.description = translate("bin use less space,but may have compatibility issues") o.rmempty = true ----- config path + o = s:option(Value, "configpath", translate("Config Path"), translate("AdGuardHome config path")) -o.default = "/etc/AdGuardHome.yaml" -o.datatype = "string" +o.default = "/etc/AdGuardHome.yaml" +o.datatype = "string" o.optional = false -o.rmempty=false -o.validate=function(self, value) -if value==nil then return nil end -if fs.stat(value,"type")=="dir" then - fs.rmdir(value) -end -if fs.stat(value,"type")=="dir" then - if m.message then - m.message =m.message.."\nerror!config path is a dir" - else - m.message ="error!config path is a dir" +o.rmempty = false +o.validate = function(self, value) + if not value then return nil end + if fs.stat(value, "type") == "dir" then + fs.rmdir(value) end - return nil -end -return value -end ----- work dir -o = s:option(Value, "workdir", translate("Work dir"), translate("AdGuardHome work dir include rules,audit log and database")) -o.default = "/etc/AdGuardHome" -o.datatype = "string" -o.optional = false -o.rmempty=false -o.validate=function(self, value) -if value=="" then return nil end -if fs.stat(value,"type")=="reg" then - if m.message then - m.message =m.message.."\nerror!work dir is a file" - else - m.message ="error!work dir is a file" + if fs.stat(value, "type") == "dir" then + m.message = (m.message or "") .. "\nerror: config path is a directory" + return nil end - return nil -end -if string.sub(value, -1)=="/" then - return string.sub(value, 1, -2) -else return value end -end ----- log file -o = s:option(Value, "logfile", translate("Runtime log file"), translate("AdGuardHome runtime Log file if 'syslog': write to system log;if empty no log")) -o.datatype = "string" -o.rmempty = true -o.validate=function(self, value) -if fs.stat(value,"type")=="dir" then - fs.rmdir(value) -end -if fs.stat(value,"type")=="dir" then - if m.message then - m.message =m.message.."\nerror!log file is a dir" - else - m.message ="error!log file is a dir" + +o = s:option(Value, "workdir", translate("Work dir"), translate("AdGuardHome work dir include rules,audit log and database")) +o.default = "/etc/AdGuardHome" +o.datatype = "string" +o.optional = false +o.rmempty = false +o.validate = function(self, value) + if value == "" then return nil end + if fs.stat(value, "type") == "reg" then + m.message = (m.message or "") .. "\nerror: work dir is a file" + return nil end - return nil + if value:sub(-1) == "/" then + return value:sub(1, -2) + end + return value end -return value + +o = s:option(Value, "logfile", translate("Runtime log file"), translate("AdGuardHome runtime Log file if 'syslog': write to system log;if empty no log")) +o.datatype = "string" +o.rmempty = true +o.validate = function(self, value) + if value and value ~= "" and fs.stat(value, "type") == "dir" then + fs.rmdir(value) + end + if value and value ~= "" and fs.stat(value, "type") == "dir" then + m.message = (m.message or "") .. "\nerror: log file is a directory" + return nil + end + return value end ----- debug + o = s:option(Flag, "verbose", translate("Verbose log")) -o.default = 0 +o.default = "0" o.optional = true ----- gfwlist -local a=luci.sys.call("grep -m 1 -q programadd "..configpath) -if (a==0) then -a="Added" + +local gfw_status +if fs.access(configpath) and luci.sys.call("grep -q 'programaddstart' " .. configpath .. " 2>/dev/null") == 0 then + gfw_status = translate("Added") else -a="Not added" + gfw_status = translate("Not added") end -o=s:option(Button,"gfwdel",translate("Del gfwlist"),translate(a)) + +o = s:option(Button, "gfwdel", translate("Del gfwlist"), gfw_status) o.optional = true -o.inputtitle=translate("Del") -o.write=function() +o.inputtitle = translate("Del") +o.write = function() luci.sys.exec("sh /usr/share/AdGuardHome/gfw2adg.sh del 2>&1") - luci.http.redirect(luci.dispatcher.build_url("admin","services","AdGuardHome")) + luci.http.redirect(luci.dispatcher.build_url("admin", "services", "AdGuardHome")) end -o=s:option(Button,"gfwadd",translate("Add gfwlist"),translate(a)) + +o = s:option(Button, "gfwadd", translate("Add gfwlist"), gfw_status) o.optional = true -o.inputtitle=translate("Add") -o.write=function() +o.inputtitle = translate("Add") +o.write = function() luci.sys.exec("sh /usr/share/AdGuardHome/gfw2adg.sh 2>&1") - luci.http.redirect(luci.dispatcher.build_url("admin","services","AdGuardHome")) + luci.http.redirect(luci.dispatcher.build_url("admin", "services", "AdGuardHome")) end -o = s:option(Value, "gfwupstream", translate("Gfwlist upstream dns server"), translate("Gfwlist domain upstream dns service")..translate(a)) -o.default = "tcp://208.67.220.220:5353" -o.datatype = "string" + +o = s:option(Value, "gfwupstream", translate("Gfwlist upstream dns server"), translate("Gfwlist domain upstream dns service") .. " (" .. gfw_status .. ")") +o.default = "tcp://208.67.220.220:5353" +o.datatype = "string" o.optional = true ----- chpass + o = s:option(Value, "hashpass", translate("Change browser management password"), translate("Press load culculate model and culculate finally save/apply")) -o.default = "" -o.datatype = "string" +o.default = "" +o.datatype = "string" o.template = "AdGuardHome/AdGuardHome_chpass" o.optional = true ----- upgrade protect + o = s:option(MultiValue, "upprotect", translate("Keep files when system upgrade")) -o:value("$binpath",translate("core bin")) -o:value("$configpath",translate("config file")) -o:value("$logfile",translate("log file")) -o:value("$workdir/data/sessions.db",translate("sessions.db")) -o:value("$workdir/data/stats.db",translate("stats.db")) -o:value("$workdir/data/querylog.json",translate("querylog.json")) -o:value("$workdir/data/filters",translate("filters")) +o:value("$binpath", translate("core bin")) +o:value("$configpath", translate("config file")) +o:value("$logfile", translate("log file")) +o:value("$workdir/data/sessions.db", translate("sessions.db")) +o:value("$workdir/data/stats.db", translate("stats.db")) +o:value("$workdir/data/querylog.json", translate("querylog.json")) +o:value("$workdir/data/filters", translate("filters")) o.widget = "checkbox" o.default = nil -o.optional=true ----- wait net on boot -o = s:option(Flag, "waitonboot", translate("On boot when network ok restart")) -o.default = 1 o.optional = true ----- backup workdir on shutdown -local workdir=uci:get("AdGuardHome","AdGuardHome","workdir") or "/etc/AdGuardHome" + +o = s:option(Flag, "waitonboot", translate("On boot when network ok restart")) +o.default = "1" +o.optional = true + +local workdir = uci:get("AdGuardHome", "AdGuardHome", "workdir") or "/etc/AdGuardHome" o = s:option(MultiValue, "backupfile", translate("Backup workdir files when shutdown")) o1 = s:option(Value, "backupwdpath", translate("Backup workdir path")) local name -o:value("filters","filters") -o:value("stats.db","stats.db") -o:value("querylog.json","querylog.json") -o:value("sessions.db","sessions.db") -o1:depends ("backupfile", "filters") -o1:depends ("backupfile", "stats.db") -o1:depends ("backupfile", "querylog.json") -o1:depends ("backupfile", "sessions.db") -for name in fs.glob(workdir.."/data/*") -do - name=fs.basename (name) - if name~="filters" and name~="stats.db" and name~="querylog.json" and name~="sessions.db" then - o:value(name,name) - o1:depends ("backupfile", name) + +o:value("filters", "filters") +o:value("stats.db", "stats.db") +o:value("querylog.json", "querylog.json") +o:value("sessions.db", "sessions.db") + +o1:depends("backupfile", "filters") +o1:depends("backupfile", "stats.db") +o1:depends("backupfile", "querylog.json") +o1:depends("backupfile", "sessions.db") + +if fs.access(workdir .. "/data") then + for name in fs.glob(workdir .. "/data/*") do + local basename = fs.basename(name) + if basename ~= "filters" and basename ~= "stats.db" and basename ~= "querylog.json" and basename ~= "sessions.db" then + o:value(basename, basename) + o1:depends("backupfile", basename) + end end end + o.widget = "checkbox" o.default = nil -o.optional=false -o.description=translate("Will be restore when workdir/data is empty") -----backup workdir path +o.optional = false +o.description = translate("Will be restore when workdir/data is empty") -o1.default = "/etc/AdGuardHome" -o1.datatype = "string" +o1.default = "/etc/AdGuardHome" +o1.datatype = "string" o1.optional = false -o1.validate=function(self, value) -if fs.stat(value,"type")=="reg" then - if m.message then - m.message =m.message.."\nerror!backup dir is a file" - else - m.message ="error!backup dir is a file" +o1.validate = function(self, value) + if value and value ~= "" and fs.stat(value, "type") == "reg" then + m.message = (m.message or "") .. "\nerror: backup dir is a file" + return nil + end + if value and value:sub(-1) == "/" then + return value:sub(1, -2) end - return nil -end -if string.sub(value,-1)=="/" then - return string.sub(value, 1, -2) -else return value end -end -----Crontab -o = s:option(MultiValue, "crontab", translate("Crontab task"),translate("Please change time and args in crontab")) -o:value("autoupdate",translate("Auto update core")) -o:value("cutquerylog",translate("Auto tail querylog")) -o:value("cutruntimelog",translate("Auto tail runtime log")) -o:value("autohost",translate("Auto update ipv6 hosts and restart adh")) -o:value("autogfw",translate("Auto update gfwlist and restart adh")) +o = s:option(MultiValue, "crontab", translate("Crontab task"), translate("Please change time and args in crontab")) +o:value("autoupdate", translate("Auto update core")) +o:value("cutquerylog", translate("Auto tail querylog")) +o:value("cutruntimelog", translate("Auto tail runtime log")) +o:value("autohost", translate("Auto update ipv6 hosts and restart adh")) +o:value("autogfw", translate("Auto update gfwlist and restart adh")) o.widget = "checkbox" o.default = nil -o.optional=true +o.optional = true -----downloadpath -o = s:option(TextValue, "downloadlinks",translate("Download links for update")) +o = s:option(TextValue, "downloadlinks", translate("Download links for update")) o.optional = false o.rows = 4 o.wrap = "soft" o.cfgvalue = function(self, section) - return fs.readfile("/usr/share/AdGuardHome/links.txt") + if fs.access("/usr/share/AdGuardHome/links.txt") then + return fs.readfile("/usr/share/AdGuardHome/links.txt") + end + return "" end o.write = function(self, section, value) - fs.writefile("/usr/share/AdGuardHome/links.txt", value:gsub("\r\n", "\n")) + if value then + fs.writefile("/usr/share/AdGuardHome/links.txt", value:gsub("\r\n", "\n")) + end end -fs.writefile("/var/run/lucilogpos","0") + +fs.writefile("/var/run/lucilogpos", "0") + function m.on_commit(map) - if (fs.access("/var/run/AdGserverdis")) then + if fs.access("/var/run/AdGserverdis") then io.popen("/etc/init.d/AdGuardHome reload &") return end - local ucitracktest=uci:get("AdGuardHome","AdGuardHome","ucitracktest") - if ucitracktest=="1" then + + local ucitracktest = uci:get("AdGuardHome", "AdGuardHome", "ucitracktest") + if ucitracktest == "1" then return - elseif ucitracktest=="0" then + elseif ucitracktest == "0" then io.popen("/etc/init.d/AdGuardHome reload &") else - if (fs.access("/var/run/AdGlucitest")) then - uci:set("AdGuardHome","AdGuardHome","ucitracktest","0") + if fs.access("/var/run/AdGlucitest") then + uci:set("AdGuardHome", "AdGuardHome", "ucitracktest", "0") io.popen("/etc/init.d/AdGuardHome reload &") else - fs.writefile("/var/run/AdGlucitest","") - if (ucitracktest=="2") then - uci:set("AdGuardHome","AdGuardHome","ucitracktest","1") + fs.writefile("/var/run/AdGlucitest", "") + if ucitracktest == "2" then + uci:set("AdGuardHome", "AdGuardHome", "ucitracktest", "1") else - uci:set("AdGuardHome","AdGuardHome","ucitracktest","2") + uci:set("AdGuardHome", "AdGuardHome", "ucitracktest", "2") end end uci:save("AdGuardHome") end end + return m diff --git a/openwrt-packages/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/manual.lua b/openwrt-packages/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/manual.lua index ecf072bbc7..3113095634 100644 --- a/openwrt-packages/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/manual.lua +++ b/openwrt-packages/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/manual.lua @@ -1,97 +1,119 @@ local m, s, o local fs = require "nixio.fs" -local uci=require"luci.model.uci".cursor() -local sys=require"luci.sys" +local uci = require "luci.model.uci".cursor() +local sys = require "luci.sys" require("string") require("io") require("table") -function gen_template_config() - local b - local d="" - for cnt in io.lines("/tmp/resolv.conf.d/resolv.conf.auto") do - b=string.match (cnt,"^[^#]*nameserver%s+([^%s]+)$") - if (b~=nil) then - d=d.." - "..b.."\n" - end - end - local f=io.open("/usr/share/AdGuardHome/AdGuardHome_template.yaml", "r+") - local tbl = {} - local a="" - while (1) do - a=f:read("*l") - if (a=="#bootstrap_dns") then - a=d - elseif (a=="#upstream_dns") then - a=d - elseif (a==nil) then - break - end - table.insert(tbl, a) - end - f:close() - return table.concat(tbl, "\n") -end + m = Map("AdGuardHome") -local configpath = uci:get("AdGuardHome","AdGuardHome","configpath") -local binpath = uci:get("AdGuardHome","AdGuardHome","binpath") + +local configpath = uci:get("AdGuardHome", "AdGuardHome", "configpath") or "/etc/AdGuardHome.yaml" +local binpath = uci:get("AdGuardHome", "AdGuardHome", "binpath") or "/usr/bin/AdGuardHome" + s = m:section(TypedSection, "AdGuardHome") -s.anonymous=true -s.addremove=false ---- config +s.anonymous = true +s.addremove = false + o = s:option(TextValue, "escconf") o.rows = 66 o.wrap = "off" o.rmempty = true + o.cfgvalue = function(self, section) - return fs.readfile("/tmp/AdGuardHometmpconfig.yaml") or fs.readfile(configpath) or gen_template_config() or "" + local tmp = fs.readfile("/tmp/AdGuardHometmpconfig.yaml") + if tmp then return tmp end + + local cfg = fs.readfile(configpath) + if cfg then return cfg end + + local dns_servers = "" + local resolv_auto = "/tmp/resolv.conf.d/resolv.conf.auto" + if fs.access(resolv_auto) then + for line in io.lines(resolv_auto) do + local ns = line:match("^[^#]*nameserver%s+([^%s]+)") + if ns then + dns_servers = dns_servers .. " - " .. ns .. "\n" + end + end + end + + local tmpl = "/usr/share/AdGuardHome/AdGuardHome_template.yaml" + local f = io.open(tmpl, "r") + if not f then return "" end + + local lines = {} + for line in f:lines() do + if line == "#bootstrap_dns" then + table.insert(lines, dns_servers) + elseif line == "#upstream_dns" then + table.insert(lines, dns_servers) + else + table.insert(lines, line) + end + end + f:close() + return table.concat(lines, "\n") end -o.validate=function(self, value) - fs.writefile("/tmp/AdGuardHometmpconfig.yaml", value:gsub("\r\n", "\n")) + +o.validate = function(self, value) + if not value then return nil end + fs.writefile("/tmp/AdGuardHometmpconfig.yaml", value:gsub("\r\n", "\n")) + if fs.access(binpath) then - if (sys.call(binpath.." -c /tmp/AdGuardHometmpconfig.yaml --check-config 2> /tmp/AdGuardHometest.log")==0) then + local ret = sys.call(binpath .. " -c /tmp/AdGuardHometmpconfig.yaml --check-config 2>/tmp/AdGuardHometest.log") + if ret == 0 then return value end else return value end - luci.http.redirect(luci.dispatcher.build_url("admin","services","AdGuardHome","manual")) + + luci.http.redirect(luci.dispatcher.build_url("admin", "services", "AdGuardHome", "manual")) return nil end + o.write = function(self, section, value) - fs.move("/tmp/AdGuardHometmpconfig.yaml",configpath) + if fs.access("/tmp/AdGuardHometmpconfig.yaml") then + fs.move("/tmp/AdGuardHometmpconfig.yaml", configpath) + end end + o.remove = function(self, section, value) fs.writefile(configpath, "") end ---- js and reload button + o = s:option(DummyValue, "") -o.anonymous=true +o.anonymous = true o.template = "AdGuardHome/yamleditor" + if not fs.access(binpath) then - o.description=translate("WARNING!!! no bin found apply config will not be test") + o.description = translate("WARNING: no binary found, config validation will be skipped") end ---- log -if (fs.access("/tmp/AdGuardHometmpconfig.yaml")) then -local c=fs.readfile("/tmp/AdGuardHometest.log") -if (c~="") then -o = s:option(TextValue, "") -o.readonly=true -o.rows = 5 -o.rmempty = true -o.name="" -o.cfgvalue = function(self, section) - return fs.readfile("/tmp/AdGuardHometest.log") -end -end -end -function m.on_commit(map) - local ucitracktest=uci:get("AdGuardHome","AdGuardHome","ucitracktest") - if ucitracktest=="1" then - return - elseif ucitracktest=="0" then - io.popen("/etc/init.d/AdGuardHome reload &") - else - fs.writefile("/var/run/AdGlucitest","") + +if fs.access("/tmp/AdGuardHometest.log") then + local errlog = fs.readfile("/tmp/AdGuardHometest.log") + if errlog and errlog ~= "" then + o = s:option(TextValue, "") + o.readonly = true + o.rows = 5 + o.rmempty = true + o.name = "" + o.cfgvalue = function(self, section) + return fs.readfile("/tmp/AdGuardHometest.log") + end end end + +function m.on_commit(map) + local ucitracktest = uci:get("AdGuardHome", "AdGuardHome", "ucitracktest") + if ucitracktest == "1" then + return + elseif ucitracktest == "0" then + io.popen("/etc/init.d/AdGuardHome reload &") + else + fs.writefile("/var/run/AdGlucitest", "") + end +end + return m diff --git a/openwrt-packages/luci-app-adguardhome/po/zh_Hans/adguardhome.po b/openwrt-packages/luci-app-adguardhome/po/zh_Hans/adguardhome.po index 0ace89bae4..dc476dc21e 100644 --- a/openwrt-packages/luci-app-adguardhome/po/zh_Hans/adguardhome.po +++ b/openwrt-packages/luci-app-adguardhome/po/zh_Hans/adguardhome.po @@ -1,408 +1,278 @@ msgid "" msgstr "" "Content-Type: text/plain; charset=UTF-8\n" -"Project-Id-Version: PACKAGE VERSION\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"Project-Id-Version: luci-app-adguardhome\n" +"PO-Revision-Date: 2024\n" +"Last-Translator: kenzok8\n" +"Language-Team: Chinese\n" "Language: zh_Hans\n" "MIME-Version: 1.0\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" -#: /mnt/A/openwrt-latest/package/ctcgfw/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/base.lua:27 -msgid "" -"/dev/null 2>&1 - if [ $? -eq 0 ]; then - return - fi + local addr="127.0.0.1#$PORT" + local OLD_SERVER="$(uci get dhcp.@dnsmasq[0].server 2>/dev/null)" + echo "$OLD_SERVER" | grep -q "^$addr" + [ $? -eq 0 ] && return + uci delete dhcp.@dnsmasq[0].server 2>/dev/null - uci add_list dhcp.@dnsmasq[0].server=$addr + uci add_list dhcp.@dnsmasq[0].server="$addr" for server in $OLD_SERVER; do - if [ "$server" = "$addr" ]; then - continue - fi - # uci add_list dhcp.@dnsmasq[0].server=$server + [ "$server" = "$addr" ] && continue done uci delete dhcp.@dnsmasq[0].resolvfile 2>/dev/null uci set dhcp.@dnsmasq[0].noresolv=1 @@ -40,16 +36,14 @@ set_forward_dnsmasq() stop_forward_dnsmasq() { local OLD_PORT="$1" - addr="127.0.0.1#$OLD_PORT" - OLD_SERVER="`uci get dhcp.@dnsmasq[0].server 2>/dev/null`" - echo $OLD_SERVER | grep "^$addr" >/dev/null 2>&1 - if [ $? -ne 0 ]; then - return - fi + local addr="127.0.0.1#$OLD_PORT" + local OLD_SERVER="$(uci get dhcp.@dnsmasq[0].server 2>/dev/null)" + echo "$OLD_SERVER" | grep -q "^$addr" + [ $? -ne 0 ] && return - uci del_list dhcp.@dnsmasq[0].server=$addr 2>/dev/null - addrlist="`uci get dhcp.@dnsmasq[0].server 2>/dev/null`" - if [ -z "$addrlist" ] ; then + uci del_list dhcp.@dnsmasq[0].server="$addr" 2>/dev/null + local addrlist="$(uci get dhcp.@dnsmasq[0].server 2>/dev/null)" + if [ -z "$addrlist" ]; then uci set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.d/resolv.conf.auto 2>/dev/null uci delete dhcp.@dnsmasq[0].noresolv 2>/dev/null fi @@ -59,8 +53,9 @@ stop_forward_dnsmasq() set_iptable() { - local ipv6_server=$1 - local tcp_server=$2 + local ipv6_server="$1" + local tcp_server="$2" + uci -q batch <<-EOF >/dev/null 2>&1 delete firewall.AdGuardHome set firewall.AdGuardHome=include @@ -68,28 +63,22 @@ set_iptable() set firewall.AdGuardHome.path=/usr/share/AdGuardHome/firewall.start set firewall.AdGuardHome.reload=1 commit firewall -EOF + EOF - IPS="`ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F : '{print $2}'`" - for IP in $IPS - do - if [ "$tcp_server" == "1" ]; then - iptables -t nat -I PREROUTING -p tcp -d $IP --dport 53 -j REDIRECT --to-ports $AdGuardHome_PORT >/dev/null 2>&1 - fi - iptables -t nat -I PREROUTING -p udp -d $IP --dport 53 -j REDIRECT --to-ports $AdGuardHome_PORT >/dev/null 2>&1 + local IPS="$(ip -4 addr show | grep inet | grep -v ':' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1)" + for IP in $IPS; do + [ -z "$IP" ] && continue + iptables -t nat -I PREROUTING -p udp -d "$IP" --dport 53 -j REDIRECT --to-ports "$AdGuardHome_PORT" >/dev/null 2>&1 + [ "$tcp_server" = "1" ] && iptables -t nat -I PREROUTING -p tcp -d "$IP" --dport 53 -j REDIRECT --to-ports "$AdGuardHome_PORT" >/dev/null 2>&1 done - if [ "$ipv6_server" == 0 ]; then - return - fi + [ "$ipv6_server" = "0" ] && return - IPS="`ifconfig | grep "inet6 addr" | grep -v " fe80::" | grep -v " ::1" | grep "Global" | awk '{print $3}'`" - for IP in $IPS - do - if [ "$tcp_server" == "1" ]; then - ip6tables -t nat -I PREROUTING -p tcp -d $IP --dport 53 -j REDIRECT --to-ports $AdGuardHome_PORT >/dev/null 2>&1 - fi - ip6tables -t nat -I PREROUTING -p udp -d $IP --dport 53 -j REDIRECT --to-ports $AdGuardHome_PORT >/dev/null 2>&1 + IPS="$(ip -6 addr show | grep inet6 | grep -v 'fe80::' | grep -v '::1' | grep 'Global' | awk '{print $2}' | cut -d'/' -f1)" + for IP in $IPS; do + [ -z "$IP" ] && continue + ip6tables -t nat -I PREROUTING -p udp -d "$IP" --dport 53 -j REDIRECT --to-ports "$AdGuardHome_PORT" >/dev/null 2>&1 + [ "$tcp_server" = "1" ] && ip6tables -t nat -I PREROUTING -p tcp -d "$IP" --dport 53 -j REDIRECT --to-ports "$AdGuardHome_PORT" >/dev/null 2>&1 done } @@ -98,113 +87,115 @@ clear_iptable() uci -q batch <<-EOF >/dev/null 2>&1 delete firewall.AdGuardHome commit firewall -EOF + EOF + local OLD_PORT="$1" - local ipv6_server=$2 - IPS="`ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F : '{print $2}'`" - for IP in $IPS - do - iptables -t nat -D PREROUTING -p udp -d $IP --dport 53 -j REDIRECT --to-ports $OLD_PORT >/dev/null 2>&1 - iptables -t nat -D PREROUTING -p tcp -d $IP --dport 53 -j REDIRECT --to-ports $OLD_PORT >/dev/null 2>&1 + local ipv6_server="$2" + local IPS="$(ip -4 addr show | grep inet | grep -v ':' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1)" + for IP in $IPS; do + [ -z "$IP" ] && continue + iptables -t nat -D PREROUTING -p udp -d "$IP" --dport 53 -j REDIRECT --to-ports "$OLD_PORT" >/dev/null 2>&1 + iptables -t nat -D PREROUTING -p tcp -d "$IP" --dport 53 -j REDIRECT --to-ports "$OLD_PORT" >/dev/null 2>&1 done - if [ "$ipv6_server" == 0 ]; then - return - fi + [ "$ipv6_server" = "0" ] && return echo "warn ip6tables nat mod is needed" - IPS="`ifconfig | grep "inet6 addr" | grep -v " fe80::" | grep -v " ::1" | grep "Global" | awk '{print $3}'`" - for IP in $IPS - do - ip6tables -t nat -D PREROUTING -p udp -d $IP --dport 53 -j REDIRECT --to-ports $OLD_PORT >/dev/null 2>&1 - ip6tables -t nat -D PREROUTING -p tcp -d $IP --dport 53 -j REDIRECT --to-ports $OLD_PORT >/dev/null 2>&1 + IPS="$(ip -6 addr show | grep inet6 | grep -v 'fe80::' | grep -v '::1' | grep 'Global' | awk '{print $2}' | cut -d'/' -f1)" + for IP in $IPS; do + [ -z "$IP" ] && continue + ip6tables -t nat -D PREROUTING -p udp -d "$IP" --dport 53 -j REDIRECT --to-ports "$OLD_PORT" >/dev/null 2>&1 + ip6tables -t nat -D PREROUTING -p tcp -d "$IP" --dport 53 -j REDIRECT --to-ports "$OLD_PORT" >/dev/null 2>&1 done } service_triggers() { procd_add_reload_trigger "$CONFIGURATION" - [ "$(uci get AdGuardHome.AdGuardHome.redirect)" == "redirect" ] && procd_add_reload_trigger firewall + [ "$(uci get AdGuardHome.AdGuardHome.redirect 2>/dev/null)" = "redirect" ] && procd_add_reload_trigger firewall } isrunning(){ config_load "${CONFIGURATION}" _isrunning local r=$? - ([ "$r" == "0" ] && echo "running") || ([ "$r" == "1" ] && echo "not run" ) || echo "no bin" + if [ "$r" = "0" ]; then + echo "running" + elif [ "$r" = "1" ]; then + echo "not run" + else + echo "no bin" + fi return $r } _isrunning(){ config_get binpath $CONFIGURATION binpath "/usr/bin/AdGuardHome" [ ! -f "$binpath" ] && return 2 - pgrep $binpath 2>&1 >/dev/null && return 0 + pgrep -f "$binpath" >/dev/null 2>&1 && return 0 return 1 } force_reload(){ config_load "${CONFIGURATION}" - _isrunning && procd_send_signal "$CONFIGURATION" || start + if _isrunning; then + procd_send_signal "$CONFIGURATION" + else + start + fi } get_tz() { SET_TZ="" - if [ -e "/etc/localtime" ]; then - return - fi + [ -e "/etc/localtime" ] && return - for tzfile in /etc/TZ /var/etc/TZ - do - if [ ! -e "$tzfile" ]; then - continue - fi - - tz="`cat $tzfile 2>/dev/null`" + for tzfile in /etc/TZ /var/etc/TZ; do + [ ! -e "$tzfile" ] && continue + tz="$(cat "$tzfile" 2>/dev/null)" done - if [ -z "$tz" ]; then - return - fi - - SET_TZ=$tz + [ -z "$tz" ] && return + SET_TZ="$tz" } rm_port53() { - local AdGuardHome_PORT=$(config_editor "dns.port" "" "$configpath" "1") - dnsmasq_port=$(uci get dhcp.@dnsmasq[0].port 2>/dev/null) - if [ -z "$dnsmasq_port" ]; then - dnsmasq_port="53" - fi - if [ "$dnsmasq_port" == "$AdGuardHome_PORT" ]; then - if [ "$dnsmasq_port" == "53" ]; then - dnsmasq_port="1745" - fi - elif [ "$dnsmasq_port" == "53" ]; then + local AdGuardHome_PORT + AdGuardHome_PORT="$(config_editor "dns.port" "" "$configpath" "1")" + local dnsmasq_port="$(uci get dhcp.@dnsmasq[0].port 2>/dev/null)" + [ -z "$dnsmasq_port" ] && dnsmasq_port="53" + + if [ "$dnsmasq_port" = "$AdGuardHome_PORT" ]; then + [ "$dnsmasq_port" = "53" ] && dnsmasq_port="1745" + elif [ "$dnsmasq_port" = "53" ]; then return fi + config_editor "dns.port" "$dnsmasq_port" "$configpath" uci set dhcp.@dnsmasq[0].port="53" uci commit dhcp + config_get binpath $CONFIGURATION binpath "/usr/bin/AdGuardHome" - killall -9 $binpath + local binname="${binpath##*/}" + pkill -TERM -f "$binname" 2>/dev/null + sleep 2 + pkill -KILL -f "$binname" 2>/dev/null /etc/init.d/dnsmasq restart } use_port53() { - local AdGuardHome_PORT=$(config_editor "dns.port" "" "$configpath" "1") - dnsmasq_port=$(uci get dhcp.@dnsmasq[0].port 2>/dev/null) - if [ -z "$dnsmasq_port" ]; then - dnsmasq_port="53" - fi - if [ "$dnsmasq_port" == "$AdGuardHome_PORT" ]; then - if [ "$dnsmasq_port" == "53" ]; then - AdGuardHome_PORT="1745" - fi - elif [ "$AdGuardHome_PORT" == "53" ]; then + local AdGuardHome_PORT + AdGuardHome_PORT="$(config_editor "dns.port" "" "$configpath" "1")" + local dnsmasq_port="$(uci get dhcp.@dnsmasq[0].port 2>/dev/null)" + [ -z "$dnsmasq_port" ] && dnsmasq_port="53" + + if [ "$dnsmasq_port" = "$AdGuardHome_PORT" ]; then + [ "$dnsmasq_port" = "53" ] && AdGuardHome_PORT="1745" + elif [ "$AdGuardHome_PORT" = "53" ]; then return fi + config_editor "dns.port" "53" "$configpath" uci set dhcp.@dnsmasq[0].port="$AdGuardHome_PORT" uci commit dhcp @@ -214,53 +205,55 @@ use_port53() do_redirect() { config_load "${CONFIGURATION}" - _do_redirect $1 + _do_redirect "$1" } _do_redirect() { local section="$CONFIGURATION" - args="" ipv6_server=1 tcp_server=0 - enabled=$1 - if [ "$enabled" == "1" ]; then - echo -n "1">/var/run/AdGredir + local enabled="$1" + + if [ "$enabled" = "1" ]; then + echo -n "1" > /var/run/AdGredir else - echo -n "0">/var/run/AdGredir - fi - config_get configpath $CONFIGURATION configpath "/etc/AdGuardHome.yaml" - AdGuardHome_PORT=$(config_editor "dns.port" "" "$configpath" "1") - if [ ! -s "$configpath" ]; then - cp -f /usr/share/AdGuardHome/AdGuardHome_template.yaml $configpath - fi - if [ -z "$AdGuardHome_PORT" ]; then - AdGuardHome_PORT="0" - fi - config_get "redirect" "$section" "redirect" "none" - config_get "old_redirect" "$section" "old_redirect" "none" - config_get "old_port" "$section" "old_port" "0" - config_get "old_enabled" "$section" "old_enabled" "0" - uci get dhcp.@dnsmasq[0].port >/dev/null 2>&1 || uci set dhcp.@dnsmasq[0].port="53" >/dev/null 2>&1 - if [ "$old_enabled" = "1" -a "$old_redirect" == "exchange" ]; then - AdGuardHome_PORT=$(uci get dhcp.@dnsmasq[0].port 2>/dev/null) + echo -n "0" > /var/run/AdGredir fi - if [ "$old_redirect" != "$redirect" ] || [ "$old_port" != "$AdGuardHome_PORT" ] || [ "$old_enabled" = "1" -a "$enabled" = "0" ]; then + config_get configpath $CONFIGURATION configpath "/etc/AdGuardHome.yaml" + AdGuardHome_PORT="$(config_editor "dns.port" "" "$configpath" "1")" + + [ ! -s "$configpath" ] && cp -f /usr/share/AdGuardHome/AdGuardHome_template.yaml "$configpath" + [ -z "$AdGuardHome_PORT" ] && AdGuardHome_PORT="0" + + config_get redirect "$section" redirect "none" + config_get old_redirect "$section" old_redirect "none" + config_get old_port "$section" old_port "0" + config_get old_enabled "$section" old_enabled "0" + + uci get dhcp.@dnsmasq[0].port >/dev/null 2>&1 || uci set dhcp.@dnsmasq[0].port="53" >/dev/null 2>&1 + + if [ "$old_enabled" = "1" ] && [ "$old_redirect" = "exchange" ]; then + AdGuardHome_PORT="$(uci get dhcp.@dnsmasq[0].port 2>/dev/null)" + fi + + if [ "$old_redirect" != "$redirect" ] || [ "$old_port" != "$AdGuardHome_PORT" ] || { [ "$old_enabled" = "1" ] && [ "$enabled" = "0" ]; }; then if [ "$old_redirect" != "none" ]; then - if [ "$old_redirect" == "redirect" -a "$old_port" != "0" ]; then + if [ "$old_redirect" = "redirect" ] && [ "$old_port" != "0" ]; then clear_iptable "$old_port" "$ipv6_server" - elif [ "$old_redirect" == "dnsmasq-upstream" ]; then + elif [ "$old_redirect" = "dnsmasq-upstream" ]; then stop_forward_dnsmasq "$old_port" - elif [ "$old_redirect" == "exchange" ]; then + elif [ "$old_redirect" = "exchange" ]; then rm_port53 fi fi - elif [ "$old_enabled" = "1" -a "$enabled" = "1" ]; then - if [ "$old_redirect" == "redirect" -a "$old_port" != "0" ]; then + elif [ "$old_enabled" = "1" ] && [ "$enabled" = "1" ]; then + if [ "$old_redirect" = "redirect" ] && [ "$old_port" != "0" ]; then clear_iptable "$old_port" "$ipv6_server" fi fi + uci delete AdGuardHome.@AdGuardHome[0].old_redirect 2>/dev/null uci delete AdGuardHome.@AdGuardHome[0].old_port 2>/dev/null uci delete AdGuardHome.@AdGuardHome[0].old_enabled 2>/dev/null @@ -268,103 +261,120 @@ _do_redirect() uci add_list AdGuardHome.@AdGuardHome[0].old_port="$AdGuardHome_PORT" 2>/dev/null uci add_list AdGuardHome.@AdGuardHome[0].old_enabled="$enabled" 2>/dev/null uci commit AdGuardHome - [ "$enabled" == "0" ] && return 1 - if [ "$AdGuardHome_PORT" == "0" ]; then - return 1 - fi + + [ "$enabled" = "0" ] && return 1 + [ "$AdGuardHome_PORT" = "0" ] && return 1 + if [ "$redirect" = "redirect" ]; then - set_iptable $ipv6_server $tcp_server + set_iptable "$ipv6_server" "$tcp_server" elif [ "$redirect" = "dnsmasq-upstream" ]; then set_forward_dnsmasq "$AdGuardHome_PORT" - elif [ "$redirect" == "exchange" -a "$(uci get dhcp.@dnsmasq[0].port 2>/dev/null)" == "53" ]; then + elif [ "$redirect" = "exchange" ] && [ "$(uci get dhcp.@dnsmasq[0].port 2>/dev/null)" = "53" ]; then use_port53 fi } get_filesystem() { -# print out path filesystem - echo $1 | awk ' - BEGIN{ - while (("mount"| getline ret) > 0) - { - split(ret,d); - fs[d[3]]=d[5]; - m=index(d[1],":") - if (m==0) - { - pt[d[3]]=d[1] - }else{ - pt[d[3]]=substr(d[1],m+1) - }}}{ - split($0,d,"/"); - if ("/" in fs) - { - result1=fs["/"]; - } - if ("/" in pt) - { - result2=pt["/"]; - } - for (i=2;i<=length(d);i++) - { - p[i]=p[i-1]"/"d[i]; - if (p[i] in fs) - { - result1=fs[p[i]]; - result2=pt[p[i]]; - } - } - if (result2 in fs){ - result=fs[result2]} - else{ - result=result1} - print(result);}' + local path="$1" + local mntpt="" + local fstype="" + + while IFS= read -r line; do + case "$line" in + /dev/root|/dev/ubi0*|/dev/mtdblock*) + continue + ;; + esac + local mp="$(echo "$line" | awk '{print $2}')" + local fs="$(echo "$line" | awk '{print $3}')" + case "$path" in + "$mp"*) + fstype="$fs" + mntpt="$mp" + break + ;; + esac + done < /proc/mounts + + if [ -z "$mntpt" ]; then + mntpt="/" + fstype="$(awk '$2=="/" {print $3}' /proc/mounts)" + fi + + echo "$fstype" } config_editor() { - awk -v yaml="$1" -v value="$2" -v file="$3" -v ro="$4" ' - BEGIN{split(yaml,part,"\.");s="";i=1;l=length(part);} - { - if (match($0,s""part[i]":")) - { - if (i==l) - { - split($0,t,": "); - if (ro==""){ - system("sed -i '\''"FNR"c \\"t[1]": "value"'\'' "file); - }else{ - print(t[2]); + local yaml="$1" + local value="$2" + local file="$3" + local ro="$4" + + if [ "$ro" = "1" ]; then + awk -v yaml="$yaml" ' + BEGIN { + split(yaml, part, "\\.") + i = 1 + l = length(part) + s = "" + } + { + if (match($0, s "" part[i] ":")) { + if (i == l) { + sub(/^[^:]+: */, "") + print + exit } - exit; - } - s=s"[- ]{2}"; - i++; - } - }' $3 + s = s "[- ]{2}" + i++ + } + }' "$file" + else + awk -v yaml="$yaml" -v value="$value" -v file="$file" ' + BEGIN { + split(yaml, part, "\\.") + i = 1 + l = length(part) + s = "" + } + { + if (match($0, s "" part[i] ":")) { + if (i == l) { + sub(/^[^:]+:.*$/, t[1] ": " value) + print > file + exit + } + s = s "[- ]{2}" + i++ + } + }' "$file" + fi } boot_service() { - rm /var/run/AdGserverdis >/dev/null 2>&1 + rm -f /var/run/AdGserverdis >/dev/null 2>&1 config_load "${CONFIGURATION}" config_get waitonboot $CONFIGURATION waitonboot "0" config_get_bool enabled $CONFIGURATION enabled 0 config_get binpath $CONFIGURATION binpath "/usr/bin/AdGuardHome" + [ -f "$binpath" ] && start_service - if [ "$enabled" == "1" ] && [ "$waitonboot" == "1" ]; then - procd_open_instance "waitnet" + + if [ "$enabled" = "1" ] && [ "$waitonboot" = "1" ]; then + procd_open_instance procd_set_param command "/usr/share/AdGuardHome/waitnet.sh" procd_close_instance - echo "no net start pinging" + echo "AdGuardHome: waiting for network..." fi } testbackup(){ config_load "${CONFIGURATION}" - if [ "$1" == "backup" ]; then + if [ "$1" = "backup" ]; then backup - elif [ "$1" == "restore" ]; then + elif [ "$1" = "restore" ]; then restore fi } @@ -373,30 +383,30 @@ restore() { config_get workdir $CONFIGURATION workdir "/etc/AdGuardHome" config_get backupwdpath $CONFIGURATION backupwdpath "/etc/AdGuardHome" - cp -u -r -f $backupwdpath/data $workdir + [ -d "$backupwdpath/data" ] && cp -u -r -f "$backupwdpath/data" "$workdir/" } backup() { config_get backupwdpath $CONFIGURATION backupwdpath "/etc/AdGuardHome" - mkdir -p $backupwdpath/data + mkdir -p "$backupwdpath/data" config_get workdir $CONFIGURATION workdir "/etc/AdGuardHome" config_get backupfile $CONFIGURATION backupfile "" - for one in $backupfile; - do - while : - do + + for one in $backupfile; do + while : ; do + local cpret if [ -d "$backupwdpath/data/$one" ]; then - cpret=$(cp -u -r -f $workdir/data/$one $backupwdpath/data 2>&1) + cpret="$(cp -u -r -f "$workdir/data/$one" "$backupwdpath/data" 2>&1)" else - cpret=$(cp -u -r -f $workdir/data/$one $backupwdpath/data/$one 2>&1) + cpret="$(cp -u -r -f "$workdir/data/$one" "$backupwdpath/data/$one" 2>&1)" fi echo "$cpret" - echo "$cpret" | grep "no space left on device" - if [ "$?" == "0" ]; then - echo "磁盘已满,删除log重试中" + echo "$cpret" | grep -q "no space left on device" + if [ $? -eq 0 ]; then + echo "disk full, deleting querylog and retrying..." del_querylog && continue - rm -f -r $backupwdpath/data/filters - rm -f -r $workdir/data/filters && continue + rm -rf "$backupwdpath/data/filters" + rm -rf "$workdir/data/filters" && continue echo "backup failed" fi break @@ -405,135 +415,151 @@ backup() { } start_service() { - # Reading config - rm /var/run/AdGserverdis >/dev/null 2>&1 + rm -f /var/run/AdGserverdis >/dev/null 2>&1 config_load "${CONFIGURATION}" - # update password + config_get hashpass $CONFIGURATION hashpass "" config_get configpath $CONFIGURATION configpath "/etc/AdGuardHome.yaml" + if [ -n "$hashpass" ]; then config_editor "users.password" "$hashpass" "$configpath" - uci set $CONFIGURATION.$CONFIGURATION.hashpass="" + uci set "$CONFIGURATION"."$CONFIGURATION".hashpass="" + uci commit AdGuardHome fi + local enabled config_get_bool enabled $CONFIGURATION enabled 0 - # update crontab + do_crontab - if [ "$enabled" == "0" ]; then + + if [ "$enabled" = "0" ]; then _do_redirect 0 return fi - #what need to do before reload - config_get workdir $CONFIGURATION workdir "/etc/AdGuardHome" + config_get workdir $CONFIGURATION workdir "/etc/AdGuardHome" config_get backupfile $CONFIGURATION backupfile "" - mkdir -p $workdir/data + mkdir -p "$workdir/data" + if [ -n "$backupfile" ] && [ ! -d "$workdir/data" ]; then restore fi - # for overlay data-stk-oo not suppport - local cwdfs=$(get_filesystem $workdir) - echo "workdir is a $cwdfs filesystem" - if [ "$cwdfs" == "jffs2" ]; then - echo "fs error ln db to tmp $workdir $cwdfs" - logger "AdGuardHome" "warning db redirect to tmp" - touch $workdir/data/stats.db - if [ ! -L $workdir/data/stats.db ]; then - mv -f $workdir/data/stats.db /tmp/stats.db 2>/dev/null - ln -s /tmp/stats.db $workdir/data/stats.db 2>/dev/null - fi - touch $workdir/data/sessions.db - if [ ! -L $workdir/data/sessions.db ]; then - mv -f $workdir/data/sessions.db /tmp/sessions.db 2>/dev/null - ln -s /tmp/sessions.db $workdir/data/sessions.db 2>/dev/null - fi + + local cwdfs + cwdfs="$(get_filesystem "$workdir")" + echo "AdGuardHome: workdir is on $cwdfs filesystem" + if [ "$cwdfs" = "jffs2" ]; then + logger -t AdGuardHome -p daemon.warn "jffs2 detected, redirecting db to tmp" + mkdir -p /tmp/adg_tmp + for db in stats.db sessions.db; do + touch "$workdir/data/$db" + [ ! -L "$workdir/data/$db" ] && mv -f "$workdir/data/$db" "/tmp/adg_tmp/$db" 2>/dev/null + [ ! -e "/tmp/adg_tmp/$db" ] && touch "/tmp/adg_tmp/$db" + [ -f "/tmp/adg_tmp/$db" ] && ln -sf "/tmp/adg_tmp/$db" "$workdir/data/$db" + done fi + local ADDITIONAL_ARGS="" config_get binpath $CONFIGURATION binpath "/usr/bin/AdGuardHome" + mkdir -p "${binpath%/*}" - mkdir -p ${binpath%/*} - ADDITIONAL_ARGS="$ADDITIONAL_ARGS -c $configpath" - ADDITIONAL_ARGS="$ADDITIONAL_ARGS -w $workdir" + ADDITIONAL_ARGS="-c $configpath -w $workdir" config_get httpport $CONFIGURATION httpport 3000 ADDITIONAL_ARGS="$ADDITIONAL_ARGS -p $httpport" - # hack to save config file when upgrade system config_get upprotect $CONFIGURATION upprotect "" - eval upprotect=${upprotect// /\\\\n} - echo -e "$upprotect">/lib/upgrade/keep.d/luci-app-adguardhome + if [ -n "$upprotect" ]; then + { + for item in $upprotect; do + echo "$item" | sed 's/\\n/\n/g' + done + } > /lib/upgrade/keep.d/luci-app-adguardhome + fi config_get logfile $CONFIGURATION logfile "" - if [ -n "$logfile" ]; then - ADDITIONAL_ARGS="$ADDITIONAL_ARGS -l $logfile" - fi + [ -n "$logfile" ] && ADDITIONAL_ARGS="$ADDITIONAL_ARGS -l $logfile" if [ ! -f "$binpath" ]; then _do_redirect 0 - /usr/share/AdGuardHome/update_core.sh 2>&1 >/tmp/AdGuardHome_update.log & + /usr/share/AdGuardHome/update_core.sh >/tmp/AdGuardHome_update.log 2>&1 & exit 0 fi config_get_bool verbose $CONFIGURATION verbose 0 - if [ "$verbose" -eq 1 ]; then - ADDITIONAL_ARGS="$ADDITIONAL_ARGS -v" - fi + [ "$verbose" -eq 1 ] && ADDITIONAL_ARGS="$ADDITIONAL_ARGS -v" procd_open_instance get_tz - if [ -n "$SET_TZ" ]; then - procd_set_param env TZ="$SET_TZ" - fi + [ -n "$SET_TZ" ] && procd_set_param env TZ="$SET_TZ" procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5} procd_set_param limits core="unlimited" nofile="65535 65535" procd_set_param stderr 1 procd_set_param command $binpath $ADDITIONAL_ARGS procd_set_param file "$configpath" "/etc/hosts" "/etc/config/AdGuardHome" procd_close_instance + if [ -f "$configpath" ]; then _do_redirect 1 else _do_redirect 0 - config_get "redirect" "AdGuardHome" "redirect" "none" + config_get redirect "$CONFIGURATION" redirect "none" if [ "$redirect" != "none" ]; then - procd_open_instance "waitconfig" + procd_open_instance procd_set_param command "/usr/share/AdGuardHome/watchconfig.sh" procd_close_instance - echo "no config start watching" + echo "AdGuardHome: no config found, watching for config file..." fi fi - echo "AdGuardHome service enabled" - echo "luci enable switch=$enabled" - (sleep 10 && [ -z "$(pgrep $binpath)" ] && logger "AdGuardHome" "no process in 10s cancel redirect" && _do_redirect 0 )& - if [[ "`uci get bypass.@global[0].global_server 2>/dev/null`" && "`uci get bypass.@global[0].adguardhome 2>/dev/null`" == 1 && "$(uci get dhcp.@dnsmasq[0].port)" == "53" ]]; then - uci -q set AdGuardHome.AdGuardHome.redirect='exchange' - uci commit AdGuardHome - do_redirect 1 + + echo "AdGuardHome service enabled (switch=$enabled)" + + (sleep 10 && \ + pgrep -f "$binpath" >/dev/null 2>&1 || { \ + logger -t AdGuardHome "no process found after 10s, canceling redirect"; \ + _do_redirect 0; \ + }) & + + local bypass_global="$(uci get bypass.@global[0].global_server 2>/dev/null)" + local bypass_adg="$(uci get bypass.@global[0].adguardhome 2>/dev/null)" + local dnsmasq_port="$(uci get dhcp.@dnsmasq[0].port 2>/dev/null)" + if [ -n "$bypass_global" ] && [ "$bypass_adg" = "1" ] && [ "$dnsmasq_port" = "53" ]; then + uci -q set AdGuardHome.AdGuardHome.redirect='exchange' + uci commit AdGuardHome + do_redirect 1 fi } reload_service() { - rm /var/run/AdGlucitest >/dev/null 2>&1 + rm -f /var/run/AdGlucitest >/dev/null 2>&1 echo "AdGuardHome reloading" start } del_querylog(){ - local btarget=$(ls $backupwdpath/data | grep -F "querylog.json" | sort -r | head -n 1) - local wtarget=$(ls $workdir/data | grep -F "querylog.json" | sort -r | head -n 1) - if [ "$btarget"x == "$wtarget"x ]; then + local backupwdpath + config_get backupwdpath $CONFIGURATION backupwdpath "/etc/AdGuardHome" + local workdir + config_get workdir $CONFIGURATION workdir "/etc/AdGuardHome" + + local btarget + btarget="$(ls "$backupwdpath/data" 2>/dev/null | grep "querylog.json" | sort -r | head -n1)" + local wtarget + wtarget="$(ls "$workdir/data" 2>/dev/null | grep "querylog.json" | sort -r | head -n1)" + + if [ "$btarget" = "$wtarget" ]; then [ -z "$btarget" ] && return 1 - rm -f $workdir/data/$wtarget - rm -f $backupwdpath/data/$btarget + rm -f "$workdir/data/$wtarget" + rm -f "$backupwdpath/data/$btarget" return 0 fi + if [ "$btarget" \> "$wtarget" ]; then - rm -f $backupwdpath/data/$btarget - return 0 + rm -f "$backupwdpath/data/$btarget" else - rm -f $workdir/data/$wtarget - return 0 + rm -f "$workdir/data/$wtarget" fi + return 0 } stop_service() @@ -541,12 +567,12 @@ stop_service() config_load "${CONFIGURATION}" _do_redirect 0 do_crontab + if [ "$1" != "nobackup" ]; then config_get backupfile $CONFIGURATION backupfile "0" - if [ -n "$backupfile" ]; then - backup - fi + [ -n "$backupfile" ] && backup fi + echo "AdGuardHome service disabled" touch /var/run/AdGserverdis } @@ -566,77 +592,66 @@ test_crontab(){ do_crontab(){ config_get_bool enabled $CONFIGURATION enabled 0 config_get crontab $CONFIGURATION crontab "" - local findstr default cronenable replace commit local cronreload=0 - local commit=0 + + local findstr default cronenable findstr="/usr/share/AdGuardHome/update_core.sh" - default="30 3 * * * /usr/share/AdGuardHome/update_core.sh 2>&1" - [ "$enabled" == "0" ] || [ "${crontab//autoupdate/}" == "$crontab" ] && cronenable=0 || cronenable=1 + default="30 3 * * * /usr/share/AdGuardHome/update_core.sh" + [ "$enabled" = "0" ] || [ "${crontab//autoupdate/}" = "$crontab" ] && cronenable=0 || cronenable=1 crontab_editor - config_get workdir $CONFIGURATION workdir "/etc/AdGuardHome" - config_get lastworkdir $CONFIGURATION lastworkdir "/etc/AdGuardHome" - findstr="/usr/share/AdGuardHome/tailto.sh [0-9]* \$(uci get AdGuardHome.AdGuardHome.workdir)/data/querylog.json" - #[ -n "$lastworkdir" ] && findstr="/usr/share/AdGuardHome/tailto.sh [0-9]* $lastworkdir/data/querylog.json" && [ "$lastworkdir" != "$workdir" ] && replace="${lastworkdir//\//\\/}/${workdir//\//\\/}" + findstr="/usr/share/AdGuardHome/tailto.sh" default="0 * * * * /usr/share/AdGuardHome/tailto.sh 2000 \$(uci get AdGuardHome.AdGuardHome.workdir)/data/querylog.json" - [ "$enabled" == "0" ] || [ "${crontab//cutquerylog/}" == "$crontab" ] && cronenable=0 || cronenable=1 + [ "$enabled" = "0" ] || [ "${crontab//cutquerylog/}" = "$crontab" ] && cronenable=0 || cronenable=1 crontab_editor - #[ "$lastworkdir" != "$workdir" ] && uci set AdGuardHome.AdGuardHome.lastworkdir="$workdir" && commit=1 - config_get logfile $CONFIGURATION logfile "" - config_get lastlogfile $CONFIGURATION lastlogfile "" - findstr="/usr/share/AdGuardHome/tailto.sh [0-9]* \$(uci get AdGuardHome.AdGuardHome.logfile)" + findstr="/usr/share/AdGuardHome/tailto.sh" default="30 3 * * * /usr/share/AdGuardHome/tailto.sh 2000 \$(uci get AdGuardHome.AdGuardHome.logfile)" - #[ -n "$lastlogfile" ] && findstr="/usr/share/AdGuardHome/tailto.sh [0-9]* $lastlogfile" && [ -n "$logfile" ] && [ "$lastlogfile" != "$logfile" ] && replace="${lastlogfile//\//\\/}/${logfile//\//\\/}" - [ "$logfile" == "syslog" ] || [ "$logfile" == "" ] || [ "$enabled" == "0" ] || [ "${crontab//cutruntimelog/}" == "$crontab" ] && cronenable=0 || cronenable=1 + [ "$enabled" = "0" ] || [ "${crontab//cutruntimelog/}" = "$crontab" ] && cronenable=0 || cronenable=1 crontab_editor - #[ -n "$logfile" ] && [ "$lastlogfile" != "$logfile" ] && uci set AdGuardHome.AdGuardHome.lastlogfile="$logfile" && commit=1 findstr="/usr/share/AdGuardHome/addhost.sh" default="0 * * * * /usr/share/AdGuardHome/addhost.sh" - [ "$enabled" == "0" ] || [ "${crontab//autohost/}" == "$crontab" ] && cronenable=0 || cronenable=1 + [ "$enabled" = "0" ] || [ "${crontab//autohost/}" = "$crontab" ] && cronenable=0 || cronenable=1 crontab_editor - [ "$cronenable" == "0" ] && /usr/share/AdGuardHome/addhost.sh "del" "noreload" || /usr/share/AdGuardHome/addhost.sh "" "noreload" findstr="/usr/share/AdGuardHome/gfw2adg.sh" default="30 3 * * * /usr/share/AdGuardHome/gfw2adg.sh" - [ "$enabled" == "0" ] || [ "${crontab//autogfw/}" == "$crontab" ] && cronenable=0 || cronenable=1 + [ "$enabled" = "0" ] || [ "${crontab//autogfw/}" = "$crontab" ] && cronenable=0 || cronenable=1 crontab_editor + [ "$cronreload" -gt 0 ] && /etc/init.d/cron restart - #[ "$commit" -gt 0 ] && uci commit AdGuardHome } crontab_editor(){ - #usage input: - #findstr= - #default= - #cronenable= - #replace="${last//\//\\/}/${now//\//\\/}" - #output:cronreload:if >1 please /etc/init.d/cron restart manual - local testline reload - local line="$(grep "$findstr" $CRON_FILE)" - [ -n "$replace" ] && [ -n "$line" ] && eval testline="\${line//$replace}" && [ "$testline" != "$line" ] && line="$testline" && reload="1" && replace="" - if [ "${line:0:1}" != "#" ]; then - if [ $cronenable -eq 1 ]; then - [ -z "$line" ] && line="$default" && reload="1" - if [ -n "$reload" ]; then - sed -i "\,$findstr,d" $CRON_FILE - echo "$line" >> $CRON_FILE - cronreload=$((cronreload+1)) - fi - elif [ -n "$line" ]; then - sed -i "\,$findstr,d" $CRON_FILE - echo "#$line" >> $CRON_FILE - cronreload=$((cronreload+1)) + local line + local reload + line="$(grep "$findstr" "$CRON_FILE" 2>/dev/null)" + + if [ "${line#\#}" != "$line" ]; then + if [ "$cronenable" = "1" ]; then + sed -i "\|$findstr|d" "$CRON_FILE" + echo "${line#\#}" >> "$CRON_FILE" + cronreload=$((cronreload + 1)) + elif [ -z "$reload" ]; then + sed -i "\|$findstr|d" "$CRON_FILE" + echo "$line" >> "$CRON_FILE" fi else - if [ $cronenable -eq 1 ]; then - sed -i "\,$findstr,d" $CRON_FILE - echo "${line:1}" >> $CRON_FILE - cronreload=$((cronreload+1)) - elif [ -z "$reload" ]; then - sed -i "\,$findstr,d" $CRON_FILE - echo "$line" >> $CRON_FILE + if [ "$cronenable" = "1" ]; then + if [ -z "$line" ]; then + line="$default" + reload=1 + fi + if [ -n "$reload" ]; then + sed -i "\|$findstr|d" "$CRON_FILE" + echo "$line" >> "$CRON_FILE" + cronreload=$((cronreload + 1)) + fi + elif [ -n "$line" ]; then + sed -i "\|$findstr|d" "$CRON_FILE" + echo "#$line" >> "$CRON_FILE" + cronreload=$((cronreload + 1)) fi fi } diff --git a/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/addhost.sh b/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/addhost.sh index 6c6b7b7691..a23a2efc30 100755 --- a/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/addhost.sh +++ b/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/addhost.sh @@ -1,35 +1,54 @@ #!/bin/sh checkmd5(){ -local nowmd5=$(md5sum /etc/hosts) -nowmd5=${nowmd5%% *} -local lastmd5=$(uci get AdGuardHome.AdGuardHome.hostsmd5 2>/dev/null) -if [ "$nowmd5" != "$lastmd5" ]; then - uci set AdGuardHome.AdGuardHome.hostsmd5="$nowmd5" - uci commit AdGuardHome - [ "$1" == "noreload" ] || /etc/init.d/AdGuardHome reload -fi + local nowmd5 + nowmd5="$(md5sum /etc/hosts 2>/dev/null)" + nowmd5="${nowmd5%% *}" + local lastmd5 + lastmd5="$(uci get AdGuardHome.AdGuardHome.hostsmd5 2>/dev/null)" + if [ "$nowmd5" != "$lastmd5" ]; then + uci set AdGuardHome.AdGuardHome.hostsmd5="$nowmd5" + uci commit AdGuardHome + [ "$1" != "noreload" ] && /etc/init.d/AdGuardHome reload >/dev/null 2>&1 + fi } -[ "$1" == "del" ] && sed -i '/programaddstart/,/programaddend/d' /etc/hosts && checkmd5 "$2" && exit 0 -/usr/bin/awk 'BEGIN{ -while ((getline < "/tmp/dhcp.leases") > 0) -{ - a[$2]=$4; -} -while (("ip -6 neighbor show | grep -v fe80" | getline) > 0) -{ - if (a[$5]) {print $1" "a[$5] >"/tmp/tmphost"; } -} -print "#programaddend" >"/tmp/tmphost"; -}' -grep programaddstart /etc/hosts >/dev/null 2>&1 -if [ "$?" == "0" ]; then - sed -i '/programaddstart/,/programaddend/c\#programaddstart' /etc/hosts - sed -i '/programaddstart/'r/tmp/tmphost /etc/hosts -else - echo "#programaddstart" >>/etc/hosts - cat /tmp/tmphost >> /etc/hosts +if [ "$1" = "del" ]; then + sed -i '/programaddstart/,/programaddend/d' /etc/hosts + checkmd5 "$2" + exit 0 fi -rm /tmp/tmphost + +awk 'BEGIN { + dhcp[""] = "" +} +{ + if (FILENAME == "/tmp/dhcp.leases" && (NF >= 4)) { + dhcp[$2] = $4 + } +} +END { + cmd = "ip -6 neighbor show 2>/dev/null | grep -v fe80" + while ((cmd | getline line) > 0) { + split(line, f) + if (f[5] in dhcp && f[5] != "") { + print f[1] " " dhcp[f[5]] + } + } + close(cmd) + print "#programaddend" +}' /tmp/dhcp.leases > /tmp/tmphost 2>/dev/null + +grep -q "programaddstart" /etc/hosts 2>/dev/null +if [ $? -eq 0 ]; then + sed -i '/programaddstart/,/programaddend/c\#programaddstart' /etc/hosts + sed -i '/programaddstart/r /tmp/tmphost' /etc/hosts +else + { + echo "#programaddstart" + cat /tmp/tmphost + } >> /etc/hosts +fi + +rm -f /tmp/tmphost checkmd5 "$2" diff --git a/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/gfw2adg.sh b/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/gfw2adg.sh index a3add84e8b..dc48dbf90f 100755 --- a/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/gfw2adg.sh +++ b/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/gfw2adg.sh @@ -3,87 +3,137 @@ PATH="/usr/sbin:/usr/bin:/sbin:/bin" checkmd5(){ -local nowmd5=$(md5sum /tmp/adguard.list 2>/dev/null) -nowmd5=${nowmd5%% *} -local lastmd5=$(uci get AdGuardHome.AdGuardHome.gfwlistmd5 2>/dev/null) -if [ "$nowmd5" != "$lastmd5" ]; then - uci set AdGuardHome.AdGuardHome.gfwlistmd5="$nowmd5" - uci commit AdGuardHome - [ "$1" == "noreload" ] || /etc/init.d/AdGuardHome reload -fi + local nowmd5 + nowmd5="$(md5sum /tmp/adguard.list 2>/dev/null)" + nowmd5="${nowmd5%% *}" + local lastmd5 + lastmd5="$(uci get AdGuardHome.AdGuardHome.gfwlistmd5 2>/dev/null)" + if [ "$nowmd5" != "$lastmd5" ]; then + uci set AdGuardHome.AdGuardHome.gfwlistmd5="$nowmd5" + uci commit AdGuardHome + [ "$1" != "noreload" ] && /etc/init.d/AdGuardHome reload >/dev/null 2>&1 + fi } -configpath=$(uci get AdGuardHome.AdGuardHome.configpath 2>/dev/null) -[ "$1" == "del" ] && sed -i '/programaddstart/,/programaddend/d' $configpath && checkmd5 "$2" && exit 0 -gfwupstream=$(uci get AdGuardHome.AdGuardHome.gfwupstream 2>/dev/null) -if [ -z $gfwupstream ]; then -gfwupstream="tcp://208.67.220.220:5353" +configpath +configpath="$(uci get AdGuardHome.AdGuardHome.configpath 2>/dev/null)" +if [ -z "$configpath" ]; then + configpath="/etc/AdGuardHome.yaml" fi + +if [ "$1" = "del" ]; then + sed -i '/programaddstart/,/programaddend/d' "$configpath" + checkmd5 "$2" + exit 0 +fi + +local gfwupstream +gfwupstream="$(uci get AdGuardHome.AdGuardHome.gfwupstream 2>/dev/null)" +if [ -z "$gfwupstream" ]; then + gfwupstream="tcp://208.67.220.220:5353" +fi + if [ ! -f "$configpath" ]; then - echo "please make a config first" + echo "Error: config file not found, please create config first" exit 1 fi -wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O- | base64 -d > /tmp/gfwlist.txt -cat /tmp/gfwlist.txt | awk -v upst="$gfwupstream" 'BEGIN{getline;}{ -s1=substr($0,1,1); -if (s1=="!") -{next;} -if (s1=="@"){ - $0=substr($0,3); - s1=substr($0,1,1); - white=1;} -else{ - white=0; -} -if (s1=="|") - {s2=substr($0,2,1); - if (s2=="|") - { - $0=substr($0,3); - split($0,d,"/"); - $0=d[1]; - }else{ - split($0,d,"/"); - $0=d[3]; - }} -else{ - split($0,d,"/"); - $0=d[1]; -} -star=index($0,"*"); -if (star!=0) -{ - $0=substr($0,star+1); - dot=index($0,"."); - if (dot!=0) - $0=substr($0,dot+1); - else - next; - s1=substr($0,1,1); -} -if (s1==".") -{fin=substr($0,2);} -else{fin=$0;} -if (index(fin,".")==0) next; -if (index(fin,"%")!=0) next; -if (index(fin,":")!=0) next; -match(fin,"^[0-9\.]+") -if (RSTART==1 && RLENGTH==length(fin)) {print "ipset add gfwlist "fin>"/tmp/doipset.sh";next;} -if (fin=="" || finl==fin) next; -finl=fin; -if (white==0) - {print(" - '\''[/"fin"/]"upst"'\''");} -else{ - print(" - '\''[/"fin"/]#'\''");} -}END{print(" - '\''[/programaddend/]#'\''")}' > /tmp/adguard.list -grep programaddstart $configpath -if [ "$?" == "0" ]; then - sed -i '/programaddstart/,/programaddend/c\ - '\''\[\/programaddstart\/\]#'\''' $configpath - sed -i '/programaddstart/'r/tmp/adguard.list $configpath +echo "Downloading gfwlist..." +GFWLIST_URL="https://gitlab.com/gfwlist/gfwlist/raw/master/gfwlist.txt" +if curl -sL -k --retry 2 --connect-timeout 20 -o /tmp/gfwlist.txt "$GFWLIST_URL" 2>/dev/null; then + : +elif wget-ssl --no-check-certificate -t 2 -T 20 -O /tmp/gfwlist.txt "$GFWLIST_URL" 2>/dev/null; then + : else - sed -i '1i\ - '\''[/programaddstart/]#'\''' /tmp/adguard.list - sed -i '/upstream_dns:/'r/tmp/adguard.list $configpath + echo "Error: failed to download gfwlist" + exit 1 fi + +if [ ! -s /tmp/gfwlist.txt ]; then + echo "Error: gfwlist download is empty" + rm -f /tmp/gfwlist.txt + exit 1 +fi + +base64 -d < /tmp/gfwlist.txt > /tmp/gfwlist_decoded.txt 2>/dev/null +if [ $? -ne 0 ] || [ ! -s /tmp/gfwlist_decoded.txt ]; then + echo "Error: failed to decode gfwlist" + rm -f /tmp/gfwlist.txt + exit 1 +fi + +awk -v upst="$gfwupstream" ' +BEGIN { + getline +} +{ + s1 = substr($0, 1, 1) + if (s1 == "!") next + white = 0 + if (s1 == "@") { + $0 = substr($0, 3) + s1 = substr($0, 1, 1) + white = 1 + } + + if (s1 == "|") { + s2 = substr($0, 2, 1) + if (s2 == "|") { + $0 = substr($0, 3) + n = split($0, d, "/") + $0 = d[1] + } else { + n = split($0, d, "/") + $0 = d[3] + } + } else { + n = split($0, d, "/") + $0 = d[1] + } + + star = index($0, "*") + if (star != 0) { + $0 = substr($0, star + 1) + dot = index($0, ".") + if (dot != 0) + $0 = substr($0, dot + 1) + else + next + s1 = substr($0, 1, 1) + } + + if (s1 == ".") + fin = substr($0, 2) + else + fin = $0 + + if (index(fin, ".") == 0) next + if (index(fin, "%") != 0) next + if (index(fin, ":") != 0) next + + if (match(fin, "^[0-9.]+$")) next + if (fin == "" || fin == finl) next + finl = fin + + if (white == 0) + print " - [/." fin "/]" upst + else + print " - [/." fin "/]#" +} +END { + print " - [/programaddend/]#" +}' /tmp/gfwlist_decoded.txt > /tmp/adguard.list + +rm -f /tmp/gfwlist.txt /tmp/gfwlist_decoded.txt + +grep -q "programaddstart" "$configpath" +if [ $? -eq 0 ]; then + sed -i '/programaddstart/,/programaddend/d' "$configpath" + cat /tmp/adguard.list >> "$configpath" +else + sed -i '1i\ - [/programaddstart/]#' /tmp/adguard.list + sed -i '/^upstream_dns:/r /tmp/adguard.list' "$configpath" +fi + checkmd5 "$2" -rm -f /tmp/gfwlist.txt /tmp/adguard.list +rm -f /tmp/adguard.list diff --git a/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/update_core.sh b/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/update_core.sh index 74ba7268d5..8dd6ae0f5e 100755 --- a/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/update_core.sh +++ b/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/update_core.sh @@ -1,236 +1,271 @@ -#!/bin/bash +#!/bin/sh PATH="/usr/sbin:/usr/bin:/sbin:/bin" -binpath=$(uci get AdGuardHome.AdGuardHome.binpath) -if [ -z "$binpath" ]; then -uci set AdGuardHome.AdGuardHome.binpath="/tmp/AdGuardHome/AdGuardHome" -binpath="/tmp/AdGuardHome/AdGuardHome" -fi -mkdir -p ${binpath%/*} -upxflag=$(uci get AdGuardHome.AdGuardHome.upxflag 2>/dev/null) -check_if_already_running(){ - running_tasks="$(ps |grep "AdGuardHome" |grep "update_core" |grep -v "grep" |awk '{print $1}' |wc -l)" - [ "${running_tasks}" -gt "2" ] && echo -e "\nA task is already running." && EXIT 2 +binpath="$(uci get AdGuardHome.AdGuardHome.binpath 2>/dev/null)" +if [ -z "$binpath" ]; then + uci set AdGuardHome.AdGuardHome.binpath="/tmp/AdGuardHome/AdGuardHome" + binpath="/tmp/AdGuardHome/AdGuardHome" +fi + +mkdir -p "${binpath%/*}" + +upxflag="$(uci get AdGuardHome.AdGuardHome.upxflag 2>/dev/null)" + +cleanup() { + rm -f /var/run/update_core 2>/dev/null + [ "$1" != "0" ] && touch /var/run/update_core_error + exit "$1" +} + +check_already_running(){ + local running_tasks + running_tasks="$(ps | grep -E "AdGuardHome|update_core" | grep -v grep | wc -l)" + [ "${running_tasks}" -gt "2" ] && echo "A task is already running." && cleanup 2 } check_wgetcurl(){ - which curl && downloader="curl -L -k --retry 2 --connect-timeout 20 -o" && return - which wget-ssl && downloader="wget-ssl --no-check-certificate -t 2 -T 20 -O" && return - [ -z "$1" ] && opkg update || (echo error opkg && EXIT 1) - [ -z "$1" ] && (opkg remove wget wget-nossl --force-depends ; opkg install wget ; check_wgetcurl 1 ;return) - [ "$1" == "1" ] && (opkg install curl ; check_wgetcurl 2 ; return) - echo error curl and wget && EXIT 1 + if which curl >/dev/null 2>&1; then + downloader="curl -L -k --retry 2 --connect-timeout 20 -o" + return 0 + fi + if which wget-ssl >/dev/null 2>&1; then + downloader="wget-ssl --no-check-certificate -t 2 -T 20 -O" + return 0 + fi + + if [ -z "$1" ]; then + opkg update >/dev/null 2>&1 || { echo "Error: opkg failed"; cleanup 1; } + fi + + if [ -z "$1" ]; then + opkg remove wget wget-nossl --force-depends >/dev/null 2>&1 + opkg install wget >/dev/null 2>&1 && check_wgetcurl 1 && return 0 + fi + + if [ "$1" = "1" ]; then + opkg install curl >/dev/null 2>&1 && check_wgetcurl 2 && return 0 + fi + + if [ "$1" = "2" ]; then + check_wgetcurl && return 0 + fi + + echo "Error: neither curl nor wget available" + cleanup 1 +} + +detect_arch(){ + local Archt + Archt="$(opkg info kernel 2>/dev/null | grep Architecture | awk '{print $2}')" + + case "$Archt" in + i386|i686) + Arch="386" + ;; + x86) + Arch="amd64" + ;; + mipsel) + Arch="mipsle" + ;; + mips64el) + Arch="mips64le" + ;; + mips) + Arch="mips" + ;; + mips64) + Arch="mips64" + ;; + arm) + Arch="arm" + ;; + armeb) + Arch="armeb" + ;; + aarch64) + Arch="arm64" + ;; + *) + echo "Error: unsupported architecture: $Archt" + cleanup 1 + ;; + esac } check_latest_version(){ check_wgetcurl - latest_ver="$($downloader - https://api.github.com/repos/AdguardTeam/AdGuardHome/releases/latest 2>/dev/null|grep -E 'tag_name' |grep -E 'v[0-9.]+' -o 2>/dev/null)" + echo "Checking latest version..." + + local api_result + api_result="$($downloader - "https://api.github.com/repos/AdguardTeam/AdGuardHome/releases/latest" 2>/dev/null)" + latest_ver="$(echo "$api_result" | grep -oE '"tag_name": *"v[^"]+"' | head -1 | sed 's/.*"v\(.*\)".*/v\1/')" + if [ -z "${latest_ver}" ]; then - echo -e "\nFailed to check latest version, please try again later." && EXIT 1 + echo "Failed to check latest version, please try again later." + cleanup 1 fi - now_ver="$($binpath -c /dev/null --check-config 2>&1| grep -m 1 -E 'v[0-9.]+' -o)" - if [ "${latest_ver}"x != "${now_ver}"x ] || [ "$1" == "force" ]; then - echo -e "Local version: ${now_ver}., cloud version: ${latest_ver}." - doupdate_core + + if [ -x "$binpath" ]; then + now_ver="$($binpath -c /dev/null --check-config 2>&1 | grep -oE 'v[0-9.]+' | head -1)" else - echo -e "\nLocal version: ${now_ver}, cloud version: ${latest_ver}." - echo -e "You're already using the latest version." - if [ ! -z "$upxflag" ]; then - filesize=$(ls -l $binpath | awk '{ print $5 }') - if [ $filesize -gt 8000000 ]; then - echo -e "start upx may take a long time" - doupx - mkdir -p "/tmp/AdGuardHomeupdate/AdGuardHome" >/dev/null 2>&1 - rm -fr /tmp/AdGuardHomeupdate/AdGuardHome/${binpath##*/} - /tmp/upx-${upx_latest_ver}-${Arch}_linux/upx $upxflag $binpath -o /tmp/AdGuardHomeupdate/AdGuardHome/${binpath##*/} - rm -rf /tmp/upx-${upx_latest_ver}-${Arch}_linux - /etc/init.d/AdGuardHome stop nobackup - rm $binpath - mv -f /tmp/AdGuardHomeupdate/AdGuardHome/${binpath##*/} $binpath - /etc/init.d/AdGuardHome start - echo -e "finished" - fi - fi - EXIT 0 + now_ver="" + fi + + echo "Local version: ${now_ver:-none}, cloud version: ${latest_ver}" + + if [ "${latest_ver}" != "${now_ver}" ] || [ "$1" = "force" ]; then + update_core + else + echo "You're already using the latest version." + apply_upx + cleanup 0 fi } -doupx(){ - Archt="$(opkg info kernel | grep Architecture | awk -F "[ _]" '{print($2)}')" - case $Archt in - "i386") - Arch="i386" - ;; - "i686") - Arch="i386" - echo -e "i686 use $Arch may have bug" - ;; - "x86") - Arch="amd64" - ;; - "mipsel") - Arch="mipsel" - ;; - "mips64el") - Arch="mips64el" - Arch="mipsel" - echo -e "mips64el use $Arch may have bug" - ;; - "mips") - Arch="mips" - ;; - "mips64") - Arch="mips64" - Arch="mips" - echo -e "mips64 use $Arch may have bug" - ;; - "arm") - Arch="arm" - ;; - "armeb") - Arch="armeb" - ;; - "aarch64") - Arch="arm64" - ;; - "powerpc") - Arch="powerpc" - ;; - "powerpc64") - Arch="powerpc64" - ;; - *) - echo -e "error not support $Archt if you can use offical release please issue a bug" - EXIT 1 - ;; - esac - upx_latest_ver="$($downloader - https://api.github.com/repos/upx/upx/releases/latest 2>/dev/null|grep -E 'tag_name' |grep -E '[0-9.]+' -o 2>/dev/null)" - $downloader /tmp/upx-${upx_latest_ver}-${Arch}_linux.tar.xz "https://github.com/upx/upx/releases/download/v${upx_latest_ver}/upx-${upx_latest_ver}-${Arch}_linux.tar.xz" 2>&1 - #tar xvJf - which xz || (opkg list | grep ^xz || opkg update && opkg install xz) || (echo "xz download fail" && EXIT 1) - mkdir -p /tmp/upx-${upx_latest_ver}-${Arch}_linux - xz -d -c /tmp/upx-${upx_latest_ver}-${Arch}_linux.tar.xz| tar -x -C "/tmp" >/dev/null 2>&1 - if [ ! -e "/tmp/upx-${upx_latest_ver}-${Arch}_linux/upx" ]; then - echo -e "Failed to download upx." - EXIT 1 - fi - rm /tmp/upx-${upx_latest_ver}-${Arch}_linux.tar.xz -} +apply_upx(){ + [ -z "$upxflag" ] && return + + local filesize + filesize="$(ls -l "$binpath" 2>/dev/null | awk '{print $5}')" + [ "$filesize" -le 8000000 ] && return + + echo "Binary size > 8MB, applying upx compression..." + fetch_upx + + local UPX_BIN="/tmp/upx-${upx_latest_ver}-${Arch}_linux/upx" + [ ! -x "$UPX_BIN" ] && { echo "upx binary not found"; return; } -doupdate_core(){ - echo -e "Updating core..." mkdir -p "/tmp/AdGuardHomeupdate" - rm -rf /tmp/AdGuardHomeupdate/* >/dev/null 2>&1 - Archt="$(opkg info kernel | grep Architecture | awk -F "[ _]" '{print($2)}')" - case $Archt in - "i386") - Arch="386" - ;; - "i686") - Arch="386" - ;; - "x86") - Arch="amd64" - ;; - "mipsel") - Arch="mipsle" - ;; - "mips64el") - Arch="mips64le" - Arch="mipsle" - echo -e "mips64el use $Arch may have bug" - ;; - "mips") - Arch="mips" - ;; - "mips64") - Arch="mips64" - Arch="mips" - echo -e "mips64 use $Arch may have bug" - ;; - "arm") - Arch="arm" - ;; - "aarch64") - Arch="arm64" - ;; - "powerpc") - Arch="ppc" - echo -e "error not support $Archt" - EXIT 1 - ;; - "powerpc64") - Arch="ppc64" - echo -e "error not support $Archt" - EXIT 1 - ;; + rm -rf "/tmp/AdGuardHomeupdate/${binpath##*/}" 2>/dev/null + + $UPX_BIN $upxflag "$binpath" -o "/tmp/AdGuardHomeupdate/${binpath##*/}" + local upxret=$? + rm -rf "/tmp/upx-${upx_latest_ver}-${Arch}_linux" + + if [ $upxret -eq 0 ]; then + /etc/init.d/AdGuardHome stop nobackup 2>/dev/null + rm -f "$binpath" + mv -f "/tmp/AdGuardHomeupdate/${binpath##*/}" "$binpath" + chmod 755 "$binpath" + /etc/init.d/AdGuardHome start 2>/dev/null + echo "upx compression finished" + fi +} + +fetch_upx(){ + local Archt_upx + Archt_upx="$(opkg info kernel 2>/dev/null | grep Architecture | awk '{print $2}')" + + case "$Archt_upx" in + i386|i686) Arch="i386";; + x86) Arch="amd64";; + mipsel) Arch="mipsel";; + mips64el) Arch="mipsel";; + mips) Arch="mips";; + mips64) Arch="mips";; + arm) Arch="arm";; + aarch64) Arch="arm64";; *) - echo -e "error not support $Archt if you can use offical release please issue a bug" - EXIT 1 + echo "upx: unsupported arch $Archt_upx" + return 1 ;; esac - echo -e "start download" - grep -v "^#" /usr/share/AdGuardHome/links.txt >/tmp/run/AdHlinks.txt - while read link - do + + upx_latest_ver="$($downloader - "https://api.github.com/repos/upx/upx/releases/latest" 2>/dev/null | grep -oE '"tag_name": *"[^"]+"' | head -1 | sed 's/.*"\(.*\)"/\1/')" + + if [ -z "$upx_latest_ver" ]; then + echo "Failed to get upx version" + return 1 + fi + + local UPX_URL="https://github.com/upx/upx/releases/download/${upx_latest_ver}/upx-${upx_latest_ver}-${Arch}_linux.tar.xz" + $downloader "/tmp/upx-${upx_latest_ver}-${Arch}_linux.tar.xz" "$UPX_URL" 2>&1 + [ $? -ne 0 ] && { echo "Failed to download upx"; return 1; } + + which xz >/dev/null 2>&1 || opkg install xz >/dev/null 2>&1 || { echo "xz not available"; return 1; } + + mkdir -p "/tmp/upx-${upx_latest_ver}-${Arch}_linux" + xz -d -c "/tmp/upx-${upx_latest_ver}-${Arch}_linux.tar.xz" | tar -x -C "/tmp" >/dev/null 2>&1 + + [ ! -x "/tmp/upx-${upx_latest_ver}-${Arch}_linux/upx" ] && { echo "upx extraction failed"; return 1; } + rm -f "/tmp/upx-${upx_latest_ver}-${Arch}_linux.tar.xz" +} + +update_core(){ + echo "Updating AdGuardHome core..." + mkdir -p "/tmp/AdGuardHomeupdate" + rm -rf "/tmp/AdGuardHomeupdate/*" 2>/dev/null + + detect_arch + echo "Architecture: $Arch" + + echo "Fetching download links..." + mkdir -p /tmp/run + grep -v "^#" /usr/share/AdGuardHome/links.txt > /tmp/run/AdHlinks.txt + + local downloadbin="" + local success="" + + while read link; do + [ -z "$link" ] && continue eval link="$link" - $downloader /tmp/AdGuardHomeupdate/${link##*/} "$link" 2>&1 - if [ "$?" != "0" ]; then - echo "download failed try another download" - rm -f /tmp/AdGuardHomeupdate/${link##*/} - else - local success="1" + echo "Trying: $link" + $downloader "/tmp/AdGuardHomeupdate/${link##*/}" "$link" 2>&1 + if [ $? -eq 0 ] && [ -s "/tmp/AdGuardHomeupdate/${link##*/}" ]; then + downloadbin="/tmp/AdGuardHomeupdate/${link##*/}" + success="1" + echo "Download successful" break + else + echo "Download failed, trying next..." + rm -f "/tmp/AdGuardHomeupdate/${link##*/}" fi - done < "/tmp/run/AdHlinks.txt" - rm /tmp/run/AdHlinks.txt - [ -z "$success" ] && echo "no download success" && EXIT 1 - if [ "${link##*.}" == "gz" ]; then - tar -zxf "/tmp/AdGuardHomeupdate/${link##*/}" -C "/tmp/AdGuardHomeupdate/" - if [ ! -e "/tmp/AdGuardHomeupdate/AdGuardHome" ]; then - echo -e "Failed to download core." - rm -rf "/tmp/AdGuardHomeupdate" >/dev/null 2>&1 - EXIT 1 + done < /tmp/run/AdHlinks.txt + + rm -f /tmp/run/AdHlinks.txt + + if [ -z "$success" ]; then + echo "Error: all download sources failed" + cleanup 1 + fi + + if [ "${downloadbin##*.}" = "gz" ]; then + tar -zxf "$downloadbin" -C "/tmp/AdGuardHomeupdate/" 2>/dev/null + if [ -d "/tmp/AdGuardHomeupdate/AdGuardHome" ]; then + downloadbin="/tmp/AdGuardHomeupdate/AdGuardHome/AdGuardHome" + else + echo "Error: failed to extract archive" + cleanup 1 fi - downloadbin="/tmp/AdGuardHomeupdate/AdGuardHome/AdGuardHome" - else - downloadbin="/tmp/AdGuardHomeupdate/${link##*/}" fi - chmod 755 $downloadbin - echo -e "download success start copy" - if [ -n "$upxflag" ]; then - echo -e "start upx may take a long time" - doupx - /tmp/upx-${upx_latest_ver}-${Arch}_linux/upx $upxflag $downloadbin - rm -rf /tmp/upx-${upx_latest_ver}-${Arch}_linux - fi - echo -e "start copy" - /etc/init.d/AdGuardHome stop nobackup - rm "$binpath" - mv -f "$downloadbin" "$binpath" - if [ "$?" == "1" ]; then - echo "mv failed maybe not enough space please use upx or change bin to /tmp/AdGuardHome" - EXIT 1 - fi - /etc/init.d/AdGuardHome start - rm -rf "/tmp/AdGuardHomeupdate" >/dev/null 2>&1 - echo -e "Succeeded in updating core." - echo -e "Local version: ${latest_ver}, cloud version: ${latest_ver}.\n" - EXIT 0 + + chmod 755 "$downloadbin" + echo "Download complete, applying upx if configured..." + apply_upx + + echo "Stopping service..." + /etc/init.d/AdGuardHome stop nobackup 2>/dev/null + + echo "Installing new binary..." + rm -f "$binpath" 2>/dev/null + mv -f "$downloadbin" "$binpath" 2>/dev/null + [ $? -ne 0 ] && { echo "mv failed - disk space issue?"; cleanup 1; } + chmod 755 "$binpath" + + rm -rf "/tmp/AdGuardHomeupdate" 2>/dev/null + + echo "Starting service..." + /etc/init.d/AdGuardHome start 2>/dev/null + + echo "Succeeded in updating AdGuardHome to ${latest_ver}." + cleanup 0 } -EXIT(){ - rm /var/run/update_core 2>/dev/null - [ "$1" != "0" ] && touch /var/run/update_core_error - exit $1 -} +trap "cleanup 1" SIGTERM SIGINT +touch /var/run/update_core +rm -f /var/run/update_core_error 2>/dev/null -main(){ - check_if_already_running - check_latest_version $1 -} - trap "EXIT 1" SIGTERM SIGINT - touch /var/run/update_core - rm /var/run/update_core_error 2>/dev/null - main $1 +check_already_running +check_latest_version "$1" diff --git a/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/waitnet.sh b/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/waitnet.sh index c7745e101d..d45518af89 100755 --- a/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/waitnet.sh +++ b/openwrt-packages/luci-app-adguardhome/root/usr/share/AdGuardHome/waitnet.sh @@ -1,35 +1,21 @@ #!/bin/sh PATH="/usr/sbin:/usr/bin:/sbin:/bin" + count=0 -while : -do - ping -c 1 -W 1 -q www.baidu.com 1>/dev/null 2>&1 - if [ "$?" == "0" ]; then - /etc/init.d/AdGuardHome force_reload - break - fi - ping -c 1 -W 1 -q 202.108.22.5 1>/dev/null 2>&1 - if [ "$?" == "0" ]; then - /etc/init.d/AdGuardHome force_reload - break - fi - sleep 5 - ping -c 1 -W 1 -q www.google.com 1>/dev/null 2>&1 - if [ "$?" == "0" ]; then - /etc/init.d/AdGuardHome force_reload - break - fi - ping -c 1 -W 1 -q 8.8.8.8 1>/dev/null 2>&1 - if [ "$?" == "0" ]; then - /etc/init.d/AdGuardHome force_reload - break - fi - sleep 5 - count=$((count+1)) +while :; do + for host in www.baidu.com 223.5.5.5 www.google.com 8.8.8.8; do + ping -c 1 -W 2 -q "$host" >/dev/null 2>&1 + if [ $? -eq 0 ]; then + /etc/init.d/AdGuardHome force_reload + exit 0 + fi + done + + count=$((count + 1)) if [ $count -gt 18 ]; then /etc/init.d/AdGuardHome force_reload - break + exit 0 fi + sleep 5 done -return 0 diff --git a/openwrt-packages/luci-app-aliddns/Makefile b/openwrt-packages/luci-app-aliddns/Makefile index 386a138f04..6224f99b74 100644 --- a/openwrt-packages/luci-app-aliddns/Makefile +++ b/openwrt-packages/luci-app-aliddns/Makefile @@ -33,7 +33,7 @@ endef define Build/Prepare $(foreach po,$(wildcard ${CURDIR}/files/luci/i18n/*.po), \ - po2lmo $(po) $(PKG_BUILD_DIR)/$(patsubst %.po,%.lmo,$(notdir $(po)));) + $(STAGING_DIR_HOSTPKG)/bin/po2lmo $(po) $(PKG_BUILD_DIR)/$(patsubst %.po,%.lmo,$(notdir $(po)));) endef define Build/Configure diff --git a/openwrt-packages/luci-app-fileassistant/README.md b/openwrt-packages/luci-app-fileassistant/README.md new file mode 100644 index 0000000000..f92666e1b2 --- /dev/null +++ b/openwrt-packages/luci-app-fileassistant/README.md @@ -0,0 +1,155 @@ +# luci-app-fileassistant + +OpenWrt LuCI 文件管理器插件,提供 Web 界面进行文件浏览、上传、下载和管理。 + +## 功能特性 + +- **文件浏览**: 浏览目录结构,支持文件夹导航 +- **文件上传**: 支持拖拽上传,最大 500MB +- **文件下载**: 点击文件名直接预览/下载 +- **文件管理**: 重命名、删除文件/文件夹 +- **ipk 安装**: 支持直接从文件管理器安装 .ipk 包 +- **路径安全**: 仅允许访问白名单目录 (`/mnt`, `/etc`, `/root`, `/tmp`, `/www`) +- **响应式设计**: 支持移动端和平板设备 + +## 系统要求 + +- OpenWrt 18.06 或更高版本 +- LuCI Web 界面 +- 浏览器: Chrome, Firefox, Safari, Edge 现代版本 + +## 安装 + +### 从源码编译 + +```bash +# 克隆到 OpenWrt SDK +git clone https://github.com/kenzok78/luci-app-fileassistant.git + +# 放入 packages 目录 +mv luci-app-fileassistant /path/to/openwrt/package/feeds/luci/ + +# 编译 +make package/luci-app-fileassistant/compile +``` + +### 在线安装 + +通过 OpenWrt Web 界面或命令行: + +```bash +opkg update +opkg install luci-app-fileassistant +``` + +## 配置 + +### 路径白名单 + +默认允许访问以下目录: + +| 路径 | 用途 | +|------|------| +| `/mnt` | 挂载存储 | +| `/etc` | 系统配置 | +| `/root` | 用户目录 | +| `/tmp` | 临时文件 | +| `/www` | Web 根目录 | + +如需修改白名单,编辑 `luasrc/controller/fileassistant.lua`: + +```lua +local ALLOWED_PATHS = { + "/mnt", + "/etc", + "/root", + "/tmp", + "/www" +} +``` + +### 上传限制 + +默认最大上传文件大小: **500MB** + +修改 `luasrc/controller/fileassistant.lua`: + +```lua +local MAX_UPLOAD_SIZE = 500 * 1024 * 1024 -- 500MB +``` + +## 使用方法 + +1. 登录 LuCI 管理界面 +2. 进入 **NAS → 文件助手** +3. 使用顶部路径栏导航目录 +4. 点击文件夹进入,双击 `..` 返回上级 +5. 使用右侧按钮进行重命名/删除操作 +6. 点击文件名预览/下载文件 + +## 目录结构 + +``` +luci-app-fileassistant/ +├── htdocs/ +│ └── luci-static/ +│ └── resources/ +│ └── fileassistant/ +│ ├── fb.css # 样式表 +│ ├── fb.js # 前端脚本 +│ ├── file-icon.png # 文件图标 +│ ├── folder-icon.png # 文件夹图标 +│ └── link-icon.png # 链接图标 +├── luasrc/ +│ ├── controller/ +│ │ └── fileassistant.lua # 后端控制器 +│ └── view/ +│ └── fileassistant.htm # 模板 +├── root/ +│ └── usr/ +│ └── share/ +│ └── rpcd/ +│ └── acl.d/ +│ └── luci-app-fileassistant.json # ACL 权限 +└── Makefile +``` + +## 安全说明 + +- 所有文件操作使用 Lua 原生 API,避免 shell 命令注入 +- 路径访问受白名单限制,防止目录遍历 +- 文件名经过严格过滤,禁止特殊字符 +- 前端输出经过 HTML 转义,防止 XSS 攻击 +- 上传文件大小受限 + +## 更新日志 + +### v2.0.0 (2026-03-22) + +- 重构后端代码,使用 `nixio.fs` 替代 `popen` 调用 +- 添加路径白名单安全机制 +- 添加上传文件大小限制 (500MB) +- 修复 XSS 安全漏洞 +- 修复资源泄漏问题 +- 添加上传进度显示 +- 优化文件列表渲染性能 +- 完善 MIME 类型支持 +- 添加响应式布局支持 + +### v1.x + +- 初始版本,基于 luci-app-filebrowser + +## 许可证 + +Apache License 2.0 + +## 致谢 + +- 原始项目: [luci-app-filebrowser](https://github.com/DarkDean89/luci-app-filebrowser) +- 灵感来源: [oh-my-openwrt](https://github.com/stuarthua/oh-my-openwrt) + +## 反馈 + +- Issue: [GitHub Issues](https://github.com/kenzok78/luci-app-fileassistant/issues) +- 邮件: 请通过 GitHub Issues 联系 diff --git a/openwrt-packages/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.css b/openwrt-packages/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.css index 96cbbb3fc5..d0bf995750 100644 --- a/openwrt-packages/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.css +++ b/openwrt-packages/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.css @@ -1,18 +1,23 @@ .fb-container { margin-top: 1rem; } + .fb-container .cbi-button { height: 1.8rem; + margin-right: 0.25rem; } + .fb-container .cbi-input-text { margin-bottom: 1rem; width: 100%; } + .fb-container .panel-title { padding-bottom: 0; width: 50%; border-bottom: none; } + .fb-container .panel-container { display: flex; align-items: center; @@ -20,49 +25,107 @@ padding-bottom: 1rem; border-bottom: 1px solid #eee; } + .fb-container .upload-container { display: none; margin: 1rem 0; + align-items: center; + gap: 1rem; } + .fb-container .upload-file { - margin-right: 2rem; + max-width: 20rem; } + .fb-container .cbi-value-field { text-align: left; } + .fb-container .parent-icon strong { margin-left: 1rem; } + .fb-container td[class$="-icon"] { cursor: pointer; } -.fb-container .file-icon, .fb-container .folder-icon, .fb-container .link-icon { + +.fb-container .file-icon, +.fb-container .folder-icon, +.fb-container .link-icon { position: relative; } -.fb-container .file-icon:before, .fb-container .folder-icon:before, .fb-container .link-icon:before { + +.fb-container .file-icon:before, +.fb-container .folder-icon:before, +.fb-container .link-icon:before { display: inline-block; width: 1.5rem; height: 1.5rem; content: ''; background-size: contain; + background-repeat: no-repeat; margin: 0 0.5rem 0 1rem; vertical-align: middle; } + .fb-container .file-icon:before { - background-image: url(file-icon.png); + background-image: url(/luci-static/resources/fileassistant/file-icon.png); } + .fb-container .folder-icon:before { - background-image: url(folder-icon.png); + background-image: url(/luci-static/resources/fileassistant/folder-icon.png); } + .fb-container .link-icon:before { - background-image: url(link-icon.png); + background-image: url(/luci-static/resources/fileassistant/link-icon.png); } -@media screen and (max-width: 480px) { + +.fb-container .parent-icon:before { + display: inline-block; + width: 1.5rem; + height: 1.5rem; + content: '↑'; + font-size: 1.2rem; + text-align: center; + line-height: 1.5rem; + margin: 0 0.5rem 0 1rem; + vertical-align: middle; +} + +.fb-container .cbi-section-table { + width: 100%; + border-collapse: collapse; +} + +.fb-container .cbi-section-table-row td { + padding: 0.5rem; + border-bottom: 1px solid #eee; +} + +.fb-container .cbi-section-table-cell { + white-space: nowrap; + text-align: right !important; +} + +@media screen and (max-width: 768px) { .fb-container .upload-file { - width: 14.6rem; + width: 100%; + max-width: 14.6rem; } + .fb-container .cbi-value-owner, .fb-container .cbi-value-perm { display: none; } + + .fb-container .cbi-section-table { + font-size: 0.9rem; + } +} + +@media screen and (max-width: 480px) { + .fb-container .cbi-value-date, + .fb-container .cbi-value-size { + display: none; + } } diff --git a/openwrt-packages/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.js b/openwrt-packages/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.js index 2e3addef81..f4fef6ec4c 100644 --- a/openwrt-packages/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.js +++ b/openwrt-packages/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.js @@ -1,34 +1,49 @@ -String.prototype.replaceAll = function(search, replacement) { - var target = this; - return target.replace(new RegExp(search, 'g'), replacement); -}; (function () { + 'use strict'; + + function escapeHtml(str) { + if (str === null || str === undefined) { + return ''; + } + var div = document.createElement('div'); + div.textContent = String(str); + return div.innerHTML; + } + var iwxhr = new XHR(); var listElem = document.getElementById("list-content"); listElem.onclick = handleClick; var currentPath; var pathElem = document.getElementById("current-path"); + pathElem.onblur = function () { - update_list(this.value.trim()); + var newPath = this.value.trim(); + if (newPath && newPath !== currentPath) { + update_list(newPath); + } }; + pathElem.onkeyup = function (evt) { - if (evt.keyCode == 13) { + if (evt.keyCode === 13) { this.blur(); } }; + function removePath(filename, isdir) { - var c = confirm('你确定要删除 ' + filename + ' 吗?'); - if (c) { - iwxhr.get('/cgi-bin/luci/admin/nas/fileassistant/delete', - { + var msg = isdir === "1" ? '你确定要删除目录 ' : '你确定要删除文件 '; + if (confirm(msg + escapeHtml(filename) + ' 吗?')) { + iwxhr.get('/cgi-bin/luci/admin/nas/fileassistant/delete', { path: concatPath(currentPath, filename), isdir: isdir }, function (x, res) { if (res.ec === 0) { refresh_list(res.data, currentPath); + } else { + alert('删除失败: ' + (res.error || '未知错误')); } - }); + } + ); } } @@ -37,53 +52,51 @@ String.prototype.replaceAll = function(search, replacement) { alert('这是一个目录,请选择 ipk 文件进行安装!'); return; } - var isipk = isIPK(filename); - if (isipk === 0) { + if (!isIPK(filename)) { alert('只允许安装 ipk 格式的文件!'); return; } - var c = confirm('你确定要安装 ' + filename + ' 吗?'); - if (c) { - iwxhr.get('/cgi-bin/luci/admin/nas/fileassistant/install', - { + if (confirm('你确定要安装 ' + escapeHtml(filename) + ' 吗?')) { + iwxhr.get('/cgi-bin/luci/admin/nas/fileassistant/install', { filepath: concatPath(currentPath, filename), isdir: isdir }, function (x, res) { if (res.ec === 0) { - location.reload(); alert('安装成功!'); + location.reload(); } else { - alert('安装失败,请检查文件格式!'); + alert('安装失败: ' + (res.error || '请检查文件格式')); } - }); + } + ); } } function isIPK(filename) { - var index= filename.lastIndexOf("."); - var ext = filename.substr(index+1); - if (ext === 'ipk') { - return 1; - } else { - return 0; - } + var ext = filename.slice(filename.lastIndexOf(".") + 1); + return ext.toLowerCase() === 'ipk' ? 1 : 0; } function renamePath(filename) { var newname = prompt('请输入新的文件名:', filename); if (newname) { newname = newname.trim(); - if (newname != filename) { + if (newname && newname !== filename) { + if (!/^[\w\-.\s]+$/.test(newname)) { + alert('文件名包含非法字符'); + return; + } var newpath = concatPath(currentPath, newname); - iwxhr.get('/cgi-bin/luci/admin/nas/fileassistant/rename', - { + iwxhr.get('/cgi-bin/luci/admin/nas/fileassistant/rename', { filepath: concatPath(currentPath, filename), newpath: newpath }, function (x, res) { if (res.ec === 0) { refresh_list(res.data, currentPath); + } else { + alert('重命名失败: ' + (res.error || '未知错误')); } } ); @@ -99,184 +112,245 @@ String.prototype.replaceAll = function(search, replacement) { } function getFileElem(elem) { - if (elem.className.indexOf('-icon') > -1) { + if (!elem) { + return null; + } + if (elem.className && elem.className.indexOf('-icon') > -1) { return elem; } - else if (elem.parentNode.className.indexOf('-icon') > -1) { + if (elem.parentNode && elem.parentNode.className && elem.parentNode.className.indexOf('-icon') > -1) { return elem.parentNode; } + return null; } function concatPath(path, filename) { if (path === '/') { return path + filename; } - else { - return path.replace(/\/$/, '') + '/' + filename; - } + return path.replace(/\/$/, '') + '/' + filename; } function handleClick(evt) { var targetElem = evt.target; + if (!targetElem) { + return; + } + var targetClass = targetElem.className || ''; var infoElem; - if (targetElem.className.indexOf('cbi-button-remove') > -1) { - infoElem = targetElem.parentNode.parentNode; - removePath(infoElem.dataset['filename'] , infoElem.dataset['isdir']) - } - else if (targetElem.className.indexOf('cbi-button-install') > -1) { - infoElem = targetElem.parentNode.parentNode; - installPath(infoElem.dataset['filename'] , infoElem.dataset['isdir']) - } - else if (targetElem.className.indexOf('cbi-button-edit') > -1) { - renamePath(targetElem.parentNode.parentNode.dataset['filename']); - } - else if (targetElem = getFileElem(targetElem)) { - if (targetElem.className.indexOf('parent-icon') > -1) { - update_list(currentPath.replace(/\/[^/]+($|\/$)/, '')); + + if (targetClass.indexOf('cbi-button-remove') > -1) { + infoElem = targetElem.closest('tr'); + if (infoElem) { + removePath(infoElem.dataset.filename, infoElem.dataset.isdir); } - else if (targetElem.className.indexOf('file-icon') > -1) { - openpath(targetElem.parentNode.dataset['filename']); + } else if (targetClass.indexOf('cbi-button-install') > -1) { + infoElem = targetElem.closest('tr'); + if (infoElem) { + installPath(infoElem.dataset.filename, infoElem.dataset.isdir); } - else if (targetElem.className.indexOf('link-icon') > -1) { - infoElem = targetElem.parentNode; - var filepath = infoElem.dataset['linktarget']; - if (filepath) { - if (infoElem.dataset['isdir'] === "1") { - update_list(filepath); - } - else { - var lastSlash = filepath.lastIndexOf('/'); - openpath(filepath.substring(lastSlash + 1), filepath.substring(0, lastSlash)); + } else if (targetClass.indexOf('cbi-button-edit') > -1) { + infoElem = targetElem.closest('tr'); + if (infoElem) { + renamePath(infoElem.dataset.filename); + } + } else { + var fileElem = getFileElem(targetElem); + if (fileElem) { + var fileClass = fileElem.className || ''; + var row = fileElem.closest('tr'); + if (fileClass.indexOf('parent-icon') > -1) { + update_list(currentPath.replace(/\/[^/]+(\/|$)/, '')); + } else if (fileClass.indexOf('file-icon') > -1 && row) { + openpath(row.dataset.filename); + } else if (fileClass.indexOf('link-icon') > -1) { + if (row && row.dataset.linktarget) { + if (row.dataset.isdir === "1") { + update_list(row.dataset.linktarget); + } else { + var target = row.dataset.linktarget; + var lastSlash = target.lastIndexOf('/'); + openpath(target.substring(lastSlash + 1), target.substring(0, lastSlash || 1)); + } } + } else if (fileClass.indexOf('folder-icon') > -1 && row) { + update_list(concatPath(currentPath, row.dataset.filename)); } } - else if (targetElem.className.indexOf('folder-icon') > -1) { - update_list(concatPath(currentPath, targetElem.parentNode.dataset['filename'])) - } } } + function refresh_list(filenames, path) { var listHtml = ''; if (path !== '/') { listHtml += ''; } - if (filenames) { + if (filenames && filenames.length) { for (var i = 0; i < filenames.length; i++) { var line = filenames[i]; if (line) { - var f = line.match(/(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+([\S\s]+)/); - var isLink = f[1][0] === 'z' || f[1][0] === 'l' || f[1][0] === 'x'; - var o = { - displayname: f[9], - filename: isLink ? f[9].split(' -> ')[0] : f[9], - perms: f[1], - date: f[7] + ' ' + f[6] + ' ' + f[8], - size: f[5], - owner: f[3], - icon: (f[1][0] === 'd') ? "folder-icon" : (isLink ? "link-icon" : "file-icon") - }; - - var install_btn = ''; - var index= o.filename.lastIndexOf("."); - var ext = o.filename.substr(index+1); - if (ext === 'ipk') { - install_btn = ''; + var f = line.match(/^([drwl-][r-][w-][x-][r-][w-][x-][r-][w-][x-])\s+(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\S+\s+\d+\s+\d+:\d+)\s+(.+)$/); + if (!f) { + continue; } - - listHtml += '' - + '' + + '' + + '' + + '' + + '' + + '' + + '' - + '' - + '' - + '' - + '' - + '' + ''; } } } - listHtml += "
..
' - + '' + o.displayname + '' + var perm = f[1]; + var owner = f[3]; + var size = f[5]; + var date = f[6]; + var name = f[7]; + var isLink = perm[0] === 'l' || perm[0] === 'z' || perm[0] === 'x'; + var displayname = name; + var filename = name; + var linktarget = ''; + if (isLink && name.indexOf(' -> ') > -1) { + var parts = name.split(' -> '); + displayname = parts[0] + ' -> ' + escapeHtml(parts[1]); + filename = parts[0]; + linktarget = parts[1]; + } else { + displayname = escapeHtml(name); + } + var icon = (perm[0] === 'd') ? 'folder-icon' : (isLink ? 'link-icon' : 'file-icon'); + var installBtn = ''; + if (filename.slice(filename.lastIndexOf('.') + 1).toLowerCase() === 'ipk') { + installBtn = ''; + } + listHtml += '
' + displayname + '' + escapeHtml(owner) + '' + escapeHtml(date) + '' + escapeHtml(size) + '' + escapeHtml(perm) + '' + + '' + + '' + + installBtn + ''+o.owner+''+o.date+''+o.size+''+o.perms+'\ - \ - ' - + install_btn - + '
"; + listHtml += ''; listElem.innerHTML = listHtml; } + function update_list(path, opt) { opt = opt || {}; path = concatPath(path, ''); - if (currentPath != path) { - iwxhr.get('/cgi-bin/luci/admin/nas/fileassistant/list', - {path: path}, + if (currentPath !== path) { + iwxhr.get('/cgi-bin/luci/admin/nas/fileassistant/list', { + path: path + }, function (x, res) { if (res.ec === 0) { refresh_list(res.data, path); - } - else { + } else { refresh_list([], path); + if (res.error) { + console.error('Error:', res.error); + } } } ); if (!opt.popState) { - history.pushState({path: path}, null, '?path=' + path); + history.pushState({path: path}, null, '?path=' + encodeURIComponent(path)); } currentPath = path; pathElem.value = currentPath; } - }; + } var uploadToggle = document.getElementById('upload-toggle'); var uploadContainer = document.getElementById('upload-container'); var isUploadHide = true; - uploadToggle.onclick = function() { - if (isUploadHide) { - uploadContainer.style.display = 'inline-flex'; - } - else { - uploadContainer.style.display = 'none'; - } - isUploadHide = !isUploadHide; - }; - var uploadBtn = uploadContainer.getElementsByClassName('cbi-input-apply')[0]; - uploadBtn.onclick = function (evt) { - var uploadinput = document.getElementById('upload-file'); - var fullPath = uploadinput.value; - if (!fullPath) { + + if (uploadToggle && uploadContainer) { + uploadToggle.onclick = function () { + isUploadHide = !isUploadHide; + uploadContainer.style.display = isUploadHide ? 'none' : 'inline-flex'; + }; + } + + var uploadBtn = uploadContainer ? uploadContainer.querySelector('.cbi-input-apply') : null; + if (uploadBtn) { + uploadBtn.onclick = function (evt) { evt.preventDefault(); - } - else { + var uploadInput = document.getElementById('upload-file'); + if (!uploadInput || !uploadInput.files || !uploadInput.files[0]) { + alert('请选择要上传的文件'); + return; + } + var file = uploadInput.files[0]; var formData = new FormData(); - var startIndex = (fullPath.indexOf('\\') >= 0 ? fullPath.lastIndexOf('\\') : fullPath.lastIndexOf('/')); - formData.append('upload-filename', fullPath.substring(startIndex + 1)); + var filename = file.name; + var lastSlash = Math.max(filename.lastIndexOf('\\'), filename.lastIndexOf('/')); + if (lastSlash >= 0) { + filename = filename.substring(lastSlash + 1); + } + formData.append('upload-filename', filename); formData.append('upload-dir', concatPath(currentPath, '')); - formData.append('upload-file', uploadinput.files[0]); + formData.append('upload-file', file); + var xhr = new XMLHttpRequest(); - xhr.open("POST", "/cgi-bin/luci/admin/nas/fileassistant/upload", true); - xhr.onload = function() { - if (xhr.status == 200) { - var res = JSON.parse(xhr.responseText); - refresh_list(res.data, currentPath); - uploadinput.value = ''; + xhr.open('POST', '/cgi-bin/luci/admin/nas/fileassistant/upload', true); + + xhr.upload.onprogress = function (e) { + if (e.lengthComputable) { + var percent = Math.round((e.loaded / e.total) * 100); + console.log('Upload: ' + percent + '%'); } - else { + }; + + xhr.onload = function () { + if (xhr.status === 200) { + try { + var res = JSON.parse(xhr.responseText); + if (res.ec === 0) { + refresh_list(res.data, currentPath); + uploadInput.value = ''; + alert('上传成功!'); + } else { + alert('上传失败: ' + (res.error || '未知错误')); + } + } catch (e) { + alert('上传失败: 响应解析错误'); + } + } else { alert('上传失败,请稍后再试...'); } }; - xhr.send(formData); - } - }; - document.addEventListener('DOMContentLoaded', function(evt) { + xhr.onerror = function () { + alert('上传失败,请检查网络连接'); + }; + + xhr.send(formData); + }; + } + + function init() { var initPath = '/'; - if (/path=([/\w]+)/.test(location.search)) { - initPath = RegExp.$1; + var match = location.search.match(/path=([^&]+)/); + if (match && match[1]) { + try { + initPath = decodeURIComponent(match[1]); + } catch (e) { + initPath = '/'; + } } update_list(initPath, {popState: true}); - }); + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); + } else { + init(); + } + window.addEventListener('popstate', function (evt) { var path = '/'; if (evt.state && evt.state.path) { @@ -285,4 +359,4 @@ String.prototype.replaceAll = function(search, replacement) { update_list(path, {popState: true}); }); -})(); \ No newline at end of file +})(); diff --git a/openwrt-packages/luci-app-fileassistant/luasrc/controller/fileassistant.lua b/openwrt-packages/luci-app-fileassistant/luasrc/controller/fileassistant.lua index 0899edf339..b5fe2a6b46 100644 --- a/openwrt-packages/luci-app-fileassistant/luasrc/controller/fileassistant.lua +++ b/openwrt-packages/luci-app-fileassistant/luasrc/controller/fileassistant.lua @@ -1,9 +1,19 @@ module("luci.controller.fileassistant", package.seeall) -function index() - entry({"admin", "nas"}, firstchild(), _("NAS") , 45).dependent = false +require("nixio.fs") - entry({"admin", "nas"}, firstchild(), "NAS", 44).dependent = false +local ALLOWED_PATHS = { + "/mnt", + "/etc", + "/root", + "/tmp", + "/www" +} + +local MAX_UPLOAD_SIZE = 500 * 1024 * 1024 + +function index() + entry({"admin", "nas"}, firstchild(), _("NAS"), 44).dependent = false local page page = entry({"admin", "nas", "fileassistant"}, template("fileassistant"), _("文件助手"), 1) @@ -11,27 +21,15 @@ function index() page.dependent = true page.acl_depends = { "luci-app-fileassistant" } - page = entry({"admin", "nas", "fileassistant", "list"}, call("fileassistant_list"), nil) - page.leaf = true - - page = entry({"admin", "nas", "fileassistant", "open"}, call("fileassistant_open"), nil) - page.leaf = true - - page = entry({"admin", "nas", "fileassistant", "delete"}, call("fileassistant_delete"), nil) - page.leaf = true - - page = entry({"admin", "nas", "fileassistant", "rename"}, call("fileassistant_rename"), nil) - page.leaf = true - - page = entry({"admin", "nas", "fileassistant", "upload"}, call("fileassistant_upload"), nil) - page.leaf = true - - page = entry({"admin", "nas", "fileassistant", "install"}, call("fileassistant_install"), nil) - page.leaf = true - + entry({"admin", "nas", "fileassistant", "list"}, call("fileassistant_list"), nil) + entry({"admin", "nas", "fileassistant", "open"}, call("fileassistant_open"), nil) + entry({"admin", "nas", "fileassistant", "delete"}, call("fileassistant_delete"), nil) + entry({"admin", "nas", "fileassistant", "rename"}, call("fileassistant_rename"), nil) + entry({"admin", "nas", "fileassistant", "upload"}, call("fileassistant_upload"), nil) + entry({"admin", "nas", "fileassistant", "install"}, call("fileassistant_install"), nil) end -function list_response(path, success) +function list_response(path, success, error_msg) luci.http.prepare_content("application/json") local result if success then @@ -42,191 +40,375 @@ function list_response(path, success) } else result = { - ec = 1 + ec = 1, + error = error_msg or "Operation failed" } end luci.http.write_json(result) end +function is_path_allowed(path) + if not path or path == "" then + return false + end + local realpath = nixio.fs.realpath(path) + if not realpath then + return false + end + for _, allowed in ipairs(ALLOWED_PATHS) do + if realpath:find("^" .. allowed) or realpath == allowed then + return true, realpath + end + end + return false, realpath +end + +function sanitize_path(path) + if not path then + return nil + end + path = path:gsub("<>", "/"):gsub("//+", "/"):gsub("/$", "") + if path == "" then + return "/" + end + return path +end + function fileassistant_list() - local path = luci.http.formvalue("path") + local path = sanitize_path(luci.http.formvalue("path")) or "/" + local allowed, realpath = is_path_allowed(path) + if not allowed then + list_response(path, false, "Path not allowed") + return + end + if not nixio.fs.stat(realpath, "type") == "dir" and not nixio.fs.stat(realpath) then + list_response(path, false, "Invalid directory") + return + end list_response(path, true) end function fileassistant_open() - local path = luci.http.formvalue("path") - local filename = luci.http.formvalue("filename") - local io = require "io" + local path = sanitize_path(luci.http.formvalue("path")) or "/" + local filename = luci.http.formvalue("filename") or "" + local allowed, realpath = is_path_allowed(path) + if not allowed then + luci.http.status(403, "Forbidden") + return + end + if filename:match("[\\/]") or filename:match("%..*%.") then + luci.http.status(400, "Invalid filename") + return + end + local filepath = realpath .. "/" .. filename + if not nixio.fs.stat(filepath) then + luci.http.status(404, "File not found") + return + end local mime = to_mime(filename) - - file = path..filename - - local download_fpi = io.open(file, "r") - luci.http.header('Content-Disposition', 'inline; filename="'..filename..'"' ) + local fp = io.open(filepath, "r") + if not fp then + luci.http.status(500, "Cannot open file") + return + end + luci.http.header('Content-Disposition', 'inline; filename="' .. filename .. '"') luci.http.prepare_content(mime) - luci.ltn12.pump.all(luci.ltn12.source.file(download_fpi), luci.http.write) + luci.ltn12.pump.all(luci.ltn12.source.file(fp), luci.http.write) + fp:close() end function fileassistant_delete() - local path = luci.http.formvalue("path") + local path = sanitize_path(luci.http.formvalue("path")) local isdir = luci.http.formvalue("isdir") - path = path:gsub("<>", "/") - path = path:gsub(" ", "\ ") - local success - if isdir then - success = os.execute('rm -r "'..path..'"') - else - success = os.remove(path) + if not path then + list_response("/", false, "Invalid path") + return end - list_response(nixio.fs.dirname(path), success) + local allowed, realpath = is_path_allowed(path) + if not allowed then + list_response(path, false, "Path not allowed") + return + end + local success, err + if isdir == "1" then + if nixio.fs.stat(realpath, "type") == "dir" then + success, err = rmtree(realpath) + else + success = false + err = "Not a directory" + end + else + if nixio.fs.stat(realpath, "type") == "reg" then + success = nixio.fs.unlink(realpath) + err = success and nil or "Failed to delete file" + else + success = false + err = "Not a regular file" + end + end + list_response(nixio.fs.dirname(realpath), success, err) +end + +function rmtree(path) + local handle = nixio.fs.dir(path) + if handle then + for entry in handle do + if entry ~= "." and entry ~= ".." then + local subpath = path .. "/" .. entry + if nixio.fs.stat(subpath, "type") == "dir" then + if not rmtree(subpath) then + return false + end + else + if not nixio.fs.unlink(subpath) then + return false + end + end + end + end + handle:close() + end + return nixio.fs.rmdir(path) end function fileassistant_rename() local filepath = luci.http.formvalue("filepath") local newpath = luci.http.formvalue("newpath") - local success = os.execute('mv "'..filepath..'" "'..newpath..'"') - list_response(nixio.fs.dirname(filepath), success) + if not filepath or not newpath then + list_response("/", false, "Invalid parameters") + return + end + local old_allowed, old_realpath = is_path_allowed(filepath) + local new_allowed, new_realpath = is_path_allowed(newpath) + if not old_allowed or not new_allowed then + list_response(filepath, false, "Path not allowed") + return + end + if not nixio.fs.stat(old_realpath) then + list_response(filepath, false, "Source file not found") + return + end + local success = nixio.fs.rename(old_realpath, new_realpath) + list_response(nixio.fs.dirname(old_realpath), success, success and nil or "Rename failed") end function fileassistant_install() local filepath = luci.http.formvalue("filepath") local isdir = luci.http.formvalue("isdir") - local ext = filepath:match(".+%.(%w+)$") - filepath = filepath:gsub("<>", "/") - filepath = filepath:gsub(" ", "\ ") - local success - if isdir == "1" then - success = false - elseif ext == "ipk" then - success = installIPK(filepath) - else - success = false + if not filepath then + list_response("/", false, "Invalid filepath") + return end - list_response(nixio.fs.dirname(filepath), success) + local allowed, realpath = is_path_allowed(filepath) + if not allowed then + list_response(filepath, false, "Path not allowed") + return + end + if isdir == "1" then + list_response(realpath, false, "Cannot install directory") + return + end + local ext = filepath:match("%.(%w+)$") + if ext ~= "ipk" then + list_response(realpath, false, "Only ipk files allowed") + return + end + local success, err = installIPK(realpath) + list_response(nixio.fs.dirname(realpath), success, err) end function installIPK(filepath) - luci.sys.exec('opkg --force-depends install "'..filepath..'"') + local output = luci.sys.exec('opkg --force-depends install "' .. filepath .. '" 2>&1') luci.sys.exec('rm -rf /tmp/luci-*') - return true; + if output:match("Installing") and output:match("completed") then + return true + end + return false, output end function fileassistant_upload() - local filecontent = luci.http.formvalue("upload-file") - local filename = luci.http.formvalue("upload-filename") - local uploaddir = luci.http.formvalue("upload-dir") - local filepath = uploaddir..filename - + local uploaddir = sanitize_path(luci.http.formvalue("upload-dir")) or "/" + local allowed, realpath = is_path_allowed(uploaddir) + if not allowed then + list_response(uploaddir, false, "Path not allowed") + return + end + if not nixio.fs.stat(realpath, "type") == "dir" then + list_response(uploaddir, false, "Invalid directory") + return + end + local filename + local filepath + local uploaded_size = 0 local fp - luci.http.setfilehandler( - function(meta, chunk, eof) - if not fp and meta and meta.name == "upload-file" then - fp = io.open(filepath, "w") + luci.http.setfilehandler(function(meta, chunk, eof) + if not fp and meta and meta.name == "upload-file" then + filename = sanitize_filename(meta.file) + if not filename then + return end - if fp and chunk then - fp:write(chunk) + filepath = realpath .. "/" .. filename + fp = io.open(filepath, "w") + if not fp then + return end - if fp and eof then + end + if fp and chunk then + uploaded_size = uploaded_size + #chunk + if uploaded_size > MAX_UPLOAD_SIZE then fp:close() + fp = nil + nixio.fs.unlink(filepath) + return end - end - ) - + fp:write(chunk) + end + if fp and eof then + fp:close() + end + end) list_response(uploaddir, true) end -function scandir(directory) - local i, t, popen = 0, {}, io.popen +function sanitize_filename(filename) + if not filename or filename == "" then + return nil + end + filename = filename:gsub("[^%w%-_.]", "_"):gsub("_+", "_") + if #filename > 255 or filename:match("^%.") then + return nil + end + return filename +end - local pfile = popen("ls -lh \""..directory.."\" | egrep '^d' ; ls -lh \""..directory.."\" | egrep -v '^d|^l'") - for fileinfo in pfile:lines() do - i = i + 1 - t[i] = fileinfo +function scandir(directory) + local results = {} + local allowed, realpath = is_path_allowed(directory) + if not allowed then + return results end - pfile:close() - pfile = popen("ls -lh \""..directory.."\" | egrep '^l' ;") - for fileinfo in pfile:lines() do - i = i + 1 - linkindex, _, linkpath = string.find(fileinfo, "->%s+(.+)$") - local finalpath; - if string.sub(linkpath, 1, 1) == "/" then - finalpath = linkpath - else - finalpath = nixio.fs.realpath(directory..linkpath) - end - local linktype; - if not finalpath then - finalpath = linkpath; - linktype = 'x' - elseif nixio.fs.stat(finalpath, "type") == "dir" then - linktype = 'z' - else - linktype = 'l' - end - fileinfo = string.sub(fileinfo, 2, linkindex - 1) - fileinfo = linktype..fileinfo.."-> "..finalpath - t[i] = fileinfo + local dir = nixio.fs.dir(realpath) + if not dir then + return results end - pfile:close() - return t + local entries = {} + for entry in dir do + if entry ~= "." and entry ~= ".." then + table.insert(entries, entry) + end + end + dir:close() + table.sort(entries) + for _, name in ipairs(entries) do + local fullpath = realpath .. "/" .. name + local stat = nixio.fs.stat(fullpath) + if stat then + local filetype = stat.type + local size = stat.size or 0 + local mtime = stat.mtime or 0 + local perms = stat.modedec or "---------" + + local line + if filetype == "dir" then + line = string.format("drwxr-xr-x %6d %-8s %-8s %10d %s %s", + 1, stat.uid or "root", stat.gid or "root", size, + os.date("%b %d %H:%M", mtime), name) + elseif filetype == "lnk" then + local target = nixio.fs.readlink(fullpath) + local linktype = "l" + if target then + local target_real = nixio.fs.realpath(fullpath) + if target_real then + local target_stat = nixio.fs.stat(target_real) + if target_stat and target_stat.type == "dir" then + linktype = "z" + end + end + end + line = string.format("%srwxr-xr-x %6d %-8s %-8s %10d %s %s -> %s", + linktype, 1, stat.uid or "root", stat.gid or "root", size, + os.date("%b %d %H:%M", mtime), name, target or "") + else + line = string.format("-rw-r--r-- %6d %-8s %-8s %10d %s %s", + 1, stat.uid or "root", stat.gid or "root", size, + os.date("%b %d %H:%M", mtime), name) + end + table.insert(results, line) + end + end + return results end MIME_TYPES = { - ["txt"] = "text/plain"; - ["conf"] = "text/plain"; - ["ovpn"] = "text/plain"; - ["log"] = "text/plain"; - ["js"] = "text/javascript"; - ["json"] = "application/json"; - ["css"] = "text/css"; - ["htm"] = "text/html"; - ["html"] = "text/html"; - ["patch"] = "text/x-patch"; - ["c"] = "text/x-csrc"; - ["h"] = "text/x-chdr"; - ["o"] = "text/x-object"; - ["ko"] = "text/x-object"; - - ["bmp"] = "image/bmp"; - ["gif"] = "image/gif"; - ["png"] = "image/png"; - ["jpg"] = "image/jpeg"; - ["jpeg"] = "image/jpeg"; - ["svg"] = "image/svg+xml"; - - ["zip"] = "application/zip"; - ["pdf"] = "application/pdf"; - ["xml"] = "application/xml"; - ["xsl"] = "application/xml"; - ["doc"] = "application/msword"; - ["ppt"] = "application/vnd.ms-powerpoint"; - ["xls"] = "application/vnd.ms-excel"; - ["odt"] = "application/vnd.oasis.opendocument.text"; - ["odp"] = "application/vnd.oasis.opendocument.presentation"; - ["pl"] = "application/x-perl"; - ["sh"] = "application/x-shellscript"; - ["php"] = "application/x-php"; - ["deb"] = "application/x-deb"; - ["iso"] = "application/x-cd-image"; - ["tgz"] = "application/x-compressed-tar"; - - ["mp3"] = "audio/mpeg"; - ["ogg"] = "audio/x-vorbis+ogg"; - ["wav"] = "audio/x-wav"; - - ["mpg"] = "video/mpeg"; - ["mpeg"] = "video/mpeg"; - ["avi"] = "video/x-msvideo"; + ["txt"] = "text/plain", + ["conf"] = "text/plain", + ["ovpn"] = "text/plain", + ["log"] = "text/plain", + ["js"] = "text/javascript", + ["json"] = "application/json", + ["css"] = "text/css", + ["htm"] = "text/html", + ["html"] = "text/html", + ["patch"] = "text/x-patch", + ["c"] = "text/x-csrc", + ["h"] = "text/x-chdr", + ["o"] = "text/x-object", + ["ko"] = "text/x-object", + ["bmp"] = "image/bmp", + ["gif"] = "image/gif", + ["png"] = "image/png", + ["jpg"] = "image/jpeg", + ["jpeg"] = "image/jpeg", + ["svg"] = "image/svg+xml", + ["webp"] = "image/webp", + ["ico"] = "image/x-icon", + ["zip"] = "application/zip", + ["pdf"] = "application/pdf", + ["xml"] = "application/xml", + ["xsl"] = "application/xml", + ["doc"] = "application/msword", + ["ppt"] = "application/vnd.ms-powerpoint", + ["xls"] = "application/vnd.ms-excel", + ["odt"] = "application/vnd.oasis.opendocument.text", + ["odp"] = "application/vnd.oasis.opendocument.presentation", + ["pl"] = "application/x-perl", + ["sh"] = "application/x-shellscript", + ["bash"] = "application/x-shellscript", + ["zsh"] = "application/x-shellscript", + ["php"] = "application/x-php", + ["deb"] = "application/x-deb", + ["ipk"] = "application/x-ipkg", + ["iso"] = "application/x-cd-image", + ["tar"] = "application/x-tar", + ["gz"] = "application/gzip", + ["tgz"] = "application/x-compressed-tar", + ["xz"] = "application/x-xz", + ["bz2"] = "application/x-bzip2", + ["7z"] = "application/x-7z-compressed", + ["rar"] = "application/vnd.rar", + ["bin"] = "application/octet-stream", + ["img"] = "application/octet-stream", + ["apk"] = "application/vnd.android.package-archive", + ["mp3"] = "audio/mpeg", + ["ogg"] = "audio/x-vorbis+ogg", + ["wav"] = "audio/x-wav", + ["flac"] = "audio/flac", + ["aac"] = "audio/aac", + ["mpg"] = "video/mpeg", + ["mpeg"] = "video/mpeg", + ["mp4"] = "video/mp4", + ["avi"] = "video/x-msvideo", + ["mkv"] = "video/x-matroska", + ["webm"] = "video/webm", + ["mov"] = "video/quicktime" } function to_mime(filename) if type(filename) == "string" then - local ext = filename:match("[^%.]+$") - + local ext = filename:match("%.([^%.]+)$") if ext and MIME_TYPES[ext:lower()] then return MIME_TYPES[ext:lower()] end end - return "application/octet-stream" -end \ No newline at end of file +end diff --git a/openwrt-packages/luci-app-fileassistant/root/usr/share/rpcd/acl.d/luci-app-fileassistant.json b/openwrt-packages/luci-app-fileassistant/root/usr/share/rpcd/acl.d/luci-app-fileassistant.json index 8db4ea32f9..b6055ac50a 100644 --- a/openwrt-packages/luci-app-fileassistant/root/usr/share/rpcd/acl.d/luci-app-fileassistant.json +++ b/openwrt-packages/luci-app-fileassistant/root/usr/share/rpcd/acl.d/luci-app-fileassistant.json @@ -1,11 +1,16 @@ { "luci-app-fileassistant": { - "description": "Grant UCI access for luci-app-fileassistant", + "description": "Grant file access permissions for luci-app-fileassistant", "read": { - "uci": [ "fileassistant" ] + "ubus": { + "file": ["list", "read"] + } }, "write": { - "uci": [ "fileassistant" ] + "ubus": { + "file": ["write", "remove"] + }, + "cgi-io": ["upload"] } } } diff --git a/openwrt-packages/luci-app-guest-wifi/Makefile b/openwrt-packages/luci-app-guest-wifi/Makefile index 3064d53f97..22df899c81 100644 --- a/openwrt-packages/luci-app-guest-wifi/Makefile +++ b/openwrt-packages/luci-app-guest-wifi/Makefile @@ -1,13 +1,19 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-guest-wifi +PKG_MAINTAINER:=kenzok8 PKG_VERSION:=2.0.1 -PKG_RELEASE:=1 +PKG_RELEASE:=2 LUCI_TITLE:=LuCI support for guest-wifi LUCI_DEPENDS:=+luci-base +luci-compat LUCI_PKGARCH:=all +LUCI_DESCRIPTION:=Simple guest WiFi configuration interface for LuCI + +define Package/$(PKG_NAME)/conffiles +/etc/config/wireless +endef include $(TOPDIR)/feeds/luci/luci.mk -# call BuildPackage - OpenWrt buildroot signature \ No newline at end of file +# call BuildPackage - OpenWrt buildroot signature diff --git a/openwrt-packages/luci-app-guest-wifi/README.md b/openwrt-packages/luci-app-guest-wifi/README.md index 6abbbbd79e..def7b15d54 100644 --- a/openwrt-packages/luci-app-guest-wifi/README.md +++ b/openwrt-packages/luci-app-guest-wifi/README.md @@ -1 +1,77 @@ -# luci-app-guest-wifi \ No newline at end of file +# luci-app-guest-wifi + +适用于 OpenWrt/LuCI 的访客 WiFi 配置插件。 + +## 功能特性 + +- **访客网络配置**: 通过 Web 界面配置独立的访客无线网络 +- **加密选项**: 支持无加密、WPA2-PSK、WPA3-SAE、WPA2/WPA3 混合模式 +- **AP 隔离**: 可选的客户端隔离功能,防止访客设备之间互相访问 +- **自动生效**: 保存配置后自动重新加载无线设置 + +## 依赖 + +- `luci` +- `luci-base` +- `luci-compat` (用于兼容旧版 LuCI CBI 模型) + +## 安装 + +```bash +# 添加 feed +echo 'src-git guestwifi https://github.com/kenzok78/luci-app-guest-wifi' >> feeds.conf.default +./scripts/feeds update -a +./scripts/feeds install -a -p guestwifi + +# 编译 +make package/luci-app-guest-wifi/compile V=s +``` + +## 使用说明 + +1. 访问 OpenWrt Web 管理界面 → 网络 → 访客WiFi +2. 添加访客 WiFi 配置段(如果没有自动创建) +3. 启用访客网络,设置 SSID 和加密方式 +4. 可选启用 AP 隔离功能 +5. 保存并应用 + +## 配置说明 + +| 选项 | 说明 | +|------|------| +| 启用 | 是否启用访客 WiFi | +| 网络名称(SSID) | 无线网络名称 | +| 加密方式 | 无/WPA2-PSK/WPA3-SAE/WPA2/WPA3混合 | +| 密码 | 无线连接密码(加密模式下必填)| +| AP 隔离 | 防止客户端之间互相通信 | + +## 目录结构 + +``` +luci-app-guest-wifi/ +├── Makefile +├── luasrc/ +│ ├── controller/ # LuCI 控制器 +│ └── model/cbi/ # CBI 模型 (兼容旧版) +├── htdocs/luci-static/resources/view/ +│ └── guest-wifi/wifi.js # JavaScript 视图 (现代 LuCI) +├── po/ # 翻译文件 +└── root/ + ├── etc/ + │ ├── config/ # UCI 配置 (通过 LuCI 管理) + │ ├── init.d/ # 启动脚本 + │ └── uci-defaults/ # 初始化脚本 + └── usr/share/ + ├── luci/menu.d/ # 菜单配置 + └── rpcd/acl.d/ # ACL 权限 +``` + +## 工作原理 + +- 插件通过 UCI 配置管理 `/etc/config/wireless` 中的 `wifi-iface` 段落 +- 通过在 `wifi-iface` 配置中添加 `option guest_wifi '1'` 来标识访客网络 +- 控制器和视图会自动过滤显示所有标记为访客的 WiFi 配置段 + +## 许可证 + +Apache-2.0 diff --git a/openwrt-packages/luci-app-guest-wifi/htdocs/luci-static/resources/view/guest-wifi.js b/openwrt-packages/luci-app-guest-wifi/htdocs/luci-static/resources/view/guest-wifi.js deleted file mode 100755 index 85123258ee..0000000000 --- a/openwrt-packages/luci-app-guest-wifi/htdocs/luci-static/resources/view/guest-wifi.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; -'require form'; -'require view'; -'require uci'; -'require ui'; - -return view.extend({ - load: function() { - return Promise.all([ - uci.load('wireless') - ]); - }, - - render: function() { - const m = new form.Map('wireless', _('Guest WiFi'), - _('Guest WiFi provides a separate wireless network for guest access with isolated permissions.')); - - const s = m.section(form.TypedSection, 'wifi-iface', _('Guest WiFi Settings')); - s.anonymous = true; - s.addremove = true; - - s.option(form.Flag, 'guest_wifi', _('Enable'), - _('Enable guest WiFi network')); - - s.option(form.Value, 'ssid', _('Network Name (SSID)')); - - const o = s.option(form.ListValue, 'encryption', _('Encryption')); - o.value('none', _('No Encryption')); - o.value('psk2', _('WPA2-PSK')); - o.value('sae', _('WPA3-SAE')); - o.value('sae-mixed', _('WPA2/WPA3-Mixed')); - o.default = 'psk2'; - - const key = s.option(form.Value, 'key', _('Password')); - key.depends('encryption', 'psk2'); - key.depends('encryption', 'sae'); - key.depends('encryption', 'sae-mixed'); - key.datatype = 'wpakey'; - key.password = true; - - s.option(form.Flag, 'isolate', _('AP Isolation'), - _('Prevents wireless clients from communicating with each other')); - - return m.render(); - } -}); \ No newline at end of file diff --git a/openwrt-packages/luci-app-guest-wifi/htdocs/luci-static/resources/view/guest-wifi/wifi.js b/openwrt-packages/luci-app-guest-wifi/htdocs/luci-static/resources/view/guest-wifi/wifi.js index ead8f27e51..f9bda8dda3 100755 --- a/openwrt-packages/luci-app-guest-wifi/htdocs/luci-static/resources/view/guest-wifi/wifi.js +++ b/openwrt-packages/luci-app-guest-wifi/htdocs/luci-static/resources/view/guest-wifi/wifi.js @@ -2,57 +2,65 @@ 'require form'; 'require view'; 'require uci'; -'require ui'; return view.extend({ - load: function() { - return Promise.all([ - uci.load('wireless') - ]); - }, + load: function() { + return uci.load('wireless'); + }, - render: function() { - const m = new form.Map('wireless', _('Guest WiFi'), - _('Guest WiFi provides a separate wireless network for guest access with isolated permissions.')); + render: function() { + var m = new form.Map('wireless', _('Guest WiFi'), + _('Guest WiFi provides a separate wireless network for guest access with isolated permissions.')); - const s = m.section(form.TypedSection, 'wifi-iface', _('Guest WiFi Settings')); - s.anonymous = true; - s.addremove = true; - s.filter = function(section_id) { - return uci.get('wireless', section_id, 'guest_wifi') === '1'; - }; + var s = m.section(form.TypedSection, 'wifi-iface', _('Guest WiFi Settings')); + s.anonymous = true; + s.addremove = true; + s.filter = function(section_id) { + return uci.get('wireless', section_id, 'guest_wifi') === '1'; + }; + s.cfgvalue = function(section_id) { + return uci.get('wireless', section_id, 'guest_wifi'); + }; + s.handleApply = function(section, ev) { + uci.save(function() { + uci.apply(function() { + uci.load('wireless'); + XHR.poll(2); + }); + }); + }; - let o; + var o = null; - o = s.option(form.Flag, 'guest_wifi', _('Enable'), - _('Enable guest WiFi network')); - o.rmempty = false; - o.default = '0'; + o = s.option(form.Flag, 'guest_wifi', _('Enable'), + _('Enable guest WiFi network')); + o.rmempty = false; + o.default = '0'; - o = s.option(form.Value, 'ssid', _('Network Name (SSID)')); - o.rmempty = false; + o = s.option(form.Value, 'ssid', _('Network Name (SSID)')); + o.rmempty = false; - o = s.option(form.ListValue, 'encryption', _('Encryption')); - o.value('none', _('No Encryption')); - o.value('psk2', _('WPA2-PSK')); - o.value('sae', _('WPA3-SAE')); - o.value('sae-mixed', _('WPA2/WPA3-Mixed')); - o.rmempty = false; - o.default = 'psk2'; + o = s.option(form.ListValue, 'encryption', _('Encryption')); + o.value('none', _('No Encryption')); + o.value('psk2', _('WPA2-PSK')); + o.value('sae', _('WPA3-SAE')); + o.value('sae-mixed', _('WPA2/WPA3-Mixed')); + o.rmempty = false; + o.default = 'psk2'; - o = s.option(form.Value, 'key', _('Password')); - o.depends('encryption', 'psk2'); - o.depends('encryption', 'sae'); - o.depends('encryption', 'sae-mixed'); - o.datatype = 'wpakey'; - o.rmempty = false; - o.password = true; + o = s.option(form.Value, 'key', _('Password')); + o.depends('encryption', 'psk2'); + o.depends('encryption', 'sae'); + o.depends('encryption', 'sae-mixed'); + o.datatype = 'wpakey'; + o.rmempty = false; + o.password = true; - o = s.option(form.Flag, 'isolate', _('AP Isolation'), - _('Prevents wireless clients from communicating with each other')); - o.rmempty = false; - o.default = '1'; + o = s.option(form.Flag, 'isolate', _('AP Isolation'), + _('Prevents wireless clients from communicating with each other')); + o.rmempty = false; + o.default = '1'; - return m.render(); - } -}); \ No newline at end of file + return m.render(); + } +}); diff --git a/openwrt-packages/luci-app-guest-wifi/luasrc/controller/guest-wifi.lua b/openwrt-packages/luci-app-guest-wifi/luasrc/controller/guest-wifi.lua index 4f39cbba66..a7624ed198 100755 --- a/openwrt-packages/luci-app-guest-wifi/luasrc/controller/guest-wifi.lua +++ b/openwrt-packages/luci-app-guest-wifi/luasrc/controller/guest-wifi.lua @@ -1,9 +1,11 @@ module("luci.controller.guest-wifi", package.seeall) -function index() - if not nixio.fs.access("/etc/config/wireless") then - return - end +local fs = require "nixio.fs" - entry({"admin", "network", "guest-wifi"}, view("guest-wifi/wifi"), _("Guest WiFi"), 60) -end \ No newline at end of file +function index() + if not fs.access("/etc/config/wireless") then + return + end + + entry({"admin", "network", "guest-wifi"}, view("guest-wifi/wifi"), _("Guest WiFi"), 60) +end diff --git a/openwrt-packages/luci-app-guest-wifi/luasrc/model/cbi/guest-wifi/wifi.lua b/openwrt-packages/luci-app-guest-wifi/luasrc/model/cbi/guest-wifi/wifi.lua index 4dfb58bb7c..b321aa86cb 100755 --- a/openwrt-packages/luci-app-guest-wifi/luasrc/model/cbi/guest-wifi/wifi.lua +++ b/openwrt-packages/luci-app-guest-wifi/luasrc/model/cbi/guest-wifi/wifi.lua @@ -1,21 +1,26 @@ +local form = require("form") local m, s, o m = Map("wireless", translate("Guest WiFi"), - translate("Guest WiFi provides a separate wireless network for guest access with isolated permissions.")) + translate("Guest WiFi provides a separate wireless network for guest access with isolated permissions.")) -s = m:section(TypedSection, "wifi-iface", translate("Guest WiFi Settings")) +s = m:section(form.TypedSection, "wifi-iface", translate("Guest WiFi Settings")) s.anonymous = true s.addremove = true +s.filter = function(section_id) + local val = uci:get("wireless", section_id, "guest_wifi") + return val == "1" +end -o = s:option(Flag, "guest_wifi", translate("Enable"), - translate("Enable guest WiFi network")) +o = s:option(form.Flag, "guest_wifi", translate("Enable"), + translate("Enable guest WiFi network")) o.rmempty = false o.default = "0" -o = s:option(Value, "ssid", translate("Network Name (SSID)")) +o = s:option(form.Value, "ssid", translate("Network Name (SSID)")) o.rmempty = false -o = s:option(ListValue, "encryption", translate("Encryption")) +o = s:option(form.ListValue, "encryption", translate("Encryption")) o:value("none", translate("No Encryption")) o:value("psk2", translate("WPA2-PSK")) o:value("sae", translate("WPA3-SAE")) @@ -23,7 +28,7 @@ o:value("sae-mixed", translate("WPA2/WPA3-Mixed")) o.rmempty = false o.default = "psk2" -o = s:option(Value, "key", translate("Password")) +o = s:option(form.Value, "key", translate("Password")) o:depends("encryption", "psk2") o:depends("encryption", "sae") o:depends("encryption", "sae-mixed") @@ -31,9 +36,9 @@ o.datatype = "wpakey" o.rmempty = false o.password = true -o = s:option(Flag, "isolate", translate("AP Isolation"), - translate("Prevents wireless clients from communicating with each other")) +o = s:option(form.Flag, "isolate", translate("AP Isolation"), + translate("Prevents wireless clients from communicating with each other")) o.rmempty = false o.default = "1" -return m \ No newline at end of file +return m diff --git a/openwrt-packages/luci-app-guest-wifi/po/templates/guest-wifi.pot b/openwrt-packages/luci-app-guest-wifi/po/templates/guest-wifi.pot index 5483d560fb..6a6d341796 100755 --- a/openwrt-packages/luci-app-guest-wifi/po/templates/guest-wifi.pot +++ b/openwrt-packages/luci-app-guest-wifi/po/templates/guest-wifi.pot @@ -1,5 +1,14 @@ msgid "" -msgstr "Content-Type: text/plain; charset=UTF-8" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Project-Id-Version: luci-app-guest-wifi\n" +"PO-Revision-Date: 2024\n" +"Last-Translator: kenzok8\n" +"Language-Team: Chinese\n" +"Language: zh_Hans\n" +"MIME-Version: 1.0\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" msgid "Guest WiFi" msgstr "" @@ -41,4 +50,4 @@ msgid "AP Isolation" msgstr "" msgid "Prevents wireless clients from communicating with each other" -msgstr "" \ No newline at end of file +msgstr "" diff --git a/openwrt-packages/luci-app-guest-wifi/po/zh-cn b/openwrt-packages/luci-app-guest-wifi/po/zh-cn new file mode 120000 index 0000000000..8d69574ddd --- /dev/null +++ b/openwrt-packages/luci-app-guest-wifi/po/zh-cn @@ -0,0 +1 @@ +zh_Hans \ No newline at end of file diff --git a/openwrt-packages/luci-app-guest-wifi/po/zh_Hans b/openwrt-packages/luci-app-guest-wifi/po/zh_Hans deleted file mode 120000 index 41451e4a19..0000000000 --- a/openwrt-packages/luci-app-guest-wifi/po/zh_Hans +++ /dev/null @@ -1 +0,0 @@ -zh-cn \ No newline at end of file diff --git a/openwrt-packages/luci-app-guest-wifi/po/zh-cn/guest-wifi.po b/openwrt-packages/luci-app-guest-wifi/po/zh_Hans/guest-wifi.po similarity index 68% rename from openwrt-packages/luci-app-guest-wifi/po/zh-cn/guest-wifi.po rename to openwrt-packages/luci-app-guest-wifi/po/zh_Hans/guest-wifi.po index 46fc769e80..6784b4a3a5 100755 --- a/openwrt-packages/luci-app-guest-wifi/po/zh-cn/guest-wifi.po +++ b/openwrt-packages/luci-app-guest-wifi/po/zh_Hans/guest-wifi.po @@ -1,3 +1,15 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Project-Id-Version: luci-app-guest-wifi\n" +"PO-Revision-Date: 2024\n" +"Last-Translator: kenzok8\n" +"Language-Team: Chinese\n" +"Language: zh_Hans\n" +"MIME-Version: 1.0\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + msgid "Guest WiFi" msgstr "访客WiFi" @@ -38,4 +50,4 @@ msgid "AP Isolation" msgstr "AP隔离" msgid "Prevents wireless clients from communicating with each other" -msgstr "防止无线客户端之间相互通信" \ No newline at end of file +msgstr "防止无线客户端之间相互通信" diff --git a/openwrt-packages/luci-app-guest-wifi/root/etc/config/guest-wifi b/openwrt-packages/luci-app-guest-wifi/root/etc/config/guest-wifi deleted file mode 100755 index 410be80e94..0000000000 --- a/openwrt-packages/luci-app-guest-wifi/root/etc/config/guest-wifi +++ /dev/null @@ -1,3 +0,0 @@ -config guest-wifi 'config' - option enabled '0' - option isolate '1' \ No newline at end of file diff --git a/openwrt-packages/luci-app-guest-wifi/root/etc/init.d/guest-wifi b/openwrt-packages/luci-app-guest-wifi/root/etc/init.d/guest-wifi index e83f3be42d..4e321c0659 100755 --- a/openwrt-packages/luci-app-guest-wifi/root/etc/init.d/guest-wifi +++ b/openwrt-packages/luci-app-guest-wifi/root/etc/init.d/guest-wifi @@ -4,13 +4,13 @@ START=99 USE_PROCD=1 reload_service() { - wifi reload + wifi reload >/dev/null 2>&1 } service_triggers() { - procd_add_reload_trigger "wireless" + procd_add_reload_trigger "wireless" } start_service() { - reload_service -} \ No newline at end of file + reload_service +} diff --git a/openwrt-packages/luci-app-guest-wifi/root/etc/uci-defaults/40_luci-guest-wifi b/openwrt-packages/luci-app-guest-wifi/root/etc/uci-defaults/40_luci-guest-wifi index 66e017c0a8..42a0e48dde 100755 --- a/openwrt-packages/luci-app-guest-wifi/root/etc/uci-defaults/40_luci-guest-wifi +++ b/openwrt-packages/luci-app-guest-wifi/root/etc/uci-defaults/40_luci-guest-wifi @@ -1,11 +1,6 @@ #!/bin/sh -uci -q batch <<-EOF >/dev/null - delete ucitrack.@guest-wifi[-1] - add ucitrack guest-wifi - set ucitrack.@guest-wifi[-1].init=guest-wifi - commit ucitrack -EOF +[ -z "${IPKG_INSTROOT}" ] || exit 0 -rm -f /tmp/luci-indexcache -exit 0 \ No newline at end of file +rm -f /tmp/luci-indexcache 2>/dev/null +exit 0 diff --git a/openwrt-packages/luci-app-guest-wifi/root/etc/uci-defaults/luci-i18n-guest-wifi-zh-cn b/openwrt-packages/luci-app-guest-wifi/root/etc/uci-defaults/luci-i18n-guest-wifi-zh-cn deleted file mode 100755 index 85dcbcf8b3..0000000000 --- a/openwrt-packages/luci-app-guest-wifi/root/etc/uci-defaults/luci-i18n-guest-wifi-zh-cn +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - set luci.languages.zh_cn='chinese' - commit luci -EOF - -exit 0 \ No newline at end of file diff --git a/openwrt-packages/luci-app-guest-wifi/root/usr/lib/lua/luci/controller/guest-wifi.lua b/openwrt-packages/luci-app-guest-wifi/root/usr/lib/lua/luci/controller/guest-wifi.lua deleted file mode 100755 index 88a79b5025..0000000000 --- a/openwrt-packages/luci-app-guest-wifi/root/usr/lib/lua/luci/controller/guest-wifi.lua +++ /dev/null @@ -1,9 +0,0 @@ -module("luci.controller.guest-wifi", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/wireless") then - return - end - - entry({"admin", "network", "guest-wifi"}, view("guest-wifi/wifi"), _("Guest WiFi"), 60) -end \ No newline at end of file diff --git a/openwrt-packages/luci-app-guest-wifi/root/usr/sbin/guest-wifi b/openwrt-packages/luci-app-guest-wifi/root/usr/sbin/guest-wifi deleted file mode 100755 index 276879c580..0000000000 --- a/openwrt-packages/luci-app-guest-wifi/root/usr/sbin/guest-wifi +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -# 检查无线配置 -check_wireless() { - local enabled - config_load wireless - config_get enabled guest_wifi enabled 0 - - if [ "$enabled" = "1" ]; then - # 应用guest wifi配置 - wifi reload - fi -} - -# 主循环 -while true; do - check_wireless - sleep 300 -done \ No newline at end of file diff --git a/openwrt-packages/luci-app-guest-wifi/root/usr/share/rpcd/acl.d/luci-app-guest-wifi.json b/openwrt-packages/luci-app-guest-wifi/root/usr/share/rpcd/acl.d/luci-app-guest-wifi.json index 1e93a90cd9..49b73ab8da 100755 --- a/openwrt-packages/luci-app-guest-wifi/root/usr/share/rpcd/acl.d/luci-app-guest-wifi.json +++ b/openwrt-packages/luci-app-guest-wifi/root/usr/share/rpcd/acl.d/luci-app-guest-wifi.json @@ -1,14 +1,14 @@ { - "luci-app-guest-wifi": { - "description": "Grant access to guest-wifi configuration", - "read": { - "uci": [ "wireless", "guest-wifi" ], - "ubus": { - "iwinfo": [ "devices", "info", "assoclist" ] - } - }, - "write": { - "uci": [ "wireless", "guest-wifi" ] - } - } -} \ No newline at end of file + "luci-app-guest-wifi": { + "description": "Grant access to guest-wifi configuration", + "read": { + "uci": [ "wireless" ], + "ubus": { + "iwinfo": [ "devices", "info", "assoclist" ] + } + }, + "write": { + "uci": [ "wireless" ] + } + } +} diff --git a/openwrt-packages/luci-theme-alpha/Makefile b/openwrt-packages/luci-theme-alpha/Makefile index 9d9515ed1d..7fbbcd1961 100644 --- a/openwrt-packages/luci-theme-alpha/Makefile +++ b/openwrt-packages/luci-theme-alpha/Makefile @@ -10,7 +10,7 @@ THEME_NAME:=alpha THEME_TITLE:=Alpha PKG_NAME:=luci-theme-$(THEME_NAME) -PKG_VERSION:=3.9.6_beta +PKG_VERSION:=3.9.7_beta PKG_RELEASE:=10 include $(INCLUDE_DIR)/package.mk diff --git a/openwrt-packages/luci-theme-alpha/js/menu-alpha.js b/openwrt-packages/luci-theme-alpha/js/menu-alpha.js index 62cae62e7b..1b8de894ab 100644 --- a/openwrt-packages/luci-theme-alpha/js/menu-alpha.js +++ b/openwrt-packages/luci-theme-alpha/js/menu-alpha.js @@ -30,29 +30,42 @@ return baseclass.extend({ ); document.querySelector(".main > .loading").style.opacity = "0"; document.querySelector(".main > .loading").style.visibility = "hidden"; - if (window.innerWidth <= 1152) - document.querySelector(".main-left").style.width = "0"; + if (window.innerWidth <= 1152) { + document.querySelector(".main-left").style.transform = "translateX(-20rem)"; + } window.addEventListener("resize", this.handleSidebarToggle, true); }, handleMenuExpand: function (ev) { var a = ev.target, ul1 = a.parentNode, - ul2 = a.nextElementSibling; + ul2 = a.nextElementSibling, + isActive = ul1.classList.contains("active"); document.querySelectorAll("li.slide.active").forEach(function (li) { if (li !== a.parentNode || li == ul1) { + var menu = li.querySelector("ul"); + if (menu) { + if (!menu.style.maxHeight || menu.style.maxHeight === "1200px") { + menu.style.maxHeight = menu.scrollHeight + "px"; + } + void menu.offsetHeight; // Force layout + menu.style.maxHeight = "0px"; + } li.classList.remove("active"); li.childNodes[0].classList.remove("active"); } if (li == ul1) return; }); if (!ul2) return; - if ( - ul2.parentNode.offsetLeft + ul2.offsetWidth <= - ul1.offsetLeft + ul1.offsetWidth - ) - ul2.classList.add("align-left"); - ul1.classList.add("active"); - a.classList.add("active"); + if (!isActive) { + if ( + ul2.parentNode.offsetLeft + ul2.offsetWidth <= + ul1.offsetLeft + ul1.offsetWidth + ) + ul2.classList.add("align-left"); + ul1.classList.add("active"); + a.classList.add("active"); + ul2.style.maxHeight = ul2.scrollHeight + "px"; + } a.blur(); ev.preventDefault(); ev.stopPropagation(); @@ -167,13 +180,38 @@ return baseclass.extend({ darkMask = document.querySelector(".darkMask"), mainRight = document.querySelector(".main-right"), mainLeft = document.querySelector(".main-left"), - open = mainLeft.style.width == ""; - if (width > 1152 || ev.type == "resize") open = true; - darkMask.style.visibility = open ? "" : "visible"; - darkMask.style.opacity = open ? "" : 1; - if (width <= 1152) mainLeft.style.width = open ? "0" : ""; - else mainLeft.style.width = ""; - mainLeft.style.visibility = open ? "" : "visible"; - mainRight.style["overflow-y"] = open ? "visible" : "hidden"; + open = mainLeft.style.transform === ""; // true if currently open + + // If it's a resize event, we simulate that the sidebar was "open" so the logic below closes it for mobile, and opens it for desktop + if (ev.type == "resize") { + open = true; + } + + // Logics: 'open' true means we want to CLOSE it on mobile, but OPEN it on desktop. + // Actually, let's make it clearer: we toggle the state. + var willOpen = !open; + if (ev.type == "resize") { + willOpen = width > 1152; + } + + if (width <= 1152) { + // Mobile behavior + mainLeft.style.width = ""; // Reset width + mainLeft.style.transform = willOpen ? "" : "translateX(-20rem)"; + mainLeft.style.visibility = willOpen ? "visible" : ""; + darkMask.style.visibility = willOpen ? "visible" : ""; + darkMask.style.opacity = willOpen ? 1 : ""; + mainRight.style.width = ""; + } else { + // Desktop behavior + mainLeft.style.width = ""; // Reset width + mainLeft.style.transform = willOpen ? "" : "translateX(-20rem)"; + mainLeft.style.visibility = willOpen ? "visible" : "hidden"; + mainRight.style.width = willOpen ? "" : "100%"; + darkMask.style.visibility = ""; + darkMask.style.opacity = ""; + } + if (ev && ev.preventDefault) ev.preventDefault(); + if (ev && ev.stopPropagation) ev.stopPropagation(); }, }); diff --git a/openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css b/openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css index e16a8e0db8..f097894309 100755 --- a/openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css +++ b/openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css @@ -783,6 +783,7 @@ float: right; width: calc(100% - 16rem); height: 100%; + transition: width 450ms cubic-bezier(0.16, 1, 0.3, 1); } .nowrap:not(.td) { @@ -795,6 +796,17 @@ } /* Sidebar */ + .showSide { + position: -webkit-sticky; + position: sticky; + top: 0rem; + display: inline-flex; + align-items: center; + height: 100%; + margin-right: 0.7rem; + cursor: pointer; + } + .main>.main-left { position: fixed; top: 4.8rem; @@ -802,7 +814,7 @@ float: left; overflow-x: auto; background-color: #2222359a; - transition: visibility 400ms, width 400ms; + transition: visibility 450ms, transform 450ms cubic-bezier(0.16, 1, 0.3, 1); border-top-left-radius: 0px; border-top-right-radius: 20px; border-bottom-left-radius: 0px; @@ -2499,7 +2511,7 @@ width: 100%; height: 100%; content: ""; - transition: opacity 400ms, visibility 400ms; + transition: opacity 450ms cubic-bezier(0.16, 1, 0.3, 1), visibility 450ms; visibility: hidden; opacity: 0; background-color: #2222359a; @@ -2840,7 +2852,10 @@ .alert-message .btn, .modal .btn { - padding: 0.3rem 0.6rem; + padding: 0 1.2rem; + display: inline-flex; + align-items: center; + justify-content: center; } .container .alert, @@ -2866,14 +2881,8 @@ border-radius: 10px; } - .main>.main-left>.nav>.slide>ul, - .main>.main-left[style*="overflow: hidden"]>.nav>.slide>.menu::before, - .tr.placeholder .td[data-title]::before, - .cbi-dropdown>ul.preview, - .cbi-dropdown>ul>li .hide-close, .cbi-dropdown[open]>ul.dropdown>li .hide-open, .hidden, - .showSide, .node-main-login>.main>.main-left, [data-page^="admin-system-commands"] .panel-title, [data-page^="command-cfg"] .mobile-hide, @@ -2881,7 +2890,6 @@ display: none; } - .main>.main-left>.nav>.slide.active>ul, .cbi-dropdown[empty]>ul>li, .cbi-dropdown[optional][open]>ul.dropdown>li[placeholder], .cbi-dropdown[multiple][open]>ul.dropdown>li>form, @@ -2892,6 +2900,21 @@ display: block; } + .main>.main-left>.nav>.slide>ul { + display: block; + overflow: hidden; + max-height: 0; + opacity: 0; + visibility: hidden; + transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease-out, visibility 0.4s; + } + .main>.main-left>.nav>.slide.active>ul { + max-height: 1200px; /* Fallback for initial load */ + opacity: 1; + visibility: visible; + transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.4s ease-in, visibility 0s; + } + .main>.main-left>.nav>li:hover, .main>.main-left>.nav>.slide>.menu:hover, .main>.main-left>.nav>.slide>.slide-menu>li:hover { @@ -3194,16 +3217,26 @@ width: 100%; } - .showSide { - position: -webkit-sticky; - position: sticky; - top: 0rem; - display: inline-flex; - align-items: center; - height: 100%; - margin-right: 0.7rem; - cursor: pointer; - } + .showSide { + position: -webkit-sticky !important; + position: sticky !important; + top: 0rem; + display: inline-flex !important; + align-items: center; + min-width: 40px; + height: 100%; + margin-right: 0.7rem; + cursor: pointer; + flex-shrink: 0 !important; + z-index: 3000 !important; + } + .showSide img { + width: 30px !important; + height: auto !important; + display: block !important; + visibility: visible !important; + opacity: 1 !important; + } body:not(.logged-in) .showSide { visibility: hidden; diff --git a/openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css.bak b/openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css.bak deleted file mode 100644 index 0b9b3d5435..0000000000 --- a/openwrt-packages/luci-theme-alpha/luasrc/gaya/gaya.css.bak +++ /dev/null @@ -1,3625 +0,0 @@ - /* Base */ - @font-face { - font-family: "Inter-Regular"; - src: url('/luci-static/alpha/fonts/Inter-Regular.woff2'); - } - - @font-face { - font-family: "Inter-Medium"; - src: url('/luci-static/alpha/fonts/Inter-Medium.woff2'); - } - - @font-face { - font-family: "Inter-Black"; - src: url('/luci-static/alpha/fonts/Inter-Black.woff2'); - } - - @font-face { - font-family: "Inter-Bold"; - src: url('/luci-static/alpha/fonts/Inter-Bold.woff2'); - } - - @font-face { - font-family: "Quicksand-Bold"; - src: url('/luci-static/alpha/fonts/Quicksand-Bold.ttf'); - } - - @font-face { - font-family: argon; - src: url('/luci-static/alpha/fonts/argon.woff'); - - } - - [class^="icon-"], - [class*=" icon-"] { - font-family: argon !important; - font-style: normal; - font-weight: 400; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - } - - a { - color: #5a8dee; - text-decoration: none; - background-color: transparent; - } - - b { - color: #5a8dee; - text-decoration: none; - background-color: transparent; - font-family: "Quicksand-Bold"; - - } - - ::-webkit-scrollbar:hover { - background-color: rgba(100, 100, 100, 0.09); - } - - ::-webkit-scrollbar-thumb:vertical { - background: rgba(100, 100, 100, 0.5); - -webkit-border-radius: 100px; - } - - ::-webkit-scrollbar-thumb:vertical:active { - background: rgba(100, 100, 100, 0.61); - -webkit-border-radius: 100px; - } - - ::-webkit-scrollbar { - width: 0.2em !important; - overflow: visible; - border-radius: 4px; - -webkit-border-radius: 4px; - } - - ::-webkit-scrollbar-track { - opacity: 0; - -webkit-transition: all 0.5s; - } - - ::-webkit-scrollbar-thumb { - overflow: visible; - border-radius: 4px; - background: rgba(100, 100, 100, 0.2); - } - - .icon-hello-world:before { - content: "\e90e"; - } - - .icon-expand_more:before { - content: "\e20b"; - } - - .icon-menu:before { - content: "\e20e"; - } - - .icon-favorite:before { - content: "\e291"; - } - - .icon-spinner:before { - content: "\e603"; - } - - .icon-delete:before { - content: "\e900"; - } - - .icon-edit:before { - content: "\e901"; - } - - .icon-use:before { - content: "\e902"; - } - - .icon-loading:before { - content: "\e903"; - } - - .icon-switch:before { - content: "\e904"; - } - - .icon-error:before { - content: "\e905"; - } - - .icon-dashboard:before { - content: "\e906"; - } - - .icon-logout:before { - content: "\e907"; - } - - .icon-Network:before { - content: "\e908"; - } - - .icon-services:before { - content: "\e909"; - } - - .icon-system:before { - content: "\e90a"; - } - - .icon-vpn:before { - content: "\e90b"; - } - - .icon-storage:before { - content: "\e90c"; - } - - .icon-statistics:before { - content: "\e90d"; - } - - .icon-angle-right:before { - content: "\e90f"; - } - - .icon-user:before { - content: "\e971"; - } - - .icon-question:before { - content: "\f059"; - } - - :root { - --main-color: #09c; - --header-bg: #161624; - --header-color: rgb(10, 10, 10); - --bar-bg: #3f3f3f69; - --menu-bg-color: #fff; - --menu-color: #5f6368; - --menu-color-hover: #202124; - --main-menu-color: #202124; - --submenu-bg-hover: #4d5ca5; - --submenu-bg-hover-active: #09c; - --font-body: 'Inter-Regular'; - } - - tt { - font-family: "Quicksand-Bold"; - color: #09c; - } - - em { - font-style: italic; - color: #fff - } - - p { - display: block; - margin-block-start: 1em; - margin-block-end: 1em; - margin-inline-start: 0px; - margin-inline-end: 0px; - color: #ffffff; - } - - li { - display: block; - list-style-type: disc; - margin-block-start: 5px; - margin-block-end: 5px; - margin-inline-start: 0px; - margin-inline-end: 0px; - color: #ffffff; - } - - small { - font-size: smaller; - color: #ffff; - } - - label { - cursor: default; - color: #ffffff; - } - - .table { - position: relative; - display: table; - } - - .tr { - display: table-row; - } - - .thead { - display: table-header-group; - } - - .tbody { - display: table-row-group; - } - - .tfoot { - display: table-footer-group; - } - - .td, - .th { - line-height: normal; - display: table-cell; - vertical-align: middle; - padding: 0.5em; - } - - .th { - font-weight: 700; - } - - .tr.placeholder { - height: 4em; - } - - .tr.placeholder>.td { - line-height: 3; - position: absolute; - right: 0; - bottom: 0; - left: 0; - text-align: center !important; - background: inherit; - } - - .table[width="33%"], - .th[width="33%"], - .td[width="33%"] { - width: 33%; - } - - .col-1 { - flex: 1 1 30px !important; - } - - .col-2 { - flex: 2 2 60px !important; - } - - .col-3 { - flex: 3 3 90px !important; - } - - .col-4 { - flex: 4 4 120px !important; - } - - .col-5 { - flex: 5 5 150px !important; - } - - .col-6 { - flex: 6 6 180px !important; - } - - .col-7 { - flex: 7 7 210px !important; - } - - .col-8 { - flex: 8 8 240px !important; - } - - .col-9 { - flex: 9 9 270px !important; - } - - .col-10 { - flex: 10 10 300px !important; - } - - * { - box-sizing: border-box; - padding: 0; - } - - .h1, - .h2, - .h3, - .h4, - .h5, - .h6, - h1, - h2, - h3, - h4, - h5, - h6 { - font-family: inherit; - font-weight: 400; - line-height: 1.1 !important; - color: #fff; - } - - html { - overflow-y: hidden; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; - } - - body { - font-size: 0.8rem; - height: 100%; - background-position: center; - background-repeat: no-repeat; - background-size: cover; - background-attachment: fixed; - background-color: rgb(10, 10, 10); - } - - .text { - font-style: italic; - color: #fff; - } - - html, - body { - font-family: var(--font-body); - height: 100%; - margin: 0; - padding: 0; - } - - select { - color: #555; - border: thin solid #ccc; - background-color: #fff; - background-image: none; - padding: 0.36rem 0.8rem; - } - - .btn, - button, - select, - input, - .cbi-dropdown { - height: 2.3rem; - color: rgba(255, 255, 255, 0.87); - border: 0; - border-bottom: 2px solid #30304b; - border-radius: 10px; - border-radius: 20px; - outline: 0; - background-color: #222235; - background-image: none; - box-shadow: none; - padding: 0.5rem; - } - - select, - .cbi-dropdown { - width: inherit; - cursor: default; - } - - select:not([multiple="multiple"]):focus, - input:not(.cbi-button):focus, - .cbi-dropdown:focus { - border-color: var(--main-color); - } - - .cbi-dropdown, - select[multiple="multiple"] { - height: auto; - } - - pre { - overflow: auto; - color: #fff; - } - - code { - font-size: 1rem; - font-size-adjust: 0.35; - color: #101010; - border-radius: 0px; - background: #ddd; - padding: 1px 3px; - } - - abbr { - cursor: help; - text-decoration: underline; - color: #84d0ea; - } - - hr { - opacity: 0.1; - border-color: #eee; - margin: 1rem 0; - } - - /* End Base */ - - /* Header */ - header, - .main { - position: absolute; - width: 100%; - } - - header { - position: fixed; - z-index: 2000; - float: left; - height: 4rem; - transition: box-shadow 0.2s; - color: var(--header-color); - background: #2222359a; - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - } - - header>.fill>.container { - margin-top: 0.5rem; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - padding: 0.5rem 1rem 0; - } - - header>.fill>.container>#logo { - padding: 0; - margin: 0 !important; - position: absolute; - left: 0; - top: 50%; - height: 100%; - transform: translateY(-50%); - padding: 1rem; - display: flex; - justify-content: center; - width: calc(16rem); - } - - header>.fill>.container>#logo>img { - width: auto; - height: 100%; - margin-top: -0.1rem; - } - - header>.fill>.container>.brand { - font-size: 1.4rem; - position: absolute; - cursor: default; - vertical-align: text-bottom; - text-decoration: none; - color: var(--header-color); - } - - header>.fill>.container>.status { - position: fixed; - top: 9px; - right: 1em; - float: right; - } - - header>.fill>.container>.status>* { - position: relative; - top: 0.2rem; - float: left; - left: -2.5rem; - margin-left: 0.3rem; - cursor: pointer; - } - - header>.fill>.container>.logout { - position: fixed; - top: 9px; - right: 1em; - float: right; - } - - header>.fill>.container>.logout>* { - position: relative; - top: 0.2rem; - float: left; - right: 0rem; - margin-left: 0.3rem; - cursor: pointer; - content: ""; - } - - .logout a { - position: absolute; - right: 14px; - width: 32px; - height: 32px; - content: ""; - background: url(./icon/logout.svg) no-repeat; - text-indent: -9999px; - background-size: 32px; - } - - /* End Header */ - - /* Footer */ - footer { - font-size: 0.8rem; - overflow: hidden; - text-align: center; - white-space: nowrap; - color: #000000; - padding: 1rem; - } - - footer>a { - text-decoration: none; - align-items: center; - color: #e6e6e696; - border-bottom: 0; - background-color: #2222359a; - border-radius: 10px; - padding: 9px; - padding-bottom: 3px; - padding-top: 3px; - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - } - - small { - font-size: 90%; - line-height: 1.42857143; - white-space: normal; - } - - /* End Footer */ - - /* Navbar */ - @media screen and (min-width: 720px) { - .navbar { - position: fixed; - bottom: 50%; - transform: translateY(50%); - transition-duration: 200ms; - right: 30px; - border-top: var(--navBorder); - text-align: center; - background-color: #000000da; - box-shadow: 0 0 10px 0px #0000002d; - box-sizing: content-box; - border-radius: 10px; - } - - .navbar--hidden { - transform: translateY(60px); - box-shadow: none; - } - - .navbar .toggler { - transition-duration: 100ms; - position: absolute; - background: #ffffffb0; - box-shadow: 0 0 10px 0 #0000000f; - transform: translateY(50%); - bottom: 50%; - right: calc(100% + 10px); - width: 32px; - height: 32px; - padding: 8px; - border-radius: 100%; - content: ""; - box-sizing: border-box; - cursor: pointer; - } - - .navbar .toggler img { - transform: rotate(270deg); - } - - .navbar .dropdown { - display: flex; - flex-direction: column; - overflow: hidden; - width: 64px; - padding: 0.25rem; - } - - .navbar .dropdown a { - display: block; - text-align: center; - padding: 8px; - text-decoration: none; - max-width: 100px; - width: 100%; - } - - .navbar .dropdown a img { - width: 100%; - } - - .navbar.active { - right: -64px; - } - - .navbar.active .toggler { - right: calc(100% + 10px); - } - - .navbar.active .toggler img { - transform: rotate(90deg); - } - } - - @media screen and (max-width: 720px) { - .navbar { - - overflow: hidden; - position: fixed; - bottom: 5px; - top: auto; - left: 10px; - right: auto; - width: 95%; - align: center; - transition: transform 0.5s; - border-top: var(--navBorder); - text-align: center; - height: calc(50px + constant(safe-area-inset-bottom)); - height: calc(50px + env(safe-area-inset-bottom)); - background-color: #00000079; - border-radius: 20px; - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - - } - - .navbar--hidden { - transform: translateY(60px); - box-shadow: none; - } - - .navbar a { - float: left; - text-align: center; - padding: 8px 0; - text-decoration: none; - } - - .navbar a img { - width: 28px; - } - } - - /* End Navbar */ - - .main { - position: relative; - top: 4rem; - bottom: 0; - overflow-y: auto; - height: calc(100% - 4rem); - } - - .main>.loading { - position: fixed; - z-index: 1000; - top: 0; - opacity: 1; - visibility: visible; - width: 100%; - height: 100%; - pointer-events: none; - background-color: rgba(0, 0, 0, 0.781); - transition: .4s ease-in-out; - border-radius: 10px; - } - - .main>.loading>span { - font-family: monospace; - font-size: 2rem; - font-size-adjust: 0.35; - position: relative; - top: 12.5%; - display: block; - text-align: center; - color: #888; - } - - .main>.loading>span>.loading-img { - display: inline-flex; - gap: 10px; - } - - .main>.loading>span>.loading-img:before, - .loading-img:after { - content: ""; - height: 20px; - aspect-ratio: 1; - border-radius: 50%; - background: - linear-gradient(#222 0 0) top/100% 0% no-repeat, - radial-gradient(farthest-side, #000 95%, #0000) 50%/8px 8px no-repeat #ffffff; - animation: l9 4s infinite ease-in; - } - - @keyframes l9 { - 0% { - background-size: 100% 0%, 8px 8px; - background-position: top, 50% 50% - } - - 80% { - background-size: 100% 70%, 8px 8px; - background-position: top, 50% 70% - } - - 84%, - 100% { - background-size: 100% 0%, 8px 8px; - background-position: top, 50% 50% - } - } - - .cbi-map { - margin-top: 10px; - } - - #cbi-shadowsocksr .cbi-map-descr { - display: none; - } - - strong { - font-weight: bold; - color: rgb(255, 255, 255); - } - - .main-right { - float: right; - width: calc(100% - 16rem); - height: 100%; - } - - .nowrap:not(.td) { - white-space: nowrap; - color: #ffffff; - } - - [disabled="disabled"] { - pointer-events: none; - } - - /* Sidebar */ - .main>.main-left { - position: fixed; - top: 4.8rem; - width: calc(0% + 16rem); - float: left; - overflow-x: auto; - background-color: #2222359a; - transition: visibility 400ms, width 400ms; - border-top-left-radius: 0px; - border-top-right-radius: 20px; - border-bottom-left-radius: 0px; - border-bottom-right-radius: 20px; - backdrop-filter: blur(20px); - -webkit-backdrop-filter: blur(20px); - height: calc(100% - 3.5rem); - - } - - .main>.main-left>.nav { - padding: 0.5rem 0.5rem 2rem; - } - - .main>.main-left>.nav>li { - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - } - - .main>.main-left>.nav>li>[data-title="Log out"], - .main>.main-left>.nav>li>[data-title="Logout"] { - display: flex; - padding: 0.5rem 1rem; - } - - .main>.main-left>.nav>li a { - display: block; - color: #cbcbcb; - } - - .main>.main-left>.nav>li>[data-title="Log out"], - .main>.main-left>.nav>li>[data-title="Logout"], - .main>.main-left>.nav>li>[data-title="iStore"] { - font-size: 1rem; - color: #fff; - } - - .main>.main-left>.nav>li.slide.active { - background-color: unset; - } - - .main>.main-left>.nav>.slide { - padding: 0; - } - - .main>.main-left>.nav>.slide>.menu, - .main>.main-left>.nav>li>[data-title="Logout"], - .main>.main-left>.nav>li>[data-title="iStore"], - .main>.main-left>.nav>li>[data-title="Dashboard"] { - font-size: 1rem; - font-weight: 500; - display: flex; - align-items: center; - width: 100%; - text-decoration: none; - color: #fff; - padding: 0.5rem 1rem; - transition-duration: 200ms; - margin-bottom: 5px; - } - - .main>.main-left>.nav>.slide>.menu::before { - position: absolute; - right: 14px; - width: 25px; - height: 25px; - content: ""; - background: url(./icon/sidebar-icon/app.svg) no-repeat; - background-size: 25px; - } - - .main>.main-left>.nav>.slide>.menu.active::before {} - - .main>.main-left>.nav>.slide>[data-title="Status"]:before { - position: absolute; - right: 14px; - width: 25px; - height: 25px; - content: ""; - background: url(./icon/sidebar-icon/status.svg) no-repeat; - background-size: 25px; - } - - .main>.main-left>.nav>.slide>[data-title="System"]:before { - position: absolute; - right: 14px; - width: 25px; - height: 25px; - content: ""; - background: url(./icon/sidebar-icon/system.svg) no-repeat; - background-size: 25px; - } - - .main>.main-left>.nav>.slide>[data-title="Services"]:before { - position: absolute; - right: 14px; - width: 25px; - height: 25px; - content: ""; - background: url(./icon/sidebar-icon/services.svg) no-repeat; - background-size: 25px; - } - - .main>.main-left>.nav>.slide>[data-title="NAS"]:before { - position: absolute; - right: 14px; - width: 25px; - height: 25px; - content: ""; - background: url(./icon/sidebar-icon/nas.svg) no-repeat; - background-size: 25px; - } - - .main>.main-left>.nav>.slide>[data-title="Modem"]:before { - position: absolute; - right: 14px; - width: 25px; - height: 25px; - content: ""; - background: url(./icon/sidebar-icon/modem.svg) no-repeat; - background-size: 25px; - } - - .main>.main-left>.nav>.slide>[data-title="Network"]:before { - position: absolute; - right: 14px; - width: 25px; - height: 25px; - content: ""; - background: url(./icon/sidebar-icon/network.svg) no-repeat; - background-size: 25px; - } - - .main>.main-left>.nav>.slide>[data-title="VPN"]:before { - position: absolute; - right: 14px; - width: 25px; - height: 25px; - content: ""; - background: url(./icon/sidebar-icon/vpn.svg) no-repeat; - background-size: 25px; - } - - .main>.main-left>.nav>.slide>[data-title="Docker"]:before { - position: absolute; - right: 14px; - width: 25px; - height: 25px; - content: ""; - background: url(./icon/sidebar-icon/docker.svg) no-repeat; - background-size: 25px; - } - - .main>.main-left>.nav>li>[data-title="iStore"]:before { - position: absolute; - right: 14px; - width: 25px; - height: 25px; - content: ""; - background: url(./icon/sidebar-icon/istore.svg) no-repeat; - background-size: 25px; - } - - /* End Sidebar */ - - .modemenu-buttons { - display: flex; - flex-wrap: wrap; - align-items: center; - color: var(--header-color); - background: var(--header-bg); - transition: box-shadow 0.2s; - box-shadow: 0 2px 5px rgb(0 0 0 / 26%); - padding: 0.5rem; - } - - #modemenu { - display: flex; - align-items: center; - flex-wrap: wrap; - margin: 0.25rem; - } - - #modemenu>li.divider { - margin-left: 0.25rem; - margin-right: 0.25rem; - border: 0.5rem solid var(--submenu-bg-hover); - border-left: 1px solid var(--submenu-bg-hover); - border-right: 1px solid var(--submenu-bg-hover); - border-radius: 1rem; - } - - .danger { - background-color: #ff7d60 !important; - } - - .warning { - background-color: #bebebe87 !important; - border-radius: 10px; - color: #fff; - } - - .success { - background-color: #5cb85c !important; - } - - .error { - color: red; - } - - .alert, - .alert-message { - font-weight: 700; - margin-bottom: 1em; - border: 0; - border-radius: 20px; - background-color: #2222359a; - padding: 1rem; - margin: 1rem; - } - - .alert-message>h4 { - font-size: 110%; - font-weight: 700; - } - - .alert-message>* { - margin: 0.5rem 0; - } - - body[class*="node-"]>.main>.main-left>.nav>.slide>.menu::before { - transition: transform 0.1s ease-in-out; - } - - body[class*="node-"]>.main>.main-left>.nav>.slide>.menu.active::before { - transition: transform 0.2s ease-in-out; - } - - .main>.main-left>.nav>li>[data-title="Logout"]::before, - .main>.main-left>.nav>li>[data-title="Log out"]::before { - position: absolute; - right: 14px; - width: 25px; - height: 25px; - content: ""; - background: url(./icon/logout.svg) no-repeat; - background-size: 25px; - } - - .main>.main-left>.nav>.slide:hover { - background: none; - } - - .main>.main-left>.nav>.slide>.slide-menu>li>a { - white-space: nowrap; - text-decoration: none; - padding: 0.4rem 2rem; - } - - .main>.main-left>.nav>.slide>.slide-menu>li:not(.active):hover>a { - color: #fff; - } - - .main>.main-left>.nav>.slide>.slide-menu>.active:hover { - background-color: var(--main-color); - } - - .main>.main-left>.nav>.slide>.menu, - .main>.main-left>.nav>.slide>.slide-menu>li, - .main>.main-left>.nav>li>[data-title="Logout"], - .main>.main-left>.nav>li>[data-title="Log out"], - .main>.main-left>.nav>li>[data-title="iStore"] { - position: relative; - overflow: hidden; - transform: translate3d(0, 0, 0); - } - - .main>.main-left>.nav>.slide>.menu::after, - .main>.main-left>.nav>.slide>.slide-menu>li::after, - .main>.main-left>.nav>li>[data-title="Logout"]::after, - .main>.main-left>.nav>li>[data-title="Log out"]::after, - .main>.main-left>.nav>li>[data-title="iStore"]::after { - position: absolute; - top: 0; - left: 0; - display: block; - width: 100%; - height: 100%; - content: ""; - transition: transform 0.5s, opacity 1s; - transform: scale(10, 10); - pointer-events: none; - opacity: 0; - background-image: radial-gradient(circle, #000 10%, transparent 10.01%); - background-repeat: no-repeat; - background-position: 50%; - } - - .main>.main-left>.nav>.slide>.menu:active::after, - .main>.main-left>.nav>.slide>.slide-menu>li:active::after, - .main>.main-left>.nav>li>[data-title="Logout"]:active::after, - .main>.main-left>.nav>li>[data-title="Log out"]:active::after, - .main>.main-left>.nav>li>[data-title="iStore"]:active::after { - transition: 0s; - transform: scale(0, 0); - opacity: 0.2; - } - - #maincontent>.container { - margin: 0 2rem 1rem; - } - - ul { - line-height: normal; - } - - li { - list-style-type: none; - } - - h1 { - font-size: 2rem; - padding-bottom: 10px; - border-bottom: thin solid #eee; - } - - h2 { - font-size: 1.8rem; - font-family: "Quicksand-Bold"; - letter-spacing: 5px; - text-align: center; - padding-bottom: 10px; - margin: 2rem 0 0; - color: #ffffff; - animation-duration: 1s; - animation-name: down; - } - - h3 { - font-size: 1.2rem; - font-family: 'Inter-Bold'; - letter-spacing: 2px; - padding-bottom: 10px; - margin: 2rem 0 0; - color: #ffffff; - } - - h4 { - font-size: 1.2rem; - color: #fff; - padding-bottom: 10px; - margin: 2rem 0 0; - } - - h5 { - font-size: 1rem; - padding-bottom: 10px; - margin: 2rem 0 0; - } - - .cbi-tab-descr { - color: #09c; - margin: 1em; - padding: 1rem; - } - - #tabmenu { - padding: 0; - } - - .cbi-section, - .cbi-section-error, - #iptables, - .Firewall form, - #cbi-network>.cbi-section-node, - #cbi-wireless>.cbi-section-node, - #cbi-wireless>#wifi_assoclist_table, - [data-tab-title], - [data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), - [data-page="admin-system-opkg"] #maincontent>.container { - font-family: inherit; - font-weight: 400; - font-style: normal; - line-height: normal; - min-width: inherit; - border: 0; - border-radius: 0; - background-color: #2222359a; - margin: 1rem 0 0; - padding: 2rem; - border-radius: 20px; - backdrop-filter: blur(20px); - -webkit-backdrop-filter: blur(20px); - } - - .cbi-modal .cbi-section, - .cbi-section .cbi-section {} - - .cbi-modal .cbi-tabmenu { - margin-left: 0; - } - - .cbi-map-descr, - .cbi-section-descr { - font-size: small; - text-align: center; - line-height: 1.42857143; - color: #999; - padding: 0.5rem; - } - - .cbi-section>legend { - display: none !important; - } - - fieldset>fieldset, - .cbi-section>.cbi-section { - border: 0; - box-shadow: none; - margin: 0; - padding: 0; - } - - .cbi-section>h3:first-child, - .panel-title { - font-size: 1.4rem; - line-height: 1; - display: block; - width: 100%; - padding-bottom: 1rem; - color: #e4e4e4; - border-bottom: thin solid #eeeeee00; - margin: 0 0 0.5rem; - } - - .cbi-section>h4:first-child, - .cbi-section>p:first-child, - [data-tab-title]>h3:first-child, - [data-tab-title]>h4:first-child, - [data-tab-title]>p:first-child { - padding-top: 1rem; - } - - table { - border-spacing: 0; - border-collapse: collapse; - } - - table, - .table { - overflow-y: hidden; - width: 100%; - border-radius: 10px; - } - - .container>.cbi-section:first-of-type>.table[width="100%"]>.tr>.td { - padding: 0.6rem; - } - - .cbi-section-table-cell { - line-height: 1.1; - align-self: flex-end; - flex: 1 1 auto; - } - - tr>td, - tr>th, - .tr>.td, - .tr>.th, - .cbi-section-table-row::before, - #cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) { - color: #ffffff; - border-top: thin solid rgba(255, 255, 255, 0); - } - - .table[width="100%"]>.tr:first-child>.td { - margin: auto 0; - } - - .cbi-section-table-row { - margin-bottom: 1rem; - text-align: center !important; - } - - .cbi-section-table-row:last-child { - margin-bottom: 0; - } - - .cbi-section-table-row>.cbi-value-field [data-dynlist]>input, - .cbi-section-table-row>.cbi-value-field input.cbi-input-password { - width: calc(100% - 1.5rem); - } - - table table, - .table .table, - .cbi-value-field table, - .cbi-value-field .table, - td>table>tbody>tr>td, - .td>.table>.tbody>.tr>.td, - .cbi-value-field>table>tbody>tr>td, - .cbi-value-field>.table>.tbody>.tr>.td { - border: 0; - } - - .btn, - .cbi-button, - .item::after { - font-size: 0.8rem; - display: inline-block; - width: auto !important; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - transition: all 0.2s ease-in-out; - text-align: center; - vertical-align: middle; - white-space: nowrap; - text-decoration: none; - text-transform: uppercase; - color: rgba(0, 0, 0, 0.87); - border: 0; - background-color: #f0f0f0; - background-image: none; - -webkit-appearance: none; - -ms-touch-action: manipulation; - touch-action: manipulation; - padding: 0 0.8rem; - } - - .cbi-button-up { - transform: scaleY(-1); - } - - .cbi-button:not(select) { - -webkit-appearance: none !important; - } - - .cbi-button+.cbi-button { - margin-left: 0.6rem; - } - - .btn:hover, - .btn:focus, - .btn:active, - .cbi-button:hover, - .cbi-button:focus, - .cbi-button:active, - .item:hover::after, - .item:focus::after, - .item:active::after, - .cbi-page-actions .cbi-button-apply+.cbi-button-save:hover, - .cbi-page-actions .cbi-button-apply+.cbi-button-save:focus, - .cbi-page-actions .cbi-button-apply+.cbi-button-save:active { - text-decoration: none; - outline: 0; - } - - .btn:hover, - .btn:focus, - .cbi-button:hover, - .cbi-button:focus, - .item:hover::after, - .item:focus::after { - box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 2px rgba(0, 0, 0, 0.2); - } - - .btn:active, - .cbi-button:active, - .item:active::after { - box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23); - } - - .cbi-button-up:hover, - .cbi-button-up:focus { - box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 -2px 2px rgba(0, 0, 0, 0.2); - } - - .cbi-button-up:active { - box-shadow: 0 -10px 20px rgba(0, 0, 0, 0.19), 0 -6px 6px rgba(0, 0, 0, 0.23); - } - - .btn:disabled, - .cbi-button:disabled { - cursor: not-allowed; - pointer-events: none; - opacity: 0.5; - box-shadow: none; - } - - .alert-message [class="btn"], - .modal div[class="btn"], - .cbi-button-find, - .cbi-button-link, - .cbi-button-up, - .cbi-button-down, - .cbi-button-neutral, - .cbi-button[name="zero"], - .cbi-button[name="restart"], - .cbi-button[onclick="hide_empty(this)"] { - font-weight: 700; - background-color: #d4d4d4; - } - - .btn.primary, - .cbi-page-actions .cbi-button-save, - .cbi-page-actions .cbi-button-apply+.cbi-button-save, - .cbi-button-add, - .cbi-button-save, - .cbi-button-positive, - .cbi-button-link, - .cbi-button[value="Enable"], - .cbi-button[value="Scan"], - .cbi-button[value^="Back"], - .cbi-button-neutral[onclick="handleConfig(event)"] { - font-weight: 400; - color: #fff; - background-color: rgba(0, 229, 255, 0.47); - border-radius: 20px; - } - - .cbi-page-actions .cbi-button-apply, - .cbi-section-actions .cbi-button-edit, - .cbi-button-edit, - .cbi-button-apply, - .cbi-button-reload, - .cbi-button-action, - .cbi-button[value="Submit"], - .cbi-button[value="Upload"], - .cbi-button[value$="Apply"], - .cbi-button[onclick="addKey(event)"] { - font-weight: 400; - color: #fff; - background-color: rgba(0, 229, 255, 0.47); - border-radius: 20px; - } - - .btn.danger, - .cbi-section-remove>.cbi-button, - .cbi-button-remove, - .cbi-button-reset, - .cbi-button-negative, - .cbi-button[value="Stop"], - .cbi-button[value="Kill"], - .cbi-button[onclick="reboot(this)"], - .cbi-button-neutral[value="Restart"] { - font-weight: 400; - color: #fff; - background-color: rgba(255, 0, 0, 0.47); - border-radius: 20px; - } - - .btn[value="Dismiss"], - .cbi-button[value="Terminate"], - .cbi-button[value="Reset"], - .cbi-button[value="Disabled"], - .cbi-button[onclick^="iface_reconnect"], - .cbi-button[onclick="handleReset(event)"], - .cbi-button-neutral[value="Disable"] { - font-weight: 400; - color: #fff; - border: thin solid #eea236; - background-color: #f0ad4e; - } - - .cbi-button-success, - .cbi-button-download, - .cbi-button[name="backup"], - .cbi-button[value="Download"], - .cbi-button[value="Save mtdblock"] { - font-weight: 400; - color: #fff; - border: thin solid #4cae4c; - background-color: #5cb85c; - } - - .a-to-btn { - text-decoration: none; - } - - .cbi-value-field .cbi-button-add { - font-weight: 700; - margin: 9px 0 4px 3px; - padding: 1px 6px; - } - - .tabs { - border-bottom: 0; - background-color: #2222359a; - border-radius: 20px; - padding: 9px; - padding-bottom: 3px; - padding-top: 3px; - backdrop-filter: blur(20px); - -webkit-backdrop-filter: blur(20px); - } - - .tabs>li, - .cbi-tabmenu>li { - display: inline-block; - cursor: pointer; - padding: 0.4rem; - margin: 0.3rem; - align-items: center; - - } - - .tool_label_span { - color: aqua; - } - - .tabs>li { - padding-bottom: 0.4rem; - } - - .tabs>li[class~="active"], - .tabs>li:hover { - border-bottom-color: var(--main-color); - } - - .tabs>li:hover { - cursor: pointer; - border-bottom-color: #c9c9c9; - } - - .tabs>li>a, - .cbi-tabmenu>li>a { - text-decoration: none; - color: #ffffff; - padding: 0.6rem 0.9rem; - - } - - .tabs>li[class~="active"]>a { - color: var(--main-color); - } - - .cbi-tabmenu { - border-bottom: 0; - background-color: #2222359a; - border-radius: 20px; - padding: 9px; - padding-bottom: 3px; - padding-top: 3px; - backdrop-filter: blur(20px); - -webkit-backdrop-filter: blur(20px); - } - - .cbi-tabmenu>li:hover { - background-color: #474747; - border-radius: 20px; - - - } - - .cbi-tabmenu>li[class~="cbi-tab"] { - background-color: #ff94946a; - border-radius: 20px; - } - - .cbi-tabmenu>li[class~=data-tab=] { - color: #ffffff; - } - - [data-tab-title] { - overflow: hidden; - height: 0; - opacity: 0; - margin: 0; - padding: 0rem 1rem !important; - } - - [data-tab-active="true"] { - overflow: visible; - height: auto; - opacity: 1; - transition: opacity 0.25s ease-in; - margin: inherit !important; - } - - .cbi-section-node-tabbed { - margin-top: 0; - border-top: 0; - padding: 0; - } - - .cbi-value-field, - .cbi-value-description { - line-height: 1.25; - display: table-cell; - } - - .cbi-value-description { - font-size: small; - padding-top: 0.4rem; - opacity: 0.5; - color: #fff; - } - - .cbi-value-title { - display: table-cell; - float: left; - width: 23rem; - padding-top: 0.35rem; - padding-right: 2rem; - text-align: right; - word-wrap: break-word; - } - - .cbi-value { - display: inline-block; - width: 100%; - padding: 0.35rem 1rem 0.2rem; - } - - .cbi-value ul { - line-height: 1.25; - } - - .cbi-value-field .cbi-dropdown, - .cbi-value-field .cbi-input-select, - .cbi-value input[type="text"], - .cbi-value input[type="password"] { - min-width: 25rem; - } - - #cbi-firewall-zone .cbi-input-select, - #cbi-network-switch_vlan .cbi-input-select { - min-width: 11rem; - } - - #cbi-network-switch_vlan .cbi-input-text { - max-width: 3rem; - } - - .cbi-input-invalid { - color: red; - border-bottom-color: red; - } - - .cbi-section-error { - font-weight: 700; - line-height: 1.42857143; - border: thin solid red; - border-radius: 3px; - background-color: #fce6e6; - margin: 18px; - padding: 6px; - } - - .cbi-section-error ul { - margin: 0 0 0 20px; - } - - .cbi-section-error ul li { - font-weight: 700; - color: red; - } - - .td[data-title]::before { - font-weight: 700; - display: none; - content: attr(data-title) ":\20"; - text-align: left; - white-space: nowrap; - padding: 0.25rem 0; - } - - .tr[data-title]::before, - .tr.cbi-section-table-titles.named::before { - font-weight: 700; - display: table-cell; - align-self: center; - flex: 1 1 5%; - content: attr(data-title) "\20"; - text-align: center; - vertical-align: middle; - white-space: normal; - word-wrap: break-word; - padding: 0.25rem; - } - - .cbi-rowstyle-2 .cbi-button-up, - .cbi-rowstyle-2 .cbi-button-down, - body:not(.Interfaces) .cbi-rowstyle-2:first-child {} - - .cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { - width: auto !important; - } - - .td.cbi-section-actions { - text-align: right !important; - vertical-align: middle; - display: flex; - justify-content: center; - flex-wrap: wrap; - gap: 5px; - } - - .td.cbi-section-actions>* { - display: inline-flex; - } - - .td.cbi-section-actions>button { - display: block; - } - - .td.cbi-section-actions>*>*, - .td.cbi-section-actions>*>form>* { - margin: 0 5px; - } - - .td.cbi-section-actions>*>form { - display: inline-flex; - margin: 0; - } - - .cbi-dynlist { - line-height: 1.3; - flex-direction: column; - min-height: 30px; - cursor: text; - } - - .cbi-dynlist>.item { - position: relative; - max-width: 25rem; - margin-right: 2em; - pointer-events: none; - color: #666; - border-bottom: 2px solid rgba(0, 0, 0, 0.26); - outline: 0; - padding: 0.5em 0.25em 0.25em 0; - } - - .cbi-dynlist[name="sshkeys"]>.item { - max-width: none; - } - - .cbi-dynlist>.item::after { - font-weight: 700; - position: absolute; - right: -2em; - bottom: 0; - display: inline-flex; - min-height: 17px; - content: "\00D7"; - pointer-events: auto; - color: #fff; - border: thin solid #d43f3a; - background-color: #d9534f; - padding: 0 6px; - border-radius: 5px; - } - - .cbi-dynlist>.item>span { - white-space: normal; - word-break: break-word; - } - - .cbi-dynlist>.add-item { - display: inline-flex; - align-items: center; - width: 100%; - min-width: 16rem; - } - - .cbi-dynlist>.add-item:not([ondrop])>input { - overflow: hidden; - width: 100%; - min-width: 15rem; - white-space: nowrap; - text-overflow: ellipsis; - } - - .cbi-dynlist>.add-item[ondrop]>input { - min-width: 13rem; - } - - .cbi-dynlist, - .cbi-dropdown { - position: relative; - display: inline-flex; - padding: 0; - } - - .cbi-dropdown[placeholder*="select"] { - max-width: 25rem; - height: auto; - margin-top: -3px; - } - - .cbi-dropdown>ul { - display: flex; - overflow-x: hidden; - overflow-y: auto; - width: 100%; - list-style: none; - outline: 0; - margin: 0 !important; - padding: 0; - } - - .cbi-dropdown>.open { - flex-basis: 15px; - } - - .cbi-dropdown>.open, - .cbi-dropdown>.more { - font-size: 1rem; - font-weight: 900; - line-height: 2; - display: flex; - flex-direction: column; - flex-grow: 0; - flex-shrink: 0; - justify-content: center; - cursor: default; - text-align: center; - outline: 0; - padding: 0 0.25em; - } - - .cbi-dropdown.btn { - min-height: 1.8rem; - padding-top: 0px; - padding-bottom: 0px; - padding-right: 0px; - } - - .cbi-dropdown.btn>.open { - font-size: 0.8rem; - margin: 0 5px; - padding: 0px; - } - - .cbi-dropdown.btn>div { - margin: 0px; - } - - .cbi-dropdown>.more, - .cbi-dropdown>ul>li[placeholder] { - font-weight: 700; - display: none; - color: #777; - } - - .cbi-dropdown>ul>li { - display: none; - overflow: hidden; - align-items: center; - align-self: center; - flex-grow: 1; - flex-shrink: 1; - min-height: 20px; - white-space: nowrap; - text-overflow: ellipsis; - padding: 0.3rem 1rem 0.3rem 1rem; - } - - .cbi-dropdown>ul>li[display]:not([display="0"]) { - border-left: thin solid #ccc; - } - - .cbi-dropdown[empty]>ul { - max-width: 1px; - } - - .cbi-dropdown>ul>li>form { - display: none; - pointer-events: none; - margin: 0; - padding: 0; - } - - .cbi-dropdown>ul>li img { - margin-right: 0.25em; - vertical-align: middle; - } - - .cbi-dropdown>ul>li>form>input[type="checkbox"] { - height: auto; - margin: 0; - } - - .cbi-dropdown>ul>li input[type="text"] { - height: 20px; - } - - .cbi-dropdown[open]>ul.dropdown { - position: absolute; - z-index: 1100; - display: block; - width: auto; - min-width: 100%; - max-width: none; - max-height: 200px !important; - border: thin solid #918e8c; - background: #787878a8; - box-shadow: 0 0 4px #918e8c; - color: var(--main-menu-color); - } - - .cbi-dropdown>ul>li[display], - .cbi-dropdown[open]>ul.preview, - .cbi-dropdown[open]>ul.dropdown>li, - .cbi-dropdown[multiple]>ul>li>label, - .cbi-dropdown[multiple][open]>ul.dropdown>li, - .cbi-dropdown[multiple][more]>.more, - .cbi-dropdown[multiple][empty]>.more { - display: flex; - align-items: center; - flex-grow: 1; - justify-content: space-around; - } - - .cbi-dropdown[open]>ul.dropdown>li {} - - .cbi-dropdown[open]>ul.dropdown>li[selected] { - background: #b0d0f0; - } - - .cbi-dropdown[open]>ul.dropdown>li.focus { - background: linear-gradient(90deg, #a3c2e8 0%, #84aad9 100%); - } - - .cbi-dropdown[open]>ul.dropdown>li:last-child { - margin-bottom: 0; - } - - .cbi-dropdown[open]>ul.dropdown>li[unselectable] { - opacity: 0.7; - } - - .cbi-dropdown[disabled] { - pointer-events: none; - opacity: 0.6; - } - - .cbi-dropdown[open] .zonebadge { - width: auto; - } - - .cbi-progressbar { - border-radius: 15px; - overflow: hidden; - position: relative; - min-width: 170px; - height: 30px; - background: #11111d61; - margin: 6px 0; - } - - .cbi-progressbar title { - font-family: "Quicksand-Bold"; - letter-spacing: 5px; - text-align: center; - padding-bottom: 10px; - margin: 2rem 0 0; - color: #ffffff; - } - - .cbi-progressbar>div { - width: 0; - height: 100%; - transition: width 2s ease-in; - background: #0099cc; - padding: 0.5rem; - } - - .cbi-progressbar::after { - font-family: monospace; - font-size: 1.2em; - font-weight: 700; - font-size-adjust: 0.38; - line-height: normal; - position: absolute; - top: 50%; - transform: translateY(-50%); - right: 0; - left: 0; - overflow: hidden; - content: attr(title); - text-align: center; - white-space: pre; - text-overflow: ellipsis; - text-shadow: 0 0 2px #eee; - } - - #modal_overlay { - position: fixed; - z-index: 900; - top: 4rem; - right: 10000px; - bottom: 0; - left: -10000px; - overflow-y: scroll; - transition: opacity 0.125s ease-in; - opacity: 0; - background: rgba(0, 0, 0, 0.7); - -webkit-overflow-scrolling: touch; - } - - .modal { - display: flex; - align-items: center; - flex-wrap: wrap; - width: 90%; - min-width: 270px; - max-width: 600px; - min-height: 32px; - border-radius: 20px !important; - background: #8f8f8f75; - margin: 5em auto; - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - padding: 1em; - - } - - .modal>* { - line-height: normal; - flex-basis: 100%; - margin-bottom: 0.5em; - max-width: 100%; - } - - .modal>pre, - .modal>textarea { - font-size: 1rem; - font-size-adjust: 0.35; - overflow: auto; - margin-bottom: 0.5em; - cursor: auto; - white-space: pre-wrap; - color: #eee; - outline: 0; - background-color: #101010; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); - padding: 8.5px; - } - - .modal>h4 { - margin: 0.5em 0; - } - - .modal ul { - margin-left: 2.2em; - } - - .modal li { - list-style-type: square; - color: rgb(216, 216, 216); - } - - .modal p { - padding-left: 0.25rem; - word-break: break-word; - } - - .modal .label { - font-size: 0.6rem; - font-weight: 400; - cursor: default; - border-radius: 0; - padding: 0.1rem 0.3rem 0; - } - - .modal .label.warning { - background-color: #f0ad4e !important; - } - - .modal.cbi-modal { - max-width: 90%; - max-height: none; - } - - body.modal-overlay-active { - overflow: hidden; - height: 100vh; - } - - body.modal-overlay-active #modal_overlay { - right: 0; - left: 0; - opacity: 1; - } - - .spinning { - position: relative; - align-items: center; - padding-left: 32px !important; - color: #fff; - } - - .spinning::before { - position: absolute; - font-size: medium; - font-style: "Quicksand-Bold"; - left: 8px; - width: 16px; - height: 16px; - content: ""; - animation: anim-rotate 2s infinite cubic-bezier(0.18, 0.89, 0.32, 1.28); - background: url(./icon/loading.svg) no-repeat center; - background-size: 20px; - } - - .left, - .left::before { - text-align: left !important; - } - - .right, - .right::before { - text-align: right !important; - } - - .top { - align-self: flex-start !important; - vertical-align: top !important; - } - - .bottom { - align-self: flex-end !important; - vertical-align: bottom !important; - } - - .inline { - display: inline; - } - - .cbi-page-actions { - padding-top: 1rem; - text-align: center; - } - - .cbi-page-actions>form[method="post"] { - display: inline-block; - } - - .th[data-type="button"], - .td[data-type="button"], - .th[data-type="fvalue"], - .td[data-type="fvalue"] { - flex: 1 1 2em; - text-align: center; - } - - .ifacebadge { - display: inline-flex; - background: #ffffff33; - padding: 0.5rem 0.8rem; - border-radius: 10px; - } - - td>.ifacebadge, - .td>.ifacebadge { - font-size: 0.8rem; - background-color: #000000; - border-radius: 10px; - } - - .ifacebadge>em, - .ifacebadge>img { - display: inline-block; - align-self: flex-start; - margin: 0 0.2rem; - } - - .ifacebadge>img+img { - margin: 0 0.2rem 0 0; - } - - .network-status-table .ifacebox { - flex-grow: 1; - margin: 0.5em; - } - - .network-status-table .ifacebox-body { - display: flex; - flex-direction: column; - height: 100%; - } - - .network-status-table .ifacebox-body>span { - flex: 10 10 auto; - height: 100%; - } - - .network-status-table .ifacebox-body .ifacebadge { - align-items: center; - flex: 1 1 auto; - min-width: 220px; - background-color: #11111d; - margin: 0.5em 0.25em 0; - padding: 0.5em; - border-radius: 10px; - } - - .cbi-input-textarea { - font-family: monospace; - width: 100%; - min-height: 14rem; - color: #000; - padding: 0.8rem; - } - - #syslog { - font-size: small; - overflow-y: hidden; - width: 100%; - min-height: 15rem; - resize: none; - color: #eee; - border: 0; - border-radius: 20px; - background-color: #10101057; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); - padding: 1rem; - } - - #syslog:focus { - outline: 0; - } - - .uci-change-list { - font-family: monospace; - } - - .uci-change-list ins, - .uci-change-legend-label ins { - display: block; - text-decoration: none; - border: thin solid #0f0; - background-color: #cfc; - padding: 2px; - } - - .uci-change-list del, - .uci-change-legend-label del { - font-style: normal; - display: block; - text-decoration: none; - border: thin solid red; - background-color: #fcc; - padding: 2px; - } - - .uci-change-list var, - .uci-change-legend-label var { - font-style: normal; - display: block; - text-decoration: none; - border: thin solid #ccc; - background-color: #eee; - padding: 2px; - } - - .uci-change-list var ins, - .uci-change-list var del { - font-style: normal; - white-space: pre; - border: 0; - padding: 0; - } - - .uci-change-legend { - padding: 5px; - } - - .uci-change-legend-label { - float: left; - width: 150px; - color: #fff; - } - - .uci-change-legend-label>ins, - .uci-change-legend-label>del, - .uci-change-legend-label>var { - display: block; - float: left; - width: 10px; - height: 10px; - margin-right: 4px; - } - - .uci-change-legend-label var ins, - .uci-change-legend-label var del { - line-height: 0.4; - border: 0; - } - - #iwsvg, - #iwsvg2, - #bwsvg { - border: thin solid #d4d4d4 !important; - } - - .ifacebox { - line-height: 1.25; - display: inline-flex; - flex-direction: column; - min-width: 100px; - background-color: #54545450; - border-radius: 20px; - flex-wrap: nowrap; - align-content: center; - justify-content: flex-start; - align-items: center; - color: #fff; - } - - div.ifacebox-head { - --zone-color-rgb: 144, 240, 144; - background-color: rgb(43, 79, 43); - } - - style attribute { - --zone-color-rgb: 144, 240, 144; - background-color: rgb(43, 79, 43); - } - - .ifacebox-head { - background: #939393; - padding: 0.25em; - color: #fff; - } - - .ifacebox-head.active { - background: var(--bar-bg); - } - - .ifacebox-body { - padding: 0.25em; - } - - .cbi-image-button { - margin-left: 0.5rem; - } - - .zonebadge { - display: inline-block; - padding: 0.2rem 0.5rem; - } - - .zonebadge .ifacebadge { - border: thin solid #6c6c6c; - margin: 0.1rem 0.2rem; - padding: 0.2rem 0.3rem; - } - - .zonebadge>input[type="text"] { - min-width: 10rem; - margin-top: 0.3rem; - padding: 0.16rem 1rem; - } - - .zonebadge>em, - .zonebadge>strong { - display: inline-block; - margin: 0 0.2rem; - } - - .cbi-value-field .cbi-input-checkbox, - .cbi-value-field .cbi-input-radio { - margin-top: 0.1rem; - } - - .cbi-value-field>ul>li .ifacebadge { - margin-top: -0.5rem; - margin-left: 0.4rem; - background-color: #eee; - } - - .cbi-section-table-row>.cbi-value-field .cbi-dropdown { - min-width: 7rem; - } - - .cbi-section-create { - display: inline-flex; - align-items: center; - margin: 0.5rem -3px; - } - - .cbi-section-create>* { - margin: 0.5rem; - } - - div.cbi-value var, - td.cbi-value-field var, - .td.cbi-value-field var { - font-style: italic; - color: #0069d6; - } - - .cbi-optionals { - border-top: thin solid #ccc; - padding: 1rem 1rem 0; - } - - .cbi-dropdown-container { - position: relative; - } - - .cbi-tooltip-container, - span[data-tooltip], - span[data-tooltip] .label { - cursor: help !important; - text-align: left !important; - font-size: 80% !important; - color: #fff !important; - } - - .cbi-tooltip { - position: absolute; - z-index: 1000; - left: -1000px; - transition: opacity 0.25s ease-out; - white-space: pre; - pointer-events: none; - opacity: 0; - border-radius: 20px; - background: #54545450; - box-shadow: 0 0 2px #444; - padding: 2px 5px; - -webkit-backdrop-filter: blur(20px); - backdrop-filter: blur(20px); - - } - - .cbi-tooltip-container:hover .cbi-tooltip { - left: auto; - transition: opacity 0.25s ease-in; - opacity: 1; - } - - .zonebadge .cbi-tooltip { - background: inherit; - margin: -1.5rem 0 0 -0.5rem; - padding: 0.25rem; - } - - .zonebadge-empty { - color: #404040; - background: repeating-linear-gradient(45deg, - rgba(204, 204, 204, 0.5), - rgba(204, 204, 204, 0.5) 5px, - rgba(255, 255, 255, 0.5) 5px, - rgba(255, 255, 255, 0.5) 10px); - } - - .zone-forwards { - display: flex; - min-width: 10rem; - } - - .zone-forwards>* { - flex: 1 1 45%; - } - - .zone-forwards>span { - flex-basis: 10%; - text-align: center; - padding: 0 0.25rem; - } - - .zone-forwards .zone-src, - .zone-forwards .zone-dest { - display: flex; - flex-direction: column; - } - - label>input[type="checkbox"], - label>input[type="radio"] { - position: relative; - top: 0.4rem; - right: 0.2rem; - vertical-align: bottom; - margin: 0; - } - - label[data-index][data-depends] { - padding-right: 2em; - } - - .darkMask { - position: fixed; - z-index: 99; - width: 100%; - height: 100%; - content: ""; - transition: opacity 400ms, visibility 400ms; - visibility: hidden; - opacity: 0; - background-color: #2222359a; - } - - #diag-rc-output>pre, - #command-rc-output>pre, - [data-page="admin-services-wol"] .notice code { - font-size: 1.2rem; - font-size-adjust: 0.35; - line-height: normal; - display: block; - overflow-y: hidden; - width: 100%; - white-space: pre; - color: #eee; - background-color: #101010; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); - padding: 8.5px; - } - - input[name="ping"], - input[name="traceroute"], - input[name="nslookup"] { - width: 80%; - } - - .node-main-login>.main fieldset { - display: inline; - overflow: hidden; - margin-bottom: 1rem; - border: 0; - background: none; - box-shadow: none; - padding: 0.5rem; - } - - .node-main-login>.main .cbi-value-title { - width: 9.5rem; - } - - .node-main-login>.main #maincontent { - text-align: center; - } - - .node-main-login>.main .container { - display: inline-block; - margin-top: 2rem !important; - text-align: left; - background-color: #2e2b2b00; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); - padding: 1rem 3.5rem 2rem; - } - - .node-main-login>.main .cbi-value>* { - display: inline-block !important; - } - - .node-main-login>.main .cbi-input-text { - width: 100% !important; - min-width: 15rem; - } - - .node-status-overview>.main fieldset:nth-child(4) .td:nth-child(2), - .node-status-processes>.main .table .tr .td:nth-child(3) { - white-space: normal; - } - - [data-page="admin-system-reboot"] p { - padding-left: 2rem; - } - - [data-page="admin-system-reboot"] p>span { - position: relative; - top: 0.1rem; - left: 1rem; - } - - #cbi-samba [data-tab="template"] .cbi-value-title { - width: auto; - padding-bottom: 0.6rem; - } - - .controls>*>.btn:not([aria-label$="page"]) { - flex-grow: initial !important; - margin-top: 0.1rem; - } - - .controls>#pager>.btn[aria-label$="page"] { - font-size: 1.4rem; - font-weight: 700; - } - - .controls>*>label { - margin-bottom: 0.2rem; - } - - [data-page="admin-system-opkg"] div.btn { - display: inline; - padding: 0.3rem 0.6rem; - } - - [data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear), - [data-page="admin-system-opkg"] #maincontent>.container { - margin-top: 2rem; - padding-top: 0.1rem; - } - - [data-page="admin-system-opkg"] #maincontent>.container { - margin: 2rem 2rem 1rem; - } - - .td.version, - .td.size { - white-space: normal !important; - word-break: break-word; - } - - .cbi-tabmenu+.cbi-section { - margin-top: 0; - } - - #cbi-wireless>#wifi_assoclist_table>.tr { - box-shadow: inset 1px -1px 0 #ddd, inset -1px -1px 0 #ddd; - } - - #cbi-wireless>#wifi_assoclist_table>.tr.placeholder>.td { - right: 33px; - bottom: 33px; - left: 33px; - border-top: thin solid #ddd !important; - } - - #cbi-wireless>#wifi_assoclist_table>.tr.table-titles { - box-shadow: inset 1px 0 0 #ddd, inset -1px 0 0 #ddd; - } - - #cbi-wireless>#wifi_assoclist_table>.tr.table-titles>.th { - border-bottom: thin solid #ddd; - box-shadow: 0 -1px 0 0 #ddd; - } - - #wifi_assoclist_table>.tr>.td[data-title="RX Rate / TX Rate"] { - width: 23rem; - } - - #iptables { - margin: 0; - } - - .Firewall form { - box-shadow: none; - margin: 2rem 2rem 0 0; - padding: 0; - } - - #cbi-firewall-redirect table *, - #cbi-network-switch_vlan table *, - #cbi-firewall-zone table * { - font-size: small; - } - - #cbi-firewall-redirect table input[type="text"], - #cbi-network-switch_vlan table input[type="text"], - #cbi-firewall-zone table input[type="text"] { - width: 5rem; - } - - #cbi-firewall-redirect table select, - #cbi-network-switch_vlan table select, - #cbi-firewall-zone table select { - min-width: 3.5rem; - } - - #cbi-network-switch_vlan .th, - #cbi-network-switch_vlan .td { - flex-basis: 12%; - } - - #applyreboot-container { - margin: 2rem; - } - - #applyreboot-section { - line-height: 300%; - margin: 2rem; - } - - .OpenVPN a { - line-height: initial !important; - } - - .commandbox { - width: 24% !important; - border-bottom: thin solid #ccc; - background: #eee; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), - 0 1px 2px rgba(0, 0, 0, 0.05); - margin: 10px 0 0 10px !important; - padding: 0.5rem 1rem; - } - - .commandbox h3 { - line-height: normal !important; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - margin: 6px 0 !important; - } - - .commandbox div { - left: auto !important; - } - - .commandbox code { - position: absolute; - overflow: hidden; - max-width: 60%; - margin-left: 4px; - white-space: nowrap; - text-overflow: ellipsis; - padding: 2px 3px; - } - - .commandbox code:hover { - overflow-y: auto; - max-height: 50px; - white-space: normal; - } - - .commandbox p:first-of-type { - margin-top: -6px; - } - - .commandbox p:nth-of-type(2) { - margin-top: 2px; - } - - #command-rc-output .alert-message { - line-height: 1.42857143; - position: absolute; - top: 40px; - right: 32px; - max-width: 40%; - animation: anim-fade-in 1.5s forwards; - word-break: break-word; - opacity: 0; - margin: 0; - } - - .table[width="100%"], - .th[width="100%"], - .td[width="100%"], - .cbi-section-table-row>.cbi-value-field .cbi-dropdown, - .cbi-section-table-row>.cbi-value-field .cbi-input-select, - .cbi-section-table-row>.cbi-value-field .cbi-input-text, - .cbi-section-table-row>.cbi-value-field .cbi-input-password, - .cbi-dropdown[open]>ul.dropdown>li>input.create-item-input:first-child:last-child, - .cbi-dropdown .zonebadge, - .node-main-login>.main>.main-right, - #cbi-firewall-zone .td, - #cbi-network-switch_vlan .td { - width: 100%; - min-width: 60px; - } - - .cbi-rowstyle-2 { - background-color: ; - } - - .pull-right, - .node-main-login>.main form>div:last-child { - float: right; - } - - .pull-left, - .cbi-page-actions .cbi-button-link:first-child { - float: left; - } - - #modemenu>li>a, - .label { - background-color: rgb(104, 104, 104); - color: #fff !important; - font-size: 0.8rem; - font-weight: 700; - text-decoration: none; - text-shadow: none; - text-transform: uppercase; - white-space: nowrap; - padding: 0.3rem 0.8rem; - border-radius: 10px; - } - - [data-indicator="poll-status"][data-style="active"] { - position: absolute; - right: 14px; - width: 32px; - height: 32px; - content: ""; - background: url(./icon/loading.svg) no-repeat; - text-indent: -9999px; - animation: anim-rotate 5s infinite ease-in-out; - background-size: 32px; - } - - [data-indicator="poll-status"][data-style="inactive"] { - position: absolute; - right: 14px; - width: 32px; - height: 32px; - content: ""; - background: url(./icon/pause.svg) no-repeat; - text-indent: -9999px; - background-size: 32px; - } - - - [data-indicator="uci-changes"][data-style="active"] { - position: absolute; - width: 32px; - height: 32px; - content: ""; - background: url(./icon/save.svg) no-repeat; - text-indent: -9999px; - background-size: 32px; - } - - #modemenu>li>a.active, - .notice { - background-color: rgb(66, 66, 66) !important; - } - - #xhr_poll_status, - .cbi-value-field>ul>li { - display: flex; - } - - .alert-message .btn, - .modal .btn { - padding: 0.3rem 0.6rem; - } - - .container .alert, - .container .alert-message, - .cbi-map-descr+fieldset { - margin-top: 1rem; - } - - .main>.main-left>.nav, - .cbi-value-field>ul>li>label { - margin-top: 0.5rem; - } - - .main>.main-left>.nav>li.active>a, - .main>.main-left>.nav>.slide>.slide-menu>.active>a { - color: #fff; - } - - .main>.main-left>.nav>li.active, - .main>.main-left>.nav>.slide>.slide-menu>.active { - - background-color: var(--submenu-bg-hover-active); - border-radius: 10px; - } - - .main>.main-left>.nav>.slide>ul, - .main>.main-left[style*="overflow: hidden"]>.nav>.slide>.menu::before, - .tr.placeholder .td[data-title]::before, - .cbi-dropdown>ul.preview, - .cbi-dropdown>ul>li .hide-close, - .cbi-dropdown[open]>ul.dropdown>li .hide-open, - .hidden, - .showSide, - .node-main-login>.main>.main-left, - [data-page^="admin-system-commands"] .panel-title, - [data-page^="command-cfg"] .mobile-hide, - [data-page^="command-cfg"] .showSide { - display: none; - } - - .main>.main-left>.nav>.slide.active>ul, - .cbi-dropdown[empty]>ul>li, - .cbi-dropdown[optional][open]>ul.dropdown>li[placeholder], - .cbi-dropdown[multiple][open]>ul.dropdown>li>form, - .node-main-login>.main .cbi-value, - #cbi-samba [data-tab="template"] .cbi-value-field, - #cbi-firewall-zone .table, - #cbi-network-switch_vlan .table { - display: block; - } - - .main>.main-left>.nav>li:hover, - .main>.main-left>.nav>.slide>.menu:hover, - .main>.main-left>.nav>.slide>.slide-menu>li:hover { - background: var(--submenu-bg-hover); - border-radius: 10px; - } - - table>tbody>tr>td, - table>tbody>tr>th, - table>tfoot>tr>td, - table>tfoot>tr>th, - table>thead>tr>td, - table>thead>tr>th, - .table>.tbody>.tr>.td, - .table>.tbody>.tr>.th, - .table>.tfoot>.tr>.td, - .table>.tfoot>.tr>.th, - .table>.thead>.tr>.td, - .table>.thead>.tr>.th, - .table>.tr>.td.cbi-value-field, - .table>.tr>.th.cbi-section-table-cell, - .uci-change-list var, - .uci-change-list del, - .uci-change-list ins, - .cbi-section-remove { - padding: 0.5rem; - } - - #cbi-wireless .td, - #cbi-network .tr:first-child>.td, - .table[width="100%"]>.tr:first-child>.td, - [data-page="admin-network-diagnostics"] .tr>.td, - .tr.table-titles>.th, - .tr.cbi-section-table-titles>.th, - #iwsvg, - [data-page="admin-status-realtime-bandwidth"] #bwsvg { - border-top: 0 !important; - } - - .cbi-section-table-row .td, - .center, - .center::before { - text-align: center !important; - } - - div>table>tbody>tr:nth-of-type(2n), - div>.table>.tr:nth-of-type(2n), - .cbi-section .cbi-section-remove:nth-of-type(2n), - .container>.cbi-section .cbi-section-node:nth-of-type(2n), - .cbi-section[id] .cbi-section-remove:nth-of-type(4n + 3), - .cbi-section[id] .cbi-section-node:nth-of-type(4n + 4), - .cbi-tabcontainer>.cbi-value:nth-of-type(2n), - .cbi-rowstyle-1 {} - - .cbi-dropdown>ul>li .hide-open, - .cbi-dropdown[open]>ul.dropdown>li .hide-close { - display: initial; - } - - .network-status-table, - .network-status-table .ifacebox-body>div { - display: flex; - flex-wrap: wrap; - } - - [data-page="admin-network-diagnostics"] .table, - .node-main-login .cbi-section { - box-shadow: none; - } - - @keyframes down { - from { - margin-left: 50%; - opacity: 0; - } - - to { - margin-left: 0%; - opacity: 1; - } - } - - @keyframes anim-rotate { - 0% { - -webkit-transform: rotate(0); - -ms-transform: rotate(0); - transform: rotate(0); - } - - 100% { - -webkit-transform: rotate(360deg); - -ms-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - @media screen and (min-height: 585px) { - .node-main-login footer { - position: absolute; - bottom: 0; - width: 100%; - } - } - - @keyframes anim-fade-in { - 100% { - opacity: 1; - } - } - - @media all and (-ms-high-contrast: none) { - .main>.main-left>.nav>.slide>.menu::before { - top: 30.25%; - } - - .main>.main-left>.nav>li:last-child::before { - top: 20%; - } - - .showSide::before { - top: -12px; - } - } - - @media screen and (max-width: 1600px) { - header>.fill>.container { - display: flex; - align-items: center; - margin-top: 0; - } - - header>.fill>.container>#logo { - width: calc(13rem); - } - - .main>.main-left { - width: calc(0% + 13rem); - } - - .main>.main-right { - width: calc(100% - 13rem); - } - - .btn:not(button), - .cbi-button { - font-size: 0.8rem; - padding: 0.3rem 0.6rem; - position: relative; - /*bottom: -0.5rem;*/ - } - - .label, - [data-indicator] { - padding: 0.2rem 0.6rem; - } - - fieldset, - .cbi-section { - padding: 1rem; - } - - .cbi-value-title { - width: 15rem; - padding-right: 0.6rem; - } - - .cbi-value-field .cbi-dropdown, - .cbi-value-field .cbi-input-select, - .cbi-value input[type="text"], - .cbi-value input[type="password"] { - min-width: 22rem; - } - - #cbi-firewall-zone .cbi-input-select { - min-width: 9rem; - } - - .cbi-input-textarea { - font-size: small; - } - - .node-admin-status>.main fieldset li>a { - padding: 0.3rem 0.6rem; - } - } - - @media screen and (max-width: 2000000000px) { - header { - height: 3.5rem; - } - - header>.fill>.container { - margin-top: 0.25rem; - cursor: default; - padding: 0.5rem 1rem; - } - - .main { - top: 3.5rem; - height: calc(100% - 3.5rem); - } - - .main>.main-left { - top: 4.3rem; - width: calc(0% + 13rem); - height: calc(100% - 3.5rem); - } - - .main>.main-right { - width: calc(100% - 13rem); - } - - .tabs>li>a, - .cbi-tabmenu>li>a { - padding: 0.2rem 0.5rem; - } - - .cbi-section>h3:first-child, - .panel-title { - font-size: 1.1rem; - padding-bottom: 1rem; - } - - table { - font-size: 0.7rem !important; - width: 100% !important; - } - - .table .cbi-input-text { - width: 100%; - } - - .cbi-value-field .cbi-dropdown, - .cbi-value-field .cbi-input-select, - .cbi-value input[type="text"], - .cbi-value input[type="password"] { - min-width: 19rem; - } - - #cbi-firewall-zone .cbi-input-select { - min-width: 4rem; - } - - .main>.main-left>.nav>li, - .main>.main-left>.nav>li a, - .main>.main-left>.nav>.slide>.menu, - .main>.main-left>.nav>li>[data-title="Logout"], - .main>.main-left>.nav>li>[data-title="Logout"], - .main>.main-left>.nav>li>[data-title="iStore"] { - font-size: 1rem; - color: #fff; - } - - .main>.main-left>.nav>.slide>.slide-menu>li>a { - font-size: 0.7rem; - color: #fff; - } - - #modal_overlay { - top: 3.5rem; - } - - [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table) { - display: block; - } - - [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table), - [data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table), - [data-page="admin-network-hosts"] .table, - [data-page="admin-network-routes"] .table { - overflow-y: visible; - } - - .commandbox { - width: 32% !important; - } - } - - @media screen and (max-width: 1152px) { - header>.fill>.container>.brand { - position: relative; - } - - html, - .main { - overflow-y: visible; - } - - .main>.loading>span { - top: 25%; - } - - .main>.main-left { - position: fixed; - z-index: 100; - visibility: hidden; - } - - .main>.main-right { - width: 100%; - } - - .showSide { - position: -webkit-sticky; - position: sticky; - top: 0rem; - display: inline-flex; - align-items: center; - height: 100%; - margin-right: 0.7rem; - cursor: pointer; - } - - body:not(.logged-in) .showSide { - visibility: hidden; - width: 0; - margin: 0; - } - - .cbi-value-title { - width: 12rem; - padding-right: 1rem; - } - - .cbi-value-field .cbi-dropdown, - .cbi-value-field .cbi-input-select, - .cbi-value input[type="text"] { - width: 16rem; - min-width: 16rem; - color: rgb(255, 255, 255); - } - - .cbi-value input[type="password"], - .cbi-value input[name^="pw"], - .cbi-value input[data-update="change"]:nth-child(2) { - width: 13rem !important; - min-width: 13rem; - color: #fff; - } - - #diag-rc-output>pre, - #command-rc-output>pre, - [data-page="admin-services-wol"] .notice code { - font-size: 1rem; - } - - .Interfaces .table { - overflow-x: hidden; - } - - #packages.table { - display: grid; - } - - .tr { - display: flex; - flex-direction: row; - flex-wrap: wrap; - } - - .Overview .table[width="100%"]>.tr { - flex-wrap: nowrap; - } - - .tr.placeholder { - border-bottom: thin solid #ddd; - } - - .tr.placeholder>.td, - #cbi-firewall .tr>.td, - #cbi-network .tr:nth-child(2)>.td, - .cbi-section #wifi_assoclist_table .tr>.td { - border-top: 0; - } - - .th, - .td { - display: inline-block; - align-self: flex-start; - flex: 2 2 25%; - text-overflow: ellipsis; - word-wrap: break-word; - } - - .td select, - .td input[type="text"] { - width: 100%; - word-wrap: normal; - } - - .td [data-dynlist]>input, - .td input.cbi-input-password { - width: calc(100% - 1.5rem); - } - - .td[data-type="button"], - .td[data-type="fvalue"] { - flex: 1 1 12.5%; - text-align: left; - } - - .th.cbi-value-field, - .td.cbi-value-field, - .th.cbi-section-table-cell, - .td.cbi-section-table-cell { - flex-basis: auto; - padding-top: 1rem; - } - - .cbi-section-table-row { - display: flex; - flex-direction: row; - flex-wrap: wrap; - justify-content: space-between; - } - - .td.cbi-value-field, - .cbi-section-table-cell { - display: inline-block; - flex: 10 10 auto; - flex-basis: 50%; - text-align: center; - } - - .td.cbi-section-actions { - vertical-align: bottom; - } - - .tr[data-title]::before, - .tr.cbi-section-table-titles.named::before { - font-size: 0.9rem; - display: block; - flex: 1 1 100%; - border-bottom: thin solid rgba(0, 0, 0, 0.26); - background: #90c0e0; - } - - .cbi-button+.cbi-button { - margin-left: 0; - } - - .td.cbi-section-actions>*>*, - .td.cbi-section-actions>*>form>* { - margin: 2.1px 3px; - } - - .Firewall form { - position: static !important; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 2px 0 rgba(0, 0, 0, 0.12); - margin: 0 0 2rem; - padding: 2rem; - } - - .Firewall form input { - width: 100% !important; - margin: 1rem 0 0; - } - - .Firewall .center, - .Firewall .center::before { - text-align: left !important; - } - - .commandbox { - width: 100% !important; - margin-left: 0 !important; - } - - .tr.table-titles, - .tr.cbi-section-table-titles, - .tr.cbi-section-table-descr { - display: none; - } - - .node-main-login>.main .cbi-value-title, - .td[data-title], - [data-page^="admin-status-realtime"] .td[id] { - text-align: left; - color: #ffffff; - } - - .table, - .td[data-title]::before { - display: block; - } - } - - @media screen and (max-width: 600px) { - header>.fill>.container>#logo { - padding: 1rem; - margin: 0; - position: absolute; - left: 50%; - top: 0; - width: 100px; - transform: translateX(-50%); - } - - header>.fill>.container>#logo>img { - width: 100%; - margin-top: 0; - } - - .cbi-progressbar::after { - font-size: 0.95em; - line-height: 1.5; - } - - fieldset, - .cbi-section { - margin: 1rem 0 0; - } - - } - - #maincontent>.container { - margin: 0 0.5rem 1.5rem; - } - - .main>.main-left>.nav>.slide>.menu, - .main>.main-left>.nav>li>[data-title="Logout"], - .main>.main-left>.nav>li>[data-title="Log out"], - .main>.main-left>.nav>li>[data-title="iStore"] { - font-size: 1.1rem; - } - - .cbi-value-title { - display: block; - min-width: 0 !important; - text-align: left; - margin: 0.5rem 0; - } - - .cbi-value>.cbi-value-field { - display: inline-block; - } - - .tabs>li>a, - .cbi-tabmenu>li>a { - padding: 0.2rem 0.3rem; - } - - .cbi-page-actions>.cbi-button { - margin-top: 0.2rem; - } - - .node-main-login>.main .container { - margin: 2rem 1.2rem 1.5rem !important; - padding: 0.3rem 1.7rem 2rem 1.6rem; - } - - .node-main-login>.main .cbi-value { - padding: 0; - } - - .node-main-login>.main form>div:last-child { - margin-top: 2rem; - } - - .node-main-login>.main .cbi-value-title { - font-size: 1.2rem; - width: 100% !important; - } - - .node-main-login>.main fieldset { - margin: 0; - padding: 0.5rem; - } - - .commandbox p:first-of-type { - margin-top: -8px; - } - - #syslog, - #diag-rc-output>pre, - #command-rc-output>pre, - [data-page="admin-services-wol"] .notice code { - font-size: 0.8rem !important; - } - - h2 {} - - .cbi-section>h3:first-child, - .panel-title { - font-size: 1.2rem; - padding-bottom: 1rem; - } - - .node-system-packages>.main .cbi-value.cbi-value-last>div { - width: 100% !important; - } - - .th, - .td { - flex-basis: 50%; - color: #fff; - } - - .tr>.td[data-title="Sensor"] { - text-align: center; - } - - .tr>.td[data-title="Temperature"] { - text-align: center; - } - - .tr>.td[data-title="Hostname"] { - text-align: center; - } - - .tr>.td[data-title="IPv4 address"] { - text-align: center; - } - - .tr>.td[data-title="MAC address"] { - text-align: center; - } - - .tr>.td[data-title="Lease time remaining"] { - text-align: center; - } - - - .td.cbi-value-field { - flex-basis: 100%; - } - - .td.cbi-value-field[data-type="button"], - .td.cbi-value-field[data-type="fvalue"] { - flex-basis: 25%; - text-align: left; - } - - td>.ifacebadge, - .td>.ifacebadge { - font-size: 0.62rem; - } - - #cbi-wireless>#wifi_assoclist_table .td { - overflow: hidden; - } - - #cbi-wireless>.cbi-section-node .td, - .Interfaces .td.cbi-section-actions { - text-align: center !important; - } - - .cbi-modal { - padding: 0.5rem; - } - - .cbi-modal .cbi-value { - padding: 0 0 0.25rem; - } - - .cbi-modal [data-tab-title] { - padding: 0 0.25rem !important; - } - - [data-tab-title] { - padding: 0 0.5rem !important; - } - - body, - code { - font-size: 0.8rem; - } - - .main>.main-left>.nav>.slide>.slide-menu>li>a, - .tr[data-title]::before, - .tr.cbi-section-table-titles.named::before { - font-size: - } - - .cbi-value-title, - .cbi-value-description, - .cbi-value-field, - .cbi-value-field .cbi-dropdown, - .cbi-value-field .cbi-input-select, - .cbi-value input[type="text"], - .node-system-packages>.main .cbi-value .cbi-value-field input { - width: 100%; - display: flex; - color: #fff; - flex-direction: column-reverse; - flex-wrap: wrap; - align-content: stretch; - align-items: flex-start; -} - } - - .cbi-page-actions>div>input, - .mobile-hide, - [data-page="admin-status-processes"] .td[data-title="Hang Up"]::before, - [data-page="admin-status-processes"] .td[data-title="Terminate"]::before, - [data-page="admin-status-processes"] .td[data-title="Kill"]::before, - .hide-sm, - .hide-xs:not([data-title="MAC-Address"]) { - display: none; - } - - .tabs>li>a, - select, - input { - font-size: 0.9rem; - } - - - @media screen and (min-width: 600px) { - ::-webkit-scrollbar { - width: 10px; - height: 10px; - } - - ::-webkit-scrollbar, - ::-webkit-scrollbar-corner { - background: transparent; - } - - ::-webkit-scrollbar-thumb { - background: #9e9e9e; - } - - ::-webkit-scrollbar-thumb:hover { - background: #757575; - } - - ::-webkit-scrollbar-thumb:active { - background: #424242; - } - } diff --git a/openwrt-packages/luci-theme-alpha/luasrc/style/catatan.txt b/openwrt-packages/luci-theme-alpha/luasrc/style/catatan.txt deleted file mode 100644 index c74e132eef..0000000000 --- a/openwrt-packages/luci-theme-alpha/luasrc/style/catatan.txt +++ /dev/null @@ -1 +0,0 @@ -buat tambah login page disini diff --git a/openwrt-packages/luci-theme-alpha/luasrc/style/openwrt20thanniversary.png b/openwrt-packages/luci-theme-alpha/luasrc/style/openwrt20thanniversary.png index 18ae1ecdd306eb90f59965a64acfbf940f59b6c0..b7d675560e8ae8cd1ae42e4f6abd3899c3769300 100644 GIT binary patch literal 126625 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 literal 183284 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 + + + + + + + --- Calculate link width for responsive design -local link_width = string.format("calc(100%% / %d)", num_links) - --- Retrieve theme properties -local background_color = config.color or '#2222359a' -local blur_value = tonumber(config.blur) or 20 -local link_blur = string.format("blur(%dpx)", blur_value) -%> - - - - - - - - - - - - - + \ No newline at end of file diff --git a/openwrt-packages/luci-theme-alpha/template/footer.ut b/openwrt-packages/luci-theme-alpha/template/footer.ut index 888b0e5523..f6740eb1b0 100644 --- a/openwrt-packages/luci-theme-alpha/template/footer.ut +++ b/openwrt-packages/luci-theme-alpha/template/footer.ut @@ -54,7 +54,7 @@

Wy`_1Qn=+b&JXNkc{%#@o?KiAp>`l1r9tPNE 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 diff --git a/openwrt-packages/luci-theme-alpha/luasrc/style/style.css b/openwrt-packages/luci-theme-alpha/luasrc/style/style.css index f43a7c5255..0f650fd614 100644 --- a/openwrt-packages/luci-theme-alpha/luasrc/style/style.css +++ b/openwrt-packages/luci-theme-alpha/luasrc/style/style.css @@ -410,7 +410,8 @@ img.bawah { display: block; padding: 20px; text-decoration: none; - width: 25rem; + width: 14rem; + max-width: 80vw; } .icon-credits a { diff --git a/openwrt-packages/luci-theme-alpha/template/footer.htm b/openwrt-packages/luci-theme-alpha/template/footer.htm index 37d6091d6a..19ba13585d 100644 --- a/openwrt-packages/luci-theme-alpha/template/footer.htm +++ b/openwrt-packages/luci-theme-alpha/template/footer.htm @@ -1,127 +1,108 @@ -<%# - Alpha os is made from me for all .. especially for indo wrt members and fan of OpenWrt or DBAI Community - luci-theme-alpha - Copyright 2024 derisamedia +<%# Alpha os is made from me for all .. especially for indo wrt members and fan of OpenWrt or DBAI Community + luci-theme-alpha Copyright 2024 derisamedia Have a bug? Please create an issue here on GitHub! luci-theme-material Copyright 2015 Lutty Yang - luci-theme-bootstrap: - Copyright 2008 Steven Barth - Copyright 2008 Jo-Philipp Wich - Copyright 2012 David Menting + luci-theme-bootstrap: + Copyright 2008 Steven Barth + Copyright 2008 Jo-Philipp Wich + Copyright 2012 David Menting - MUI: - https://github.com/muicss/mui + MUI: + https://github.com/muicss/mui - Licensed to the public under the Apache License 2.0 --%> -<% -local ver = require "luci.version" -local uci = require "luci.model.uci".cursor() -local config = uci:get_all("alpha", "theme") + Licensed to the public under the Apache License 2.0 + -%> + <% local ver=require "luci.version" local uci=require "luci.model.uci" .cursor() local + config=uci:get_all("alpha", "theme" ) -- Table to store navbar icons local icon={} -- Iterate + through all navbar entries uci:foreach("alpha", "navbar" , function(section) local + address=section.address local icon_url=section.icon if address and icon_url then -- + Remove '/www/luci-static/alpha/' from icon_url + icon_url=string.gsub(icon_url, "^/www/luci%-static/alpha/" , "" ) icon[address]=icon_url end + end) -- Check navbar enable status local navbar_enabled=config.navbar=="1" -- Calculate number + of enabled navbar links local num_links=0 uci:foreach("alpha", "navbar" , function(section) if + section.enable=="Enable" then num_links=num_links + 1 end end) -- Calculate link width for + responsive design local link_width=string.format("calc(100%% / %d)", num_links) -- Retrieve + theme properties local background_color=config.color or '#2222359a' local + blur_value=tonumber(config.blur) or 20 local link_blur=string.format("blur(%dpx)", blur_value) + %> --- Table to store navbar icons -local icon = {} + --- Calculate number of enabled navbar links -local num_links = 0 -uci:foreach("alpha", "navbar", function(section) - if section.enable == "Enable" then - num_links = num_links + 1 - end -end) + +