diff options
-rw-r--r-- | sys/dev/pci/if_bge.c | 92 |
1 files changed, 29 insertions, 63 deletions
diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c index b5cddb3080f..884b4516c8f 100644 --- a/sys/dev/pci/if_bge.c +++ b/sys/dev/pci/if_bge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bge.c,v 1.212 2007/05/03 10:11:25 tom Exp $ */ +/* $OpenBSD: if_bge.c,v 1.213 2007/06/21 01:11:50 dlg Exp $ */ /* * Copyright (c) 2001 Wind River Systems @@ -157,8 +157,7 @@ void bge_ifmedia_sts(struct ifnet *, struct ifmediareq *); u_int8_t bge_eeprom_getbyte(struct bge_softc *, int, u_int8_t *); int bge_read_eeprom(struct bge_softc *, caddr_t, int, int); -void bge_setmulti(struct bge_softc *); -void bge_setpromisc(struct bge_softc *); +void bge_iff(struct bge_softc *); int bge_alloc_jumbo_mem(struct bge_softc *); void *bge_jalloc(struct bge_softc *); @@ -1061,52 +1060,38 @@ bge_init_tx_ring(struct bge_softc *sc) } void -bge_setmulti(struct bge_softc *sc) +bge_iff(struct bge_softc *sc) { struct arpcom *ac = &sc->arpcom; struct ifnet *ifp = &ac->ac_if; struct ether_multi *enm; struct ether_multistep step; - u_int32_t hashes[4] = { 0, 0, 0, 0 }; - u_int32_t h; - int i; + u_int8_t hashes[16]; + u_int32_t h, rxmode; /* First, zot all the existing filters. */ - for (i = 0; i < 4; i++) - CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0); - - /* Now program new ones. */ - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { -allmulti: - for (i = 0; i < 4; i++) - CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0xFFFFFFFF); - return; - } + rxmode = CSR_READ_4(sc, BGE_RX_MODE) & ~BGE_RXMODE_RX_PROMISC; + ifp->if_flags &= ~IFF_ALLMULTI; + memset(hashes, 0x00, sizeof(hashes)); - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { - if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { - ifp->if_flags |= IFF_ALLMULTI; - goto allmulti; + if (ifp->if_flags & IFF_PROMISC) + rxmode |= BGE_RXMODE_RX_PROMISC; + else if (ac->ac_multirangecnt > 0) { + ifp->if_flags |= IFF_ALLMULTI; + memset(hashes, 0xff, sizeof(hashes)); + } else { + ETHER_FIRST_MULTI(step, ac, enm); + while (enm != NULL) { + h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN); + setbit(hashes, h & 0x7F); + ETHER_NEXT_MULTI(step, enm); } - h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) & 0x7F; - hashes[(h & 0x60) >> 5] |= 1 << (h & 0x1F); - ETHER_NEXT_MULTI(step, enm); } - for (i = 0; i < 4; i++) - CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), hashes[i]); -} - -void -bge_setpromisc(struct bge_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; + bus_space_write_raw_region_4(sc->bge_btag, sc->bge_bhandle, BGE_MAR0, + hashes, sizeof(hashes)); - if (ifp->if_flags & IFF_PROMISC) - BGE_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC); - else - BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC); + CSR_WRITE_4(sc, BGE_RX_MODE, rxmode); } /* @@ -2956,14 +2941,11 @@ bge_init(void *xsc) CSR_WRITE_4(sc, BGE_MAC_ADDR1_LO, htons(m[0])); CSR_WRITE_4(sc, BGE_MAC_ADDR1_HI, (htons(m[1]) << 16) | htons(m[2])); - /* Enable or disable promiscuous mode as needed. */ - bge_setpromisc(sc); - /* Disable hardware decapsulation of vlan frames. */ BGE_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_KEEP_VLAN_DIAG); - /* Program multicast filter. */ - bge_setmulti(sc); + /* Program promiscuous mode and multicast filters. */ + bge_iff(sc); /* Init RX ring. */ bge_init_rx_ring_std(sc); @@ -3150,26 +3132,10 @@ bge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) break; case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { - /* - * If only the state of the PROMISC flag changed, - * then just use the 'set promisc mode' command - * instead of reinitializing the entire NIC. Doing - * a full re-init means reloading the firmware and - * waiting for it to start up, which may take a - * second or two. Similarly for ALLMULTI. - */ - if (ifp->if_flags & IFF_RUNNING && - ((ifp->if_flags ^ sc->bge_if_flags) & - IFF_PROMISC)) { - bge_setpromisc(sc); - bge_setmulti(sc); - } else if (ifp->if_flags & IFF_RUNNING && - (ifp->if_flags ^ sc->bge_if_flags) & IFF_ALLMULTI) { - bge_setmulti(sc); - } else { - if (!(ifp->if_flags & IFF_RUNNING)) - bge_init(sc); - } + if (ifp->if_flags & IFF_RUNNING) + bge_iff(sc); + else + bge_init(sc); } else { if (ifp->if_flags & IFF_RUNNING) bge_stop(sc); @@ -3184,7 +3150,7 @@ bge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) if (error == ENETRESET) { if (ifp->if_flags & IFF_RUNNING) - bge_setmulti(sc); + bge_iff(sc); error = 0; } break; |