summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjmcneill <jmcneill@FreeBSD.org>2016-06-12 22:55:50 +0000
committerjmcneill <jmcneill@FreeBSD.org>2016-06-12 22:55:50 +0000
commit83b176045cd0be35522afc4c6ac8a114bee4c924 (patch)
tree8d7e9916011e617fcd5b498eab61f00fdb37e29e
parent480f64e0481af9d3d82f2e2db4c4bd08105333dd (diff)
downloadFreeBSD-src-83b176045cd0be35522afc4c6ac8a114bee4c924.zip
FreeBSD-src-83b176045cd0be35522afc4c6ac8a114bee4c924.tar.gz
Fix an issue with multicast hash filters on Amlogic and Allwinner boards.
For DWC_GMAC_ALT_DESC implementations, the multicast hash table has only 64 entries. Instead of 8 registers starting at 0x500, a pair of registers at 0x08 and 0x0c are used instead. Approved by: re (hrs) Submitted by: Guy Yur <guyyur@gmail.com>
-rw-r--r--sys/dev/dwc/if_dwc.c19
-rw-r--r--sys/dev/dwc/if_dwc.h2
2 files changed, 13 insertions, 8 deletions
diff --git a/sys/dev/dwc/if_dwc.c b/sys/dev/dwc/if_dwc.c
index d7a38a0..a34879b 100644
--- a/sys/dev/dwc/if_dwc.c
+++ b/sys/dev/dwc/if_dwc.c
@@ -587,14 +587,13 @@ dwc_setup_rxfilter(struct dwc_softc *sc)
struct ifmultiaddr *ifma;
struct ifnet *ifp;
uint8_t *eaddr, val;
- uint32_t crc, ffval, hashbit, hashreg, hi, lo, hash[8], hmask;
+ uint32_t crc, ffval, hashbit, hashreg, hi, lo, hash[8];
int nhash, i;
DWC_ASSERT_LOCKED(sc);
ifp = sc->ifp;
nhash = sc->mactype == DWC_GMAC_ALT_DESC ? 2 : 8;
- hmask = ((nhash << 5) - 1) | 0xf;
/*
* Set the multicast (group) filter hash.
@@ -615,11 +614,10 @@ dwc_setup_rxfilter(struct dwc_softc *sc)
ifma->ifma_addr), ETHER_ADDR_LEN);
/* Take lower 8 bits and reverse it */
- val = bitreverse(~crc & 0xff) & hmask;
+ val = bitreverse(~crc & 0xff);
if (sc->mactype == DWC_GMAC_ALT_DESC)
- hashreg = (val >> 5) == 0;
- else
- hashreg = (val >> 5);
+ val >>= nhash; /* Only need lower 6 bits */
+ hashreg = (val >> 5);
hashbit = (val & 31);
hash[hashreg] |= (1 << hashbit);
}
@@ -642,8 +640,13 @@ dwc_setup_rxfilter(struct dwc_softc *sc)
WRITE4(sc, MAC_ADDRESS_LOW(0), lo);
WRITE4(sc, MAC_ADDRESS_HIGH(0), hi);
WRITE4(sc, MAC_FRAME_FILTER, ffval);
- for (i = 0; i < nhash; i++)
- WRITE4(sc, HASH_TABLE_REG(i), hash[i]);
+ if (sc->mactype == DWC_GMAC_ALT_DESC) {
+ WRITE4(sc, GMAC_MAC_HTLOW, hash[0]);
+ WRITE4(sc, GMAC_MAC_HTHIGH, hash[1]);
+ } else {
+ for (i = 0; i < nhash; i++)
+ WRITE4(sc, HASH_TABLE_REG(i), hash[i]);
+ }
}
static int
diff --git a/sys/dev/dwc/if_dwc.h b/sys/dev/dwc/if_dwc.h
index c9403da..d88ca0d 100644
--- a/sys/dev/dwc/if_dwc.h
+++ b/sys/dev/dwc/if_dwc.h
@@ -53,6 +53,8 @@
#define FRAME_FILTER_HMC (1 << 2)
#define FRAME_FILTER_HUC (1 << 1)
#define FRAME_FILTER_PR (1 << 0) /* All Incoming Frames */
+#define GMAC_MAC_HTHIGH 0x08
+#define GMAC_MAC_HTLOW 0x0c
#define GMII_ADDRESS 0x10
#define GMII_ADDRESS_PA_MASK 0x1f /* Phy device */
#define GMII_ADDRESS_PA_SHIFT 11
OpenPOWER on IntegriCloud