Multicast filters on DWC_GMAC_ALT_DESC type implementations use a different

hash register setup. In addition, strip trailing FCS in receive path.

Reviewed by:		loos
Differential Revision:	https://reviews.freebsd.org/D6653
This commit is contained in:
jmcneill 2016-06-08 20:22:25 +00:00
parent ee466067e5
commit 53a6d64e30

View File

@ -587,19 +587,26 @@ dwc_setup_rxfilter(struct dwc_softc *sc)
struct ifmultiaddr *ifma; struct ifmultiaddr *ifma;
struct ifnet *ifp; struct ifnet *ifp;
uint8_t *eaddr, val; uint8_t *eaddr, val;
uint32_t crc, ffval, hashbit, hashreg, hi, lo, reg; uint32_t crc, ffval, hashbit, hashreg, hi, lo, hash[8], hmask;
int nhash, i;
DWC_ASSERT_LOCKED(sc); DWC_ASSERT_LOCKED(sc);
ifp = sc->ifp; ifp = sc->ifp;
nhash = sc->mactype == DWC_GMAC_ALT_DESC ? 2 : 8;
hmask = ((nhash << 5) - 1) | 0xf;
/* /*
* Set the multicast (group) filter hash. * Set the multicast (group) filter hash.
*/ */
if ((ifp->if_flags & IFF_ALLMULTI)) if ((ifp->if_flags & IFF_ALLMULTI) != 0) {
ffval = (FRAME_FILTER_PM); ffval = (FRAME_FILTER_PM);
else { for (i = 0; i < nhash; i++)
hash[i] = ~0;
} else {
ffval = (FRAME_FILTER_HMC); ffval = (FRAME_FILTER_HMC);
for (i = 0; i < nhash; i++)
hash[i] = 0;
if_maddr_rlock(ifp); if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) { TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK) if (ifma->ifma_addr->sa_family != AF_LINK)
@ -608,13 +615,13 @@ dwc_setup_rxfilter(struct dwc_softc *sc)
ifma->ifma_addr), ETHER_ADDR_LEN); ifma->ifma_addr), ETHER_ADDR_LEN);
/* Take lower 8 bits and reverse it */ /* Take lower 8 bits and reverse it */
val = bitreverse(~crc & 0xff); val = bitreverse(~crc & 0xff) & hmask;
hashreg = (val >> 5); if (sc->mactype == DWC_GMAC_ALT_DESC)
hashreg = (val >> 5) == 0;
else
hashreg = (val >> 5);
hashbit = (val & 31); hashbit = (val & 31);
hash[hashreg] |= (1 << hashbit);
reg = READ4(sc, HASH_TABLE_REG(hashreg));
reg |= (1 << hashbit);
WRITE4(sc, HASH_TABLE_REG(hashreg), reg);
} }
if_maddr_runlock(ifp); if_maddr_runlock(ifp);
} }
@ -635,6 +642,8 @@ dwc_setup_rxfilter(struct dwc_softc *sc)
WRITE4(sc, MAC_ADDRESS_LOW(0), lo); WRITE4(sc, MAC_ADDRESS_LOW(0), lo);
WRITE4(sc, MAC_ADDRESS_HIGH(0), hi); WRITE4(sc, MAC_ADDRESS_HIGH(0), hi);
WRITE4(sc, MAC_FRAME_FILTER, ffval); WRITE4(sc, MAC_FRAME_FILTER, ffval);
for (i = 0; i < nhash; i++)
WRITE4(sc, HASH_TABLE_REG(i), hash[i]);
} }
static int static int
@ -759,6 +768,9 @@ dwc_rxfinish_locked(struct dwc_softc *sc)
m->m_len = len; m->m_len = len;
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
/* Remove trailing FCS */
m_adj(m, -ETHER_CRC_LEN);
DWC_UNLOCK(sc); DWC_UNLOCK(sc);
(*ifp->if_input)(ifp, m); (*ifp->if_input)(ifp, m);
DWC_LOCK(sc); DWC_LOCK(sc);