The squashfs images of the TP-Link RE200 v1 and RE210 v1 differ between
builds; the uncompressed kernel of the RE200 one was 271 bytes larger,
from its device tree on:
-00001040: 6d00 0080 00cb 1a9e 0000 0000 0000 006f
+00001040: 6d00 0080 00da 1b9e 0000 0000 0000 006f
The RE210 device tree is exactly 271 bytes larger than the RE200 one, so
the RE200 image carried the kernel of the RE210.
tplink-v1-okli-image puts kernel and rootfs together in
$(IMAGE_ROOTFS).factory or .sysupgrade, a name shared by all devices with
the same rootfs. Both devices are built at the same time, so one can
overwrite the file of the other between cp, cat and mktplinkfw, and an
image can end up with the kernel and device tree of the other device.
Link: https://github.com/openwrt/openwrt/pull/25816
Signed-off-by: Paul Spooren <mail@aparcar.org>
On RTL839x a route through a gateway the switch holds no L2 entry for
gets one invented by otto_l2_nexthop_add(): static, with the don't-care
port. The gateway is then cut off from the switch, and what the route
should forward goes to the CPU instead. Measured on an HPE 1920-48G
(RTL8393), main f29dfe25ba, gateway G on a bridge VLAN behind lan48,
with a permanent neighbour and a MAC the switch had not seen, 8 echo
requests to a destination behind it, forwarding off:
- G's L2 entry was written static, port 63
- G got 0 of 3 replies from the switch; the 8 echo requests reached
the CPU, none reached G
- with the neighbour made dynamic the entry stayed as it was
- with the route removed G got 3 of 3 replies, and the switch learnt
it on port 47
Setting lan48's static move action to forward did not restore it, so
that alone does not explain it; the mechanism is not known.
RTL930x stopped inventing that entry in 138fabb79f ("realtek: l3: do
not invent an L2 entry for a next hop") wherever a route can trap, and
since #25805 an RTL839x route can. Require an entry the switch already
holds on every family: the route traps until the switch learns the
gateway from the traffic the CPU routes, and a later neighbour update
programs it. Nothing asks otto_l2_nexthop_add() to invent an entry any
more, so the flag and the invented entry go. A route trapped for want
of one is now logged on RTL839x as on RTL930x. On RTL839x an L2 entry
that is a next hop already is now pointed at its gateway's ROUTING row
as on RTL930x, one row per gateway MAC since c282dd1f4d.
The same case with this change: no entry written, the route trapped,
G got 3 of 3 replies and was learnt on port 47; the 8 echo requests
reached the CPU and, with forwarding on, G through the kernel, TTL 63.
With the neighbour made dynamic the route forwarded on the learnt
entry, 8 of 8 at G, none at the CPU. The cases from #25805 rerun (two
prefixes in both orders, neighbour loss): same results. Since that run
only the log line and comments changed.
As 138fabb79f says, a route through a permanent neighbour the switch
had not learnt stays with the CPU, since such a neighbour sees no
update: measured here too, it stayed trapped after G was learnt, until
the neighbour was made dynamic. Also as on RTL930x, a route that claims
an entry the switch learnt again after a flush counts itself on top of
the count the flushed entry left, so that entry can stay a next hop
once the route is gone; not tested.
RTL930x: no change, it already required such an entry. RTL838x and
RTL931x have no setup, so their FIB and neighbour events are ignored and
none of this runs there. Compile-tested on rtl930x.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25824
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
The NBG7815 cools itself with a GPIO driven fan on TLMM 21. A second
tmp103 sits on the second I2C bus (BLSP QUP4), which the stock firmware
reads as the board temperature, and the stock firmware keeps GPIO 22
high to enable the second fan.
The switching points come from the stock firmware, which controls the
fan from a shell daemon /usr/sbin/fanctld, configured in
/etc/config/fanctld:
config fanctld config
option Enabled '1'
option Delay '20'
option Hits '3'
option TempTrig '108'
option TempClr '85'
fanctld polls every 20 s and starts the fan once any of thermal_zone0
(nss-top), wifi0 or wifi1 has been at or above TempTrig for three
consecutive polls. It stops the fan again only after all three have been
at or below TempClr for three polls:
if [ $temp1 -ge $temp_trig -o $temp2 -ge $temp_trig -o $temp3 -ge $temp_trig ]; then
echo 2
elif [ $temp1 -le $temp_clr -a $temp2 -le $temp_clr -a $temp3 -le $temp_clr ]; then
echo 1
The trip is placed at 85 degC with 5 degC hysteresis, so the fan runs
from 85 degC and stops again at 80 degC, rather than at the stock 108/85:
the SoC hardly reaches 108, so the case gets uncomfortably hot under load
before the fan would ever start, as reported for this device in
https://github.com/openwrt/openwrt/pull/14210
It sits on the CPU cluster rather than on the sensors the stock daemon
polls: the wifi sensors are only reachable through the vendor thermaltool
there, and one zone is enough to drive the fan.
Add the gpio-fan as a cooling device with that trip, enable the second
I2C bus with its tmp103, add the gpio-hog for the second fan enable and
describe the USB VBUS switch on GPIO 32 as a regulator rather than
hogging it.
That regulator carries enable-active-high. For regulator-fixed, gpiolib
ignores the flag in the GPIO specifier and takes the line as active low
without that property, so the regulator would drive GPIO 32 low at probe
- logged as "enforce active low on GPIO handle" - while the stock
firmware holds the line high.
The AQR PHY is deliberately left out of the cooling maps: its driver
rejects the low trip the thermal core installs by default, so a thermal
zone bound to it fails to set its trips.
Co-developed-by: Semih Baskan <strst.gs@gmail.com>
Signed-off-by: Semih Baskan <strst.gs@gmail.com>
Signed-off-by: André Valentin <avalentin@marcant.net>
The front panel of the NBG7815 carries nine RGB LEDs, driven by three TI
LP5569 controllers on the first I2C bus. The stock firmware keeps GPIO 60
high to enable the LED board.
The third controller sits at 0x40, where the stock firmware pokes two
registers directly instead of binding a driver, and the board schematics
call it an LP5009. It answers to the lp5569 register layout though: a
write to the pwm registers at 0x16 lights the LEDs, while the lp50xx
driver only ever got -EIO. Verified on the device by reading back the
registers and by the LEDs actually turning on.
Placement and colours were measured with a camera pointed at the front bar,
one frame per lit LED against a dark frame. LED1 to LED6 walk through the bar
monotonically, so the two controllers form one continuous chain: 0x32
ascending, 0x35 descending, which is also the channel order the stock
zled_ctrl script uses. Red, green and blue each come out as the dominant
channel on all three controllers.
The three groups of the controller at 0x40 light the same spot near the
middle of the bar instead, each with about twice the output of a bar segment,
so they feed one brighter element together rather than three segments of
their own.
Channel numbers are per controller. Getting that wrong is quiet but
destructive: lp55xx_multicolor_brightness() adds the number to the pwm
register base without checking it against the channel count, so the
writes land in the current registers of other channels instead.
Add the controller nodes with the channel mapping and the LED currents
of the stock firmware, the gpio-hog for the LED board enable, and set
LED7 to white through board.d. That is the brighter element in the middle
rather than one end of the bar, and it is the one the stock firmware keeps
driving in every state through its two register writes to 0x40.
The same LED is wired to the led-running and led-upgrade aliases, so
diag.sh turns it on once the system is up and blinks it while a sysupgrade
runs. Measured with a camera at 30 fps: 36 cycles of 200 ms on and 200 ms
off for the duration of the flash.
led-boot and led-failsafe are deliberately absent. Both states are set
from preinit, before the i2c driver for the controller is loaded, so the
LED does not exist yet and led_set_attr() silently skips it - confirmed by
recording a boot, where the LED stays dark and then comes on in one step.
The aliases need a "label" on the multi-led node: get_dt_led() looks for
label, then chan-name, and otherwise composes a name from color and
function, which would be "rgb:" here. The lp55xx driver only reads "label"
from the controller node, so it does not affect the class device name.
Signed-off-by: André Valentin <avalentin@marcant.net>
Add a kernel module package for the TI LP5569 RGB LED controller driver,
used by the front panel LEDs of the Zyxel NBG7815.
The driver registers an i2c and an of device table, so AutoProbe is
enough and no load priority is needed. The boot flag is kept, as the
other LED modules do, so that the module is available to preinit on a
device that signals boot state through one of its LEDs.
Signed-off-by: André Valentin <avalentin@marcant.net>
The led init script already knows how to drive a multicolor LED: it reads
multi_index and writes one intensity per color to multi_intensity, taken
from color_<name> options of the led section. Nothing fills those options
in, though - generate_led only passes name, sysfs, trigger and default on
to uci, so the intensities stay at zero and the LED remains dark whatever
trigger is set. No board has been able to use it so far.
Pass any color_* key of a board.json led object through to the led
section, and add ucidef_set_led_colors() to set them from board.d:
ucidef_set_led_default "led1" "LED1" "nbg7815:led1" "1"
ucidef_set_led_colors "led1" red 255 green 255 blue 255
The colors are not restricted to RGB - the keys are matched against
whatever the LED reports in multi_index.
Signed-off-by: André Valentin <avalentin@marcant.net>
On 6.18 the rfc7539(chacha20,poly1305) template takes its ChaCha20
skcipher from crypto/chacha.ko, which CRYPTO_CHACHA20POLY1305 selects
but no package ships, and which needs lib/crypto/libchacha.ko.
Instantiating rfc7539esp(chacha20,poly1305) for IPsec then fails with
ENOSYS.
Ship chacha.ko with kmod-crypto-chacha20poly1305 on 6.18, load it
before the template and depend on kmod-crypto-lib-chacha20 for
libchacha.ko.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
Link: https://github.com/openwrt/openwrt/pull/25544
Signed-off-by: Robert Marko <robimarko@gmail.com>
The linux-riscv64-openwrt target inherits linux-generic64, which sets no
asm_arch, so OpenSSL builds only its C code on riscv64. Inherit
linux64-riscv64 instead. That adds the riscv64 assembly for AES, GHASH,
ChaCha20 and SHA-2, which uses the Zb*, Zk* and vector crypto extensions
only when the CPU reports them at runtime.
libcrypto.so.3 grows by 24 KiB, and is 2.3 KiB smaller after xz.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
Link: https://github.com/openwrt/openwrt/pull/25581
Signed-off-by: Robert Marko <robimarko@gmail.com>
Rename struct rtldsa_vlan_info to struct otto_vlan_info and update
all references to match the otto_vlan_ namespace.
No functional changes intended.
Assisted-by: ChatGPT (OpenAI GPT-6 Astra)
Link: https://github.com/openwrt/openwrt/pull/25817
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
The statistics functions already use the otto_stats_ prefix, while
the associated structure types and variables still use rtldsa_.
Rename the counter and MIB structure types, per-SoC MIB lists and
descriptors, and polling interval macros to match the module's
namespace. Update all declarations and references in the shared
header and the four SoC configurations.
No functional changes intended.
Assisted-by: ChatGPT (OpenAI GPT-6 Astra)
Link: https://github.com/openwrt/openwrt/pull/25817
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
On RTL839x a route forwards through its gateway's L2 entry. A gateway
that sends nothing lets that entry age out, and a packet routed
through it then hits the routing entry age-out exception, whose action
is forward after reset: the packet is routed and also reaches the CPU,
which routes it a second time when IPv4 forwarding is on.
Trap it instead (ROUTING_AGE, bits 15:14 of ROUTING_EXCPT_CTRL: 0 drop,
1 forward, 2 trap; Realtek GPL SDK, dal_cypress_trap.c, exception
ROUTE_EXCEPTION_TYPE_ENTRY_AGE_OUT), as the TTL exception already does.
The CPU routes such packets alone until the gateway sends again and
its entry is learnt anew.
Measured on an HPE 1920-48G (RTL8393), 10.99.0.0/16 via a gateway
that sends nothing, 8 echo requests per case, once the age of its L2
entry had run down to 0 (about 4.5 minutes on the bench):
- without this change: forwarding off, 8/8 routed and 8/8 at the CPU
as well; forwarding on, 14 at the gateway, 8 from the switch and 6
from the kernel
- with it: forwarding off, none routed, 8/8 at the CPU; forwarding
on, 8 at the gateway, none of them twice
With a fresh entry, 8/8 were routed in hardware and none reached the
CPU, without and with this change. Both images also carried the
pending switch MAC change for #25768 items 3 and 4 and bench debugfs
files.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25821
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
The GCC version string carries $(REVISION), so it changes on every
commit even when nothing under toolchain/ does. The string ends up in
the .comment section of every object and in the kernel's
CONFIG_CC_VERSION_TEXT, so packages differ between revisions built with
the same compiler, and no ccache entry for target code survives a pull.
Dropping the revision was reverted in b5ed5604cf because ccache would
then keep objects from a GCC built without a newly added patch. A hash
over the names and contents of all files under toolchain/ changes with
any GCC, binutils or libc patch or Makefile, and does not depend on a
git checkout. The toolchain Makefile computes it once per make call, on
first use, and passes it to the GCC builds.
The buildbot check that wipes the toolchain compares the same hash
instead of the last commit under toolchain/, so the toolchain is
rebuilt exactly when the version string changes, and the check no
longer needs a git checkout.
Link: https://github.com/openwrt/openwrt/pull/24364
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
Link: https://github.com/openwrt/openwrt/pull/25362
Signed-off-by: Nick Hainke <vincent@systemli.org>
Since kmod-input-evdev depends on input-support, kmod-hid and
kmod-usb-hid are hidden without it, and so is everything selecting
kmod-hid: kmod-bluetooth, kmod-hci-uart and kmod-btusb. A device that
lists one of them in DEVICE_PACKAGES fails to build as a single profile:
ERROR: unable to select packages:
kmod-hci-uart (no such package):
Neither module needs evdev, so select it only with input-support.
Fixes: a7c50f7d73 ("input-support: add a package for input device handling")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
Link: https://github.com/openwrt/openwrt/pull/25565
Signed-off-by: Nick Hainke <vincent@systemli.org>
As the MIPI-DBI firmware blobs are carrying target-dependencies to only
be available and get built for the targets they are actually used by,
the package needs to be flagged as 'nonshared'.
While at it, remove the duplicated firmware compiler and instead use the
(archived) upstream repo it came from.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
The RTL839x route rules match the destination in the template's DIP
fields, and the trap rules the switch MAC too, but never the frame
type. An IPv6 frame fills those fields too, so an
IPv6 frame to the switch whose destination ends in the 32 bits of an
offloaded IPv4 prefix takes that prefix's rule and is routed in
hardware, as IPv6, to the IPv4 route's gateway. IPv4-embedded IPv6
addresses under a /96 prefix (RFC 6052), such as the NAT64 prefix
64:ff9b::/96, end that way.
Match FRAME_TYPE IPv4 (2, USER_FIELD_FRAME_TYPE in the Realtek GPL
SDK), which the IACL entry keeps at bits 337:336 with its mask at
121:120, where the PIE writer already puts frame_type.
Measured on an HPE 1920-48G (RTL8393), 10.99.0.0/16 offloaded via
gateway G, forwarding off, 8 IPv6 echo requests to the switch for
2001:db8:5::a63:601 to ...:608, whose low 32 bits are 10.99.6.1 to .8:
- without this change: 8/8 routed to G (hop limit 63), the rule's
packet counter +8
- with this change: none at G, 8/8 at the CPU, counter +0
Destinations with 10.99.6.x in their high 32 bits were not routed on
either. IPv4 routing through the rules was unchanged (prefix order,
neighbour loss and back, a gateway shared by two routes). Both images
were main c282dd1f4d with bench debugfs files and the switch MAC change
for items 3 and 4 of #25768, not posted yet (a later revision of it on
the second, differing in how routes follow a MAC change).
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25818
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
The QCA8337 is behind PPE port 1, so with the plain QCA tag the EDMA
cannot offload the checksum or TSO of frames for lan3-lan8. Select the
qca-etype tag on its CPU port.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
Link: https://github.com/openwrt/openwrt/pull/25754
Signed-off-by: Robert Marko <robimarko@gmail.com>
The QCA8K header sits in place of the ethertype, so the IPQ807x EDMA,
which finds the IP header by parsing past the Ethernet header and VLAN
tags, cannot offload the TX checksum or TSO of a frame for a QCA8337
behind a PPE port, and TCP and UDP leave those ports with bad
checksums. Add a "qca-etype" tagger that puts the header behind the
802.1ad ethertype, which the EDMA parses as a VLAN tag, and let qca8k
select it and program HEADER_CTRL to match.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
Link: https://github.com/openwrt/openwrt/pull/25754
Signed-off-by: Robert Marko <robimarko@gmail.com>
phylink sets the PHY EEE advertisement from lpi_capabilities and does not
check lpi_interfaces, so the PHY of a USXGMII or 10GBASE-R port
advertises EEE although the MAC never enables LPI there. The XPCS behind
those modes reports no EEE ability (SR_XS_PCS_EEE_ABL reads 0 on IPQ8074),
and qca-ssdk does not enable MAC EEE on them for that reason. Offer EEE
only on a port whose phy-mode has MAC LPI, and add 2500BASE-X at
2.5 Gbit/s on ports 5 and 6, which qca-ssdk treats as EEE capable.
Fixes: dd052b4594 ("qualcommax: qca_ppe: add EEE support")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
Link: https://github.com/openwrt/openwrt/pull/25754
Signed-off-by: Robert Marko <robimarko@gmail.com>
On RTL839x a gateway's L2 entry names the ROUTING row that holds the
gateway's MAC, and that row was the id of the route that claimed the
entry. The other routes through that gateway go on using the row after
the route is gone, and its id can go to a later route, which writes
its own gateway's MAC into it. Those routes then forward to the wrong
gateway.
Give RTL839x the DMAC entries RTL930x has: one ROUTING row per gateway
MAC, held by every route through it (otto_l3_dmac_get()) and written
when it is first taken. The bookkeeping takes 24 KiB, allocated at
probe as on RTL930x.
Measured on an HPE 1920-48G (RTL8393) with #25805 on main 17a3a87f6e,
8 echo requests per case, forwarding off: routes A and B via gateway
G, A removed, then route C via gateway H.
- without this change, C took A's row and B's traffic arrived 8/8 at
H, sent to H's MAC
- with it, C got a row of its own and B's traffic stayed 8/8 at G
Of the #25805 bench, prefix order in both orders, blackhole, neighbour
loss and back, and 22 routes in random order gave the same results as
there.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25808
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Enabling CONFIG_TARGET_ROOTFS_PERSIST_VAR leaves /var/lock on
persistent storage, allowing stale lock files to survive reboots.
Link /var/lock to ../tmp/lock so that lock files remain volatile.
Use a relative symlink to keep build-time accesses within the
target root filesystem. Create the target directory for rootfs
preparation. procd already recreates /tmp/lock at boot.
Fixes: 57807f50de ("base-files: add option to make /var persistent")
Signed-off-by: Ivan Romanov <drizt72@zoho.eu>
Link: https://github.com/openwrt/openwrt/pull/25718
Signed-off-by: Robert Marko <robimarko@gmail.com>
On RTL839x every offloaded route is a PIE rule that matches the
destination prefix, and of the rules that match, the lowest index
acts. rtl839x_pie_rule_add() hands out the first free index, so a /16
added before a /24 inside it takes the /24's traffic. Nothing traps
either, so the switch forwards what the kernel would not: a blackhole
inside an offloaded prefix, a local prefix, routes under policy rules,
a gateway whose neighbour is gone (#25768, items 5 to 9).
Handle the rules the way the RTL930x prefix table is handled. The
rules pie.c keeps for L3 are the prefix rows: a route takes one when
it is added, longest prefix first, the local table ahead of main. The
ROUTING row with the gateway MAC gets a writer of its own. A move
writes the routes again at their new rows, since a rule holds nothing
its route does not. A route the switch must not forward redirects to
the CPU port, and only frames addressed to one of the switch's MACs
(SWITCHMAC), so a frame for another station is not taken.
The traps for routes left out, local prefixes, policy rules and a lost
neighbour now run on RTL839x too. Policy rules are checked for IPv4
only, as IPv6 is not offloaded there; the check replaces the "FIB4
default rule failed" message. A gateway whose MAC was not learnt on a
port still forwards, as before, and a lost event is still not
replayed. The debugfs route dump walks the L3 rules and shows the
trapping ones.
Measured on an HPE 1920-48G (RTL8393), RAM-booted from main
17a3a87f6e plus this series, 8 echo requests per case, the client and
both gateways behind one port in VLANs 7 and 3:
- /16 via A and /24 via B, added in both orders, forwarding off: /24
traffic 8/8 at B, the rest 8/8 at A, TTL 63, none at the CPU
- blackhole /24 inside the /16: none forwarded, 8 at the CPU
- a rule sending a /24 to table 100: offload suspended, the kernel
sends 8/8 to that table's gateway; back in hardware once it goes
- local 10.99.0.0/16 in table local: 8/8 answered by the switch
- gateway neighbour failed: 3/3 Destination Host Unreachable, back in
hardware once the gateway answers again
- 22 routes added in random order, half removed, then the rest: rows
dense and longest prefix first after each phase
The network (re)starts suspended the offload for about 10 ms each, as
the policy rules changed.
RTL930x: no change. Every changed check tests a flag or callback that
RTL930x sets, and the new row bound in otto_l3_route_place() lies
past the IPv6 catch-all row, which stops the IPv4 rows first. RTL838x
and RTL931x have no setup, so their FIB events are still ignored.
Compile-tested on rtl930x.
Not tested: a gateway MAC change, routes past rule 127 (the order
across blocks was checked by hand, #25768).
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25805
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
L3 is to keep its RTL839x routes longest prefix first, the way the
RTL930x prefix table holds them, so it needs rules that nothing else
hands out and that it writes in place. Mark blocks 0-3 as used, so
rtl839x_pie_rule_add() never returns one of them, and add a writer
for them that takes the template of the block holding the IPv4
destination.
Until L3 uses the writer, its rules come from rtl839x_pie_rule_add()
from block 4 on, where template 2 holds the destination too. Nothing
else adds RTL839x rules: tc offload is wired for RTL93xx only.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25805
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
otto_l2_nexthop_add() fails when the gateway finds no free L2 slot, or,
where the next hop has to exist already (RTL930x), when the gateway's
address has not been learnt. The route then still forwards, through
the L2 index it held before, or index 0 on its first update.
Let it trap instead. RTL930x behaves as before: the call fails before
it writes nh->port, which stays port_ignore, so no_port already traps
the route. On RTL839x the PIE rule forwards whatever the route says
until the rules can trap, so nothing changes there either.
Not tested on hardware: no failed next hop write was provoked.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25805
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Move hardware statistics helpers and packet counter allocation, read
and clear functions into stats.c.
Standardize function names on the otto_stats_ prefix, followed by the
chip identifier where applicable, and remove redundant stats suffixes.
Update declarations, includes, callers and operation tables accordingly.
No functional changes intended.
Assisted-by: ChatGPT (OpenAI GPT-6 Astra)
Link: https://github.com/openwrt/openwrt/pull/25802
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Move the hash index, hash/CAM lookup, unicast reference lookup and
ageing-time helpers into l2.c. This removes the dependency of L2 code
on lookup helpers implemented in dsa.c.
Rename the moved functions with the otto_l2_ prefix, place their
public declarations in l2.h and update includes and callers.
Leave DSA callbacks and port/bridge handling in place.
No functional changes intended.
Assisted-by: ChatGPT (OpenAI GPT-6 Astra)
Link: https://github.com/openwrt/openwrt/pull/25802
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
LAG handling is split between dsa.c and lag.c. Consolidate the remaining
LAG callbacks and helpers in lag.c to keep related functionality together.
Rename the moved functions with the otto_lag_ prefix and declare the
cross-file interfaces in lag.h. Update callers, DSA operation tables and
RTL93xx configuration references, and add the required includes.
Leave the port management functions in place for a later refactoring.
No functional changes intended.
Assisted-by: ChatGPT (OpenAI GPT-6 Astra)
Link: https://github.com/openwrt/openwrt/pull/25802
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
phram exposes a physical memory range as a read-write MTD device. This
can be used to access RAM regions reserved by firmware or described in
the device tree.
Of particular interest, phram nodes carved out of the reserved region
can survive soft reboots, making it a useful primitive to pass one-shot
bootenv overrides to uboot (fw_setenv -c) without the risk of bricking,
having to wire up a serial console etc.
This patch does the kernel module enablement, paving the way for
potential userspace integrations further down the line (ubus, procd,
sysupgrade etc.)
Run-tested on Linksys E8450 (UBI) with OpenWrt uboot.
Signed-off-by: Gary Dotzler <geldot@protonmail.com>
Link: https://github.com/openwrt/openwrt/pull/25692
Signed-off-by: Nick Hainke <vincent@systemli.org>
Add the Dual Queue Coupled AQM (RFC 9332) queuing discipline, which
gives L4S traffic a low latency without starving classic traffic. It
is available since kernel 6.17, tc supports it already.
Link: https://github.com/openwrt/openwrt/pull/25779
Signed-off-by: Nick Hainke <vincent@systemli.org>
Add the Earliest TxTime First queuing discipline, which sends packets
at the time set with SO_TXTIME. It is used for Time-Sensitive
Networking, also together with taprio in txtime-assist mode.
Link: https://github.com/openwrt/openwrt/pull/25777
Signed-off-by: Nick Hainke <vincent@systemli.org>
Add the Time Aware Priority (IEEE 802.1Qbv) queuing discipline, used
for Time-Sensitive Networking.
The Hellcreek switch driver depends on taprio, so disable it to avoid
a new config prompt.
Link: https://github.com/openwrt/openwrt/pull/25777
Signed-off-by: Nick Hainke <vincent@systemli.org>
The Felix switch of the LS1028A is built in and depends on taprio
being built in or disabled. If taprio is built as a module, e.g. by
the upcoming kmod-sched-taprio, Felix can only be built as a module as
well and the switch is missing in the image.
Build taprio into the kernel, so that the switch stays built in and
Felix and ENETC can offload taprio, cbs and the gate action.
Link: https://github.com/openwrt/openwrt/pull/25777
Signed-off-by: Nick Hainke <vincent@systemli.org>
hostapd-utils and wpa-cli use VARIANT:=*, so every variant packs them.
Since the variants are built in parallel, they write the same package
file and pkginfo files at the same time. This makes the build fail
randomly:
Package hostapd-utils is missing dependencies for the following libraries:
libgcc_s.so.1
Only pack them in the first selected variant that builds them.
Fixes: b029d56e0b ("hostapd: build the variants in parallel")
Link: https://github.com/openwrt/openwrt/pull/25796
Signed-off-by: Nick Hainke <vincent@systemli.org>
The vendor BL2 of the Wavlink WL-WNT100X3 initializes DDR3 at
1866 MT/s:
NOTICE: BL2: v2.7(release):292bca1-dirty
NOTICE: DDR3 1866MHZ
NOTICE: EMI: Using DDR3 settings
while the plain spim-nand-ddr3 BL2 used by the ubootmod variant runs
DDR3 at the default 2133 MT/s, which is above what the vendor
qualified on this board.
Switch the ubootmod BL2 to the existing DDR3 1866 MT/s build, in line
with the vendor firmware.
Tested on WL-WNT100X3: BL2 reports the ddr3-1866 build, the memory
test passes, U-Boot and OpenWrt boot from UBI.
Fixes: d2fabb974c ("mediatek: add support for Wavlink WL-WNT100X3 ubootmod")
Signed-off-by: Fil Dunsky <filipp.dunsky@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25763
Signed-off-by: Robert Marko <robimarko@gmail.com>
qca8k was built into the kernel so the MX65's QCA8337 switches work in
failsafe. However, the QCA8337 PHY driver was not, so the internal PHYs
bound to genphy and missed the chip-specific setup in
qca83xx_config_init(), such as disabling EEE.
Switch to kmod-dsa-qca8k for the MX65 instead, which now pulls in
kmod-phy-qca83xx. Both are loaded in preinit, and the PHY driver loads
first, so failsafe keeps working and the PHYs get the right driver.
This also removes qca8k from the kernel of every other bcm53xx device.
Attach an extra patch sent upstream to use the internal MDIO, which no
longer supports generic PHY.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25767
Signed-off-by: Robert Marko <robimarko@gmail.com>
The internal PHYs of the QCA8327/8334/8337 switches are handled by the
qca83xx PHY driver. Without it they silently fall back to genphy and
lose the chip-specific setup and fixups. Every device using
kmod-dsa-qca8k already pulls it in manually except the MikroTik
RB960PGS, which was missing it.
Add the dependency, like other DSA packages do with their PHY drivers,
and drop the now-redundant device package entries.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25767
Signed-off-by: Robert Marko <robimarko@gmail.com>
All of these AR8327s are claimed through the PHY ID by
ar8xxx_phy_probe(), which needs a plain ethernet-phy@0 node carrying
qca,ar8327-initvals, while a CPU port has to hang off a phandle to
that PHY. The switch nodes already in the tree take the other path:
ar8xxx_mdiodev_probe() claims them by compatible and the CPU port
runs off a fixed-link. Both end up with the same single swconfig
device and the same initvals.
Switch the remaining boards over to that second form, i.e. an
ethernet-switch@10 with compatible = "qca,ar8327" and reg = <0x10>.
0x10 is the first register of the AR8327 window, 0x18 being the page
select register, so that is the address to probe at. Where the phy-mode
only lived on the PHY node, move it to the MAC that took over the
link.
For zyxel,nbg6x16, wd,mynet-n750, and comfast,cf-wr650ac, fix the address
from 1f to 10. The former is for built-in 100Mbps switches. The mdio1
stuff is also irrelevant. Both ethernet interfaces are part of the switch.
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25467
Signed-off-by: Robert Marko <robimarko@gmail.com>
These external AR8236s were copied from the builtin-switch pattern
(switch0@1f). QCA9558 has no builtin switch; AR8236 register access
starts at MDIO 0x10.
Use ethernet-switch@10 with compatible = "qca,ar8236" and reg = <0x10>,
matching the other external QCA switches.
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25467
Signed-off-by: Robert Marko <robimarko@gmail.com>