summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_msk.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/if_msk.c')
-rw-r--r--sys/dev/pci/if_msk.c86
1 files changed, 47 insertions, 39 deletions
diff --git a/sys/dev/pci/if_msk.c b/sys/dev/pci/if_msk.c
index 8098c94e8cd..44e0af57b5d 100644
--- a/sys/dev/pci/if_msk.c
+++ b/sys/dev/pci/if_msk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_msk.c,v 1.78 2009/10/04 18:32:02 deraadt Exp $ */
+/* $OpenBSD: if_msk.c,v 1.79 2009/10/15 17:54:56 deraadt Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000
@@ -151,7 +151,7 @@ void msk_start(struct ifnet *);
int msk_ioctl(struct ifnet *, u_long, caddr_t);
void msk_init(void *);
void msk_init_yukon(struct sk_if_softc *);
-void msk_stop(struct sk_if_softc *);
+void msk_stop(struct sk_if_softc *, int);
void msk_watchdog(struct ifnet *);
int msk_ifmedia_upd(struct ifnet *);
void msk_ifmedia_sts(struct ifnet *, struct ifmediareq *);
@@ -612,7 +612,7 @@ msk_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
} else {
if (ifp->if_flags & IFF_RUNNING)
- msk_stop(sc_if);
+ msk_stop(sc_if, 0);
}
sc_if->sk_if_flags = ifp->if_flags;
break;
@@ -1003,7 +1003,10 @@ msk_detach(struct device *self, int flags)
if (sc->sk_if[sc_if->sk_port] == NULL)
return (0);
- timeout_del(&sc_if->sk_tick_ch);
+ msk_stop(sc_if, 1);
+
+ if (sc_if->sk_sdhook != NULL)
+ shutdownhook_disestablish(sc_if->sk_sdhook);
/* Detach any PHYs we might have. */
if (LIST_FIRST(&sc_if->sk_mii.mii_phys) != NULL)
@@ -1012,17 +1015,14 @@ msk_detach(struct device *self, int flags)
/* Delete any remaining media. */
ifmedia_delete_instance(&sc_if->sk_mii.mii_media, IFM_INST_ANY);
- if (sc_if->sk_sdhook != NULL)
- shutdownhook_disestablish(sc_if->sk_sdhook);
-
ether_ifdetach(ifp);
if_detach(ifp);
- bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_ring_map);
bus_dmamem_unmap(sc->sc_dmatag, (caddr_t)sc_if->sk_rdata,
sizeof(struct msk_ring_data));
bus_dmamem_free(sc->sc_dmatag,
&sc_if->sk_ring_seg, sc_if->sk_ring_nseg);
+ bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_ring_map);
sc->sk_if[sc_if->sk_port] = NULL;
return (0);
@@ -1319,8 +1319,6 @@ mskc_attach(struct device *parent, struct device *self, void *aux)
return;
-fail_5:
- bus_dmamap_destroy(sc->sc_dmatag, sc->sk_status_map);
fail_4:
bus_dmamem_unmap(sc->sc_dmatag, (caddr_t)sc->sk_status_ring,
MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc));
@@ -1328,6 +1326,8 @@ fail_3:
bus_dmamem_free(sc->sc_dmatag,
&sc->sk_status_seg, sc->sk_status_nseg);
sc->sk_status_nseg = 0;
+fail_5:
+ bus_dmamap_destroy(sc->sc_dmatag, sc->sk_status_map);
fail_2:
pci_intr_disestablish(sc->sk_pc, sc->sk_intrhand);
sc->sk_intrhand = NULL;
@@ -1342,6 +1342,9 @@ mskc_detach(struct device *self, int flags)
struct sk_softc *sc = (struct sk_softc *)self;
int rv;
+ if (sc->sk_intrhand)
+ pci_intr_disestablish(sc->sk_pc, sc->sk_intrhand);
+
rv = config_detach_children(self, flags);
if (rv != 0)
return (rv);
@@ -1354,9 +1357,6 @@ mskc_detach(struct device *self, int flags)
&sc->sk_status_seg, sc->sk_status_nseg);
}
- if (sc->sk_intrhand)
- pci_intr_disestablish(sc->sk_pc, sc->sk_intrhand);
-
if (sc->sk_bsize > 0)
bus_space_unmap(sc->sk_btag, sc->sk_bhandle, sc->sk_bsize);
@@ -1733,6 +1733,8 @@ msk_intr(void *xsc)
struct msk_status_desc *cur_st;
status = CSR_READ_4(sc, SK_Y2_ISSR2);
+ if (status == 0xffffffff)
+ return (0);
if (status == 0) {
CSR_WRITE_4(sc, SK_Y2_ICR, 2);
return (0);
@@ -1933,7 +1935,7 @@ msk_init(void *xsc_if)
s = splnet();
/* Cancel pending I/O and free all RX/TX buffers. */
- msk_stop(sc_if);
+ msk_stop(sc_if, 0);
/* Configure I2C registers */
@@ -1981,7 +1983,7 @@ msk_init(void *xsc_if)
if (msk_init_rx_ring(sc_if) == ENOBUFS) {
printf("%s: initialization failed: no "
"memory for rx buffers\n", sc_if->sk_dev.dv_xname);
- msk_stop(sc_if);
+ msk_stop(sc_if, 0);
splx(s);
return;
}
@@ -1989,7 +1991,7 @@ msk_init(void *xsc_if)
if (msk_init_tx_ring(sc_if) == ENOBUFS) {
printf("%s: initialization failed: no "
"memory for tx buffers\n", sc_if->sk_dev.dv_xname);
- msk_stop(sc_if);
+ msk_stop(sc_if, 0);
splx(s);
return;
}
@@ -2035,7 +2037,7 @@ msk_init(void *xsc_if)
}
void
-msk_stop(struct sk_if_softc *sc_if)
+msk_stop(struct sk_if_softc *sc_if, int softonly)
{
struct sk_softc *sc = sc_if->sk_softc;
struct ifnet *ifp = &sc_if->arpcom.ac_if;
@@ -2052,28 +2054,30 @@ msk_stop(struct sk_if_softc *sc_if)
/* Stop transfer of Rx descriptors */
- /* Turn off various components of this interface. */
- SK_IF_WRITE_1(sc_if,0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_SET);
- SK_IF_WRITE_1(sc_if,0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_SET);
- SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_OFFLINE);
- SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_RESET|SK_RBCTL_OFF);
- SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_BMU_CSR, SK_TXBMU_OFFLINE);
- SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_CTLTST, SK_RBCTL_RESET|SK_RBCTL_OFF);
- SK_IF_WRITE_1(sc_if, 0, SK_TXAR1_COUNTERCTL, SK_TXARCTL_OFF);
- SK_IF_WRITE_1(sc_if, 0, SK_RXLED1_CTL, SK_RXLEDCTL_COUNTER_STOP);
- SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL, SK_TXLEDCTL_COUNTER_STOP);
- SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_OFF);
- SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_LINKSYNC_OFF);
-
- SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_Y2_PREF_CSR, 0x00000001);
- SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_Y2_PREF_CSR, 0x00000001);
-
- /* Disable interrupts */
- if (sc_if->sk_port == SK_PORT_A)
- sc->sk_intrmask &= ~SK_Y2_INTRS1;
- else
- sc->sk_intrmask &= ~SK_Y2_INTRS2;
- CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask);
+ if (!softonly) {
+ /* Turn off various components of this interface. */
+ SK_IF_WRITE_1(sc_if,0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_SET);
+ SK_IF_WRITE_1(sc_if,0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_SET);
+ SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_OFFLINE);
+ SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_RESET|SK_RBCTL_OFF);
+ SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_BMU_CSR, SK_TXBMU_OFFLINE);
+ SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_CTLTST, SK_RBCTL_RESET|SK_RBCTL_OFF);
+ SK_IF_WRITE_1(sc_if, 0, SK_TXAR1_COUNTERCTL, SK_TXARCTL_OFF);
+ SK_IF_WRITE_1(sc_if, 0, SK_RXLED1_CTL, SK_RXLEDCTL_COUNTER_STOP);
+ SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL, SK_TXLEDCTL_COUNTER_STOP);
+ SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_OFF);
+ SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_LINKSYNC_OFF);
+
+ SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_Y2_PREF_CSR, 0x00000001);
+ SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_Y2_PREF_CSR, 0x00000001);
+
+ /* Disable interrupts */
+ if (sc_if->sk_port == SK_PORT_A)
+ sc->sk_intrmask &= ~SK_Y2_INTRS1;
+ else
+ sc->sk_intrmask &= ~SK_Y2_INTRS2;
+ CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask);
+ }
/* Free RX and TX mbufs still in the queues. */
for (i = 0; i < MSK_RX_RING_CNT; i++) {
@@ -2083,6 +2087,10 @@ msk_stop(struct sk_if_softc *sc_if)
}
}
+ sc_if->sk_cdata.sk_rx_prod = 0;
+ sc_if->sk_cdata.sk_rx_cons = 0;
+ sc_if->sk_cdata.sk_rx_cnt = 0;
+
for (i = 0; i < MSK_TX_RING_CNT; i++) {
if (sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf != NULL) {
m_freem(sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf);