From cdc9e06c493c4af33b25cde41e1f4493ed0c219b Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 21 Sep 2016 11:40:53 -0700 Subject: [PATCH 4/7] Add netdump hooks for vmxnet3, em, igb and bge --- sys/dev/bge/if_bge.c | 130 ++++++++++++++++++++++++++++++++++++------ sys/dev/e1000/if_em.c | 80 ++++++++++++++++++++++++++ sys/dev/e1000/if_igb.c | 96 +++++++++++++++++++++++++++++++ sys/dev/vmxnet3/vmxnet3.c | 90 +++++++++++++++++++++++++++++ sys/dev/vmxnet3/vmxnet3_int.h | 2 + sys/dev/vmxnet3/vmxnet3_tx.c | 4 +- 6 files changed, 385 insertions(+), 17 deletions(-) diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c index 46fd68d..9c18119 100644 --- a/sys/dev/bge/if_bge.c +++ b/sys/dev/bge/if_bge.c @@ -98,6 +98,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -554,6 +555,10 @@ SYSCTL_INT(_hw_bge, OID_AUTO, allow_asf, CTLFLAG_RD, &bge_allow_asf, 0, #define SPARC64_BLADE_2500_PATH_BGE "/pci@1c,600000/network@3" #define SPARC64_OFW_SUBVENDOR "subsystem-vendor-id" +/* Begin Isilon */ +NETDUMP_DEFINE(bge); +/* End Isilon */ + static int bge_has_eaddr(struct bge_softc *sc) { @@ -3761,6 +3766,13 @@ bge_attach(device_t dev) ifp->if_hwassist = 0; } + /* Begin Isilon */ + /* + * Attach driver netdump methods. + */ + NETDUMP_SET(ifp, bge); + /* End Isilon */ + /* * Figure out what sort of media we have by checking the * hardware config word in the first 32k of NIC internal memory, @@ -5328,6 +5340,26 @@ bge_encap(struct bge_softc *sc, struct mbuf **m_head, uint32_t *txidx) return (0); } +static void +bge_start_tx(struct bge_softc *sc, uint32_t prodidx) +{ + + bus_dmamap_sync(sc->bge_cdata.bge_tx_ring_tag, + sc->bge_cdata.bge_tx_ring_map, BUS_DMASYNC_PREWRITE); + /* Transmit. */ + bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); + /* 5700 b2 errata */ + if (sc->bge_chiprev == BGE_CHIPREV_5700_BX) + bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); + + sc->bge_tx_prodidx = prodidx; + + /* + * Set a timeout in case the chip goes out to lunch. + */ + sc->bge_timer = BGE_TX_TIMEOUT; +} + /* * Main transmit routine. To avoid having to do mbuf copies, we put pointers * to the mbuf data regions directly in the transmit descriptors. @@ -5384,22 +5416,8 @@ bge_start_locked(struct ifnet *ifp) #endif } - if (count > 0) { - bus_dmamap_sync(sc->bge_cdata.bge_tx_ring_tag, - sc->bge_cdata.bge_tx_ring_map, BUS_DMASYNC_PREWRITE); - /* Transmit. */ - bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); - /* 5700 b2 errata */ - if (sc->bge_chiprev == BGE_CHIPREV_5700_BX) - bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); - - sc->bge_tx_prodidx = prodidx; - - /* - * Set a timeout in case the chip goes out to lunch. - */ - sc->bge_timer = BGE_TX_TIMEOUT; - } + if (count > 0) + bge_start_tx(sc, prodidx); } /* @@ -6774,3 +6792,83 @@ bge_get_eaddr(struct bge_softc *sc, uint8_t eaddr[]) } return (*func == NULL ? ENXIO : 0); } + +/* Begin Isilon */ +#ifdef NETDUMP +static void +bge_netdump_init(struct ifnet *ifp, struct mbufq *hdrs, struct mbufq *bufs) +{ + struct bge_softc *sc; + struct mbuf *m; + + sc = ifp->if_softc; + for (int i = 0; i < sc->bge_return_ring_cnt; i++) { + m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR); + mbufq_enqueue(bufs, m); + } +} + +static void +bge_netdump_event(struct ifnet *ifp, enum netdump_ev event) +{ + struct bge_softc *sc; + + sc = ifp->if_softc; + switch (event) { + case NETDUMP_START: + bge_writembx(sc, BGE_MBX_IRQ0_LO, 1); + break; + case NETDUMP_END: + bge_writembx(sc, BGE_MBX_IRQ0_LO, 0); + break; + } +} + +static int +bge_netdump_transmit(struct ifnet *ifp, struct mbuf *m) +{ + struct bge_softc *sc; + uint32_t prodidx; + int error; + + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING) + return (1); + + sc = ifp->if_softc; + prodidx = sc->bge_tx_prodidx; + error = bge_encap(sc, &m, &prodidx); + if (error == 0) + bge_start_tx(sc, prodidx); + return (error); +} + +static int +bge_netdump_poll(struct ifnet *ifp, int count) +{ + struct bge_softc *sc; + uint16_t rx_prod, tx_cons; + + sc = ifp->if_softc; + + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING) + return (1); + + bus_dmamap_sync(sc->bge_cdata.bge_status_tag, + sc->bge_cdata.bge_status_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + + rx_prod = sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx; + tx_cons = sc->bge_ldata.bge_status_block->bge_idx[0].bge_tx_cons_idx; + + bus_dmamap_sync(sc->bge_cdata.bge_status_tag, + sc->bge_cdata.bge_status_map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + + (void)bge_rxeof(sc, rx_prod, 0); + bge_txeof(sc, tx_cons); + return (0); +} +#endif /* NETDUMP */ +/* End Isilon */ diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index ca1a422..a39617d 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -79,6 +79,9 @@ #include #include #include +/* Begin Isilon */ +#include +/* End Isilon */ #include #include @@ -348,6 +351,10 @@ DRIVER_MODULE(em, pci, em_driver, em_devclass, 0, 0); MODULE_DEPEND(em, pci, 1, 1, 1); MODULE_DEPEND(em, ether, 1, 1, 1); +/* Begin Isilon */ +NETDUMP_DEFINE(em); +/* End Isilon */ + /********************************************************************* * Tunable default values. *********************************************************************/ @@ -838,6 +845,13 @@ em_attach(device_t dev) em_netmap_attach(adapter); #endif /* DEV_NETMAP */ + /* Begin Isilon */ + /* + * Attach driver netdump methods. + */ + NETDUMP_SET(adapter->ifp, em); + /* End Isilon */ + INIT_DEBUGOUT("em_attach: end"); return (0); @@ -6364,3 +6378,69 @@ em_print_debug_info(struct adapter *adapter) device_printf(dev, "RX Next to Check = %d\n", rxr->next_to_check); device_printf(dev, "RX Next to Refresh = %d\n", rxr->next_to_refresh); } + +/* Begin Isilon */ +#ifdef NETDUMP +static void +em_netdump_init(struct ifnet *ifp, struct mbufq *hdrs, struct mbufq *bufs) +{ + struct adapter *adapter; + struct mbuf *m; + + adapter = ifp->if_softc; + + for (int i = 0; i < adapter->num_queues * NETDUMP_MAX_IN_FLIGHT; i++) { + m = m_getjcl(M_WAITOK, MT_DATA, M_PKTHDR, adapter->rx_mbuf_sz); + mbufq_enqueue(bufs, m); + } +} + +static void +em_netdump_event(struct ifnet *ifp, enum netdump_ev event) +{ + struct adapter *adapter; + + adapter = ifp->if_softc; + switch (event) { + case NETDUMP_START: + em_disable_intr(adapter); + break; + case NETDUMP_END: + em_enable_intr(adapter); + break; + } +} + +static int +em_netdump_transmit(struct ifnet *ifp, struct mbuf *m) +{ + struct adapter *adapter; + struct tx_ring *txr; + + adapter = ifp->if_softc; + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING || adapter->link_active == 0) + return (1); + + txr = &adapter->tx_rings[0]; + return (em_xmit(txr, &m)); +} + +static int +em_netdump_poll(struct ifnet *ifp, int count) +{ + struct adapter *adapter; + + adapter = ifp->if_softc; + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING || adapter->link_active == 0) + return (1); + + for (int i = 0; i < adapter->num_queues; i++) + (void)em_rxeof(&adapter->rx_rings[i], count, NULL); + + (void)em_txeof(&adapter->tx_rings[0]); + return (0); +} +#endif /* NETDUMP */ +/* End Isilon */ diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index 80cca43..06ac3a5 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -81,6 +81,9 @@ #include #include #include +/* Begin Isilon */ +#include +/* End Isilon */ #include #include #include @@ -294,6 +297,10 @@ static int igb_sysctl_eee(SYSCTL_HANDLER_ARGS); static poll_handler_t igb_poll; #endif /* POLLING */ +/* Begin Isilon */ +NETDUMP_DEFINE(igb); +/* End Isilon */ + /********************************************************************* * FreeBSD Device Interface Entry Points *********************************************************************/ @@ -718,6 +725,14 @@ igb_attach(device_t dev) #ifdef DEV_NETMAP igb_netmap_attach(adapter); #endif /* DEV_NETMAP */ + + /* Begin Isilon */ + /* + * Attach driver netdump methods. + */ + NETDUMP_SET(adapter->ifp, igb); + /* End Isilon */ + INIT_DEBUGOUT("igb_attach: end"); return (0); @@ -6129,3 +6144,84 @@ igb_sysctl_eee(SYSCTL_HANDLER_ARGS) IGB_CORE_UNLOCK(adapter); return (0); } + +/* Begin Isilon */ +#ifdef NETDUMP +/* + * Netdump methods, for use after a panic. + * + * XXX we probably need to have the driver call a reinit method whenever + * appropriate - num_queues/rx_mbuf_sz/hdr_split may change at that point. + * XXX we probably want to present statistics showing netdump memory usage. + */ +static void +igb_netdump_init(struct ifnet *ifp, struct mbufq *hdrs, struct mbufq *bufs) +{ + struct adapter *adapter; + struct mbuf *m; + + adapter = ifp->if_softc; + + for (int i = 0; i < adapter->num_queues * NETDUMP_MAX_IN_FLIGHT; i++) { + m = m_getjcl(M_WAITOK, MT_DATA, M_PKTHDR, adapter->rx_mbuf_sz); + mbufq_enqueue(bufs, m); + if (adapter->rx_rings[i].hdr_split) { + m = m_gethdr(M_WAITOK, MT_DATA); + mbufq_enqueue(hdrs, m); + } + } +} + +static void +igb_netdump_event(struct ifnet *ifp, enum netdump_ev event) +{ + struct adapter *adapter; + + adapter = ifp->if_softc; + switch (event) { + case NETDUMP_START: + igb_disable_intr(adapter); + break; + case NETDUMP_END: + /* + * XXX what if interrupts were already disabled? it's probably a + * bug to netdump in that case - what if we're re-initing? + */ + igb_enable_intr(adapter); + break; + } +} + +static int +igb_netdump_transmit(struct ifnet *ifp, struct mbuf *m) +{ + struct adapter *adapter; + struct tx_ring *txr; + + adapter = ifp->if_softc; + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING || adapter->link_active == 0) + return (1); + + txr = &adapter->tx_rings[0]; + return (igb_xmit(txr, &m)); +} + +static int +igb_netdump_poll(struct ifnet *ifp, int count) +{ + struct adapter *adapter; + + adapter = ifp->if_softc; + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING || adapter->link_active == 0) + return (1); + + for (int i = 0; i < adapter->num_queues; i++) + (void)igb_rxeof(&adapter->queues[i], count, NULL); + + (void)igb_txeof(&adapter->tx_rings[0]); + return (0); +} +#endif /* NETDUMP */ +/* End Isilon */ diff --git a/sys/dev/vmxnet3/vmxnet3.c b/sys/dev/vmxnet3/vmxnet3.c index 0892946..dc284e4 100644 --- a/sys/dev/vmxnet3/vmxnet3.c +++ b/sys/dev/vmxnet3/vmxnet3.c @@ -29,11 +29,18 @@ #include #include "vmxnet3_int.h" +/* Begin Isilon */ +#include +/* End Isilon */ + const static char *vmxnet3_driver_version = "0.2.0.0"; const uint32_t vmxnet3_num_driver_version = 0x00020000; static void vmxnet3_watchdog_locked(struct ifnet *ifp, vmxnet3_adapter_t *sc); +/* Begin Isilon */ +NETDUMP_DEFINE(vmxnet3); +/* End Isilon */ /* *----------------------------------------------------------------------------- @@ -2368,6 +2375,12 @@ vmxnet3_pci_attach(device_t dev) ifp->if_data.ifi_addrlen = 6; ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); + /* Begin Isilon */ + /* + * Attach driver netdump methods. + */ + NETDUMP_SET(ifp, vmxnet3); + /* End Isilon */ /* Allocate DMA resources, tx and rx queues */ if ((error = vmxnet3_alloc_dma_resources(sc))) @@ -2834,4 +2847,81 @@ static devclass_t vmxnet3_devclass; DRIVER_MODULE(vmxnet3, pci, vmxnet3_pci_driver, vmxnet3_devclass, 0, 0); +/* Begin Isilon */ +#ifdef NETDUMP +static void +vmxnet3_netdump_init(struct ifnet *ifp, struct mbufq *hdrs, struct mbufq *bufs) +{ + vmxnet3_adapter_t *sc = ifp->if_softc; + struct mbuf *m; + int max_frame_size, rx_mbuf_size; + + max_frame_size = sc->cur_mtu + ETHER_HDR_LEN + ETHERNET_FCS_SIZE + + ETHER_ALIGN; + if (max_frame_size > MJUMPAGESIZE) + rx_mbuf_size = MJUM9BYTES; + else if (max_frame_size > MCLBYTES) + rx_mbuf_size = MJUMPAGESIZE; + else + rx_mbuf_size = MCLBYTES; + /* We always only have one queue. */ + for (int i = 0; i < sc->num_rx_queues * NETDUMP_MAX_IN_FLIGHT; i++) { + m = m_getjcl(M_WAITOK, MT_DATA, M_PKTHDR, rx_mbuf_size); + mbufq_enqueue(bufs, m); + } +} + +static void +vmxnet3_netdump_event(struct ifnet *ifp, enum netdump_ev event) +{ + vmxnet3_adapter_t *sc = ifp->if_softc; + + switch (event) { + case NETDUMP_START: + vmxnet3_disable_all_intrs(sc); + break; + case NETDUMP_END: + /* + * XXX what if interrupts were already disabled? it's probably a + * bug to netdump in that case - what if we're re-initing? + */ + vmxnet3_enable_all_intrs(sc); + break; + } +} + +static int +vmxnet3_netdump_transmit(struct ifnet *ifp, struct mbuf *m) +{ + vmxnet3_adapter_t *sc = ifp->if_softc; + vmxnet3_tx_queue_t *tq = &sc->tx_queue[0]; + + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING || tq->stopped) + return (1); + + return (vmxnet3_encap(sc, &m)); +} + +static int +vmxnet3_netdump_poll(struct ifnet *ifp, int count) +{ + vmxnet3_adapter_t *sc = ifp->if_softc; + + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING) + return (1); + + VMXNET3_LOCK(sc); + vmxnet3_rq_rx_complete(sc, sc->rx_queue); + VMXNET3_LOCK_TX(sc->tx_queue); + vmxnet3_tq_tx_complete(sc, sc->tx_queue); + VMXNET3_UNLOCK_TX(sc->tx_queue); + VMXNET3_UNLOCK(sc); + + return (0); +} + +#endif /* NETDUMP */ +/* End Isilon */ /* vim: set tabstop=3 shiftwidth=3 expandtab : */ diff --git a/sys/dev/vmxnet3/vmxnet3_int.h b/sys/dev/vmxnet3/vmxnet3_int.h index b09d63d..31a3542 100644 --- a/sys/dev/vmxnet3/vmxnet3_int.h +++ b/sys/dev/vmxnet3/vmxnet3_int.h @@ -427,6 +427,8 @@ void vmxnet3_rq_rx_complete(vmxnet3_adapter_t *sc, vmxnet3_rx_queue_t *rq); void vmxnet3_tq_tx_complete(vmxnet3_adapter_t *sc, vmxnet3_tx_queue_t *tq); /* Begin Isilon */ +int vmxnet3_encap(vmxnet3_adapter_t *sc, struct mbuf **m_header); + void vmxnet3_fill_rx(vmxnet3_adapter_t *, vmxnet3_rx_queue_t *); void vmxnet3_empty_rx(vmxnet3_adapter_t *sc, vmxnet3_rx_queue_t *rq); void vmxnet3_empty_tx(vmxnet3_adapter_t *sc, vmxnet3_tx_queue_t *tq); diff --git a/sys/dev/vmxnet3/vmxnet3_tx.c b/sys/dev/vmxnet3/vmxnet3_tx.c index 976a02d..4a22d38 100644 --- a/sys/dev/vmxnet3/vmxnet3_tx.c +++ b/sys/dev/vmxnet3/vmxnet3_tx.c @@ -484,7 +484,9 @@ vmxnet3_unmap_pkt(struct Vmxnet3_TxCompDesc *tcd, vmxnet3_tx_queue_t *tq, *----------------------------------------------------------------------------- */ -static int +/* Begin Isilon */ +int +/* End Isilon */ vmxnet3_encap(vmxnet3_adapter_t *sc, struct mbuf **m_header) { int count = 0; -- 2.10.1