From 2e6425f5e63510a3401fd0d8fb80741ee511397b Mon Sep 17 00:00:00 2001 From: d00f <8052722+DrDoof@users.noreply.github.com> Date: Mon, 12 Oct 2026 21:21:07 +0200 Subject: [PATCH] lacp: keep lacp_in() and lacp_lag_set() out of the data segment The port and group of lacp_in(), the member mask passed to lacp_lag_set() and the compiler temporaries both functions spilled took six bytes of DSEG, and with them six bytes of stack. The locals and the mask live in xdata now, the partner fields go through the scratch word, and lacp_lag_set() records the new group of a port before it releases the old one. One byte is left: the group number passed in. --- rtl837x_lacp.c | 25 +++++++++++++++---------- rtl837x_lacp.h | 3 +-- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/rtl837x_lacp.c b/rtl837x_lacp.c index e2ede9e3..f03ef8ef 100644 --- a/rtl837x_lacp.c +++ b/rtl837x_lacp.c @@ -284,12 +284,12 @@ void lacp_in(void) __banked /* Per rtl837x_common.h, pmask carries a 4-bit port number on RX * (hardware-verified on RTL8373: per-port rx counters track the actual * ingress port through full LACP convergence). */ - uint8_t port = ((uint8_t)HTONS(LACP_H->rtl_tag.pmask)) & 0x0f; + __xdata uint8_t port = ((uint8_t)HTONS(LACP_H->rtl_tag.pmask)) & 0x0f; if (port < machine.min_port || port > machine.max_port) return; /* Only ports assigned to a LACP-mode LAG participate in the protocol. */ - uint8_t lag = lacp_port_lag[port]; + __xdata uint8_t lag = lacp_port_lag[port]; if (lag == LACP_LAG_NONE) return; if (lacp_sys_eq(LACP_I->actor.sys, uip_ethaddr.addr)) @@ -305,10 +305,14 @@ void lacp_in(void) __banked /* Record partner = the remote's Actor block (802.3ad 43.4.9 recordPDU) */ memcpy(lacp_partner_sys[port], LACP_I->actor.sys, 6); - lacp_partner_key[port] = HTONS(LACP_I->actor.key); - lacp_partner_port[port] = HTONS(LACP_I->actor.port); - lacp_partner_sys_prio[port] = HTONS(LACP_I->actor.sys_prio); - lacp_partner_port_prio[port] = HTONS(LACP_I->actor.port_prio); + lacp_scratch_mask = HTONS(LACP_I->actor.key); + lacp_partner_key[port] = lacp_scratch_mask; + lacp_scratch_mask = HTONS(LACP_I->actor.port); + lacp_partner_port[port] = lacp_scratch_mask; + lacp_scratch_mask = HTONS(LACP_I->actor.sys_prio); + lacp_partner_sys_prio[port] = lacp_scratch_mask; + lacp_scratch_mask = HTONS(LACP_I->actor.port_prio); + lacp_partner_port_prio[port] = lacp_scratch_mask; lacp_partner_state[port] = LACP_I->actor.state; /* Receive machine -> CURRENT, (re)arm partner timeout (43.4.12) */ @@ -508,7 +512,7 @@ void lacp_init(void) __banked * The engine's RMA trap is enabled on the first LACP LAG and torn down with the * last. Never wipes a static "lag" the user configured on a different group. */ -void lacp_lag_set(uint8_t lag, uint16_t ports) __banked +void lacp_lag_set(uint8_t lag, __xdata uint16_t ports) __banked { if (lag >= LACP_NUM_LAGS) return; @@ -542,9 +546,11 @@ void lacp_lag_set(uint8_t lag, uint16_t ports) __banked if (!(ports & port_bit(i))) continue; lacp_scratch_lag = lacp_port_lag[i]; + lacp_port_lag[i] = lag; if (lacp_scratch_lag != LACP_LAG_NONE && lacp_scratch_lag != lag) { - lacp_lag_ports[lacp_scratch_lag] &= ~port_bit(i); - if (!lacp_lag_ports[lacp_scratch_lag]) { + lacp_scratch_mask = lacp_lag_ports[lacp_scratch_lag] & ~port_bit(i); + lacp_lag_ports[lacp_scratch_lag] = lacp_scratch_mask; + if (!lacp_scratch_mask) { lacp_agg_valid[lacp_scratch_lag] = 0; if (lacp_members_last[lacp_scratch_lag]) { lacp_members_last[lacp_scratch_lag] = 0; @@ -552,7 +558,6 @@ void lacp_lag_set(uint8_t lag, uint16_t ports) __banked } } } - lacp_port_lag[i] = lag; lacp_port_init(i); } diff --git a/rtl837x_lacp.h b/rtl837x_lacp.h index 5f03a16e..514f9e35 100644 --- a/rtl837x_lacp.h +++ b/rtl837x_lacp.h @@ -16,7 +16,7 @@ void lacp_show(void) __banked; /* "lacp show" - per-port state + RX counters */ /* Assign a candidate-port mask to a LACP-mode LAG (`lag lacp `). * ports == 0 removes the LAG from LACP management. Enables the engine on first * LACP LAG and tears it down when the last one goes away. */ -void lacp_lag_set(uint8_t lag, uint16_t ports) __banked; +void lacp_lag_set(uint8_t lag, __xdata uint16_t ports) __banked; /* * Per-LAG LACP: each of the 4 hardware trunk groups (0-3) can independently run @@ -89,7 +89,6 @@ extern __xdata uint16_t lacp_members_last[LACP_NUM_LAGS];/* trunk members we las #define LACP_FAST_PERIODIC 0x0032 /* fast TX 1 s; partner expires at 3 s */ #define LACP_SLOW_PERIODIC 0x05dc /* slow TX 30 s; partner expires at 90 s */ #define LACP_SHORT_TIMEOUT 0x00c8 /* silent partner dropped after 4 s (802.3ad: 3 s) */ -#define LACP_LONG_TIMEOUT 0x1770 /* long-timeout variant, after 120 s (802.3ad: 90 s) */ /* Per-port LACP receive-machine state (802.3ad 43.4.12) */ #define LACP_RX_INITIALIZE 0