diff --git a/rtl837x_port.c b/rtl837x_port.c index 1e495e1..931f6a4 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -28,6 +28,10 @@ extern __xdata struct machine_runtime machine_detected; __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; 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 */ @@ -416,7 +440,6 @@ void port_l2_learned(void) __banked * 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). */ -__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 { diff --git a/rtl837x_port.h b/rtl837x_port.h index 7ee0472..ff485eb 100644 --- a/rtl837x_port.h +++ b/rtl837x_port.h @@ -55,6 +55,7 @@ void vlan_setup(void) __banked; void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __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_l2_forget_port(uint8_t port) __banked; void vlan_create(void) __banked; void vlan_delete(uint16_t vlan) __banked; void vlan_dump(void) __banked;