Rewrite and simplify the ix(4) promiscuous mode/multicast setup code and
interface flag handling code in the ioctl handler.
Please test with any ix(4) adapters. Please provide a dmesg.
Index: if_ix.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_ix.c,v
retrieving revision 1.17
diff -u -p -r1.17 if_ix.c
--- if_ix.c 29 Apr 2009 13:18:58 -0000 1.17
+++ if_ix.c 28 May 2009 00:19:10 -0000
@@ -104,9 +104,7 @@ void ixgbe_update_stats_counters(struct
int ixgbe_txeof(struct tx_ring *);
int ixgbe_rxeof(struct rx_ring *, int);
void ixgbe_rx_checksum(struct ix_softc *, uint32_t, struct mbuf *);
-void ixgbe_set_promisc(struct ix_softc *);
-void ixgbe_disable_promisc(struct ix_softc *);
-void ixgbe_set_multi(struct ix_softc *);
+void ixgbe_iff(struct ix_softc *);
#ifdef IX_DEBUG
void ixgbe_print_hw_stats(struct ix_softc *);
#endif
@@ -458,18 +456,14 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
case SIOCSIFFLAGS:
IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)");
if (ifp->if_flags & IFF_UP) {
- if ((ifp->if_flags & IFF_RUNNING)) {
- if ((ifp->if_flags ^ sc->if_flags) &
- (IFF_PROMISC | IFF_ALLMULTI)) {
- ixgbe_disable_promisc(sc);
- ixgbe_set_promisc(sc);
- }
- } else
+ if (ifp->if_flags & IFF_RUNNING)
+ error = ENETRESET;
+ else
ixgbe_init(sc);
- } else
+ } else {
if (ifp->if_flags & IFF_RUNNING)
ixgbe_stop(sc);
- sc->if_flags = ifp->if_flags;
+ }
break;
case SIOCSIFMEDIA:
@@ -485,7 +479,7 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
if (error == ENETRESET) {
if (ifp->if_flags & IFF_RUNNING) {
ixgbe_disable_intr(sc);
- ixgbe_set_multi(sc);
+ ixgbe_iff(sc);
ixgbe_enable_intr(sc);
}
error = 0;
@@ -611,9 +605,6 @@ ixgbe_init(void *arg)
ixgbe_initialize_transmit_units(sc);
- /* Setup Multicast table */
- ixgbe_set_multi(sc);
-
/*
* If we are resetting MTU smaller than 2K
* drop to small RX buffers
@@ -632,6 +623,9 @@ ixgbe_init(void *arg)
/* Configure RX settings */
ixgbe_initialize_receive_units(sc);
+ /* Program promiscuous mode and multicast filters. */
+ ixgbe_iff(sc);
+
gpie = IXGBE_READ_REG(&sc->hw, IXGBE_GPIE);
/* Enable Fan Failure Interrupt */
if (sc->hw.phy.media_type == ixgbe_media_type_copper)
@@ -956,100 +950,55 @@ xmit_fail:
}
-void
-ixgbe_set_promisc(struct ix_softc *sc)
-{
-
- uint32_t reg_rctl;
- struct ifnet *ifp = &sc->arpcom.ac_if;
-
- reg_rctl = IXGBE_READ_REG(&sc->hw, IXGBE_FCTRL);
-
- if (ifp->if_flags & IFF_PROMISC) {
- reg_rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
- IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, reg_rctl);
- } else if (ifp->if_flags & IFF_ALLMULTI) {
- reg_rctl |= IXGBE_FCTRL_MPE;
- reg_rctl &= ~IXGBE_FCTRL_UPE;
- IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, reg_rctl);
- }
- return;
-}
-
-void
-ixgbe_disable_promisc(struct ix_softc * sc)
-{
- uint32_t reg_rctl;
-
- reg_rctl = IXGBE_READ_REG(&sc->hw, IXGBE_FCTRL);
-
- reg_rctl &= (~IXGBE_FCTRL_UPE);
- reg_rctl &= (~IXGBE_FCTRL_MPE);
- IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, reg_rctl);
-
- return;
-}
-
-/*********************************************************************
- * Multicast Update
- *
- * This routine is called whenever multicast address list is updated.
- *
- **********************************************************************/
#define IXGBE_RAR_ENTRIES 16
void
-ixgbe_set_multi(struct ix_softc *sc)
+ixgbe_iff(struct ix_softc *sc)
{
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ struct arpcom *ac = &sc->arpcom;
uint32_t fctrl;
uint8_t mta[MAX_NUM_MULTICAST_ADDRESSES * IXGBE_ETH_LENGTH_OF_ADDRESS];
uint8_t *update_ptr;
struct ether_multi *enm;
struct ether_multistep step;
int mcnt = 0;
- struct ifnet *ifp = &sc->arpcom.ac_if;
- IOCTL_DEBUGOUT("ixgbe_set_multi: begin");
+ IOCTL_DEBUGOUT("ixgbe_iff: begin");
fctrl = IXGBE_READ_REG(&sc->hw, IXGBE_FCTRL);
- fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
- if (ifp->if_flags & IFF_PROMISC)
- fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
- else if (ifp->if_flags & IFF_ALLMULTI) {
- fctrl |= IXGBE_FCTRL_MPE;
- fctrl &= ~IXGBE_FCTRL_UPE;
- } else
- fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
-
- IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, fctrl);
+ fctrl &= ~(IXGBE_FCTRL_MPE | IXGBE_FCTRL_UPE);
+ ifp->if_flags &= IFF_ALLMULTI;
- ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
- while (enm != NULL) {
- if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
- ifp->if_flags |= IFF_ALLMULTI;
- mcnt = MAX_NUM_MULTICAST_ADDRESSES;
+ if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0 ||
+ ac->ac_multicnt > MAX_NUM_MULTICAST_ADDRESSES) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ fctrl |= IXGBE_FCTRL_MPE;
+ if (ifp->if_flags & IFF_PROMISC)
+ fctrl |= IXGBE_FCTRL_UPE;
+ } else {
+ ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
+ while (enm != NULL) {
+ bcopy(enm->enm_addrlo,
+ &mta[mcnt * IXGBE_ETH_LENGTH_OF_ADDRESS],
+ IXGBE_ETH_LENGTH_OF_ADDRESS);
+ mcnt++;
+ ETHER_NEXT_MULTI(step, enm);
}
- if (mcnt == MAX_NUM_MULTICAST_ADDRESSES)
- break;
- bcopy(enm->enm_addrlo,
- &mta[mcnt * IXGBE_ETH_LENGTH_OF_ADDRESS],
- IXGBE_ETH_LENGTH_OF_ADDRESS);
- mcnt++;
- ETHER_NEXT_MULTI(step, enm);
- }
- update_ptr = mta;
- ixgbe_hw(&sc->hw, update_mc_addr_list,
- update_ptr, mcnt, ixgbe_mc_array_itr);
+ update_ptr = mta;
+ ixgbe_hw(&sc->hw, update_mc_addr_list,
+ update_ptr, mcnt, ixgbe_mc_array_itr);
+ }
- return;
+ IXGBE_WRITE_REG(&sc->hw, IXGBE_FCTRL, fctrl);
}
/*
* This is an iterator function now needed by the multicast
* shared code. It simply feeds the shared code routine the
- * addresses in the array of ixgbe_set_multi() one by one.
+ * addresses in the array of ixgbe_iff() one by one.
*/
uint8_t *
ixgbe_mc_array_itr(struct ixgbe_hw *hw, uint8_t **update_ptr, uint32_t *vmdq)
Index: if_ix.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_ix.h,v
retrieving revision 1.4
diff -u -p -r1.4 if_ix.h
--- if_ix.h 24 Apr 2009 12:54:15 -0000 1.4
+++ if_ix.h 28 May 2009 00:13:32 -0000
@@ -255,7 +255,6 @@ struct ix_softc {
struct ifmedia media;
struct timeout timer;
int msix;
- int if_flags;
struct mutex core_mtx;
--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.