summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_sk.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2009-10-15 17:54:57 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2009-10-15 17:54:57 +0000
commite146ad033c7b64925ffa948f37bf1b536392e65c (patch)
treeebd18c972b363ff177bdd0820fa8d77bdaa2321e /sys/dev/pci/if_sk.c
parent2faa5c93c1cb8fe9a551a57cbe7ccee57638b318 (diff)
Add detach support to a few more drivers, and in others do the neccessary
operations in the detach function in the right order. Also ensure that the interrupt handlers not trust registers that go away. read over very carefully by dms, tested by me
Diffstat (limited to 'sys/dev/pci/if_sk.c')
-rw-r--r--sys/dev/pci/if_sk.c182
1 files changed, 92 insertions, 90 deletions
diff --git a/sys/dev/pci/if_sk.c b/sys/dev/pci/if_sk.c
index 4745cdc5336..0e7a2ef3608 100644
--- a/sys/dev/pci/if_sk.c
+++ b/sys/dev/pci/if_sk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_sk.c,v 1.154 2009/10/04 18:32:40 deraadt Exp $ */
+/* $OpenBSD: if_sk.c,v 1.155 2009/10/15 17:54:56 deraadt Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000
@@ -152,7 +152,7 @@ int sk_ioctl(struct ifnet *, u_long, caddr_t);
void sk_init(void *);
void sk_init_xmac(struct sk_if_softc *);
void sk_init_yukon(struct sk_if_softc *);
-void sk_stop(struct sk_if_softc *);
+void sk_stop(struct sk_if_softc *, int softonly);
void sk_watchdog(struct ifnet *);
int sk_ifmedia_upd(struct ifnet *);
void sk_ifmedia_sts(struct ifnet *, struct ifmediareq *);
@@ -490,7 +490,7 @@ allmulti:
case SK_GENESIS:
h = sk_xmac_hash(enm->enm_addrlo);
break;
-
+
case SK_YUKON:
case SK_YUKON_LITE:
case SK_YUKON_LP:
@@ -650,7 +650,7 @@ sk_newbuf(struct sk_if_softc *sc_if, int i, struct mbuf *m,
MGETHDR(m_new, M_DONTWAIT, MT_DATA);
if (m_new == NULL)
return (ENOBUFS);
-
+
/* Allocate the jumbo buffer */
buf = sk_jalloc(sc_if);
if (buf == NULL) {
@@ -892,7 +892,7 @@ sk_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
} else {
if (ifp->if_flags & IFF_RUNNING)
- sk_stop(sc_if);
+ sk_stop(sc_if, 0);
}
sc_if->sk_if_flags = ifp->if_flags;
break;
@@ -1243,12 +1243,12 @@ sk_attach(struct device *parent, struct device *self, void *aux)
DPRINTFN(2, ("sk_attach: end\n"));
return;
-fail_3:
- bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_ring_map);
fail_2:
bus_dmamem_unmap(sc->sc_dmatag, kva, sizeof(struct sk_ring_data));
fail_1:
bus_dmamem_free(sc->sc_dmatag, &sc_if->sk_ring_seg, sc_if->sk_ring_nseg);
+fail_3:
+ bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_ring_map);
fail:
sc->sk_if[sa->skc_port] = NULL;
}
@@ -1263,7 +1263,7 @@ sk_detach(struct device *self, int flags)
if (sc->sk_if[sc_if->sk_port] == NULL)
return (0);
- timeout_del(&sc_if->sk_tick_ch);
+ sk_stop(sc_if, 1);
/* Detach any PHYs we might have. */
if (LIST_FIRST(&sc_if->sk_mii.mii_phys) != NULL)
@@ -1278,11 +1278,11 @@ sk_detach(struct device *self, int flags)
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 sk_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);
@@ -1532,13 +1532,13 @@ skc_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);
- 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);
@@ -2560,7 +2560,7 @@ sk_init(void *xsc_if)
s = splnet();
/* Cancel pending I/O and free all RX/TX buffers. */
- sk_stop(sc_if);
+ sk_stop(sc_if, 0);
if (SK_IS_GENESIS(sc)) {
/* Configure LINK_SYNC LED */
@@ -2571,7 +2571,7 @@ sk_init(void *xsc_if)
/* Configure RX LED */
SK_IF_WRITE_1(sc_if, 0, SK_RXLED1_CTL,
SK_RXLEDCTL_COUNTER_START);
-
+
/* Configure TX LED */
SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL,
SK_TXLEDCTL_COUNTER_START);
@@ -2616,7 +2616,7 @@ sk_init(void *xsc_if)
SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_UNRESET);
SK_IF_WRITE_4(sc_if, 0, SK_RXF1_END, SK_FIFO_END);
SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_ON);
-
+
SK_IF_WRITE_4(sc_if, 0, SK_TXF1_CTL, SK_FIFO_UNRESET);
SK_IF_WRITE_4(sc_if, 0, SK_TXF1_END, SK_FIFO_END);
SK_IF_WRITE_4(sc_if, 0, SK_TXF1_CTL, SK_FIFO_ON);
@@ -2657,7 +2657,7 @@ sk_init(void *xsc_if)
if (sk_init_rx_ring(sc_if) == ENOBUFS) {
printf("%s: initialization failed: no "
"memory for rx buffers\n", sc_if->sk_dev.dv_xname);
- sk_stop(sc_if);
+ sk_stop(sc_if, 0);
splx(s);
return;
}
@@ -2665,7 +2665,7 @@ sk_init(void *xsc_if)
if (sk_init_tx_ring(sc_if) == ENOBUFS) {
printf("%s: initialization failed: no "
"memory for tx buffers\n", sc_if->sk_dev.dv_xname);
- sk_stop(sc_if);
+ sk_stop(sc_if, 0);
splx(s);
return;
}
@@ -2712,7 +2712,7 @@ sk_init(void *xsc_if)
}
void
-sk_stop(struct sk_if_softc *sc_if)
+sk_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;
@@ -2726,80 +2726,82 @@ sk_stop(struct sk_if_softc *sc_if)
ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
- /* stop Tx descriptor polling timer */
- SK_IF_WRITE_4(sc_if, 0, SK_DPT_TIMER_CTRL, SK_DPT_TCTL_STOP);
- /* stop transfer of Tx descriptors */
- CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_STOP);
- for (i = 0; i < SK_TIMEOUT; i++) {
- val = CSR_READ_4(sc, sc_if->sk_tx_bmu);
- if (!(val & SK_TXBMU_TX_STOP))
+ if (!softonly) {
+ /* stop Tx descriptor polling timer */
+ SK_IF_WRITE_4(sc_if, 0, SK_DPT_TIMER_CTRL, SK_DPT_TCTL_STOP);
+ /* stop transfer of Tx descriptors */
+ CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_STOP);
+ for (i = 0; i < SK_TIMEOUT; i++) {
+ val = CSR_READ_4(sc, sc_if->sk_tx_bmu);
+ if (!(val & SK_TXBMU_TX_STOP))
+ break;
+ DELAY(1);
+ }
+ if (i == SK_TIMEOUT)
+ printf("%s: cannot stop transfer of Tx descriptors\n",
+ sc_if->sk_dev.dv_xname);
+ /* stop transfer of Rx descriptors */
+ SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_RX_STOP);
+ for (i = 0; i < SK_TIMEOUT; i++) {
+ val = SK_IF_READ_4(sc_if, 0, SK_RXQ1_BMU_CSR);
+ if (!(val & SK_RXBMU_RX_STOP))
+ break;
+ DELAY(1);
+ }
+ if (i == SK_TIMEOUT)
+ printf("%s: cannot stop transfer of Rx descriptors\n",
+ sc_if->sk_dev.dv_xname);
+
+ if (sc_if->sk_phytype == SK_PHYTYPE_BCOM) {
+ u_int32_t val;
+
+ /* Put PHY back into reset. */
+ val = sk_win_read_4(sc, SK_GPIO);
+ if (sc_if->sk_port == SK_PORT_A) {
+ val |= SK_GPIO_DIR0;
+ val &= ~SK_GPIO_DAT0;
+ } else {
+ val |= SK_GPIO_DIR2;
+ val &= ~SK_GPIO_DAT2;
+ }
+ sk_win_write_4(sc, SK_GPIO, val);
+ }
+
+ /* Turn off various components of this interface. */
+ SK_XM_SETBIT_2(sc_if, XM_GPIO, XM_GPIO_RESETMAC);
+ switch (sc->sk_type) {
+ case SK_GENESIS:
+ SK_IF_WRITE_2(sc_if, 0, SK_TXF1_MACCTL,
+ SK_TXMACCTL_XMAC_RESET);
+ SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_RESET);
break;
- DELAY(1);
- }
- if (i == SK_TIMEOUT)
- printf("%s: cannot stop transfer of Tx descriptors\n",
- sc_if->sk_dev.dv_xname);
- /* stop transfer of Rx descriptors */
- SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_RX_STOP);
- for (i = 0; i < SK_TIMEOUT; i++) {
- val = SK_IF_READ_4(sc_if, 0, SK_RXQ1_BMU_CSR);
- if (!(val & SK_RXBMU_RX_STOP))
+ case SK_YUKON:
+ case SK_YUKON_LITE:
+ case SK_YUKON_LP:
+ 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);
break;
- DELAY(1);
- }
- if (i == SK_TIMEOUT)
- printf("%s: cannot stop transfer of Rx descriptors\n",
- sc_if->sk_dev.dv_xname);
-
- if (sc_if->sk_phytype == SK_PHYTYPE_BCOM) {
- u_int32_t val;
-
- /* Put PHY back into reset. */
- val = sk_win_read_4(sc, SK_GPIO);
- if (sc_if->sk_port == SK_PORT_A) {
- val |= SK_GPIO_DIR0;
- val &= ~SK_GPIO_DAT0;
- } else {
- val |= SK_GPIO_DIR2;
- val &= ~SK_GPIO_DAT2;
}
- sk_win_write_4(sc, SK_GPIO, val);
- }
+ 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_TXQS1_BMU_CSR, SK_TXBMU_OFFLINE);
+ SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_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_RXLEDCTL_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);
+
+ /* Disable interrupts */
+ if (sc_if->sk_port == SK_PORT_A)
+ sc->sk_intrmask &= ~SK_INTRS1;
+ else
+ sc->sk_intrmask &= ~SK_INTRS2;
+ CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask);
- /* Turn off various components of this interface. */
- SK_XM_SETBIT_2(sc_if, XM_GPIO, XM_GPIO_RESETMAC);
- switch (sc->sk_type) {
- case SK_GENESIS:
- SK_IF_WRITE_2(sc_if, 0, SK_TXF1_MACCTL,
- SK_TXMACCTL_XMAC_RESET);
- SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_RESET);
- break;
- case SK_YUKON:
- case SK_YUKON_LITE:
- case SK_YUKON_LP:
- 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);
- break;
+ SK_XM_READ_2(sc_if, XM_ISR);
+ SK_XM_WRITE_2(sc_if, XM_IMR, 0xFFFF);
}
- 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_TXQS1_BMU_CSR, SK_TXBMU_OFFLINE);
- SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_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_RXLEDCTL_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);
-
- /* Disable interrupts */
- if (sc_if->sk_port == SK_PORT_A)
- sc->sk_intrmask &= ~SK_INTRS1;
- else
- sc->sk_intrmask &= ~SK_INTRS2;
- CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask);
-
- SK_XM_READ_2(sc_if, XM_ISR);
- SK_XM_WRITE_2(sc_if, XM_IMR, 0xFFFF);
/* Free RX and TX mbufs still in the queues. */
for (i = 0; i < SK_RX_RING_CNT; i++) {
@@ -2879,7 +2881,7 @@ sk_dump_bytes(const char *data, int len)
if ((j & 0xf) == 7 && j > 0)
printf(" ");
}
-
+
for (; j < 16; j++)
printf(" ");
printf(" ");
@@ -2888,9 +2890,9 @@ sk_dump_bytes(const char *data, int len)
int ch = data[i + j] & 0xff;
printf("%c", ' ' <= ch && ch <= '~' ? ch : ' ');
}
-
+
printf("\n");
-
+
if (c < 16)
break;
}