diff options
author | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2011-07-03 20:31:40 +0000 |
---|---|---|
committer | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2011-07-03 20:31:40 +0000 |
commit | 9ca6eb5115fc227d8d888c56c59719e162247afb (patch) | |
tree | 9b0c2991ec898f13dbb9ce4f86ffe1024d575a57 /sys | |
parent | e4e3506a29df5f8cae5c404f90b5cb069804c321 (diff) |
Rewrite the multicast handling for OpenBSD. From brad@
ok and tested yasuoka@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/octeon/dev/cn30xxgmx.c | 150 |
1 files changed, 64 insertions, 86 deletions
diff --git a/sys/arch/octeon/dev/cn30xxgmx.c b/sys/arch/octeon/dev/cn30xxgmx.c index 590425712f9..550133dadde 100644 --- a/sys/arch/octeon/dev/cn30xxgmx.c +++ b/sys/arch/octeon/dev/cn30xxgmx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cn30xxgmx.c,v 1.2 2011/06/24 02:13:23 yasuoka Exp $ */ +/* $OpenBSD: cn30xxgmx.c,v 1.3 2011/07/03 20:31:39 yasuoka Exp $ */ /* * Copyright (c) 2007 Internet Initiative Japan, Inc. @@ -1042,111 +1042,89 @@ static int cn30xxgmx_rgmii_set_filter(struct cn30xxgmx_port_softc *sc) { struct ifnet *ifp = &sc->sc_port_ac->ac_if; + struct arpcom *ac = sc->sc_port_ac; #ifdef OCTEON_ETH_USE_GMX_CAM struct ether_multi *enm; struct ether_multistep step; #endif + uint64_t cam_en = 0x01ULL; uint64_t ctl = 0; int multi = 0; - uint64_t cam_en = 0x01ULL; /* XXX */ cn30xxgmx_link_enable(sc, 0); - if (ISSET(ifp->if_flags, IFF_BROADCAST)) { - dprintf("accept broadcast\n"); - SET(ctl, RXN_ADR_CTL_BCST); - } + 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); + + /* + * Always accept broadcast frames. + */ + SET(ctl, RXN_ADR_CTL_BCST); + if (ISSET(ifp->if_flags, IFF_PROMISC)) { - dprintf("promiscas(reject cam)\n"); + 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) { + SET(ifp->if_flags, IFF_ALLMULTI); + SET(ctl, RXN_ADR_CTL_MCST_ACCEPT); } else { - dprintf("not promiscas(accept cam)\n"); - SET(ctl, RXN_ADR_CTL_CAM_MODE); - } - #ifdef OCTEON_ETH_USE_GMX_CAM - /* - * Note first entry is self MAC address; other 7 entires are available - * for multicast addresses. - */ + /* + * 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: lo(%02x:%02x:%02x:%02x:%02x:%02x) - " + "hi(%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], + enm->enm_addrhi[0], enm->enm_addrhi[1], + enm->enm_addrhi[2], enm->enm_addrhi[3], + enm->enm_addrhi[4], enm->enm_addrhi[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); + } - ETHER_FIRST_MULTI(step, sc->sc_port_ac, enm); - while (enm != NULL) { - int i; - - dprintf("%d: lo(%02x:%02x:%02x:%02x:%02x:%02x) - " - "hi(%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], - enm->enm_addrhi[0], enm->enm_addrhi[1], - enm->enm_addrhi[2], enm->enm_addrhi[3], - enm->enm_addrhi[4], enm->enm_addrhi[5]); - if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { - dprintf("all multicast\n"); - SET(ifp->if_flags, IFF_ALLMULTI); - goto setmulti; - } - multi++; + for (i = 0; i < 6; i++) + dprintf("cam%d = %016llx\n", i, + _GMX_PORT_RD8(sc, cn30xxgmx_rx_adr_cam_regs[i])); - /* XXX */ - if (multi >= 8) { - SET(ifp->if_flags, IFF_ALLMULTI); - goto setmulti; + ETHER_NEXT_MULTI(step, enm); } - 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); - - } - for (i = 0; i < 6; i++) - dprintf("cam%d = %016llx\n", i, - _GMX_PORT_RD8(sc, cn30xxgmx_rx_adr_cam_regs[i])); - ETHER_NEXT_MULTI(step, enm); - } - CLR(ifp->if_flags, IFF_ALLMULTI); + if (multi) + SET(ctl, RXN_ADR_CTL_MCST_AFCAM); + else + SET(ctl, RXN_ADR_CTL_MCST_REJECT); - OCTEON_ETH_KASSERT(enm == NULL); + OCTEON_ETH_KASSERT(enm == NULL); #else - /* - * XXX - * Never use DMAC filter for multicast addresses, but register only - * single entry for self address. FreeBSD code do so. - */ - SET(ifp->if_flags, IFF_ALLMULTI); - goto setmulti; -#endif - -setmulti: - if (ISSET(ifp->if_flags, IFF_ALLMULTI) || - ISSET(ifp->if_flags, IFF_PROMISC)) { - /* XXX */ - dprintf("accept all multicast\n"); + /* + * XXX + * Never use DMAC filter for multicast addresses, but register only + * single entry for self address. FreeBSD code do so. + */ + SET(ifp->if_flags, IFF_ALLMULTI); SET(ctl, RXN_ADR_CTL_MCST_ACCEPT); - } else if (multi) { - /* XXX */ - dprintf("use cam\n"); - SET(ctl, RXN_ADR_CTL_MCST_AFCAM); - } else { - /* XXX */ - dprintf("reject all multicast\n"); - SET(ctl, RXN_ADR_CTL_MCST_REJECT); - } - - /* XXX */ - if (ISSET(ifp->if_flags, IFF_PROMISC)) { - cam_en = 0x00ULL; - } else if (ISSET(ifp->if_flags, IFF_ALLMULTI)) { - cam_en = 0x01ULL; +#endif } dprintf("ctl = %llx, cam_en = %llx\n", ctl, cam_en); |