diff options
| author | tsutsui <tsutsui@NetBSD.org> | 2007-02-10 03:58:32 +0000 |
|---|---|---|
| committer | tsutsui <tsutsui@NetBSD.org> | 2007-02-10 03:58:32 +0000 |
| commit | 83a47fa60448fda3c90263a805d6f9ae65c28164 (patch) | |
| tree | 13a5df96ae0a4c7b82a1e65afcfa797bcc163d4f /sys/dev | |
| parent | b184e0b11b8497e274b7a97e64fe4c62f0f4b288 (diff) | |
Pull a multicast fix from FreeBSD's if_re.c rev 1.81:
Fix rtk_setmulti() so that it works correctly for PCIe chips where
the multicast hash table are in reverse order compared to older
devices.
Closes PR kern/35579 from Nino Dehne.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/ic/rtl81x9.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/sys/dev/ic/rtl81x9.c b/sys/dev/ic/rtl81x9.c index 329c26bfadd..7c9bccc2530 100644 --- a/sys/dev/ic/rtl81x9.c +++ b/sys/dev/ic/rtl81x9.c @@ -1,4 +1,4 @@ -/* $NetBSD: rtl81x9.c,v 1.68 2007/02/04 06:01:30 tsutsui Exp $ */ +/* $NetBSD: rtl81x9.c,v 1.69 2007/02/10 03:58:32 tsutsui Exp $ */ /* * Copyright (c) 1997, 1998 @@ -86,7 +86,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rtl81x9.c,v 1.68 2007/02/04 06:01:30 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rtl81x9.c,v 1.69 2007/02/10 03:58:32 tsutsui Exp $"); #include "bpfilter.h" #include "rnd.h" @@ -539,7 +539,7 @@ rtk_setmulti(struct rtk_softc *sc) { struct ifnet *ifp; uint32_t hashes[2] = { 0, 0 }; - uint32_t rxfilt; + uint32_t rxfilt, hwrev; struct ether_multi *enm; struct ether_multistep step; int h, mcnt; @@ -587,8 +587,22 @@ rtk_setmulti(struct rtk_softc *sc) rxfilt &= ~RTK_RXCFG_RX_MULTI; CSR_WRITE_4(sc, RTK_RXCFG, rxfilt); - CSR_WRITE_4(sc, RTK_MAR0, hashes[0]); - CSR_WRITE_4(sc, RTK_MAR4, hashes[1]); + + /* + * For some unfathomable reason, RealTek decided to reverse + * the order of the multicast hash registers in the PCI Express + * parts. This means we have to write the hash pattern in reverse + * order for those devices. + */ + hwrev = CSR_READ_4(sc, RTK_TXCFG) & RTK_TXCFG_HWREV; + if (hwrev == RTK_HWREV_8100E || hwrev == RTK_HWREV_8101E || + hwrev == RTK_HWREV_8168_SPIN1 || hwrev == RTK_HWREV_8168_SPIN2) { + CSR_WRITE_4(sc, RTK_MAR0, bswap32(hashes[1])); + CSR_WRITE_4(sc, RTK_MAR4, bswap32(hashes[0])); + } else { + CSR_WRITE_4(sc, RTK_MAR0, hashes[0]); + CSR_WRITE_4(sc, RTK_MAR4, hashes[1]); + } } void |
