summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authortsutsui <tsutsui@NetBSD.org>2007-02-10 03:58:32 +0000
committertsutsui <tsutsui@NetBSD.org>2007-02-10 03:58:32 +0000
commit83a47fa60448fda3c90263a805d6f9ae65c28164 (patch)
tree13a5df96ae0a4c7b82a1e65afcfa797bcc163d4f /sys/dev
parentb184e0b11b8497e274b7a97e64fe4c62f0f4b288 (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.c24
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