aboutsummaryrefslogtreecommitdiff
path: root/sys/pci/if_sf.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/pci/if_sf.c')
-rw-r--r--sys/pci/if_sf.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/sys/pci/if_sf.c b/sys/pci/if_sf.c
index d0fb709c830d..5af924b0658d 100644
--- a/sys/pci/if_sf.c
+++ b/sys/pci/if_sf.c
@@ -415,8 +415,10 @@ static void sf_miibus_statchg(dev)
if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
+ csr_write_4(sc, SF_BKTOBKIPG, SF_IPGT_FDX);
} else {
SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
+ csr_write_4(sc, SF_BKTOBKIPG, SF_IPGT_HDX);
}
return;
@@ -487,6 +489,13 @@ static int sf_ifmedia_upd(ifp)
sc = ifp->if_softc;
mii = device_get_softc(sc->sf_miibus);
+ sc->sf_link = 0;
+ if (mii->mii_instance) {
+ struct mii_softc *miisc;
+ for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
+ miisc = LIST_NEXT(miisc, mii_list))
+ mii_phy_reset(miisc);
+ }
mii_mediachg(mii);
return(0);
@@ -532,11 +541,21 @@ static int sf_ioctl(ifp, command, data)
break;
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
- sf_init(sc);
+ if (ifp->if_flags & IFF_RUNNING &&
+ ifp->if_flags & IFF_PROMISC &&
+ !(sc->sf_if_flags & IFF_PROMISC)) {
+ SF_SETBIT(sc, SF_RXFILT, SF_RXFILT_PROMISC);
+ } else if (ifp->if_flags & IFF_RUNNING &&
+ !(ifp->if_flags & IFF_PROMISC) &&
+ sc->sf_if_flags & IFF_PROMISC) {
+ SF_CLRBIT(sc, SF_RXFILT, SF_RXFILT_PROMISC);
+ } else if (!(ifp->if_flags & IFF_RUNNING))
+ sf_init(sc);
} else {
if (ifp->if_flags & IFF_RUNNING)
sf_stop(sc);
}
+ sc->sf_if_flags = ifp->if_flags;
error = 0;
break;
case SIOCADDMULTI:
@@ -785,7 +804,7 @@ static int sf_attach(dev)
if (mii_phy_probe(dev, &sc->sf_miibus,
sf_ifmedia_upd, sf_ifmedia_sts)) {
printf("sf%d: MII without any phy!\n", sc->sf_unit);
- free(sc->sf_ldata, M_DEVBUF);
+ contigfree(sc->sf_ldata,sizeof(struct sf_list_data),M_DEVBUF);
bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand);
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sf_irq);
bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res);
@@ -842,7 +861,7 @@ static int sf_detach(dev)
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sf_irq);
bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res);
- free(sc->sf_ldata, M_DEVBUF);
+ contigfree(sc->sf_ldata, sizeof(struct sf_list_data), M_DEVBUF);
splx(s);
@@ -1209,13 +1228,6 @@ static void sf_init(xsc)
/* Enable autopadding of short TX frames. */
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_AUTOPAD);
- /* Make sure the duplex mode is set correctly. */
- if ((mii->mii_media.ifm_media & IFM_GMASK) == IFM_FDX) {
- SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
- } else {
- SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
- }
-
/* Enable interrupts. */
csr_write_4(sc, SF_IMR, SF_INTRS);
SF_SETBIT(sc, SF_PCI_DEVCFG, SF_PCIDEVCFG_INTR_ENB);
@@ -1224,7 +1236,8 @@ static void sf_init(xsc)
SF_SETBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_RX_ENB|SF_ETHCTL_RXDMA_ENB);
SF_SETBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_TX_ENB|SF_ETHCTL_TXDMA_ENB);
- mii_mediachg(mii);
+ /*mii_mediachg(mii);*/
+ sf_ifmedia_upd(ifp);
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
@@ -1309,6 +1322,9 @@ static void sf_start(ifp)
sc = ifp->if_softc;
+ if (!sc->sf_link)
+ return;
+
if (ifp->if_flags & IFF_OACTIVE)
return;
@@ -1370,6 +1386,8 @@ static void sf_stop(sc)
csr_write_4(sc, SF_TXDQ_CTL, 0);
sf_reset(sc);
+ sc->sf_link = 0;
+
for (i = 0; i < SF_RX_DLIST_CNT; i++) {
if (sc->sf_ldata->sf_rx_dlist_big[i].sf_mbuf != NULL) {
m_freem(sc->sf_ldata->sf_rx_dlist_big[i].sf_mbuf);
@@ -1425,6 +1443,14 @@ static void sf_stats_update(xsc)
stats.sf_tx_multi_colls + stats.sf_tx_excess_colls;
mii_tick(mii);
+ if (!sc->sf_link) {
+ mii_pollstat(mii);
+ if (mii->mii_media_status & IFM_ACTIVE &&
+ IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)
+ sc->sf_link++;
+ if (ifp->if_snd.ifq_head != NULL)
+ sf_start(ifp);
+ }
sc->sf_stat_ch = timeout(sf_stats_update, sc, hz);