Module Name: src Committed By: jdolecek Date: Wed Jun 13 19:37:23 UTC 2018
Modified Files: src/sys/dev/pci: if_msk.c if_mskvar.h Log Message: sync and adapt with OpenBSD if_msk.c rev. 1.43-1.65 (modulo some cosmetics, stuff we already had, or stuff which does not apply due to different frameworks): - Add support for fiber on 88E8021/22 - Avoid unnecessary resets. This should make fiber 88E8021/22 work completely - Only probe phy's at address 0; gets rid of bogus phy's on the Marvell Yukon 88E8036 - Remove an unused function msk_setfilt() which was copied from sk(4) - Make msk(4) detachable - Simplify the combination use of pci_mapreg_type()/pci_mapreg_map() To generate a diff of this commit: cvs rdiff -u -r1.62 -r1.63 src/sys/dev/pci/if_msk.c cvs rdiff -u -r1.13 -r1.14 src/sys/dev/pci/if_mskvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/if_msk.c diff -u src/sys/dev/pci/if_msk.c:1.62 src/sys/dev/pci/if_msk.c:1.63 --- src/sys/dev/pci/if_msk.c:1.62 Wed Jun 13 19:28:18 2018 +++ src/sys/dev/pci/if_msk.c Wed Jun 13 19:37:23 2018 @@ -1,5 +1,5 @@ -/* $NetBSD: if_msk.c,v 1.62 2018/06/13 19:28:18 jdolecek Exp $ */ -/* $OpenBSD: if_msk.c,v 1.42 2007/01/17 02:43:02 krw Exp $ */ +/* $NetBSD: if_msk.c,v 1.63 2018/06/13 19:37:23 jdolecek Exp $ */ +/* $OpenBSD: if_msk.c,v 1.65 2008/09/10 14:01:22 blambert Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -52,7 +52,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_msk.c,v 1.62 2018/06/13 19:28:18 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_msk.c,v 1.63 2018/06/13 19:37:23 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -94,10 +94,14 @@ __KERNEL_RCSID(0, "$NetBSD: if_msk.c,v 1 int mskc_probe(device_t, cfdata_t, void *); void mskc_attach(device_t, device_t, void *); +int mskc_detach(device_t, int); +void mskc_reset(struct sk_softc *); static bool mskc_suspend(device_t, const pmf_qual_t *); static bool mskc_resume(device_t, const pmf_qual_t *); int msk_probe(device_t, cfdata_t, void *); void msk_attach(device_t, device_t, void *); +int msk_detach(device_t, int); +void msk_reset(struct sk_if_softc *); int mskcprint(void *, const char *); int msk_intr(void *); void msk_intr_yukon(struct sk_if_softc *); @@ -110,7 +114,6 @@ int msk_init(struct ifnet *); void msk_init_yukon(struct sk_if_softc *); void msk_stop(struct ifnet *, int); void msk_watchdog(struct ifnet *); -void msk_reset(struct sk_softc *); int msk_newbuf(struct sk_if_softc *, int, struct mbuf *, bus_dmamap_t); int msk_alloc_jumbo_mem(struct sk_if_softc *); void *msk_jalloc(struct sk_if_softc *); @@ -124,7 +127,6 @@ int msk_miibus_readreg(device_t, int, in void msk_miibus_writereg(device_t, int, int, int); void msk_miibus_statchg(struct ifnet *); -void msk_setfilt(struct sk_if_softc *, void *, int); void msk_setmulti(struct sk_if_softc *); void msk_setpromisc(struct sk_if_softc *); void msk_tick(void *); @@ -330,17 +332,6 @@ msk_miibus_statchg(struct ifnet *ifp) } void -msk_setfilt(struct sk_if_softc *sc_if, void *addrv, int slot) -{ - char *addr = addrv; - int base = XM_RXFILT_ENTRY(slot); - - SK_XM_WRITE_2(sc_if, base, *(u_int16_t *)(&addr[0])); - SK_XM_WRITE_2(sc_if, base + 2, *(u_int16_t *)(&addr[2])); - SK_XM_WRITE_2(sc_if, base + 4, *(u_int16_t *)(&addr[4])); -} - -void msk_setmulti(struct sk_if_softc *sc_if) { struct ifnet *ifp= &sc_if->sk_ethercom.ec_if; @@ -819,12 +810,13 @@ mskc_probe(device_t parent, cfdata_t mat /* * Force the GEnesis into reset, then bring it out of reset. */ -void msk_reset(struct sk_softc *sc) +void +mskc_reset(struct sk_softc *sc) { u_int32_t imtimer_ticks, reg1; int reg; - DPRINTFN(2, ("msk_reset\n")); + DPRINTFN(2, ("mskc_reset\n")); CSR_WRITE_1(sc, SK_CSR, SK_CSR_SW_RESET); CSR_WRITE_1(sc, SK_CSR, SK_CSR_MASTER_RESET); @@ -891,8 +883,8 @@ void msk_reset(struct sk_softc *sc) sk_win_write_1(sc, SK_TESTCTL1, 1); - DPRINTFN(2, ("msk_reset: sk_csr=%x\n", CSR_READ_1(sc, SK_CSR))); - DPRINTFN(2, ("msk_reset: sk_link_ctrl=%x\n", + DPRINTFN(2, ("mskc_reset: sk_csr=%x\n", CSR_READ_1(sc, SK_CSR))); + DPRINTFN(2, ("mskc_reset: sk_link_ctrl=%x\n", CSR_READ_2(sc, SK_LINK_CTRL))); /* Disable ASF */ @@ -1023,6 +1015,18 @@ msk_probe(device_t parent, cfdata_t matc return (0); } +void +msk_reset(struct sk_if_softc *sc_if) +{ + /* GMAC and GPHY Reset */ + SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_RESET_SET); + SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, SK_GPHY_RESET_SET); + DELAY(1000); + SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, SK_GPHY_RESET_CLEAR); + SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_LOOP_OFF | + SK_GMAC_PAUSE_ON | SK_GMAC_RESET_CLEAR); +} + static bool msk_resume(device_t dv, const pmf_qual_t *qual) { @@ -1044,9 +1048,9 @@ msk_attach(device_t parent, device_t sel struct skc_attach_args *sa = aux; struct ifnet *ifp; void *kva; - bus_dma_segment_t seg; - int i, rseg; + int i; u_int32_t chunk; + int mii_flags; sc_if->sk_dev = self; sc_if->sk_port = sa->skc_port; @@ -1092,11 +1096,13 @@ msk_attach(device_t parent, device_t sel /* Allocate the descriptor queues. */ if (bus_dmamem_alloc(sc->sc_dmatag, sizeof(struct msk_ring_data), - PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) { + PAGE_SIZE, 0, &sc_if->sk_ring_seg, 1, &sc_if->sk_ring_nseg, + BUS_DMA_NOWAIT)) { aprint_error(": can't alloc rx buffers\n"); goto fail; } - if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, + if (bus_dmamem_map(sc->sc_dmatag, &sc_if->sk_ring_seg, + sc_if->sk_ring_nseg, sizeof(struct msk_ring_data), &kva, BUS_DMA_NOWAIT)) { aprint_error(": can't map dma buffers (%zu bytes)\n", sizeof(struct msk_ring_data)); @@ -1138,6 +1144,8 @@ msk_attach(device_t parent, device_t sel IFQ_SET_READY(&ifp->if_snd); strlcpy(ifp->if_xname, device_xname(sc_if->sk_dev), IFNAMSIZ); + msk_reset(sc_if); + /* * Do miibus setup. */ @@ -1153,8 +1161,11 @@ msk_attach(device_t parent, device_t sel sc_if->sk_ethercom.ec_mii = &sc_if->sk_mii; ifmedia_init(&sc_if->sk_mii.mii_media, 0, ether_mediachange, ether_mediastatus); - mii_attach(self, &sc_if->sk_mii, 0xffffffff, MII_PHY_ANY, - MII_OFFSET_ANY, MIIF_DOPAUSE|MIIF_FORCEANEG); + mii_flags = MIIF_DOPAUSE; + if (sc->sk_fibertype) + mii_flags |= MIIF_HAVEFIBER; + mii_attach(self, &sc_if->sk_mii, 0xffffffff, 0, + MII_OFFSET_ANY, mii_flags); if (LIST_FIRST(&sc_if->sk_mii.mii_phys) == NULL) { aprint_error_dev(sc_if->sk_dev, "no PHY found!\n"); ifmedia_add(&sc_if->sk_mii.mii_media, IFM_ETHER|IFM_MANUAL, @@ -1190,12 +1201,49 @@ fail_3: fail_2: bus_dmamem_unmap(sc->sc_dmatag, kva, sizeof(struct msk_ring_data)); fail_1: - bus_dmamem_free(sc->sc_dmatag, &seg, rseg); + bus_dmamem_free(sc->sc_dmatag, &sc_if->sk_ring_seg, sc_if->sk_ring_nseg); fail: sc->sk_if[sa->skc_port] = NULL; } int +msk_detach(device_t self, int flags) +{ + struct sk_if_softc *sc_if = (struct sk_if_softc *)self; + struct sk_softc *sc = sc_if->sk_softc; + struct ifnet *ifp = &sc_if->sk_ethercom.ec_if; + + if (sc->sk_if[sc_if->sk_port] == NULL) + return (0); + + rnd_detach_source(&sc->rnd_source); + + callout_halt(&sc_if->sk_tick_ch, NULL); + callout_destroy(&sc_if->sk_tick_ch); + + /* Detach any PHYs we might have. */ + if (LIST_FIRST(&sc_if->sk_mii.mii_phys) != NULL) + mii_detach(&sc_if->sk_mii, MII_PHY_ANY, MII_OFFSET_ANY); + + /* Delete any remaining media. */ + ifmedia_delete_instance(&sc_if->sk_mii.mii_media, IFM_INST_ANY); + + pmf_device_deregister(self); + + ether_ifdetach(ifp); + if_detach(ifp); + + bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_ring_map); + bus_dmamem_unmap(sc->sc_dmatag, 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); + sc->sk_if[sc_if->sk_port] = NULL; + + return (0); +} + +int mskcprint(void *aux, const char *pnp) { struct skc_attach_args *sa = aux; @@ -1224,12 +1272,10 @@ mskc_attach(device_t parent, device_t se const char *intrstr = NULL; bus_size_t size; int rc, sk_nodenum; - u_int8_t hw; + u_int8_t hw, pmd; const char *revstr = NULL; const struct sysctlnode *node; void *kva; - bus_dma_segment_t seg; - int rseg; char intrbuf[PCI_INTRSTR_LEN]; DPRINTFN(2, ("begin mskc_attach\n")); @@ -1268,17 +1314,9 @@ mskc_attach(device_t parent, device_t se /* * Map control/status registers. */ - memtype = pci_mapreg_type(pc, pa->pa_tag, SK_PCI_LOMEM); - switch (memtype) { - case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: - case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: - if (pci_mapreg_map(pa, SK_PCI_LOMEM, - memtype, 0, &sc->sk_btag, &sc->sk_bhandle, - NULL, &size) == 0) { - break; - } - default: + if (pci_mapreg_map(pa, SK_PCI_LOMEM, memtype, 0, &sc->sk_btag, + &sc->sk_bhandle, NULL, &size)) { aprint_error(": can't map mem space\n"); return; } @@ -1314,15 +1352,17 @@ mskc_attach(device_t parent, device_t se aprint_error("\n"); goto fail_1; } + sc->sk_pc = pc; if (bus_dmamem_alloc(sc->sc_dmatag, - MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), - PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) { + MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), PAGE_SIZE, + 0, &sc->sk_status_seg, 1, &sc->sk_status_nseg, BUS_DMA_NOWAIT)) { aprint_error(": can't alloc status buffers\n"); goto fail_2; } - if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, + if (bus_dmamem_map(sc->sc_dmatag, + &sc->sk_status_seg, sc->sk_status_nseg, MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), &kva, BUS_DMA_NOWAIT)) { aprint_error(": can't map dma buffers (%zu bytes)\n", @@ -1348,11 +1388,15 @@ mskc_attach(device_t parent, device_t se sc->sk_int_mod_pending = 0; /* Reset the adapter. */ - msk_reset(sc); + mskc_reset(sc); sc->sk_ramsize = sk_win_read_1(sc, SK_EPROM0) * 4096; DPRINTFN(2, ("mskc_attach: ramsize=%dK\n", sc->sk_ramsize / 1024)); + pmd = sk_win_read_1(sc, SK_PMDTYPE); + if (pmd == 'L' || pmd == 'S' || pmd == 'P') + sc->sk_fibertype = 1; + switch (sc->sk_type) { case SK_YUKON_XL: sc->sk_name = "Yukon-2 XL"; @@ -1597,11 +1641,42 @@ fail_4: bus_dmamem_unmap(sc->sc_dmatag, kva, MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc)); fail_3: - bus_dmamem_free(sc->sc_dmatag, &seg, rseg); + bus_dmamem_free(sc->sc_dmatag, + &sc->sk_status_seg, sc->sk_status_nseg); + sc->sk_status_nseg = 0; fail_2: pci_intr_disestablish(pc, sc->sk_intrhand); + sc->sk_intrhand = NULL; fail_1: bus_space_unmap(sc->sk_btag, sc->sk_bhandle, size); + sc->sk_bsize = 0; +} + +int +mskc_detach(device_t self, int flags) +{ + struct sk_softc *sc = (struct sk_softc *)self; + int rv; + + rv = config_detach_children(self, flags); + if (rv != 0) + return (rv); + + if (sc->sk_status_nseg > 0) { + bus_dmamap_destroy(sc->sc_dmatag, sc->sk_status_map); + bus_dmamem_unmap(sc->sc_dmatag, sc->sk_status_ring, + MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc)); + bus_dmamem_free(sc->sc_dmatag, + &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); + + return(0); } int @@ -1775,7 +1850,8 @@ msk_watchdog(struct ifnet *ifp) ifp->if_oerrors++; /* XXX Resets both ports; we shouldn't do that. */ - msk_reset(sc_if->sk_softc); + mskc_reset(sc_if->sk_softc); + msk_reset(sc_if); msk_init(ifp); } } @@ -1801,7 +1877,7 @@ mskc_resume(device_t dv, const pmf_qual_ DPRINTFN(2, ("mskc_resume\n")); - msk_reset(sc); + mskc_reset(sc); CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_ON); return true; @@ -1948,7 +2024,6 @@ msk_tick(void *xsc_if) { struct sk_if_softc *sc_if = xsc_if; struct mii_data *mii = &sc_if->sk_mii; - uint16_t gpsr; int s; s = splnet(); @@ -2102,17 +2177,6 @@ msk_init_yukon(struct sk_if_softc *sc_if DPRINTFN(6, ("msk_init_yukon: 1\n")); - /* GMAC and GPHY Reset */ - SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_RESET_SET); - SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, SK_GPHY_RESET_SET); - DELAY(1000); - - DPRINTFN(6, ("msk_init_yukon: 2\n")); - - SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, SK_GPHY_RESET_CLEAR); - SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_LOOP_OFF | - SK_GMAC_PAUSE_ON | SK_GMAC_RESET_CLEAR); - DPRINTFN(3, ("msk_init_yukon: gmac_ctrl=%#x\n", SK_IF_READ_4(sc_if, 0, SK_GMAC_CTRL))); @@ -2451,10 +2515,10 @@ msk_stop(struct ifnet *ifp, int disable) } CFATTACH_DECL_NEW(mskc, sizeof(struct sk_softc), mskc_probe, mskc_attach, - NULL, NULL); + mskc_detach, NULL); CFATTACH_DECL_NEW(msk, sizeof(struct sk_if_softc), msk_probe, msk_attach, - NULL, NULL); + msk_detach, NULL); #ifdef MSK_DEBUG void Index: src/sys/dev/pci/if_mskvar.h diff -u src/sys/dev/pci/if_mskvar.h:1.13 src/sys/dev/pci/if_mskvar.h:1.14 --- src/sys/dev/pci/if_mskvar.h:1.13 Mon Jun 11 19:13:38 2018 +++ src/sys/dev/pci/if_mskvar.h Wed Jun 13 19:37:23 2018 @@ -1,5 +1,5 @@ /* $OpenBSD: if_mskvar.h,v 1.3 2006/12/28 16:34:42 kettenis Exp $ */ -/* $NetBSD: if_mskvar.h,v 1.13 2018/06/11 19:13:38 jdolecek Exp $ */ +/* $NetBSD: if_mskvar.h,v 1.14 2018/06/13 19:37:23 jdolecek Exp $ */ /*- * Copyright (c) 2003 The NetBSD Foundation, Inc. @@ -187,7 +187,10 @@ struct sk_softc { device_t sk_dev; bus_space_handle_t sk_bhandle; /* bus space handle */ bus_space_tag_t sk_btag; /* bus space tag */ + bus_size_t sk_bsize; /* bus space size */ void *sk_intrhand; /* irq handler handle */ + pci_chipset_tag_t sk_pc; + u_int8_t sk_fibertype; u_int8_t sk_type; u_int8_t sk_rev; u_int32_t sk_workaround; @@ -202,6 +205,8 @@ struct sk_softc { struct sk_if_softc *sk_if[2]; struct msk_status_desc *sk_status_ring; bus_dmamap_t sk_status_map; + bus_dma_segment_t sk_status_seg; + int sk_status_nseg; int sk_status_idx; int sk_status_own_idx; krndsource_t rnd_source; @@ -224,6 +229,8 @@ struct sk_if_softc { struct msk_chain_data sk_cdata; struct msk_ring_data *sk_rdata; bus_dmamap_t sk_ring_map; + bus_dma_segment_t sk_ring_seg; + int sk_ring_nseg; int sk_status_idx; struct sk_softc *sk_softc; /* parent controller */ int sk_if_flags;