port: add a bounded single-port L2 flush

port_l2_forget() flushes the whole table and polls the flush engine
without a bound. A topology change only needs to age out the port that
changed, and the STP tick cannot afford an unbounded poll: add
port_l2_forget_port() with a single-port mask and the same bounded wait
the static-entry helper uses.
This commit is contained in:
d00f
2026-08-04 03:34:22 +02:00
parent 86fdb43255
commit f635e1d213
2 changed files with 25 additions and 1 deletions
+24 -1
View File
@@ -28,6 +28,10 @@ extern __xdata struct machine_runtime machine_detected;
__xdata uint32_t l2_head; __xdata uint32_t l2_head;
/* Bounded-wait counter for the L2 table helpers; xdata because the 8051
* internal-RAM overlay (OSEG) is full. */
__xdata uint8_t l2mc_guard;
__xdata struct vlan_settings vlan_settings; __xdata struct vlan_settings vlan_settings;
void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked
@@ -306,6 +310,26 @@ void vlan_setup(void) __banked
} }
/*
* Forget the dynamic L2 entries learned on one port.
*
* Same flush engine as port_l2_forget(), but with a single-port mask so a
* topology change only ages out the affected port instead of the whole
* table. Bounded wait (cf. port_l2mc_set): this runs from the STP tick, and
* an unbounded poll on a stuck engine would freeze the main loop.
*/
void port_l2_forget_port(uint8_t port) __banked
{
REG_SET(RTL837x_L2_TBL_FLUSH_CNF, 0x0); /* port-based, dynamic entries */
REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, L2_TBL_FLUSH_EXEC | (((uint16_t)1) << port));
l2mc_guard = 0;
do {
reg_read_m(RTL837x_L2_TBL_FLUSH_CTRL);
} while (sfr_data[1] && ++l2mc_guard);
}
/* /*
* Forget all dynamic L2 learned entries * Forget all dynamic L2 learned entries
*/ */
@@ -416,7 +440,6 @@ void port_l2_learned(void) __banked
* Overwriting the same MAC+VID replaces the entry, so a caller can retarget * Overwriting the same MAC+VID replaces the entry, so a caller can retarget
* the mask at will (e.g. back to all ports to restore flooding). * the mask at will (e.g. back to all ports to restore flooding).
*/ */
__xdata uint8_t l2mc_guard; /* xdata: the internal-RAM overlay (OSEG) is full */
void port_l2mc_set(uint8_t mac_last, __xdata uint16_t vid, __xdata uint16_t pmask) __banked void port_l2mc_set(uint8_t mac_last, __xdata uint16_t vid, __xdata uint16_t pmask) __banked
{ {
+1
View File
@@ -55,6 +55,7 @@ void vlan_setup(void) __banked;
void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked; void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked;
uint16_t port_pvid_get(uint8_t port) __banked; uint16_t port_pvid_get(uint8_t port) __banked;
void port_l2mc_set(uint8_t mac_last, __xdata uint16_t vid, __xdata uint16_t pmask) __banked; void port_l2mc_set(uint8_t mac_last, __xdata uint16_t vid, __xdata uint16_t pmask) __banked;
void port_l2_forget_port(uint8_t port) __banked;
void vlan_create(void) __banked; void vlan_create(void) __banked;
void vlan_delete(uint16_t vlan) __banked; void vlan_delete(uint16_t vlan) __banked;
void vlan_dump(void) __banked; void vlan_dump(void) __banked;