Commit Graph

70811 Commits (master)

Author SHA1 Message Date
Daniel Golle 8f071273d7 mac80211: rt2x00: drop MTD EEPROM loading
No device tree uses ralink,mtd-eeprom any more, and since the move from
rt2x00eeprom.c into rt2800lib.c the code is guarded by SOC_RT288X and
SOC_RT305X, so it was compiled out on the only two boards that still
asked for it and dead everywhere else. It also lost its
<linux/mtd/mtd.h> include in that move, which breaks the rt305x build
with implicit declarations of get_mtd_device_nm(), mtd_read() and
put_mtd_device(). Drop the patch; nvmem cells cover every remaining
user.

Fixes: bf44cb5fb0 ("mac80211: update to version 7.2")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
2026-09-15 18:03:36 +01:00
Daniel Golle 11c75d9520 bmips: hg556a-c: load wifi EEPROM from NVMEM
Describe the Ralink EEPROM as a cell of the cal_data partition and point
the card at it, so the board no longer needs ralink,mtd-eeprom.

Commit 72f43ac220 ("bmips: huawei-hg556a-c: use nvmem for wifi
eeprom") tried this before and was reverted in b270580dea because the
card came up without calibration data. That attempt named the cell
"calibration", while rt2800_read_eeprom_nvmem() looks up "eeprom", so
the driver never found it and the byte order it blamed was not involved:
both paths copy the same 512 bytes from the same offset.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
2026-09-15 18:03:36 +01:00
Daniel Golle 0772ee3e09 lantiq: arv7525pw: load wifi EEPROM from NVMEM
The board is the last lantiq device still using ralink,mtd-eeprom, which
commit 926991329b ("lantiq: convert ralink,mtd-eeprom to nvmem") left
behind. Describe the EEPROM as a cell of the board_config partition and
point the Ralink card at it. Both paths copy the same 512 bytes from the
same offset into the driver, so the data the driver sees is unchanged.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
2026-09-15 18:03:36 +01:00
Daniel Golle 1f7eb34c53 odhcpd: make the full variant displace odhcpd-ipv6only
Both variants install the same files, so selecting both breaks image
assembly. Let odhcpd provide odhcpd-ipv6only and mark the latter
DEFAULT_VARIANT: the generated conflict demotes odhcpd-ipv6only when
odhcpd is selected, and under apk the versioned provide enforces a
single instance. Imagebuilder users pass -odhcpd-ipv6only alongside
odhcpd.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
2026-09-15 17:40:48 +01:00
George Moussalem 0d754ca55b qualcommax: ipq807x: Flatten USB controller nodes
Flatten usb controller nodes and update to using latest bindings and
flattened driver approach.

In addition, fix indentation of properties in both nodes.

link: https://lore.kernel.org/r/20260906-ipq-flatten-usb-v3-9-13e4e0f63123@outlook.com

Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/25038
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-09-15 18:35:11 +02:00
George Moussalem c935b04218 qualcommax: ipq807x: move DR mode to board DTS
Both controllers are DRD capable, but DR mode currently set to host mode
in the SoC dtsi. Unset it in the SoC dtsi and set it as host mode in the
hk01 board DTS file.

link: https://lore.kernel.org/r/20260906-ipq-flatten-usb-v3-8-13e4e0f63123@outlook.com

Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/25038
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-09-15 18:35:11 +02:00
George Moussalem 6f038ccc67 qualcommax: ipq60xx: Flatten USB controller nodes
Flatten usb controller nodes and update to using latest bindings and
flattened driver approach.

link: https://lore.kernel.org/r/20260906-ipq-flatten-usb-v3-7-13e4e0f63123@outlook.com

Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/25038
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-09-15 18:35:11 +02:00
George Moussalem d7ad3dce34 qualcommax: ipq60xx: move DR mode to board DTS
DRD capable controllers are currently set to host mode in the SoC dtsi.
Unset it in the SoC dtsi and set it as host mode in the board DTS.

link: https://lore.kernel.org/r/20260906-ipq-flatten-usb-v3-6-13e4e0f63123@outlook.com

Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/25038
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-09-15 18:35:11 +02:00
George Moussalem 807daedab6 qualcommax: ipq50xx: Update to latest patches for USB3 support
Update to latest patches sent for upstream review for USB3 support.

This PHY found in IPQ5332 and IPQ5018 SoCs is actually a multi-purpose
PCIe/USB3 combo PHY. The driver was initially created for PCIe PHY
support only. As such, rename the driver and its symbol and generalize
the driver to reflect that it is a PCIe and USB3 combo PHY driver and
add USB3 support.

The PCIe and USB physical pads are muxed and selection is done via a
control register in TCSR.

Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/25038
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-09-15 18:35:11 +02:00
George Moussalem 619db5a936 qualcommax: ipq50xx: update to latest patch to flatten USB controller node
Update to the latest patch sent upstream to flatten the USB controller
node. Also set the required reference clock (mock_utmi) rate, away from
the patch to add clocks required for USB3 support.

link: https://lore.kernel.org/r/20260906-ipq-flatten-usb-v3-3-13e4e0f63123@outlook.com

Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/25038
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-09-15 18:35:11 +02:00
George Moussalem cf3fe920b9 qualcommax: usb: dwc3: Allow glue layer to pass reference clock rate
Add ability to pass the reference clock rate from the glue layer to the
DWC3 core driver. The core calculates the reference clock period and
frame length adjustment based on the reference clock rate.

In the flattened snsp-dwc3 model, it is currently not possible to pass a
reference clock that differs from the default since:
commit 613a2e655d4d ("usb: dwc3: core: Expose core driver as library")

The new glue layers (incl. Qualcomm's) set the ignore_clocks_and_resets
flag in dwc3_probe_data to true, which disables the core driver's clock
management, thus it also doesn't acquire the reference clock from the
devicetree needed in dwc3_ref_clk_period.

There's an existing DT property 'snps,ref-clock-period-ns', but that's
been deprecated. In addition, basing the rate from the period is often
not accurate enough to derive the frame length adjustment value.

This prevents moving chipsets such as IPQ5018, IPQ6018, IPQ5332, IPQ5424
and IPQ9574 with a reference clock rate that computes values for the
period and frame length adjustment different from the hardware default
from moving to the flattened model.

So, add ability to set the reference clock rate in dwc3_probe_data, then
have the core obtain the clock rate and use that to calculate the
required period and frame length adjustment.

This fixes USB2 mode on the IPQ50xx platform.

link: https://lore.kernel.org/r/20260906-ipq-flatten-usb-v3-1-13e4e0f63123@outlook.com
link: https://lore.kernel.org/r/20260906-ipq-flatten-usb-v3-2-13e4e0f63123@outlook.com

Fixes: 	409bf967e4 ("qualcommax: ipq50xx: add support for USB3")
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/25038
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-09-15 18:35:11 +02:00
Zoltan HERPAI 980becf1da imx: add support for Olimex i.MX8MP-SOM-EVB
This adds support for an i.MX8-based system-on-module + EVB board.

CPU:      NXP i.MX8MP @ 1600MHz (quad-core A53)
Memory:   4Gb
PCI:      1x PCIe M.2 2280 slot
Ethernet: 2x GE with Micrel PHY (no MAC in EEPROM)
USB:      2x 3.0
UART:     separate UARTs for the A53 and the M7 cores
Storage:  microSD slot, eMMC headers
Misc:     2KByte EEPROM (at24), audio via ES8328 (unsupported), 2x CAN, HDMI
Power:    5VDC

 - Patches refreshed as required
 - The cortexa53 subtarget selects Micrel PHY from now on
 - u-boot added for the board

Installation:
  Use the standard installation to an SD-card by writing out the
  squashfs image (openwrt-imx-cortexa53-olimex_imx8mp-som-squashfs-img.gz)
  to it.

Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
2026-09-15 18:32:14 +02:00
Zoltan HERPAI 4a07d09446 imx: image: add BOOT_SCRIPT and UBOOT to DEVICE_VARS
Currently all images are generated with the same "last" BOOT_SCRIPT
setting in the image Makefile, which is the Kontron one. Allow
per-device overriding by these variables to DEVICE_VARS.

Fixes: 07a5e432c8
Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
2026-09-15 18:32:13 +02:00
Gennaro Cimmino b2d4d802ab realtek: l3: do not add a second route for one destination
Every route add that reaches the driver arrives as
FIB_EVENT_ENTRY_REPLACE, the one behind ip route replace included, and
otto_l3_fib_add_v4() always allocates a fresh route object and a fresh
table row. Changing the gateway of an offloaded route therefore leaves
the old row in place, pointing at the old gateway, and the delete that
follows takes out only the row the second add made:

  ip route add 10.30.0.0/24 via 192.168.1.250      one row
  ip route replace 10.30.0.0/24 via 192.168.1.249  two rows, same dst
  ip route del 10.30.0.0/24                        the first row stays

The switch is left with a valid row forwarding that prefix to the old
gateway, and the first route object is leaked with its id, its next hop,
its packet counter and its PIE rule. It is not forgotten, either: it
stays in the hash under the old gateway, so every neighbour update for
that gateway writes the stale row back into hardware.

Keep the routes on a list beside the hash, look the destination up
before allocating, and take the old route out the way the delete path
does, which is now a helper the two share. The lookup carries the table
id as well, because the same prefix in two routing tables is two routes,
and it takes the entry type, so the IPv6 side needs a caller rather than
a second function.

Runs on RTL839x and, with the offload symbol on, RTL930x; RTL838x and
RTL931x return early in the notifier because cfg->setup is NULL, and
RTL839x is compile-tested only.

Functionally tested on a Hasivo S1100W-8XGT-SE (RTL9303), kernel
6.18.44, with CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD=y: the sequence
above now leaves one row after the replace and none after the delete,
and the same holds for ip route append followed by a flush.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25199
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-15 16:36:59 +02:00
Gennaro Cimmino dff4c3c0f7 realtek: l3: name the four route entry types
The two bits the hardware keeps in every route entry select IPv4 or IPv6
and unicast or multicast, and the driver spelled them 0, 1, 2 and 3 in
nine switch statements and three assignments, each with a comment saying
what the number meant.

Give them names next to the route actions they sit beside in the entry,
and drop the comments the names replace.

No functional change.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25199
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-15 16:36:59 +02:00
Gennaro Cimmino 2795383aaf realtek: l3: do not release what a pending route never got
A route whose gateway has not resolved yet carries none of the resources
otto_l3_fib_del_v4() releases: the L2 next hop, the packet counter and
the PIE rule all come from otto_l3_nexthop_update(), which only runs once
the neighbour is valid. Deleting such a route hands the sentinels
straight to the hardware helpers.

The PIE rule is the one that hurts. Its id is -1 until the rule is
added, and rtl930x_pie_rule_rm() passes it on without a test:

  rtl930x_pie_rule_del(priv, -1, -1)  ->  (-1 << 1) | (-1 << 12) | BIT(0)

writes 0xffffffff into RTL930X_PIE_CLR_CTRL and then waits for a clear
that names rule 2047, and clear_bit(-1, priv->pie_use_bm) turns into bit
0xffffffff, half a gigabyte past a 288-byte array. RTL839x has the same
two lines. The next hop id and the packet counter are zero from the
allocation, so the same call reads L2 bucket 0 and releases counter 0,
which another rule may own.

Adding a route through a gateway that never answers and deleting it is
enough, and it is what a routing daemon does when a peer goes away. On a
RTL9303 with the driver's debug output enabled:

  rtl83xx-switch ...: need to wait
  rtl83xx-switch ...: found a route with id 4, nh-id 0
  rtl83xx-switch ...: unknown nexthop, id 0
  rtl83xx-switch ...: releasing packet counter 0
  rtl930x_pie_rule_del: from -1 to -1

Test the id the driver already uses to mean "this route has a rule", and
give the counter the same -1 sentinel the rule id has, which
rtldsa_packet_cntr_free() already refuses.

Runs on RTL839x and, with the offload symbol on, RTL930x; RTL838x and
RTL931x return early in the notifier because cfg->setup is NULL. On
RTL839x the counter matters more than on RTL930x: there the allocator
hands out index 0, so releasing it returns a counter another rule is
still using.

Functionally tested on a Hasivo S1100W-8XGT-SE (RTL9303), kernel
6.18.44, with CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD=y: the same
sequence no longer reaches pie_rule_del or the next hop, the counter
release shows the sentinel, and the removal still reports the route as
not in hardware. RTL839x is compile-tested only.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25199
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-15 16:36:59 +02:00
Markus Stockhausen 63fab3bad4 realtek: dsa: fix RTL839x egress queue configuration
RTL839X_QM_PORT_QNUM contains ten packed 3-bit port fields per
register. Writing the complete register for each port therefore clears
the queue configuration of the other ports sharing that register.

Update rtl839x_set_egress_queue() to modify only the field belonging to
the requested port. Use the corrected helper during QoS initialization
for all user ports and the CPU port.

While we are here make the function static.

Assisted-by: ChatGPT (OpenAI GPT-5.6 Sol)
Link: https://github.com/openwrt/openwrt/pull/25186
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-15 16:09:30 +02:00
Markus Stockhausen 549c879311 realtek: dsa: move RTL93xx QoS code to qos.c
Keep the QoS implementation grouped by functionality instead of SoC
family. Move the RTL930x and RTL931x QoS initialization and helper
functions from the corresponding SoC files to qos.c.

Add qos.h for the public QoS interface and move the existing QoS
declarations out of rtl-otto.h. Mark configuration arrays that are now
local to qos.c as static.

No functional change intended.

Assisted-by: ChatGPT (OpenAI GPT-5.6 Sol)
Link: https://github.com/openwrt/openwrt/pull/25186
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-15 16:09:30 +02:00
Tanner Lane 1ff2a3ef77 realtek: fix MokerLink reset polarity
GPIO27 is high while the reset button is released and low while it is
pressed, so the reset line is active-low.

The original verification missed this because pressing the button caused
the device to reboot with either polarity. The test was performed on a
freshly flashed device, so the unintended factory reset was not apparent.

Declare GPIO27 active-low so short presses reboot without clearing the
configuration and long presses retain the intended factory-reset behavior.

Fixes: 7f03bc02b0 ("realtek: add support for MokerLink 10GT080M")

Signed-off-by: Tanner Lane <tannerln7@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25172
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-15 13:43:19 +02:00
André Valentin ff0a961064 qualcommax: add support for MikroTik Chateau 5G R17 ax
Ordering code S53UG+5HaxD2HaxD&RG650E-EU. First MikroTik device on this
target.

Specifications:
  SoC       Qualcomm IPQ6010, 4x Cortex-A53, 864-1800 MHz
  RAM       1 GB
  Flash     128 MB NAND (QPIC), 512 KB SPI-NOR holding RouterBOOT
  Ethernet  4x 1G, Qualcomm QCA8075 (PSGMII, MDIO 0x18-0x1b)
            1x 2.5G, Qualcomm QCA8081 (2500base-x, MDIO 0x00)
  WLAN      IPQ6010 integrated, 2x2 2.4 GHz + 2x2 5 GHz, ath11k
  Modem     Quectel RG650E-EU 5G, USB 2c7c:0122, internal bus
  USB       1x 3.0 type A, external
  LEDs      system RGB, eth, wlan, 5x LTE signal strength
  Buttons   reset, mode, WPS
  Power     12-28 VDC barrel jack, 27 W max

Serial console: header silkscreened SPI/UART, reachable only with the case
open. Viewed from the back the square pad is pin 10, bottom right:

  pin 3  RX, router input     pin 5  GND     pin 8  TX, router output

115200 8N1, 3.3 V TTL, no flow control. Do not connect VCC.

Flash layout:
  NAND mtd0  0x0000000-0x0800000    8 MB  "kernel", yaffs
       mtd1  0x0800000-0x8000000  120 MB  "ubi"
  SPI-NOR, RouterBoot partition at 0x2c0000, 512 KB, 64 KB erase blocks:
       +0x00000 bootloader, +0x20000 hard_config, +0x30000 second stage,
       +0x40000 soft_config, +0x70000 device tree

Installation: boot the initramfs image over RouterBOOT etherboot (reset
button, or boot_device=ethonce plus commit through the rb_softconfig sysfs
interface), then sysupgrade. sysupgrade writes the kernel with yafut,
since yaffs keeps metadata and ECC in the OOB area where mtd cannot reach.
It erases the partition first: from the factory 4.38 of the 8 MB are in
use, and yaffs frees the old blocks only after writing. RouterBOOT is
never written, so etherboot and Netinstall stay available.

Device tree notes:
  - soc_version_major is normally injected by the QSDK U-Boot; without it
    the CPR driver hits a BUG_ON.
  - Socket labels run opposite to the PSGMII lane order, verified socket
    by socket.
  - MAC addresses come from hard_config, one per port as the factory
    allocates them (mac_count 7: 5 ethernet, 2 radios). Without them the
    ports inherit the EDMA conduit address, which qca_edma.c only randomises
    as a fallback when no port describes one.
  - The PSGMII SerDes runs at 300 mV as Qualcomm's SSDK does, not the
    600 mV qca807x.c defaults to.
  - The watchdog is left disabled: a WDT bite is an abrupt hardware warm
    reset that skips the WCSS teardown and hangs the board in SBL1 (the
    IPQ6018 warm-reboot path). procd feeds it fine in normal operation, but
    a bite comes back stuck rather than recovering the soft hang.
  - PCIe appeared to stop the Ethernet transmit path and stays off; the
    mPCIe slot is unused since the modem is on USB. That bisect rests on
    a single boot per variant and does not carry, given that the PSGMII
    calibration fails intermittently with a similar symptom.

Board data comes out of RouterBOOT rather than out of ipq-wifi. This
unit's own board data file sits in hard_config tag 0x16 as 5100 bytes of
LZ77; rb_hardconfig decompresses it and exports a 64 KiB blob that is a
complete BDF - same 01 00 04 04 magic as the ipq-wifi files, a valid
header checksum, this unit's factory MAC addresses instead of the Qualcomm
defaults, and the chainmasks of the two 2x2 radios. RouterOS uses exactly
that: localphy-qcom reads it through getHcfgBdwlan() ("Bdwlan: bdwlan
found in hrdcfg") and only falls back to a generic <board>.bdwlan when
hard_config carries none.

The ath11k firmware hotplug script (11-ath11k-caldata) hands the blob to
the driver. ath11k first looks for a board-2.bin container and, once no
entry matches, falls back to ath11k_core_fetch_board_data_api_1() with
ATH11K_DEFAULT_BOARD_FILE; it also asks for cal-ahb-c000000.wifi.bin. The
same 64 KiB blob answers every one of those requests through
caldata_sysfsload_from_file, fed straight into the sysfs firmware
interface without being written to /lib/firmware. board.bin is what we
serve because it takes a bare BDF - no container to build and no length
arithmetic to keep in sync with the calibration variant. The blob is
passed through unchanged: the firmware validates it beyond the header
checksum and aborts with "phyrf_bdf.c:472 Assertion 0 failed" on any
modification.

uqmi does not fully drive the RG650E-EU: it only obtains a client ID for
UIM, while DMS, NAS and WDS answer "Failed to connect to service". A
libqmi based connection manager is needed for a data session.

Signed-off-by: André Valentin <avalentin@marcant.net>
Link: https://github.com/openwrt/openwrt/pull/24335
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-09-15 13:21:07 +02:00
André Valentin 6b85badadc qualcommax: add mikrotik-lzma-loader for RouterBOOT devices
RouterBOOT loads bare unsigned ARM64 ELF images only, neither FIT nor
uImage, and the yaffs kernel partition on these MikroTik devices is 8 MiB
while the raw arm64 image is around 14 MiB. This self-extracting loader
wraps the LZMA compressed kernel and the DTB in a single PT_LOAD segment,
decompresses them at runtime and jumps to the kernel. The entry sequence
follows MikroTik's own loader as found in the flash dump, noted in
start.S. It installs an identity mapping before decompressing so it does
not run entirely uncached, and keeps its stack below the load address
because RouterBOOT loads only filesz bytes and the memory beyond that is
not usable that early.

src/LzmaDecode.[ch] are the LZMA SDK 4.21 decoder by Igor Pavlov, taken
unmodified under their own license (LGPL or CPL at your choice, plus the
linking exception); everything else is written for this loader. Hence
PKG_LICENSE lists both licenses and PKG_LICENSE_FILES points at
src/LzmaDecode.c.

Signed-off-by: André Valentin <avalentin@marcant.net>
Link: https://github.com/openwrt/openwrt/pull/24335
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-09-15 13:21:07 +02:00
André Valentin ada1dcb2b4 generic: mikrotik: size RouterBoot partitions so they are usable
Two fixes to the RouterBoot partition handling, both found on a MikroTik
Chateau 5G R17 ax but neither device specific.

hard_config is not guaranteed to fit within RB_BLOCK_SIZE. On this board
the tag list spans 5576 bytes, because the WLAN calibration tag alone
carries 5100 bytes of LZ77 compressed data, so truncating the partition
makes that tag unreadable. Walk the tag list to its terminating null node
and size the partition accordingly. The result never shrinks below
RB_BLOCK_SIZE, so devices whose tag list already fits are unaffected.

soft_config carries the boot settings and is the one RouterBoot segment
meant to be written, but at RB_BLOCK_SIZE (4 KiB) on a flash with 64 KiB
erase blocks MTD always forces it read-only. Grow it to a full erase
block where the space is free, checked against the following partition so
that erasing it cannot destroy a neighbour.

That growth alone would break the checksum, because rb_softconfig derives
everything from the partition size while RouterBoot validates the CRC32
over its own 4 KiB. Introduce RB_SC_CFG_SIZE and keep reads, CRC and write
back within it; the erase still covers the whole partition.

With both in place, writing boot_device followed by commit persists across
a reboot and "ethonce" triggers a real etherboot.

Signed-off-by: André Valentin <avalentin@marcant.net>
Link: https://github.com/openwrt/openwrt/pull/24335
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-09-15 13:21:07 +02:00
Gennaro Cimmino 3a2230382f realtek: l3: do not read a route back before programming it
otto_l3_nexthop_update() starts each route with route_read(ctrl, r->id,
r), which fills the route object from the table row at that index. For a
host route the index is wrong to begin with: host ids start at
MAX_ROUTES and the prefix route table has 512 rows, so
otto_table_index_ok() refuses the access and warns.

For a prefix route the index is right and the read is worse. The object
is the one the FIB just described, so a row left behind by an earlier
route replaces its destination and prefix length, and the row is then
written back from the object. On a RTL9303 with row 3 still holding a
deleted 10.1.2.0/24, adding 10.0.0.0/8 through the same gateway took id
3, read the stale row and programmed itself as the deleted route:

  ... add IPv4 route 10.0.0.0/8 via 192.168.1.x
  ... id: 3, ip 192.168.1.x
  ... index 3 is valid: 1
  ... GW: 10.1.2.0, prefix_len: 24

Drop the read. The destination and the prefix length come from the FIB,
the next hop id from the route id, and valid, action, type and hit are
assigned right after it. Two sets of fields were being carried over from
the row and now come from the route object, which is zeroed when it is
allocated: switch_mac_id on RTL839x, and the TTL and QoS bits on
RTL930x. Nothing in the driver ever sets them, so they were already zero
in any row this driver wrote; they differ only for a row programmed by
something else, and carrying a stale row's values is part of what this
fixes.

Runs on RTL839x and, with the offload symbol on, RTL930x. The RTL930x
side was exercised on a Hasivo S1100W-8XGT-SE, kernel 6.18.44: two
routes added through one gateway each keep their own destination.
RTL839x is compile-tested only.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25194
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-15 11:40:10 +02:00
Gennaro Cimmino 3fafb65de7 realtek: l3: rtl930x: remove a prefix route from its own row
otto_l3_nexthop_update() writes a prefix route at its own id, but
removal asked otto_l3_930x_route_lookup_hw() where it was. That search
keys on the masked destination rather than on the route, so any stored
network that covers the address answers, and the answer went straight
into route_write() with the valid bit down.

On a RTL9303 with 10.0.0.0/8 at row 2 and 10.1.2.0/24 at row 3, both
through one gateway, deleting the /24 cleared the /8:

  ... searching for 10.1.2.0
  ... found: 1, index: 2
  ... Got id for prefix route: 2

The table was left holding the route that had just been deleted, while
the one still in the FIB was gone. The hardware answers with the lowest
matching row, which is also why the /24 could not be found afterwards.

Look at the row the route was written at, and fall back to the search
only when the route is not there - checking what it returns, the way the
SDK does around the same lookup: _dal_longan_l3_routeEntry_find()
re-reads the index, compares it with the route, and scans linearly when
it does not match.

RTL930x only: route_lookup_hw is set in otto_l3_930x_cfg alone and the
branch it guards does not run on the other families.

Functionally tested on a Hasivo S1100W-8XGT-SE (RTL9303), kernel
6.18.44, with CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD=y: deleting the
/24 now takes row 3, its own, and leaves 10.0.0.0/8 in place.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25194
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-15 11:40:10 +02:00
Gennaro Cimmino 2d21547582 realtek: l3: do not treat a missing port as port 0
otto_l3_port_dev_lower_find() walks the lower devices of the interface a
route or a neighbour points at and reports the first port of this switch
it finds, or the error rtl83xx_port_is_under() returned for the last
lower it looked at. The walk does not run when the interface has no
lower devices at all, and the result started at 0, which is a port
number, so a route over a tunnel or a PPP interface passed the test that
is there to keep it out.

Start from the same error the walk reports for a device that is not a
port of this switch. Both callers use the result only as that gate:
otto_l3_fib_add_v4() refuses the route and names the interface, and the
netevent notifier ignores the neighbour.

A DSA user port is not affected: its conduit is one of its lower
devices, so the walk already answered for it. No-op on RTL838x and
RTL931x, whose notifiers return early because cfg->setup is NULL.
Compile-tested only.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25194
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-15 11:40:10 +02:00
Gennaro Cimmino b9bbb562b7 realtek: l3: do not delete a route the FIB did not ask for
otto_l3_fib_del_v4() looks the gateway up in the routes table, which
holds every route behind that gateway, and walks the list for the one
whose destination and prefix length match. The walk has no failure
branch, and rhl_for_each_entry_rcu() leaves its cursor on the last
element it visited rather than clearing it, so a route that is not in
the list deletes whichever route came last: its next hop is removed, its
packet counter released, its PIE rule deleted, its hardware entry
invalidated and the object freed, while the FIB still has it.

Deleting a route the driver never saw added is enough to get there.
register_fib_notifier() is called without a dump callback, so a route
that predates the probe is missing from the table but still produces a
delete event; an add refused for a missing switch port, or for a full
table, leaves the same hole.

Say which route was not found and leave the table alone.

Runs on RTL839x and, with the offload symbol on, RTL930x; RTL838x and
RTL931x return early in the notifier because cfg->setup is NULL.
Compile-tested only.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25194
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-15 11:40:10 +02:00
Gennaro Cimmino 2337fa244e realtek: l3: refuse a route id the table cannot hold
find_first_zero_bit() returns the size it was given when every bit is
set, and neither route allocator tests for that. On a full table the id
becomes MAX_ROUTES or MAX_HOST_ROUTES and set_bit() writes one word past
the bitmap: the two bitmaps sit next to each other in struct
otto_l3_ctrl, followed by the interface array, so overflowing the prefix
one marks host route slot 0 as used and overflowing the host one sets a
bit in the first interface pointer.

A prefix route id is also the row the route is written at, so it goes on
to ask for row 512 of a 512-row table; otto_table_index_ok() refuses the
access and warns once per boot, while otto_l3_fib_add_v4() reports
success and marks the route offloaded.

Say the table is full and return NULL, which the caller already handles:
it turns a failed allocation into -ENOSPC.

No-op on RTL838x and RTL931x, whose notifiers return early because
cfg->setup is NULL. Compile-tested only: reaching either branch takes
512 prefix or 1536 host routes offloaded at once, which the bench cannot
produce.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25194
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-15 11:40:10 +02:00
Jonas Köppeler 7f4f824691 generic: backport sch_cake fix for tin clearing on rate adjust
Backport upstream commit a3729e0df005 ("net/sched: sch_cake: skip
clearing unused tins during rate adjustment"), which landed in v7.2.

cake_configure_rates() is called from the dequeue path with
rate_adjust=true, where cake_clear_tin() overwrites q->cur_tin and
q->cur_flow while cake_dequeue() is using them, and purging the unused
tins adds overhead to the hot path. Skipping the loop restores loaded
latency to pre-15c2715a5264 levels; on IPQ8074A in besteffort mode the
loaded latency drops from ~470 ms to ~4 ms in Flent's tcp_nup test.

Refresh the sync_time debugfs hack patch, whose hunks shift by two
lines.

Signed-off-by: Jonas Köppeler <j.koeppeler@tu-berlin.de>
Link: https://github.com/openwrt/openwrt/pull/25182
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-09-15 10:07:52 +02:00
Gennaro Cimmino 036f629142 realtek: l3: rtl930x: write only host routes into the host table
otto_l3_fib_add_v4() programs a host route entry for every route without
a gateway, whatever its prefix length. A connected subnet is not a host
route: the entry it gets describes the network address, which nothing
sends to, and it goes into the table the removal path searches only for
routes allocated as host routes - so it stays behind when the interface
goes down, and the previous patch is what keeps it from accumulating.

Write the entry only for the routes the host table is for. The route
object already knows: otto_l3_host_route_alloc() is used exactly when
the prefix length is 32 and the family has a host route table, and it is
the only place that sets is_host_route.

RTL930x only: the block sits inside the set_router_mac test, and that
op, like host_route_write and find_slot, is set in otto_l3_930x_cfg
alone, under a symbol no target config sets. RTL839x, the one other
family that reaches this function, does not enter the block at all.

Measured on a Hasivo S1100W-8XGT-SE (RTL9303), kernel 6.18.44, with
CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD=y: the /24 of the lan bridge
takes no host table row at all, and twelve ifdown/ifup cycles of that
interface leave the table holding only the /32 of the interface address.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25187
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-15 10:06:47 +02:00
Gennaro Cimmino d6a38f407b realtek: l3: rtl930x: reuse the slot of a connected route
otto_l3_fib_add_v4() writes every route without a gateway into the host
route table, whatever its prefix length, while otto_l3_route_remove()
clears a host entry only for a route allocated as a host route, which
means a prefix length of 32. A connected subnet therefore leaves its
entry behind when the interface goes down. That part is older than the
recent fixes; what the search fix below changed is that placement now
returns free slots rather than the head of the bucket, so the next ifup
takes a fresh one instead of overwriting the stale entry. A destination
has six slots in each of the two hash tables, and once those twelve are
taken the subnet is not offloaded at all:

  rtl83xx-switch ...: no slot for host route 192.168.1.0

Ask for the entry the route already holds before asking for a free one,
the way otto_l3_nexthop_update() does, so one destination keeps one
entry. A miss costs up to twelve table reads on the add path. Two routes
that share a destination address share the entry again, the last writer
winning: a /31 link and the local /32 the kernel installs beside it are
the case to know about.

The entry is still not cleared when the route goes away, so renumbering
leaves one behind per destination: nothing in the route object records
that a prefix route was written into the host table, and the removal
path does not know to look for it. That needs a change of its own.

Measured on a Hasivo S1100W-8XGT-SE (RTL9303), kernel 6.18.44, with
CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD=y: entries reported by the
debugfs dump for the /24 of the lan bridge, counted after each of twelve
ifdown/ifup cycles of that interface.

  883ebad9ba, before the series   1, unchanged
  current main                    2, 3, 4 ... 12, then "no slot"
  with this patch                 1, unchanged

RTL930x only: find_slot() and host_route_write() are set in
otto_l3_930x_cfg alone, and only under a symbol that no target config
sets, so a stock build does not reach this path at all.

Fixes: 4344b47ebc ("realtek: l3: rtl930x: test the slot that was read")
Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25187
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-15 10:06:47 +02:00
Zoltan HERPAI 11c64908c1 uboot-mxs: bump to 2026.04
Compile-tested: all mxs boards
Runtime-tested: Olinuxino Micro, I2SE Duckbill

While at it, rework the Duckbill series to compile on 2026.04.

Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
2026-09-14 22:11:20 +02:00
Gennaro Cimmino d92ff769b5 realtek: l3: rtl930x: reuse the slot a host route holds
otto_l3_nexthop_update() walks every route that shares the gateway, and
the routes table is keyed on the gateway address, so adding one route
reprocesses all the others behind it. Each of them asked find_slot() for
somewhere to put a route and, now that the search reports free slots
rather than the first address of the bucket, got a fresh one every time.

On a RTL9303, three /32 routes through one gateway left seventeen host
entries behind: the same destination written again on each event until
the bucket filled, then carried into the second hash table. Before the
search was fixed the duplicate was invisible, because every write landed
on the same address and overwrote the previous one.

Ask for the route's own entry first and fall back to a free slot only
when it is not there yet. A bucket that is genuinely full now returns -1
where it could not before, so both placement sites say so instead of
writing at a negative index.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25170
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-14 21:45:55 +02:00
Gennaro Cimmino 4344b47ebc realtek: l3: rtl930x: test the slot that was read
otto_l3_930x_find_slot() probed the host route table and then looked
at the caller's route instead of the entry it had just read. The
placement test asked rt->attr.valid, which both call sites set to true
right before calling, so the first address probed was always returned:
of the 6144 host route slots only the 512 bucket heads of the first
table were reachable, and a second route in a bucket overwrote the
first. The lookup test compared route_entry.dst_ip, which
otto_l3_930x_host_route_read() does not touch when the entry is
invalid or is not IPv4 unicast, so it could match an address the
reader never wrote.

Ask the entry that was read: an empty slot for placement, and for a
lookup a valid entry of the same type whose destination matches. IPv6
unicast destinations are compared with ipv6_addr_equal() instead of
through the IPv4 field.

Measured on an RTL9303 (Hasivo S1100W-8XGT-SE): two /32 host routes
hashing to bucket 281 both ended up at logical index 1686 before this
patch. With it each route takes a slot of its own, which is also what
exposed the duplicate writes the next patch removes.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25170
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-14 21:45:55 +02:00
Gennaro Cimmino 522cb4b864 realtek: l3: rtl930x: look up the route being removed
Placing a route and deleting one are different questions. The prefix
branch of otto_l3_route_remove() already asks the right one: it looks
the route up in hardware through route_lookup_hw(), which keys on the
address and returns -1 when the search misses. The host branch beside it
asked find_slot() for somewhere to place a route, and got the head of
the bucket, which belongs to whichever route wrote there last, so
removal could clear an entry belonging to another route.

Ask for the route instead, and name it when the search misses, so the
log says which route was not cleared.

The keyed search is still the old one at this point: it compares an
address that otto_l3_930x_host_route_read() leaves untouched for an
entry that is invalid or is not IPv4 unicast, so it can answer with a
slot that holds something else. The next patch fixes that.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25170
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-14 21:45:54 +02:00
Gennaro Cimmino b52cb4b16b realtek: l3: do not write a route at a negative index
otto_l3_route_remove() asks the hardware where a route lives and then
writes the entry back with the valid bit down. Both lookups can fail.
otto_l3_930x_route_lookup_hw() returns -1 when the search misses, and
otto_l3_930x_find_slot() returns -1 for a route whose own valid flag is
still down, which is what a route that never made it into the table
looks like. The comment above the prefix branch says "If there is a HW
representation of the route, delete it", but the test is on the presence
of the ops pointer rather than on the result of the lookup, so the -1
goes straight into route_write().

Removing a route that never reached the hardware is enough to hit it: a
route whose gateway is not in ARP stays pending, so nothing was written
and the lookup misses when it is deleted.

  rtl83xx-switch ...: need to wait
  rtl83xx-switch ...: found a route with id 513, nh-id 0
  WARNING: CPU: 0 PID: 12 at drivers/soc/realtek/otto_table.c:322
           otto_table_index_ok+0x7c/0x8c
  otto_table: index -1 in table 1049, which has 8192 rows
  Workqueue: rtl83xx otto_l3_fib_event_work_do

otto_table_index_ok() refuses the access, so the write silently does not
happen on every occurrence, while the warning is a WARN_ONCE shared by
every table access in the driver and prints only the first time that
check fails after boot.

Test the result before using it. The two misses log at error level, and
the prints that name the id move into the branch that has one.

Both branches are reachable on RTL930x only: route_lookup_hw(),
find_slot() and host_route_write() are set in otto_l3_930x_cfg alone,
and only under CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD, which no
target config sets. On RTL838x, RTL839x and RTL931x those ops are NULL
and the removal path is unchanged.

Functionally tested on a Hasivo S1100W-8XGT-SE (RTL9303), kernel
6.18.44, with the offload symbol set, adding a route via a gateway that
never resolves and deleting it. On pristine main a /32 warns on the host
route table (1049, 8192 rows) and a /24 on the prefix route table (1053,
512 rows); with this patch neither warns, the lookups still return -1
and the miss is reported instead of reaching the table write.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25170
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-14 21:45:54 +02:00
Max Grass 883ebad9ba qualcommax: qca_ppe: trap slow-protocol frames to the CPU
ppe_ctrlpkt_init() redirects only the STP address 01:80:c2:00:00:00
(RFDB entry 31, APP_CTRL[0]) to the CPU port. The slow-protocols
address 01:80:c2:00:00:02 has no entry, so LACPDUs sent by a switch
never reach a Linux bond on the LAN ports: the bond keeps
"Partner Mac Address: 00:00:00:00:00:00" and every 802.3ad group stays
unformed, while the switch side reports the board's own LACPDUs.

Add RFDB entry 30 for 01:80:c2:00:00:02 and let APP_CTRL[0] match
entries 30 and 31 (bits 32 and 33 of the RFDB index bitmap; the
field layout follows the SSDK hppe_ctrlpkt_reg.h / hppe_fdb_reg.h).

Tested on a Xiaomi AX3600 against a switch running LACP: lan1+lan2 in
an 802.3ad bond converge (both slaves in one aggregator, partner MAC
set, port state 0x3f on both ends) and carry ~1.3 Gbit/s per direction
over the two 1 GbE links with 8 parallel flows. Before the change the
same setup never negotiated.

Signed-off-by: Max Grass <gh-owrt-1@maxgrass.eu>
Link: https://github.com/openwrt/openwrt/pull/25184
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-09-14 20:42:45 +02:00
Gennaro Cimmino ad7179f9b9 realtek: l3: rtl930x: dump the L3 route tables in debugfs
Debugging the L3 offload means knowing what the silicon actually holds,
and nothing in the driver exposes it. The route model lives in the
hardware tables, and the HIT bit that says whether an entry was ever
used exists only there: it has no clear-on-read and no clear register,
so the driver's own view cannot answer either question.

Add realtek_otto_l3/routes, a read-only sweep of both RTL9300 route
tables, named after the realtek_otto_serdes tree in
mdio-realtek-otto-serdes.c. It walks the raw address space rather than
the driver's own list, because with the offload symbol off the driver's
table is empty while the silicon may not be, and it decodes each entry
against the field positions used by otto_l3_930x_host_route_write() and
otto_l3_930x_route_write() in this file. Both sweeps take their bound
from otto_table_rows(), so the row count of a table stays in the table
driver alone. The host table holds six entries in every eight
addresses, so the two unused slots of each bucket are skipped.

Add realtek_otto_l3/clear_route_hits next to it. Writing to it clears
the HIT bit of every unicast entry by rewriting the entry, which is what
the vendor SDK does on RTK_L3_FLAG_HIT_CLEAR; it is a separate
write-only file so that reading the table stays free of side effects,
and one write runs one sweep. Like the dump, it walks the table by the
width of each entry, because the trailing slots of a wider one hold
address bits that would read as a valid entry and be written back over
the real one. Multicast entries are left alone and their number is
reported, rather than being silently skipped, and a table that cannot
be taken is reported to the writer instead of looking like success.

The files are created from a .dbgfs_init hook in struct otto_l3_config,
so the dump follows the compatible match table like every other
family-specific operation and no family test is needed. Only the RTL9300
configuration sets the hook, and only when
CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD is on, which no target config
does. With the symbol off nothing references the dump and the compiler
drops it: l3.o then carries 40 bytes more than main, the extra
pointer in each of the four configuration tables and the NULL test in
the probe, and none of the dump itself.

Functionally tested on a Hasivo S1100W-8XGT-SE (RTL9303, RTL8264B PHYs),
kernel 6.18.44, with the symbol set. Two SVIs on separate VLANs: the
dump lists their host route entries, and a static route via a resolved
gateway appears in the prefix table as 10.99.0.0/24 with a nexthop id
and disappears when the route is deleted. Clearing and re-reading in one
command shows HIT back to 0, and it returns to 1 on the next packet, so
the file reports the live state of the hardware rather than a cached
copy.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25167
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-14 17:41:34 +02:00
Gennaro Cimmino 4a75459230 realtek: table: report the row count of a table
The number of rows of every table is already in otto_table_maps[],
where it bounds the index of an access. A consumer that has to sweep a
whole table cannot ask for it and has to keep its own copy of the
number, which is then free to drift from the one the accesses are
checked against.

Add otto_table_rows(), returning the row count of a table or a negative
errno for an id that does not name one. Nothing calls it yet, so this
changes no behaviour.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25167
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-14 17:41:34 +02:00
Zhenpeng Zhou 0d7bfcb7e3 airoha: add support for Quantum Fiber Q1000K
Add the Q1000K optical network terminal using the UBI layout prepared
by its U-Boot chainloader and installer.

Hardware:
- Airoha AN7581SIT with four Cortex-A53 cores
- 512 MiB RAM and 512 MiB SPI-NAND
- One 1 GbE port on internal switch port 1 / PHY 9
- One 10 GbE port using RTL8261N at MDIO address 8
- Reset button and GPIO status/Ethernet LEDs; no Wi-Fi
- Power input: 12 V DC, 1.5 A
- UART: internal five-pin header, accessible by opening the case;
  115200 baud, 8N1, 1.8 V logic. With Ethernet ports pointing away,
  left to right: TX - GND - VCC - N/A - RX

Configure both copper ports as LAN members. Keep GDM2 and the PON PCS
explicitly disabled until the optical data path and provisioning are
supported. The chainloader reads the factory DSD and supplies Ethernet
MAC addresses through the device tree; both LAN ports use lan_mac.

Drive the 1 GbE jack LEDs from lan1. Invert both RTL8261N SerDes
TX and RX polarity to match the OEM PHY initialization.

MAC address layout on the inspected unit (unit-specific bytes masked):
- lan1 (1 GbE): 00:58:28:xx:xx:xx, DSD lan_mac via GDM1/DSA
- lan2 (10 GbE): 00:58:28:xx:xx:xx, DSD lan_mac via GDM4
- PON (disabled): 00:58:28:xx:xx:xx, DSD wan_mac via GDM2

The chainloader reads lan_mac/wan_mac from the first 16 KiB of factory
DSD at NAND offset 0x00400000 and sets mac-address/local-mac-address in
the Linux DT. Both LAN ports share lan_mac without a per-port increment.
OpenWrt does not read the MACs from the copied factory UBI volume.

Generate an initramfs recovery FIT and a sysupgrade FIT containing the
kernel, device tree and SquashFS. Use fit_check_image()/fit_do_upgrade()
for upgrades, and limit uploads to the chainloader's 256 MiB buffer.
Reserve the vendor bootloader/DSD, chainloader, ART and BMT regions;
place writable UBI between 0x00700000 and 0x1bd00000. UBI manages bad
blocks for OpenWrt without enabling the vendor BMT mapping layer.

Install with the Q1000K chainloader and installer at:
https://github.com/lightingghost/http-uboot-q1000k/commit/4b34476f2e76

Build and installation guide: doc/board/airoha/q1000k.rst

1. Build q1000k-chainload-uboot.itb with an AArch64 cross compiler:

     CROSS_COMPILE=aarch64-linux-gnu- JOBS=8 \
       ./scripts/build-chainloader-fit.sh

2. Open the case and connect a 1.8 V serial adapter to the UART header
   described above: adapter RX to board TX, adapter TX to board RX,
   and GND to GND. Leave VCC and N/A unconnected. Power the unit from
   its own supply, use 115200 8N1, and interrupt vendor autoboot.
   Connect a PC to the 1 GbE port, set 192.168.255.3/24, and serve the
   chainloader FIT over TFTP. At the vendor console, run:

     setenv serverip 192.168.255.3
     setenv ipaddr 192.168.255.1
     tftpboot 0x89000000 q1000k-chainload-uboot.itb

     iminfo 0x89000000
     bootm 0x89000000

3. Connect a PC to the 1 GbE port, set its address to 192.168.255.2/24,
   and open http://192.168.255.1. Select NAND Backup, then Download NAND
   Backup. Save the 512 MiB data-area backup before installation; it
   does not contain per-page OOB bytes.

4. Open Update U-Boot. Set U-Boot operation to "Install U-Boot and
   prepare UBI", select the same chainloader FIT, and click
   "Install U-Boot and Prepare UBI". Confirm the erase notice and wait
   for verification and reboot. The default "Update U-Boot only
   (keep UBI)" operation does not perform initial installation.

   Installation erases existing UBI firmware and settings. It writes
   the chainloader, prepares UBI, copies factory records and selects
   the new vendor boot command. The vendor first-stage bootloader,
   original DSD, ART and BMT/BBT regions are preserved.

5. Return to the HTTP interface after reboot. Optionally upload the
   quantum_q1000k-ubi initramfs-recovery.itb through Recovery Image first.
   If Linux recovery boots, hold Reset during the next chainloader
   startup to re-enter HTTP, or interrupt autoboot and run
   http_recovery at the chainloader prompt.

6. Upload the quantum_q1000k-ubi squashfs-sysupgrade.itb through Firmware
   Recovery. Both images must use the Q1000K UBI layout. Each HTTP
   upload recreates rootfs_data, so upload recovery before firmware.

7. Once OpenWrt boots, return the PC to DHCP. OpenWrt defaults to
   192.168.1.1; use SSH, or LuCI if included in the firmware build.
   Use normal OpenWrt sysupgrade for configuration-preserving updates.

Hold Reset during chainloader startup to force HTTP recovery later.
If installation fails, inspect its serial diagnostics and RAM-boot the
corrected chainloader before retrying. Uploading a new FIT to an old
running HTTP session still uses that session's installer code.

Compile-checked the DTS and verified image profile naming/compatibility,
shell syntax and patch style.

Observed on hardware: installed FIT boot, writable UBIFS overlay and
1 Gb/s full-duplex link/bridge forwarding on lan1. Traffic through the
10 GbE port, GPIO Ethernet LEDs and factory MAC handoff still require
hardware verification. PON service is not implemented by this port.

Prepared with assistance from Codex (OpenAI).

Signed-off-by: Zhenpeng Zhou <zhenp3ngzhou@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25146
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-09-14 13:11:49 +02:00
Daniel Golle 796b5590ce toolchain: gcc: fix SHF_MERGE check with binutils 2.46
gcc probes the assembler for section merging support with
'.section .rodata.str, "aMS", @progbits, 1', which on 32-bit arm the
'@' comment character truncates. gas 2.46 no longer accepts that form,
and since gcc's %progbits fallback probe reuses the same autoconf cache
variable it never runs, so HAVE_GAS_SHF_MERGE ends up 0. String
literals then land in one plain .rodata per translation unit instead of
per-function mergeable sections, --gc-sections can no longer drop the
strings of dead functions, and the am335x SPL grows by 9.5 kB past its
110592 byte budget.

Backport the upstream fix, which gives the fallback probe its own cache
variable. It is in GCC 15 and later.

Fixes: 82f26df15c ("toolchain: binutils: change default to 2.46")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
2026-09-14 12:09:01 +01:00
Markus Stockhausen 44f7d3da70 realtek: dsa: align header naming
Use a common define naming convention for header detection.

Link: https://github.com/openwrt/openwrt/pull/25160
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-14 12:38:00 +02:00
Markus Stockhausen b994fa9910 realtek: dsa: move PIE handling to separate module
The SoC-specific driver files still contain the complete Packet Inspection
Engine implementations. This makes the files difficult to navigate and
mixes PIE handling with unrelated hardware functionality.

Move the common PIE interface and the SoC-specific implementations into
new pie.c and pie.h files. Keep the existing per-SoC operations and their
assignment in the switch configuration unchanged.

Packet counters remain in the SoC-specific files because they are also
used by the L3 offload implementation.

This is a code reorganization and does not change functionality.

Assisted-by: ChatGPT (OpenAI GPT-5.6 Sol)
Link: https://github.com/openwrt/openwrt/pull/25160
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-14 12:38:00 +02:00
Markus Stockhausen 439cafde19 realtek: dsa: prefix PIE template identifiers by SoC
The PIE template identifiers currently rely on being declared in separate
SoC-specific translation units. Their generic names would collide when the
PIE implementations are moved into a shared source file.

Prefix the template field enums, constants, template counts and fixed
template arrays with their respective SoC family names.

This is a preparatory rename and does not change functionality.

Assisted-by: ChatGPT (OpenAI GPT-5.6 Sol)
Link: https://github.com/openwrt/openwrt/pull/25160
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-09-14 12:38:00 +02:00
Daniel Golle 10f6f2a4a2 kernel: restrict media tuner modules to kernel 6.18
The media tuner packages set CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y but hang
off kmod-i2c-core rather than kmod-dvb-core, so commit ccbdf20984
("kernel: restrict DVB and rc-core modules to kernel 6.18") left them
selectable on kernel 6.12. They open the digital TV menus on their own,
target/linux/generic/config-6.12 has no answer for the symbols that
become visible and syncconfig stops waiting for input. Restrict them
the same way until config-6.12 answers those symbols.

Fixes: 1560c75fa2 ("kernel: add initial DVB support")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
2026-09-14 08:55:29 +01:00
Daniel Golle 5ad29919a7 uboot-zynq: disable mkeficapsule host tool
Since the bump to 2026.04, tools/Kconfig defaults TOOLS_MKEFICAPSULE to
y whenever EFI_LOADER is set, which the Zynq configs enable. The host
tool includes <gnutls/gnutls.h>, which the build system does not
provide, so the package fails to compile. Disable the tool, as the
other U-Boot packages carrying an EFI_LOADER config already do.

Fixes: d51c611e71 ("uboot-zynq: bump to 2026.04")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
2026-09-14 08:55:29 +01:00
Jonas Jelonek b4674004ef
realtek: pcs: add USXGMII register field definitions
Name the RTL93xx USXGMII register offsets and fields used by setup and
autonegotiation, then replace raw register numbers and bit positions
with the corresponding definitions.

Link: https://github.com/openwrt/openwrt/pull/25155
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
2026-09-14 09:17:48 +02:00
Jonas Jelonek ea6e5aeb46
realtek: pcs: rtl838x: add and use field defines
Name the RTL838x SerDes enable and CML-select fields, then use masked
writes instead of raw bit positions in the power and clock-reference
setup paths.

Link: https://github.com/openwrt/openwrt/pull/25155
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
2026-09-14 09:17:47 +02:00
Jonas Jelonek a6b6d5f085
realtek: pcs: organize register field definitions
Group paged SerDes definitions by page and register, and indent
register fields and values to expose their hierarchy. Rename existing
fields and use named register offsets in place of raw values.

Link: https://github.com/openwrt/openwrt/pull/25155
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
2026-09-14 09:17:47 +02:00
Jonas Jelonek fea90f63f4
realtek: pcs: use standard BMCR definitions
Replace hard-coded BMCR bit positions and values with the standard
definitions and mask-based register updates. This makes the affected
autonegotiation, power, and speed configuration paths easier to read.

Link: https://github.com/openwrt/openwrt/pull/25155
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
2026-09-14 09:17:47 +02:00
Aleksei Sviridkin cc96ed1e6d
mediatek: filogic: fix Keenetic phy1 MAC collision
The fixup set the 5 GHz phy address to the base MAC with only the
locally administered bit set. The userspace VIF address allocator
derives additional VIF addresses on a phy the same way: the second
interface brought up on the 2.4 GHz radio gets base | 0x02, the exact
value this fixup assigned to phy1. Any configuration with two VIFs on
the 2.4 GHz radio (AP + mesh, AP + STA, a second AP) therefore ended
up with two interfaces sharing one MAC address. Observed on a KN-3811
running an 802.11s mesh alongside the regular APs: the 2.4 GHz mesh
VIF came up with the same address as the 5 GHz AP, and every
batman-adv loop-avoidance announce returning from the mesh made the
bridge log "received packet on bat0 with own address as source" and
flap the FDB entry for that address.

Simply dropping the override is not an option on these boards. Without
it mt76 falls back to the second MAC slot in the calibration data
(MT_EE_MAC_ADDR2, eeprom offset 0xa), but the DTS of every board here
already consumes that slot as the ethernet/label address, so phy1
would collide with a wired interface instead - verified on a KN-3811,
where the slot holds the WAN MAC. On KAP-630/NAP-630 that ethernet
port and the 5 GHz AP even sit in the same bridge.

Shifting the base is not enough either: the allocator's MBSSID scheme
varies the last octet (addr[5] ^= idx), so any last-octet shift stays
reachable at some index. Reproduce instead the address mt76 derives on
its own when the second slot is empty: LA bit set and bit 7 of the
first octet flipped. Neither allocator scheme can produce it (the
default one varies bits 2-6 of octet 0, MBSSID varies octet 5), and it
matches neither the base nor the base+1 ethernet address. This also
gives the whole family one 5 GHz addressing convention, since boards
with an empty second slot already get exactly this address from the
driver. The 5 GHz BSSID of the affected boards changes accordingly.

Tested on a KN-3811: phy1 comes up as the base with the LA bit and
bit 7 flipped, no address overlaps on the device, and APs, mesh and
clients re-associate fine.

Signed-off-by: Aleksei Sviridkin <f@lex.la>
Link: https://github.com/openwrt/openwrt/pull/24623
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
2026-09-14 09:10:34 +02:00