Here is a diff for the sf(4) Starfire driver to clean up and update the
receive filter / ioctl handling code to be in line with the other drivers.
Anyone with hw and able to test? OK?
Index: aic6915.c
===================================================================
RCS file: /home/cvs/src/sys/dev/ic/aic6915.c,v
retrieving revision 1.11
diff -u -p -r1.11 aic6915.c
--- aic6915.c 26 Nov 2013 09:50:32 -0000 1.11
+++ aic6915.c 1 Dec 2013 00:48:16 -0000
@@ -89,7 +89,7 @@ void sf_macreset(struct sf_softc *);
void sf_rxdrain(struct sf_softc *);
int sf_add_rxbuf(struct sf_softc *, int);
uint8_t sf_read_eeprom(struct sf_softc *, int);
-void sf_set_filter(struct sf_softc *);
+void sf_iff(struct sf_softc *);
int sf_mii_read(struct device *, int, int);
void sf_mii_write(struct device *, int, int, int);
@@ -532,19 +532,14 @@ sf_ioctl(struct ifnet *ifp, u_long cmd,
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
- if (ifp->if_flags & IFF_RUNNING &&
- ((ifp->if_flags ^ sc->sc_flags) &
- IFF_PROMISC)) {
- sf_set_filter(sc);
- } else {
- if (!(ifp->if_flags & IFF_RUNNING))
- sf_init(ifp);
- }
+ if (ifp->if_flags & IFF_RUNNING)
+ error = ENETRESET;
+ else
+ sf_init(ifp);
} else {
if (ifp->if_flags & IFF_RUNNING)
sf_stop(ifp, 1);
}
- sc->sc_flags = ifp->if_flags;
break;
case SIOCGIFMEDIA:
@@ -558,7 +553,7 @@ sf_ioctl(struct ifnet *ifp, u_long cmd,
if (error == ENETRESET) {
if (ifp->if_flags & IFF_RUNNING)
- sf_set_filter(sc);
+ sf_iff(sc);
error = 0;
}
@@ -1087,10 +1082,9 @@ sf_init(struct ifnet *ifp)
RDC_RxBurstSize(4)); /* default */
/*
- * Set the receive filter.
+ * Program promiscuous mode and multicast filters.
*/
- sc->sc_RxAddressFilteringCtl = 0;
- sf_set_filter(sc);
+ sf_iff(sc);
/*
* Set MacConfig1. When we set the media, MacConfig1 will
@@ -1293,85 +1287,65 @@ sf_set_filter_hash(struct sf_softc *sc,
}
/*
- * sf_set_filter:
+ * sf_iff:
*
* Set the Starfire receive filter.
*/
void
-sf_set_filter(struct sf_softc *sc)
+sf_iff(struct sf_softc *sc)
{
struct arpcom *ac = &sc->sc_arpcom;
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
struct ether_multi *enm;
struct ether_multistep step;
+ uint32_t filterctl;
int i;
- /* Start by clearing the perfect and hash tables. */
+ filterctl = sf_funcreg_read(sc, SF_RxAddressFilteringCtl);
+ filterctl &= ~(RAFC_PassBroadcast | RAFC_PromiscuousMode |
+ RAFC_PerfectFilteringMode(3) | RAFC_HashFilteringMode(3));
+ ifp->if_flags &= ~IFF_ALLMULTI;
+
+ /* Clear the perfect and hash tables. */
for (i = 0; i < SF_PERFECT_SIZE; i += sizeof(uint32_t))
sf_genreg_write(sc, SF_PERFECT_BASE + i, 0);
-
for (i = 0; i < SF_HASH_SIZE; i += sizeof(uint32_t))
sf_genreg_write(sc, SF_HASH_BASE + i, 0);
/*
- * Clear the perfect and hash mode bits.
- */
- sc->sc_RxAddressFilteringCtl &=
- ~(RAFC_PerfectFilteringMode(3) | RAFC_HashFilteringMode(3));
-
- if (ifp->if_flags & IFF_BROADCAST)
- sc->sc_RxAddressFilteringCtl |= RAFC_PassBroadcast;
- else
- sc->sc_RxAddressFilteringCtl &= ~RAFC_PassBroadcast;
-
- if (ifp->if_flags & IFF_PROMISC) {
- sc->sc_RxAddressFilteringCtl |= RAFC_PromiscuousMode;
- goto allmulti;
- } else
- sc->sc_RxAddressFilteringCtl &= ~RAFC_PromiscuousMode;
-
- /*
- * Set normal perfect filtering mode.
+ * Always accept broadcast frames.
*/
- sc->sc_RxAddressFilteringCtl |= RAFC_PerfectFilteringMode(1);
+ filterctl |= RAFC_PassBroadcast;
- /*
- * First, write the station address to the perfect filter
- * table.
- */
- sf_set_filter_perfect(sc, 0, LLADDR(ifp->if_sadl));
+ if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ filterctl |= RAFC_PassMulticast;
+ if (ifp->if_flags & IFF_PROMISC)
+ filterctl |= RAFC_PromiscuousMode;
+ } else {
+ /*
+ * Set "hash only multicast dest, match regardless of VLAN ID".
+ */
+ filterctl |= RAFC_HashFilteringMode(2);
- if (ac->ac_multirangecnt > 0)
- goto allmulti;
+ ETHER_FIRST_MULTI(step, ac, enm);
+ while (enm != NULL) {
+ sf_set_filter_hash(sc, enm->enm_addrlo);
- /*
- * Now set the hash bits for each multicast address in our
- * list.
- */
- ETHER_FIRST_MULTI(step, ac, enm);
- if (enm == NULL)
- goto done;
- while (enm != NULL) {
- sf_set_filter_hash(sc, enm->enm_addrlo);
- ETHER_NEXT_MULTI(step, enm);
+ ETHER_NEXT_MULTI(step, enm);
+ }
}
- /*
- * Set "hash only multicast dest, match regardless of VLAN ID".
- */
- sc->sc_RxAddressFilteringCtl |= RAFC_HashFilteringMode(2);
- goto done;
+ if ((ifp->if_flags & IFF_PROMISC) == 0) {
+ /*
+ * Write the station address to the perfect filter table.
+ */
+ sf_set_filter_perfect(sc, 0, LLADDR(ifp->if_sadl));
- allmulti:
- /*
- * XXX RAFC_PassMulticast is sub-optimal if using VLAN mode.
- */
- sc->sc_RxAddressFilteringCtl |= RAFC_PassMulticast;
- ifp->if_flags |= IFF_ALLMULTI;
+ filterctl |= RAFC_PerfectFilteringMode(1);
+ }
- done:
- sf_funcreg_write(sc, SF_RxAddressFilteringCtl,
- sc->sc_RxAddressFilteringCtl);
+ sf_funcreg_write(sc, SF_RxAddressFilteringCtl, filterctl);
}
/*
Index: aic6915.h
===================================================================
RCS file: /home/cvs/src/sys/dev/ic/aic6915.h,v
retrieving revision 1.4
diff -u -p -r1.4 aic6915.h
--- aic6915.h 10 Aug 2009 20:29:54 -0000 1.4
+++ aic6915.h 9 Mar 2013 05:00:45 -0000
@@ -764,7 +764,6 @@ struct sf_softc {
bus_dma_tag_t sc_dmat; /* bus DMA tag */
struct arpcom sc_arpcom; /* ethernet common data */
int sc_iomapped; /* are we I/O mapped? */
- int sc_flags; /* misc. flags */
struct mii_data sc_mii; /* MII/media information */
struct timeout sc_mii_timeout; /* MII callout */
@@ -796,8 +795,6 @@ struct sf_softc {
int sc_txthresh; /* current Tx threshold */
uint32_t sc_MacConfig1; /* prototype MacConfig1 register */
-
- uint32_t sc_RxAddressFilteringCtl;
};
#define SF_CDTXDADDR(sc, x) ((sc)->sc_cddma + SF_CDTXDOFF((x)))
--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.