diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2021-02-13 17:12:39 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2021-02-13 17:12:39 +0000 |
commit | 7eefd48f3c50cb2f130e678de7fc407dbac69c38 (patch) | |
tree | 55200b77ae132a8b9d08e6a1ece811ed407f4e24 /sys/arch/octeon | |
parent | d08b3eb3a7a75d3d80c67d44af5ce38cc5c51f82 (diff) |
Revise cnmac(4)'s address filter setup
Set up the DMAC filter in one go instead of doing it separately for
unicast and multicast DMACs. This attempts to make the code a little
more readable. The setup should now run a bit faster as well because
it now does fewer register accesses.
Tested on CN5020, CN6120 and CN7130.
Diffstat (limited to 'sys/arch/octeon')
-rw-r--r-- | sys/arch/octeon/dev/cn30xxgmx.c | 137 | ||||
-rw-r--r-- | sys/arch/octeon/dev/cn30xxgmxreg.h | 9 | ||||
-rw-r--r-- | sys/arch/octeon/dev/cn30xxgmxvar.h | 4 | ||||
-rw-r--r-- | sys/arch/octeon/dev/if_cnmac.c | 11 |
4 files changed, 47 insertions, 114 deletions
diff --git a/sys/arch/octeon/dev/cn30xxgmx.c b/sys/arch/octeon/dev/cn30xxgmx.c index f27b180e493..9b601c97abf 100644 --- a/sys/arch/octeon/dev/cn30xxgmx.c +++ b/sys/arch/octeon/dev/cn30xxgmx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cn30xxgmx.c,v 1.49 2021/02/04 16:16:10 visa Exp $ */ +/* $OpenBSD: cn30xxgmx.c,v 1.50 2021/02/13 17:12:38 visa Exp $ */ /* * Copyright (c) 2007 Internet Initiative Japan, Inc. @@ -47,22 +47,7 @@ #include <octeon/dev/cn30xxpipvar.h> #include <octeon/dev/cn30xxsmivar.h> -#define dprintf(...) -#define OCTEON_ETH_KASSERT KASSERT - -#define ADDR2UINT64(u, a) \ - do { \ - u = \ - (((uint64_t)a[0] << 40) | ((uint64_t)a[1] << 32) | \ - ((uint64_t)a[2] << 24) | ((uint64_t)a[3] << 16) | \ - ((uint64_t)a[4] << 8) | ((uint64_t)a[5] << 0)); \ - } while (0) -#define UINT642ADDR(a, u) \ - do { \ - a[0] = (uint8_t)((u) >> 40); a[1] = (uint8_t)((u) >> 32); \ - a[2] = (uint8_t)((u) >> 24); a[3] = (uint8_t)((u) >> 16); \ - a[4] = (uint8_t)((u) >> 8); a[5] = (uint8_t)((u) >> 0); \ - } while (0) +#define GMX_NCAM 8 #define _GMX_RD8(sc, off) \ bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_gmx->sc_regh, (off)) @@ -127,11 +112,6 @@ int cn30xxgmx_rgmii_speed_newlink_log(struct cn30xxgmx_port_softc *, uint64_t); #endif -static const int cn30xxgmx_rx_adr_cam_regs[] = { - GMX0_RX0_ADR_CAM0, GMX0_RX0_ADR_CAM1, GMX0_RX0_ADR_CAM2, - GMX0_RX0_ADR_CAM3, GMX0_RX0_ADR_CAM4, GMX0_RX0_ADR_CAM5 -}; - struct cn30xxgmx_port_ops cn30xxgmx_port_ops_agl = { .port_ops_enable = cn30xxgmx_agl_enable, .port_ops_speed = cn30xxgmx_agl_speed, @@ -643,42 +623,17 @@ cn30xxgmx_tx_thresh(struct cn30xxgmx_port_softc *sc, int cnt) } int -cn30xxgmx_set_mac_addr(struct cn30xxgmx_port_softc *sc, uint8_t *addr) -{ - uint64_t mac; - int i; - - ADDR2UINT64(mac, addr); - - cn30xxgmx_link_enable(sc, 0); - - sc->sc_mac = mac; - _GMX_PORT_WR8(sc, GMX0_SMAC0, mac); - for (i = 0; i < 6; i++) - _GMX_PORT_WR8(sc, cn30xxgmx_rx_adr_cam_regs[i], addr[i]); - - cn30xxgmx_link_enable(sc, 1); - - return 0; -} - -int cn30xxgmx_set_filter(struct cn30xxgmx_port_softc *sc) { struct ifnet *ifp = &sc->sc_port_ac->ac_if; struct arpcom *ac = sc->sc_port_ac; struct ether_multi *enm; struct ether_multistep step; - uint64_t cam_en = 0x01ULL; + uint64_t cam[ETHER_ADDR_LEN]; + uint64_t cam_en = 0; uint64_t ctl = 0; - int multi = 0; - - cn30xxgmx_link_enable(sc, 0); - - SET(ctl, RXN_ADR_CTL_CAM_MODE); - CLR(ctl, RXN_ADR_CTL_MCST_ACCEPT | RXN_ADR_CTL_MCST_AFCAM | - RXN_ADR_CTL_MCST_REJECT); - CLR(ifp->if_flags, IFF_ALLMULTI); + uint64_t mac; + int i, cidx; /* * Always accept broadcast frames. @@ -687,63 +642,53 @@ cn30xxgmx_set_filter(struct cn30xxgmx_port_softc *sc) if (ISSET(ifp->if_flags, IFF_PROMISC)) { SET(ifp->if_flags, IFF_ALLMULTI); - CLR(ctl, RXN_ADR_CTL_CAM_MODE); SET(ctl, RXN_ADR_CTL_MCST_ACCEPT); - cam_en = 0x00ULL; - } else if (ac->ac_multirangecnt > 0 || ac->ac_multicnt > 7) { + } else if (ac->ac_multirangecnt > 0 || ac->ac_multicnt >= GMX_NCAM) { SET(ifp->if_flags, IFF_ALLMULTI); + SET(ctl, RXN_ADR_CTL_CAM_MODE); SET(ctl, RXN_ADR_CTL_MCST_ACCEPT); } else { - /* - * Note first entry is self MAC address; other 7 entires are - * available for multicast addresses. - */ - ETHER_FIRST_MULTI(step, sc->sc_port_ac, enm); - while (enm != NULL) { - int i; - - dprintf("%d: %02x:%02x:%02x:%02x:%02x:%02x\n" - multi + 1, - enm->enm_addrlo[0], enm->enm_addrlo[1], - enm->enm_addrlo[2], enm->enm_addrlo[3], - enm->enm_addrlo[4], enm->enm_addrlo[5]); - multi++; - - SET(cam_en, 1ULL << multi); /* XXX */ - - for (i = 0; i < 6; i++) { - uint64_t tmp; - - /* XXX */ - tmp = _GMX_PORT_RD8(sc, - cn30xxgmx_rx_adr_cam_regs[i]); - CLR(tmp, 0xffULL << (8 * multi)); - SET(tmp, (uint64_t)enm->enm_addrlo[i] << - (8 * multi)); - _GMX_PORT_WR8(sc, cn30xxgmx_rx_adr_cam_regs[i], - tmp); - } + CLR(ifp->if_flags, IFF_ALLMULTI); + SET(ctl, RXN_ADR_CTL_CAM_MODE); + SET(ctl, RXN_ADR_CTL_MCST_AFCAM); + } - for (i = 0; i < 6; i++) - dprintf("cam%d = %016llx\n", i, - _GMX_PORT_RD8(sc, - cn30xxgmx_rx_adr_cam_regs[i])); + mac = 0; + for (i = 0; i < ETHER_ADDR_LEN; i++) + mac |= (uint64_t)ac->ac_enaddr[i] << + ((ETHER_ADDR_LEN - 1 - i) * 8); + /* + * The first CAM entry is used for the local unicast MAC. + * The remaining entries are used for multicast MACs. + */ + memset(cam, 0, sizeof(cam)); + cidx = 0; + if (!ISSET(ifp->if_flags, IFF_PROMISC)) { + for (i = 0; i < ETHER_ADDR_LEN; i++) + cam[i] |= (uint64_t)ac->ac_enaddr[i] << (cidx * 8); + cam_en |= 1U << cidx; + cidx++; + } + if (!ISSET(ifp->if_flags, IFF_ALLMULTI)) { + ETHER_FIRST_MULTI(step, ac, enm); + while (enm != NULL && cidx < GMX_NCAM) { + for (i = 0; i < ETHER_ADDR_LEN; i++) + cam[i] |= (uint64_t)enm->enm_addrlo[i] << + (cidx * 8); + cam_en |= 1U << cidx; + cidx++; ETHER_NEXT_MULTI(step, enm); } - - if (multi) - SET(ctl, RXN_ADR_CTL_MCST_AFCAM); - else - SET(ctl, RXN_ADR_CTL_MCST_REJECT); - - OCTEON_ETH_KASSERT(enm == NULL); } - dprintf("ctl = %llx, cam_en = %llx\n", ctl, cam_en); + cn30xxgmx_link_enable(sc, 0); + _GMX_PORT_WR8(sc, GMX0_SMAC0, mac); _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, ctl); + for (i = 0; i < ETHER_ADDR_LEN; i++) + _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM(i), cam[i]); _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, cam_en); - + (void)_GMX_PORT_RD8(sc, GMX0_RX0_ADR_CAM_EN); cn30xxgmx_link_enable(sc, 1); return 0; diff --git a/sys/arch/octeon/dev/cn30xxgmxreg.h b/sys/arch/octeon/dev/cn30xxgmxreg.h index c601a40aba9..55edb362112 100644 --- a/sys/arch/octeon/dev/cn30xxgmxreg.h +++ b/sys/arch/octeon/dev/cn30xxgmxreg.h @@ -3,7 +3,7 @@ * DONT EDIT THIS FILE */ -/* $OpenBSD: cn30xxgmxreg.h,v 1.7 2020/09/08 13:54:48 visa Exp $ */ +/* $OpenBSD: cn30xxgmxreg.h,v 1.8 2021/02/13 17:12:38 visa Exp $ */ /* * Copyright (c) 2007 Internet Initiative Japan, Inc. @@ -64,12 +64,7 @@ #define GMX0_RX0_STATS_PKTS_BAD 0x0c0 #define GMX0_RX0_ADR_CTL 0x100 #define GMX0_RX0_ADR_CAM_EN 0x108 -#define GMX0_RX0_ADR_CAM0 0x180 -#define GMX0_RX0_ADR_CAM1 0x188 -#define GMX0_RX0_ADR_CAM2 0x190 -#define GMX0_RX0_ADR_CAM3 0x198 -#define GMX0_RX0_ADR_CAM4 0x1a0 -#define GMX0_RX0_ADR_CAM5 0x1a8 +#define GMX0_RX0_ADR_CAM(i) (0x180 + (i) * 8) #define GMX0_TX0_CLK 0x208 #define GMX0_TX0_THRESH 0x210 #define GMX0_TX0_APPEND 0x218 diff --git a/sys/arch/octeon/dev/cn30xxgmxvar.h b/sys/arch/octeon/dev/cn30xxgmxvar.h index 066ba8b2347..1368b5bf14c 100644 --- a/sys/arch/octeon/dev/cn30xxgmxvar.h +++ b/sys/arch/octeon/dev/cn30xxgmxvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cn30xxgmxvar.h,v 1.11 2020/09/08 13:54:48 visa Exp $ */ +/* $OpenBSD: cn30xxgmxvar.h,v 1.12 2021/02/13 17:12:38 visa Exp $ */ /* * Copyright (c) 2007 Internet Initiative Japan, Inc. @@ -61,7 +61,6 @@ struct cn30xxgmx_port_softc { bus_space_handle_t sc_port_regh; int sc_port_no; /* GMX0:0, GMX0:1, ... */ int sc_port_type; - uint64_t sc_mac; uint64_t sc_link; struct mii_data *sc_port_mii; struct arpcom *sc_port_ac; @@ -111,7 +110,6 @@ int cn30xxgmx_rx_frm_ctl_enable(struct cn30xxgmx_port_softc *, int cn30xxgmx_rx_frm_ctl_disable(struct cn30xxgmx_port_softc *, uint64_t rx_frm_ctl); int cn30xxgmx_tx_thresh(struct cn30xxgmx_port_softc *, int); -int cn30xxgmx_set_mac_addr(struct cn30xxgmx_port_softc *, uint8_t *); int cn30xxgmx_set_filter(struct cn30xxgmx_port_softc *); int cn30xxgmx_port_enable(struct cn30xxgmx_port_softc *, int); int cn30xxgmx_reset_speed(struct cn30xxgmx_port_softc *); diff --git a/sys/arch/octeon/dev/if_cnmac.c b/sys/arch/octeon/dev/if_cnmac.c index c3f20ff5f09..ebb341f5948 100644 --- a/sys/arch/octeon/dev/if_cnmac.c +++ b/sys/arch/octeon/dev/if_cnmac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_cnmac.c,v 1.80 2020/12/12 11:48:52 jan Exp $ */ +/* $OpenBSD: if_cnmac.c,v 1.81 2021/02/13 17:12:38 visa Exp $ */ /* * Copyright (c) 2007 Internet Initiative Japan, Inc. @@ -247,7 +247,6 @@ cnmac_attach(struct device *parent, struct device *self, void *aux) struct cnmac_softc *sc = (void *)self; struct cn30xxgmx_attach_args *ga = aux; struct ifnet *ifp = &sc->sc_arpcom.ac_if; - uint8_t enaddr[ETHER_ADDR_LEN]; if (cnmac_npowgroups >= OCTEON_POW_GROUP_MAX) { printf(": out of POW groups\n"); @@ -275,8 +274,8 @@ cnmac_attach(struct device *parent, struct device *self, void *aux) */ sc->sc_ip_offset = 0/* XXX */; - cnmac_board_mac_addr(enaddr); - printf(", address %s\n", ether_sprintf(enaddr)); + cnmac_board_mac_addr(sc->sc_arpcom.ac_enaddr); + printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); ml_init(&sc->sc_sendq); sc->sc_soft_req_thresh = 15/* XXX */; @@ -319,12 +318,9 @@ cnmac_attach(struct device *parent, struct device *self, void *aux) ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4 | IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6; - cn30xxgmx_set_mac_addr(sc->sc_gmx_port, enaddr); cn30xxgmx_set_filter(sc->sc_gmx_port); if_attach(ifp); - - memcpy(sc->sc_arpcom.ac_enaddr, enaddr, ETHER_ADDR_LEN); ether_ifattach(ifp); cnmac_buf_init(sc); @@ -1011,7 +1007,6 @@ cnmac_init(struct ifnet *ifp) cn30xxpip_stats_init(sc->sc_pip); cn30xxgmx_stats_init(sc->sc_gmx_port); - cn30xxgmx_set_mac_addr(sc->sc_gmx_port, sc->sc_arpcom.ac_enaddr); cn30xxgmx_set_filter(sc->sc_gmx_port); timeout_add_sec(&sc->sc_tick_misc_ch, 1); |