Here is a diff for the txp(4) 3Com 3XP Typhoon/Sidewinder 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: if_txp.c
===
RCS file: /home/cvs/src/sys/dev/pci/if_txp.c,v
retrieving revision 1.108
diff -u -p -r1.108 if_txp.c
--- if_txp.c26 Nov 2013 09:50:33 - 1.108
+++ if_txp.c2 Dec 2013 02:04:44 -
@@ -103,7 +103,7 @@ int txp_download_fw_section(struct txp_s
int txp_alloc_rings(struct txp_softc *);
void txp_dma_free(struct txp_softc *, struct txp_dma_alloc *);
int txp_dma_malloc(struct txp_softc *, bus_size_t, struct txp_dma_alloc *,
int);
-void txp_set_filter(struct txp_softc *);
+void txp_iff(struct txp_softc *);
int txp_cmd_desc_numfree(struct txp_softc *);
int txp_command(struct txp_softc *, u_int16_t, u_int16_t, u_int32_t,
@@ -1184,22 +1184,21 @@ txp_ioctl(struct ifnet *ifp, u_long comm
switch(command) {
case SIOCSIFADDR:
ifp-if_flags |= IFF_UP;
- switch (ifa-ifa_addr-sa_family) {
-#ifdef INET
- case AF_INET:
+ if (!(ifp-if_flags IFF_RUNNING))
txp_init(sc);
+
+#ifdef INET
+ if (ifa-ifa_addr-sa_family == AF_INET)
arp_ifinit(sc-sc_arpcom, ifa);
- break;
-#endif /* INET */
- default:
- txp_init(sc);
- break;
- }
+#endif
break;
case SIOCSIFFLAGS:
if (ifp-if_flags IFF_UP) {
- txp_init(sc);
+ if (ifp-if_flags IFF_RUNNING)
+ error = ENETRESET;
+ else
+ txp_init(sc);
} else {
if (ifp-if_flags IFF_RUNNING)
txp_stop(sc);
@@ -1217,7 +1216,7 @@ txp_ioctl(struct ifnet *ifp, u_long comm
if (error == ENETRESET) {
if (ifp-if_flags IFF_RUNNING)
- txp_set_filter(sc);
+ txp_iff(sc);
error = 0;
}
@@ -1235,7 +1234,8 @@ txp_init(struct txp_softc *sc)
s = splnet();
- txp_set_filter(sc);
+ /* Program promiscuous mode and multicast filters. */
+ txp_iff(sc);
txp_command(sc, TXP_CMD_TX_ENABLE, 0, 0, 0, NULL, NULL, NULL, 1);
txp_command(sc, TXP_CMD_RX_ENABLE, 0, 0, 0, NULL, NULL, NULL, 1);
@@ -1843,51 +1843,46 @@ txp_show_descriptor(void *d)
}
void
-txp_set_filter(struct txp_softc *sc)
+txp_iff(struct txp_softc *sc)
{
struct arpcom *ac = sc-sc_arpcom;
struct ifnet *ifp = sc-sc_arpcom.ac_if;
- u_int32_t hashbit, hash[2];
- u_int16_t filter;
- int mcnt = 0;
struct ether_multi *enm;
struct ether_multistep step;
+ u_int32_t hashbit, hash[2];
+ u_int16_t filter;
- if (ifp-if_flags IFF_PROMISC) {
- filter = TXP_RXFILT_PROMISC;
- goto setit;
- }
-
- if (ac-ac_multirangecnt 0)
- ifp-if_flags |= IFF_ALLMULTI;
-
- filter = TXP_RXFILT_DIRECT;
+ bzero(hash, sizeof(hash));
+ ifp-if_flags = ~IFF_ALLMULTI;
- if (ifp-if_flags IFF_BROADCAST)
- filter |= TXP_RXFILT_BROADCAST;
+ /*
+* Always accept broadcast packets.
+* Always accept frames destined to our station address.
+*/
+ filter = TXP_RXFILT_BROADCAST | TXP_RXFILT_DIRECT;
- if (ifp-if_flags IFF_ALLMULTI)
- filter |= TXP_RXFILT_ALLMULTI;
- else {
- hash[0] = hash[1] = 0;
+ if (ifp-if_flags IFF_PROMISC || ac-ac_multirangecnt 0) {
+ ifp-if_flags |= IFF_ALLMULTI;
+ if (ifp-if_flags IFF_PROMISC)
+ filter |= TXP_RXFILT_PROMISC;
+ else
+ filter |= TXP_RXFILT_ALLMULTI;
+ } else {
+ filter |= TXP_RXFILT_HASHMULTI;
ETHER_FIRST_MULTI(step, ac, enm);
while (enm != NULL) {
- mcnt++;
hashbit = (u_int16_t)(ether_crc32_be(enm-enm_addrlo,
ETHER_ADDR_LEN) (64 - 1));
+
hash[hashbit / 32] |= (1 hashbit % 32);
- ETHER_NEXT_MULTI(step, enm);
- }
- if (mcnt 0) {
- filter |= TXP_RXFILT_HASHMULTI;
- txp_command(sc, TXP_CMD_MCAST_HASH_MASK_WRITE,
- 2, hash[0], hash[1], NULL, NULL, NULL, 0);
+ ETHER_NEXT_MULTI(step, enm);
}
}
-setit:
+ txp_command(sc, TXP_CMD_MCAST_HASH_MASK_WRITE,
+ 2, hash[0], hash[1], NULL, NULL, NULL, 0);