summaryrefslogtreecommitdiffstats
path: root/sys/dev/sge
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2010-04-29 17:28:07 +0000
committeryongari <yongari@FreeBSD.org>2010-04-29 17:28:07 +0000
commita246ed9355e08cb824a3c0a02a16db772c33a915 (patch)
treece30258b1b237040fbc31ec1aa9d108631a896c7 /sys/dev/sge
parenta05508f205782767efaaf7a6043901b3e1a3056d (diff)
downloadFreeBSD-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')
-rw-r--r--sys/dev/sge/if_sge.c31
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]);
OpenPOWER on IntegriCloud