diff options
author | yongari <yongari@FreeBSD.org> | 2010-04-29 17:28:07 +0000 |
---|---|---|
committer | yongari <yongari@FreeBSD.org> | 2010-04-29 17:28:07 +0000 |
commit | a246ed9355e08cb824a3c0a02a16db772c33a915 (patch) | |
tree | ce30258b1b237040fbc31ec1aa9d108631a896c7 /sys/dev/sge/if_sge.c | |
parent | a05508f205782767efaaf7a6043901b3e1a3056d (diff) | |
download | FreeBSD-src-a246ed9355e08cb824a3c0a02a16db772c33a915.zip FreeBSD-src-a246ed9355e08cb824a3c0a02a16db772c33a915.tar.gz |
Preserve unknown bits of RX MAC control register when driver
programs RX filter configuration. It seems RX MAC control register
is one of key registers to get various offloading features as well
as performance. Blindly clearing unrelated bits can result in
unexpected results.
Tested by: xclin <xclin <> cs dot nctu dot edu dot tw >
Diffstat (limited to 'sys/dev/sge/if_sge.c')
-rw-r--r-- | sys/dev/sge/if_sge.c | 31 |
1 files changed, 16 insertions, 15 deletions
diff --git a/sys/dev/sge/if_sge.c b/sys/dev/sge/if_sge.c index 6c737bd..49f6c0e 100644 --- a/sys/dev/sge/if_sge.c +++ b/sys/dev/sge/if_sge.c @@ -453,8 +453,9 @@ sge_rxfilter(struct sge_softc *sc) SGE_LOCK_ASSERT(sc); ifp = sc->sge_ifp; - hashes[0] = hashes[1] = 0; - rxfilt = AcceptMyPhys; + rxfilt = CSR_READ_2(sc, RxMacControl); + rxfilt &= ~(AcceptBroadcast | AcceptAllPhys | AcceptMulticast); + rxfilt |= AcceptMyPhys; if ((ifp->if_flags & IFF_BROADCAST) != 0) rxfilt |= AcceptBroadcast; if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { @@ -463,20 +464,20 @@ sge_rxfilter(struct sge_softc *sc) rxfilt |= AcceptMulticast; hashes[0] = 0xFFFFFFFF; hashes[1] = 0xFFFFFFFF; - goto done; - } - rxfilt |= AcceptMulticast; - /* Now program new ones. */ - if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - crc = ether_crc32_be(LLADDR((struct sockaddr_dl *) - ifma->ifma_addr), ETHER_ADDR_LEN); - hashes[crc >> 31] |= 1 << ((crc >> 26) & 0x1f); + } else { + rxfilt |= AcceptMulticast; + hashes[0] = hashes[1] = 0; + /* Now program new ones. */ + if_maddr_rlock(ifp); + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + crc = ether_crc32_be(LLADDR((struct sockaddr_dl *) + ifma->ifma_addr), ETHER_ADDR_LEN); + hashes[crc >> 31] |= 1 << ((crc >> 26) & 0x1f); + } + if_maddr_runlock(ifp); } - if_maddr_runlock(ifp); -done: CSR_WRITE_2(sc, RxMacControl, rxfilt | 0x02); CSR_WRITE_4(sc, RxHashTable, hashes[0]); CSR_WRITE_4(sc, RxHashTable2, hashes[1]); |