Loading drivers/net/ethernet/microchip/sparx5/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -8,4 +8,4 @@ obj-$(CONFIG_SPARX5_SWITCH) += sparx5-switch.o sparx5-switch-objs := sparx5_main.o sparx5_packet.o \ sparx5_netdev.o sparx5_phylink.o sparx5_port.o sparx5_mactable.o sparx5_vlan.o \ sparx5_switchdev.o sparx5_calendar.o sparx5_ethtool.o sparx5_fdma.o \ sparx5_ptp.o sparx5_ptp.o sparx5_pgid.o drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c +23 −10 Original line number Diff line number Diff line Loading @@ -186,11 +186,11 @@ bool sparx5_mact_getnext(struct sparx5 *sparx5, return ret == 0; } static int sparx5_mact_lookup(struct sparx5 *sparx5, const unsigned char mac[ETH_ALEN], u16 vid) bool sparx5_mact_find(struct sparx5 *sparx5, const unsigned char mac[ETH_ALEN], u16 vid, u32 *pcfg2) { int ret; u32 cfg2; mutex_lock(&sparx5->lock); Loading @@ -202,16 +202,29 @@ static int sparx5_mact_lookup(struct sparx5 *sparx5, sparx5, LRN_COMMON_ACCESS_CTRL); ret = sparx5_mact_wait_for_completion(sparx5); if (ret) goto out; ret = LRN_MAC_ACCESS_CFG_2_MAC_ENTRY_VLD_GET (spx5_rd(sparx5, LRN_MAC_ACCESS_CFG_2)); if (ret == 0) { cfg2 = spx5_rd(sparx5, LRN_MAC_ACCESS_CFG_2); if (LRN_MAC_ACCESS_CFG_2_MAC_ENTRY_VLD_GET(cfg2)) *pcfg2 = cfg2; else ret = -ENOENT; } out: mutex_unlock(&sparx5->lock); return ret; return ret == 0; } static int sparx5_mact_lookup(struct sparx5 *sparx5, const unsigned char mac[ETH_ALEN], u16 vid) { u32 pcfg2; if (sparx5_mact_find(sparx5, mac, vid, &pcfg2)) return 1; return 0; } int sparx5_mact_forget(struct sparx5 *sparx5, Loading drivers/net/ethernet/microchip/sparx5/sparx5_main.c +3 −0 Original line number Diff line number Diff line Loading @@ -626,6 +626,9 @@ static int sparx5_start(struct sparx5 *sparx5) /* Init MAC table, ageing */ sparx5_mact_init(sparx5); /* Init PGID table arbitrator */ sparx5_pgid_init(sparx5); /* Setup VLANs */ sparx5_vlan_init(sparx5); Loading drivers/net/ethernet/microchip/sparx5/sparx5_main.h +23 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,12 @@ enum sparx5_vlan_port_type { #define PGID_BCAST (PGID_BASE + 6) #define PGID_CPU (PGID_BASE + 7) #define PGID_TABLE_SIZE 3290 #define PGID_MCAST_START 65 #define PGID_GLAG_START 833 #define PGID_GLAG_END 1088 #define IFH_LEN 9 /* 36 bytes */ #define NULL_VID 0 #define SPX5_MACT_PULL_DELAY (2 * HZ) Loading Loading @@ -271,6 +277,8 @@ struct sparx5 { struct mutex ptp_lock; /* lock for ptp interface state */ u16 ptp_skbs; int ptp_irq; /* PGID allocation map */ u8 pgid_map[PGID_TABLE_SIZE]; }; /* sparx5_switchdev.c */ Loading Loading @@ -302,6 +310,8 @@ int sparx5_mact_learn(struct sparx5 *sparx5, int port, const unsigned char mac[ETH_ALEN], u16 vid); bool sparx5_mact_getnext(struct sparx5 *sparx5, unsigned char mac[ETH_ALEN], u16 *vid, u32 *pcfg2); bool sparx5_mact_find(struct sparx5 *sparx5, const unsigned char mac[ETH_ALEN], u16 vid, u32 *pcfg2); int sparx5_mact_forget(struct sparx5 *sparx5, const unsigned char mac[ETH_ALEN], u16 vid); int sparx5_add_mact_entry(struct sparx5 *sparx5, Loading Loading @@ -359,6 +369,19 @@ void sparx5_ptp_txtstamp_release(struct sparx5_port *port, struct sk_buff *skb); irqreturn_t sparx5_ptp_irq_handler(int irq, void *args); /* sparx5_pgid.c */ enum sparx5_pgid_type { SPX5_PGID_FREE, SPX5_PGID_RESERVED, SPX5_PGID_MULTICAST, SPX5_PGID_GLAG }; void sparx5_pgid_init(struct sparx5 *spx5); int sparx5_pgid_alloc_glag(struct sparx5 *spx5, u16 *idx); int sparx5_pgid_alloc_mcast(struct sparx5 *spx5, u16 *idx); int sparx5_pgid_free(struct sparx5 *spx5, u16 idx); /* Clock period in picoseconds */ static inline u32 sparx5_clk_period(enum sparx5_core_clockfreq cclock) { Loading drivers/net/ethernet/microchip/sparx5/sparx5_pgid.c 0 → 100644 +60 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0+ #include "sparx5_main.h" void sparx5_pgid_init(struct sparx5 *spx5) { int i; for (i = 0; i < PGID_TABLE_SIZE; i++) spx5->pgid_map[i] = SPX5_PGID_FREE; /* Reserved for unicast, flood control, broadcast, and CPU. * These cannot be freed. */ for (i = 0; i <= PGID_CPU; i++) spx5->pgid_map[i] = SPX5_PGID_RESERVED; } int sparx5_pgid_alloc_glag(struct sparx5 *spx5, u16 *idx) { int i; for (i = PGID_GLAG_START; i <= PGID_GLAG_END; i++) if (spx5->pgid_map[i] == SPX5_PGID_FREE) { spx5->pgid_map[i] = SPX5_PGID_GLAG; *idx = i; return 0; } return -EBUSY; } int sparx5_pgid_alloc_mcast(struct sparx5 *spx5, u16 *idx) { int i; for (i = PGID_MCAST_START; i < PGID_TABLE_SIZE; i++) { if (i == PGID_GLAG_START) i = PGID_GLAG_END + 1; if (spx5->pgid_map[i] == SPX5_PGID_FREE) { spx5->pgid_map[i] = SPX5_PGID_MULTICAST; *idx = i; return 0; } } return -EBUSY; } int sparx5_pgid_free(struct sparx5 *spx5, u16 idx) { if (idx <= PGID_CPU || idx >= PGID_TABLE_SIZE) return -EINVAL; if (spx5->pgid_map[idx] == SPX5_PGID_FREE) return -EINVAL; spx5->pgid_map[idx] = SPX5_PGID_FREE; return 0; } Loading
drivers/net/ethernet/microchip/sparx5/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -8,4 +8,4 @@ obj-$(CONFIG_SPARX5_SWITCH) += sparx5-switch.o sparx5-switch-objs := sparx5_main.o sparx5_packet.o \ sparx5_netdev.o sparx5_phylink.o sparx5_port.o sparx5_mactable.o sparx5_vlan.o \ sparx5_switchdev.o sparx5_calendar.o sparx5_ethtool.o sparx5_fdma.o \ sparx5_ptp.o sparx5_ptp.o sparx5_pgid.o
drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c +23 −10 Original line number Diff line number Diff line Loading @@ -186,11 +186,11 @@ bool sparx5_mact_getnext(struct sparx5 *sparx5, return ret == 0; } static int sparx5_mact_lookup(struct sparx5 *sparx5, const unsigned char mac[ETH_ALEN], u16 vid) bool sparx5_mact_find(struct sparx5 *sparx5, const unsigned char mac[ETH_ALEN], u16 vid, u32 *pcfg2) { int ret; u32 cfg2; mutex_lock(&sparx5->lock); Loading @@ -202,16 +202,29 @@ static int sparx5_mact_lookup(struct sparx5 *sparx5, sparx5, LRN_COMMON_ACCESS_CTRL); ret = sparx5_mact_wait_for_completion(sparx5); if (ret) goto out; ret = LRN_MAC_ACCESS_CFG_2_MAC_ENTRY_VLD_GET (spx5_rd(sparx5, LRN_MAC_ACCESS_CFG_2)); if (ret == 0) { cfg2 = spx5_rd(sparx5, LRN_MAC_ACCESS_CFG_2); if (LRN_MAC_ACCESS_CFG_2_MAC_ENTRY_VLD_GET(cfg2)) *pcfg2 = cfg2; else ret = -ENOENT; } out: mutex_unlock(&sparx5->lock); return ret; return ret == 0; } static int sparx5_mact_lookup(struct sparx5 *sparx5, const unsigned char mac[ETH_ALEN], u16 vid) { u32 pcfg2; if (sparx5_mact_find(sparx5, mac, vid, &pcfg2)) return 1; return 0; } int sparx5_mact_forget(struct sparx5 *sparx5, Loading
drivers/net/ethernet/microchip/sparx5/sparx5_main.c +3 −0 Original line number Diff line number Diff line Loading @@ -626,6 +626,9 @@ static int sparx5_start(struct sparx5 *sparx5) /* Init MAC table, ageing */ sparx5_mact_init(sparx5); /* Init PGID table arbitrator */ sparx5_pgid_init(sparx5); /* Setup VLANs */ sparx5_vlan_init(sparx5); Loading
drivers/net/ethernet/microchip/sparx5/sparx5_main.h +23 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,12 @@ enum sparx5_vlan_port_type { #define PGID_BCAST (PGID_BASE + 6) #define PGID_CPU (PGID_BASE + 7) #define PGID_TABLE_SIZE 3290 #define PGID_MCAST_START 65 #define PGID_GLAG_START 833 #define PGID_GLAG_END 1088 #define IFH_LEN 9 /* 36 bytes */ #define NULL_VID 0 #define SPX5_MACT_PULL_DELAY (2 * HZ) Loading Loading @@ -271,6 +277,8 @@ struct sparx5 { struct mutex ptp_lock; /* lock for ptp interface state */ u16 ptp_skbs; int ptp_irq; /* PGID allocation map */ u8 pgid_map[PGID_TABLE_SIZE]; }; /* sparx5_switchdev.c */ Loading Loading @@ -302,6 +310,8 @@ int sparx5_mact_learn(struct sparx5 *sparx5, int port, const unsigned char mac[ETH_ALEN], u16 vid); bool sparx5_mact_getnext(struct sparx5 *sparx5, unsigned char mac[ETH_ALEN], u16 *vid, u32 *pcfg2); bool sparx5_mact_find(struct sparx5 *sparx5, const unsigned char mac[ETH_ALEN], u16 vid, u32 *pcfg2); int sparx5_mact_forget(struct sparx5 *sparx5, const unsigned char mac[ETH_ALEN], u16 vid); int sparx5_add_mact_entry(struct sparx5 *sparx5, Loading Loading @@ -359,6 +369,19 @@ void sparx5_ptp_txtstamp_release(struct sparx5_port *port, struct sk_buff *skb); irqreturn_t sparx5_ptp_irq_handler(int irq, void *args); /* sparx5_pgid.c */ enum sparx5_pgid_type { SPX5_PGID_FREE, SPX5_PGID_RESERVED, SPX5_PGID_MULTICAST, SPX5_PGID_GLAG }; void sparx5_pgid_init(struct sparx5 *spx5); int sparx5_pgid_alloc_glag(struct sparx5 *spx5, u16 *idx); int sparx5_pgid_alloc_mcast(struct sparx5 *spx5, u16 *idx); int sparx5_pgid_free(struct sparx5 *spx5, u16 idx); /* Clock period in picoseconds */ static inline u32 sparx5_clk_period(enum sparx5_core_clockfreq cclock) { Loading
drivers/net/ethernet/microchip/sparx5/sparx5_pgid.c 0 → 100644 +60 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0+ #include "sparx5_main.h" void sparx5_pgid_init(struct sparx5 *spx5) { int i; for (i = 0; i < PGID_TABLE_SIZE; i++) spx5->pgid_map[i] = SPX5_PGID_FREE; /* Reserved for unicast, flood control, broadcast, and CPU. * These cannot be freed. */ for (i = 0; i <= PGID_CPU; i++) spx5->pgid_map[i] = SPX5_PGID_RESERVED; } int sparx5_pgid_alloc_glag(struct sparx5 *spx5, u16 *idx) { int i; for (i = PGID_GLAG_START; i <= PGID_GLAG_END; i++) if (spx5->pgid_map[i] == SPX5_PGID_FREE) { spx5->pgid_map[i] = SPX5_PGID_GLAG; *idx = i; return 0; } return -EBUSY; } int sparx5_pgid_alloc_mcast(struct sparx5 *spx5, u16 *idx) { int i; for (i = PGID_MCAST_START; i < PGID_TABLE_SIZE; i++) { if (i == PGID_GLAG_START) i = PGID_GLAG_END + 1; if (spx5->pgid_map[i] == SPX5_PGID_FREE) { spx5->pgid_map[i] = SPX5_PGID_MULTICAST; *idx = i; return 0; } } return -EBUSY; } int sparx5_pgid_free(struct sparx5 *spx5, u16 idx) { if (idx <= PGID_CPU || idx >= PGID_TABLE_SIZE) return -EINVAL; if (spx5->pgid_map[idx] == SPX5_PGID_FREE) return -EINVAL; spx5->pgid_map[idx] = SPX5_PGID_FREE; return 0; }