The following diff rewrites parts of the code for promiscuous mode
and multicast handling for the ti(4) driver. Please test promisc
mode and multicast mode of operation with any ti(4) adapters.
Please provide a dmesg.
Index: ti.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/ti.c,v
retrieving revision 1.1
diff -u -p -r1.1 ti.c
--- ti.c 29 Aug 2009 21:12:55 -0000 1.1
+++ ti.c 8 Sep 2009 00:47:02 -0000
@@ -142,7 +142,7 @@ int ti_read_eeprom(struct ti_softc *, ca
void ti_add_mcast(struct ti_softc *, struct ether_addr *);
void ti_del_mcast(struct ti_softc *, struct ether_addr *);
-void ti_setmulti(struct ti_softc *);
+void ti_iff(struct ti_softc *);
void ti_mem_read(struct ti_softc *, u_int32_t, u_int32_t, void *);
void ti_mem_write(struct ti_softc *, u_int32_t, u_int32_t, const void*);
@@ -1156,59 +1156,62 @@ ti_del_mcast(struct ti_softc *sc, struct
* any given time.
*/
void
-ti_setmulti(struct ti_softc *sc)
+ti_iff(struct ti_softc *sc)
{
- struct ifnet *ifp;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
struct arpcom *ac = &sc->arpcom;
struct ether_multi *enm;
struct ether_multistep step;
struct ti_cmd_desc cmd;
struct ti_mc_entry *mc;
u_int32_t intrs;
-
- ifp = &sc->arpcom.ac_if;
-allmulti:
- if (ifp->if_flags & IFF_ALLMULTI) {
- TI_DO_CMD(TI_CMD_SET_ALLMULTI, TI_CMD_CODE_ALLMULTI_ENB, 0);
- return;
+ TI_DO_CMD(TI_CMD_SET_ALLMULTI, TI_CMD_CODE_ALLMULTI_DIS, 0);
+ TI_DO_CMD(TI_CMD_SET_PROMISC_MODE, TI_CMD_CODE_PROMISC_DIS, 0);
+ ifp->if_flags &= ~IFF_ALLMULTI;
+
+ if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ if (ifp->if_flags & IFF_PROMISC) {
+ TI_DO_CMD(TI_CMD_SET_PROMISC_MODE,
+ TI_CMD_CODE_PROMISC_ENB, 0);
+ } else {
+ TI_DO_CMD(TI_CMD_SET_ALLMULTI,
+ TI_CMD_CODE_ALLMULTI_ENB, 0);
+ }
} else {
- TI_DO_CMD(TI_CMD_SET_ALLMULTI, TI_CMD_CODE_ALLMULTI_DIS, 0);
- }
-
- /* Disable interrupts. */
- intrs = CSR_READ_4(sc, TI_MB_HOSTINTR);
- CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1);
-
- /* First, zot all the existing filters. */
- while (SLIST_FIRST(&sc->ti_mc_listhead) != NULL) {
- mc = SLIST_FIRST(&sc->ti_mc_listhead);
- ti_del_mcast(sc, &mc->mc_addr);
- SLIST_REMOVE_HEAD(&sc->ti_mc_listhead, mc_entries);
- free(mc, M_DEVBUF);
- }
-
- /* Now program new ones. */
- ETHER_FIRST_MULTI(step, ac, enm);
- while (enm != NULL) {
- if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
- /* Re-enable interrupts. */
- CSR_WRITE_4(sc, TI_MB_HOSTINTR, intrs);
-
- ifp->if_flags |= IFF_ALLMULTI;
- goto allmulti;
- }
- mc = malloc(sizeof(struct ti_mc_entry), M_DEVBUF, M_NOWAIT);
- if (mc == NULL)
- panic("ti_setmulti");
- bcopy(enm->enm_addrlo, (char *)&mc->mc_addr, ETHER_ADDR_LEN);
- SLIST_INSERT_HEAD(&sc->ti_mc_listhead, mc, mc_entries);
- ti_add_mcast(sc, &mc->mc_addr);
- ETHER_NEXT_MULTI(step, enm);
- }
-
- /* Re-enable interrupts. */
- CSR_WRITE_4(sc, TI_MB_HOSTINTR, intrs);
+ /* Disable interrupts. */
+ intrs = CSR_READ_4(sc, TI_MB_HOSTINTR);
+ CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1);
+
+ /* First, zot all the existing filters. */
+ while (SLIST_FIRST(&sc->ti_mc_listhead) != NULL) {
+ mc = SLIST_FIRST(&sc->ti_mc_listhead);
+ ti_del_mcast(sc, &mc->mc_addr);
+ SLIST_REMOVE_HEAD(&sc->ti_mc_listhead, mc_entries);
+ free(mc, M_DEVBUF);
+ }
+
+ /* Now program new ones. */
+ ETHER_FIRST_MULTI(step, ac, enm);
+ while (enm != NULL) {
+ mc = malloc(sizeof(struct ti_mc_entry), M_DEVBUF,
+ M_NOWAIT);
+ if (mc == NULL)
+ panic("ti_iff");
+
+ bcopy(enm->enm_addrlo, (char *)&mc->mc_addr,
+ ETHER_ADDR_LEN);
+ SLIST_INSERT_HEAD(&sc->ti_mc_listhead, mc,
+ mc_entries);
+ ti_add_mcast(sc, &mc->mc_addr);
+
+ ETHER_NEXT_MULTI(step, enm);
+ }
+
+ /* Re-enable interrupts. */
+ CSR_WRITE_4(sc, TI_MB_HOSTINTR, intrs);
+ }
}
/*
@@ -2250,23 +2253,15 @@ ti_init2(struct ti_softc *sc)
CSR_WRITE_4(sc, TI_GCR_PAR1, (htons(m[1]) << 16) | htons(m[2]));
TI_DO_CMD(TI_CMD_SET_MAC_ADDR, 0, 0);
- /* Enable or disable promiscuous mode as needed. */
- if (ifp->if_flags & IFF_PROMISC) {
- TI_DO_CMD(TI_CMD_SET_PROMISC_MODE, TI_CMD_CODE_PROMISC_ENB, 0);
- } else {
- TI_DO_CMD(TI_CMD_SET_PROMISC_MODE, TI_CMD_CODE_PROMISC_DIS, 0);
- }
-
- /* Program multicast filter. */
- ti_setmulti(sc);
+ /* Program promiscuous mode and multicast filters. */
+ ti_iff(sc);
/*
* If this is a Tigon 1, we should tell the
* firmware to use software packet filtering.
*/
- if (sc->ti_hwrev == TI_HWREV_TIGON) {
+ if (sc->ti_hwrev == TI_HWREV_TIGON)
TI_DO_CMD(TI_CMD_FDR_FILTERING, TI_CMD_CODE_FILT_ENB, 0);
- }
/* Init RX ring. */
if (ti_init_rx_ring_std(sc) == ENOBUFS)
@@ -2431,7 +2426,6 @@ ti_ioctl(struct ifnet *ifp, u_long comma
struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
- struct ti_cmd_desc cmd;
s = splnet();
@@ -2443,38 +2437,19 @@ ti_ioctl(struct ifnet *ifp, u_long comma
#ifdef INET
if (ifa->ifa_addr->sa_family == AF_INET)
arp_ifinit(&sc->arpcom, ifa);
-#endif /* INET */
+#endif
break;
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
- /*
- * If only the state of the PROMISC flag changed,
- * then just use the 'set promisc mode' command
- * instead of reinitializing the entire NIC. Doing
- * a full re-init means reloading the firmware and
- * waiting for it to start up, which may take a
- * second or two.
- */
- if (ifp->if_flags & IFF_RUNNING &&
- ifp->if_flags & IFF_PROMISC &&
- !(sc->ti_if_flags & IFF_PROMISC)) {
- TI_DO_CMD(TI_CMD_SET_PROMISC_MODE,
- TI_CMD_CODE_PROMISC_ENB, 0);
- } else if (ifp->if_flags & IFF_RUNNING &&
- !(ifp->if_flags & IFF_PROMISC) &&
- sc->ti_if_flags & IFF_PROMISC) {
- TI_DO_CMD(TI_CMD_SET_PROMISC_MODE,
- TI_CMD_CODE_PROMISC_DIS, 0);
- } else {
- if ((ifp->if_flags & IFF_RUNNING) == 0)
- ti_init(sc);
- }
+ if (ifp->if_flags & IFF_RUNNING)
+ error = ENETRESET;
+ else
+ ti_init(sc);
} else {
if (ifp->if_flags & IFF_RUNNING)
ti_stop(sc);
}
- sc->ti_if_flags = ifp->if_flags;
break;
case SIOCSIFMEDIA:
@@ -2488,7 +2463,7 @@ ti_ioctl(struct ifnet *ifp, u_long comma
if (error == ENETRESET) {
if (ifp->if_flags & IFF_RUNNING)
- ti_setmulti(sc);
+ ti_iff(sc);
error = 0;
}
Index: tireg.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/tireg.h,v
retrieving revision 1.1
diff -u -p -r1.1 tireg.h
--- tireg.h 29 Aug 2009 21:12:55 -0000 1.1
+++ tireg.h 8 Sep 2009 00:36:03 -0000
@@ -1142,7 +1142,6 @@ struct ti_softc {
u_int32_t ti_rx_max_coal_bds;
u_int32_t ti_tx_max_coal_bds;
u_int32_t ti_tx_buf_ratio;
- int ti_if_flags;
int ti_txcnt;
};
--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.