diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2015-11-29 20:19:36 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2015-11-29 20:19:36 +0000 |
commit | 9705f891c4a71954776c6718fdbe1f39e0139a3c (patch) | |
tree | e8bfd1c2027094fda8d615254decc2f66a50b747 /sys/dev/pci | |
parent | dc39e799c04fae1fa139fd43ae9ad029b8f954c9 (diff) |
Make it possible to detach bge(4).
ok deraadt@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_bge.c | 183 | ||||
-rw-r--r-- | sys/dev/pci/if_bgereg.h | 6 |
2 files changed, 117 insertions, 72 deletions
diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c index 710cccb2baf..a2f2f520f5f 100644 --- a/sys/dev/pci/if_bge.c +++ b/sys/dev/pci/if_bge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bge.c,v 1.379 2015/11/25 03:09:59 dlg Exp $ */ +/* $OpenBSD: if_bge.c,v 1.380 2015/11/29 20:19:35 kettenis Exp $ */ /* * Copyright (c) 2001 Wind River Systems @@ -118,10 +118,12 @@ const struct bge_revision * bge_lookup_rev(u_int32_t); int bge_can_use_msi(struct bge_softc *); int bge_probe(struct device *, void *, void *); void bge_attach(struct device *, struct device *, void *); +int bge_detach(struct device *, int); int bge_activate(struct device *, int); struct cfattach bge_ca = { - sizeof(struct bge_softc), bge_probe, bge_attach, NULL, bge_activate + sizeof(struct bge_softc), bge_probe, bge_attach, bge_detach, + bge_activate }; struct cfdriver bge_cd = { @@ -145,7 +147,7 @@ int bge_ioctl(struct ifnet *, u_long, caddr_t); int bge_rxrinfo(struct bge_softc *, struct if_rxrinfo *); void bge_init(void *); void bge_stop_block(struct bge_softc *, bus_size_t, u_int32_t); -void bge_stop(struct bge_softc *); +void bge_stop(struct bge_softc *, int); void bge_watchdog(struct ifnet *); int bge_ifmedia_upd(struct ifnet *); void bge_ifmedia_sts(struct ifnet *, struct ifmediareq *); @@ -2536,9 +2538,7 @@ bge_attach(struct device *parent, struct device *self, void *aux) pcireg_t pm_ctl, memtype, subid, reg; pci_intr_handle_t ih; const char *intrstr = NULL; - bus_size_t size, apesize; - bus_dma_segment_t seg; - int rseg, gotenaddr = 0; + int gotenaddr = 0; u_int32_t hwcfg = 0; u_int32_t mac_addr = 0; u_int32_t misccfg; @@ -2560,7 +2560,7 @@ bge_attach(struct device *parent, struct device *self, void *aux) DPRINTFN(5, ("pci_mapreg_map\n")); memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BGE_PCI_BAR0); if (pci_mapreg_map(pa, BGE_PCI_BAR0, memtype, 0, &sc->bge_btag, - &sc->bge_bhandle, NULL, &size, 0)) { + &sc->bge_bhandle, NULL, &sc->bge_bsize, 0)) { printf(": can't find mem space\n"); return; } @@ -2827,7 +2827,8 @@ bge_attach(struct device *parent, struct device *self, void *aux) if ((sc->bge_flags & BGE_APE) != 0) { memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BGE_PCI_BAR2); if (pci_mapreg_map(pa, BGE_PCI_BAR2, memtype, 0, - &sc->bge_apetag, &sc->bge_apehandle, NULL, &apesize, 0)) { + &sc->bge_apetag, &sc->bge_apehandle, NULL, + &sc->bge_apesize, 0)) { printf(": couldn't map BAR2 memory\n"); goto fail_1; } @@ -2944,14 +2945,15 @@ bge_attach(struct device *parent, struct device *self, void *aux) sc->bge_dmatag = pa->pa_dmat; DPRINTFN(5, ("bus_dmamem_alloc\n")); if (bus_dmamem_alloc(sc->bge_dmatag, sizeof(struct bge_ring_data), - PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) { + PAGE_SIZE, 0, &sc->bge_ring_seg, 1, &sc->bge_ring_nseg, + BUS_DMA_NOWAIT)) { printf(": can't alloc rx buffers\n"); goto fail_2; } DPRINTFN(5, ("bus_dmamem_map\n")); - if (bus_dmamem_map(sc->bge_dmatag, &seg, rseg, - sizeof(struct bge_ring_data), &kva, - BUS_DMA_NOWAIT)) { + if (bus_dmamem_map(sc->bge_dmatag, &sc->bge_ring_seg, + sc->bge_ring_nseg, sizeof(struct bge_ring_data), &kva, + BUS_DMA_NOWAIT)) { printf(": can't map dma buffers (%lu bytes)\n", sizeof(struct bge_ring_data)); goto fail_3; @@ -3134,18 +3136,54 @@ fail_5: bus_dmamap_destroy(sc->bge_dmatag, sc->bge_ring_map); fail_4: - bus_dmamem_unmap(sc->bge_dmatag, kva, + bus_dmamem_unmap(sc->bge_dmatag, (caddr_t)sc->bge_rdata, sizeof(struct bge_ring_data)); fail_3: - bus_dmamem_free(sc->bge_dmatag, &seg, rseg); + bus_dmamem_free(sc->bge_dmatag, &sc->bge_ring_seg, sc->bge_ring_nseg); fail_2: if ((sc->bge_flags & BGE_APE) != 0) - bus_space_unmap(sc->bge_apetag, sc->bge_apehandle, apesize); + bus_space_unmap(sc->bge_apetag, sc->bge_apehandle, + sc->bge_apesize); fail_1: - bus_space_unmap(sc->bge_btag, sc->bge_bhandle, size); + bus_space_unmap(sc->bge_btag, sc->bge_bhandle, sc->bge_bsize); +} + +int +bge_detach(struct device *self, int flags) +{ + struct bge_softc *sc = (struct bge_softc *)self; + struct ifnet *ifp = &sc->arpcom.ac_if; + + if (sc->bge_intrhand) + pci_intr_disestablish(sc->bge_pa.pa_pc, sc->bge_intrhand); + + bge_stop(sc, 1); + + /* Detach any PHYs we might have. */ + if (LIST_FIRST(&sc->bge_mii.mii_phys) != NULL) + mii_detach(&sc->bge_mii, MII_PHY_ANY, MII_OFFSET_ANY); + + /* Delete any remaining media. */ + ifmedia_delete_instance(&sc->bge_mii.mii_media, IFM_INST_ANY); + + ether_ifdetach(ifp); + if_detach(ifp); + + bus_dmamap_unload(sc->bge_dmatag, sc->bge_ring_map); + bus_dmamap_destroy(sc->bge_dmatag, sc->bge_ring_map); + bus_dmamem_unmap(sc->bge_dmatag, (caddr_t)sc->bge_rdata, + sizeof(struct bge_ring_data)); + bus_dmamem_free(sc->bge_dmatag, &sc->bge_ring_seg, sc->bge_ring_nseg); + + if ((sc->bge_flags & BGE_APE) != 0) + bus_space_unmap(sc->bge_apetag, sc->bge_apehandle, + sc->bge_apesize); + + bus_space_unmap(sc->bge_btag, sc->bge_bhandle, sc->bge_bsize); + return (0); } int @@ -3159,7 +3197,7 @@ bge_activate(struct device *self, int act) case DVACT_SUSPEND: rv = config_activate_children(self, act); if (ifp->if_flags & IFF_RUNNING) - bge_stop(sc); + bge_stop(sc, 0); break; case DVACT_RESUME: if (ifp->if_flags & IFF_UP) @@ -4155,7 +4193,7 @@ bge_init(void *xsc) ifp = &sc->arpcom.ac_if; /* Cancel pending I/O and flush buffers. */ - bge_stop(sc); + bge_stop(sc, 0); bge_sig_pre_reset(sc, BGE_RESET_START); bge_reset(sc); bge_sig_legacy(sc, BGE_RESET_START); @@ -4424,7 +4462,7 @@ bge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) bge_init(sc); } else { if (ifp->if_flags & IFF_RUNNING) - bge_stop(sc); + bge_stop(sc, 0); } break; @@ -4541,7 +4579,7 @@ bge_stop_block(struct bge_softc *sc, bus_size_t reg, u_int32_t bit) * RX and TX lists. */ void -bge_stop(struct bge_softc *sc) +bge_stop(struct bge_softc *sc, int softonly) { struct ifnet *ifp = &sc->arpcom.ac_if; struct ifmedia_entry *ifm; @@ -4556,62 +4594,63 @@ bge_stop(struct bge_softc *sc) ifq_clr_oactive(&ifp->if_snd); ifp->if_timer = 0; - /* - * Tell firmware we're shutting down. - */ - /* bge_stop_fw(sc); */ - bge_sig_pre_reset(sc, BGE_RESET_SHUTDOWN); - + if (!softonly) { + /* + * Tell firmware we're shutting down. + */ + /* bge_stop_fw(sc); */ + bge_sig_pre_reset(sc, BGE_RESET_SHUTDOWN); - /* - * Disable all of the receiver blocks - */ - bge_stop_block(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); - bge_stop_block(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); - bge_stop_block(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); - if (BGE_IS_5700_FAMILY(sc)) - bge_stop_block(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE); - bge_stop_block(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE); - bge_stop_block(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); - bge_stop_block(sc, BGE_RBDC_MODE, BGE_RBDCMODE_ENABLE); + /* + * Disable all of the receiver blocks + */ + bge_stop_block(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); + bge_stop_block(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); + bge_stop_block(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); + if (BGE_IS_5700_FAMILY(sc)) + bge_stop_block(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE); + bge_stop_block(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE); + bge_stop_block(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); + bge_stop_block(sc, BGE_RBDC_MODE, BGE_RBDCMODE_ENABLE); - /* - * Disable all of the transmit blocks - */ - bge_stop_block(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE); - bge_stop_block(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE); - bge_stop_block(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); - bge_stop_block(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE); - bge_stop_block(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE); - if (BGE_IS_5700_FAMILY(sc)) - bge_stop_block(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE); - bge_stop_block(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); + /* + * Disable all of the transmit blocks + */ + bge_stop_block(sc, BGE_SRS_MODE, BGE_SRSMODE_ENABLE); + bge_stop_block(sc, BGE_SBDI_MODE, BGE_SBDIMODE_ENABLE); + bge_stop_block(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); + bge_stop_block(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE); + bge_stop_block(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE); + if (BGE_IS_5700_FAMILY(sc)) + bge_stop_block(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE); + bge_stop_block(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); - /* - * Shut down all of the memory managers and related - * state machines. - */ - bge_stop_block(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE); - bge_stop_block(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE); - if (BGE_IS_5700_FAMILY(sc)) - bge_stop_block(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE); + /* + * Shut down all of the memory managers and related + * state machines. + */ + bge_stop_block(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE); + bge_stop_block(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE); + if (BGE_IS_5700_FAMILY(sc)) + bge_stop_block(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE); - CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF); - CSR_WRITE_4(sc, BGE_FTQ_RESET, 0); + CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF); + CSR_WRITE_4(sc, BGE_FTQ_RESET, 0); - if (!BGE_IS_5705_PLUS(sc)) { - bge_stop_block(sc, BGE_BMAN_MODE, BGE_BMANMODE_ENABLE); - bge_stop_block(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); - } + if (!BGE_IS_5705_PLUS(sc)) { + bge_stop_block(sc, BGE_BMAN_MODE, BGE_BMANMODE_ENABLE); + bge_stop_block(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); + } - bge_reset(sc); - bge_sig_legacy(sc, BGE_RESET_SHUTDOWN); - bge_sig_post_reset(sc, BGE_RESET_SHUTDOWN); + bge_reset(sc); + bge_sig_legacy(sc, BGE_RESET_SHUTDOWN); + bge_sig_post_reset(sc, BGE_RESET_SHUTDOWN); - /* - * Tell firmware we're shutting down. - */ - BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); + /* + * Tell firmware we're shutting down. + */ + BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); + } intr_barrier(sc->bge_intrhand); @@ -4644,8 +4683,10 @@ bge_stop(struct bge_softc *sc) sc->bge_tx_saved_considx = BGE_TXCONS_UNSET; - /* Clear MAC's link state (PHY may still have link UP). */ - BGE_STS_CLRBIT(sc, BGE_STS_LINK); + if (!softonly) { + /* Clear MAC's link state (PHY may still have link UP). */ + BGE_STS_CLRBIT(sc, BGE_STS_LINK); + } } void diff --git a/sys/dev/pci/if_bgereg.h b/sys/dev/pci/if_bgereg.h index 5181950fca6..597b9811b4d 100644 --- a/sys/dev/pci/if_bgereg.h +++ b/sys/dev/pci/if_bgereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bgereg.h,v 1.129 2015/11/10 20:20:34 miod Exp $ */ +/* $OpenBSD: if_bgereg.h,v 1.130 2015/11/29 20:19:35 kettenis Exp $ */ /* * Copyright (c) 2001 Wind River Systems @@ -2839,8 +2839,10 @@ struct bge_softc { struct arpcom arpcom; /* interface info */ bus_space_handle_t bge_bhandle; bus_space_tag_t bge_btag; + bus_size_t bge_bsize; bus_space_handle_t bge_apehandle; bus_space_tag_t bge_apetag; + bus_size_t bge_apesize; void *bge_intrhand; struct pci_attach_args bge_pa; struct mii_data bge_mii; @@ -2902,6 +2904,8 @@ struct bge_softc { struct bge_ring_data *bge_rdata; /* rings */ struct bge_chain_data bge_cdata; /* mbufs */ bus_dmamap_t bge_ring_map; + bus_dma_segment_t bge_ring_seg; + int bge_ring_nseg; u_int16_t bge_tx_saved_considx; u_int16_t bge_rx_saved_considx; u_int16_t bge_ev_saved_considx; |