diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-08-20 15:53:03 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-21 10:29:39 +0200 |
commit | 18fa92c2dcc6c52e0bf27d214d80f0c25a89b47d (patch) | |
tree | a3020ac5b1f366f2f0920941b589808e435dbcee /freebsd/sys | |
parent | Update to FreeBSD head 2017-12-01 (diff) | |
download | rtems-libbsd-18fa92c2dcc6c52e0bf27d214d80f0c25a89b47d.tar.bz2 |
Update to FreeBSD head 2018-02-01
Git mirror commit d079ae0442af8fa3cfd6d7ede190d04e64a2c0d4.
Update #3472.
Diffstat (limited to 'freebsd/sys')
165 files changed, 2612 insertions, 3843 deletions
diff --git a/freebsd/sys/arm/lpc/if_lpe.c b/freebsd/sys/arm/lpc/if_lpe.c deleted file mode 100755 index 99016be3..00000000 --- a/freebsd/sys/arm/lpc/if_lpe.c +++ /dev/null @@ -1,1414 +0,0 @@ -#include <machine/rtems-bsd-kernel-space.h> - -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2011 Jakub Wojciech Klama <jceel@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/endian.h> -#include <sys/systm.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/rman.h> -#include <sys/bus.h> -#include <sys/socket.h> -#include <machine/bus.h> -#ifndef __rtems__ -#include <machine/intr.h> -#endif /* __rtems__ */ - -#include <net/if.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_types.h> -#include <net/if_var.h> - -#include <net/bpf.h> - -#ifndef __rtems__ -#include <dev/ofw/ofw_bus.h> -#include <dev/ofw/ofw_bus_subr.h> -#endif /* __rtems__ */ - -#include <dev/mii/mii.h> -#include <dev/mii/miivar.h> - -#include <arm/lpc/lpcreg.h> -#include <arm/lpc/lpcvar.h> -#include <arm/lpc/if_lpereg.h> - -#include <rtems/bsd/local/miibus_if.h> -#ifdef __rtems__ -#include <machine/rtems-bsd-cache.h> -#endif /* __rtems__ */ - -#ifdef DEBUG -#define debugf(fmt, args...) do { printf("%s(): ", __func__); \ - printf(fmt,##args); } while (0) -#else -#define debugf(fmt, args...) -#endif - -struct lpe_dmamap_arg { - bus_addr_t lpe_dma_busaddr; -}; - -struct lpe_rxdesc { - struct mbuf * lpe_rxdesc_mbuf; -#ifndef __rtems__ - bus_dmamap_t lpe_rxdesc_dmamap; -#endif /* __rtems__ */ -}; - -struct lpe_txdesc { - int lpe_txdesc_first; - struct mbuf * lpe_txdesc_mbuf; -#ifndef __rtems__ - bus_dmamap_t lpe_txdesc_dmamap; -#endif /* __rtems__ */ -}; - -struct lpe_chain_data { - bus_dma_tag_t lpe_parent_tag; - bus_dma_tag_t lpe_tx_ring_tag; - bus_dmamap_t lpe_tx_ring_map; - bus_dma_tag_t lpe_tx_status_tag; - bus_dmamap_t lpe_tx_status_map; - bus_dma_tag_t lpe_tx_buf_tag; - bus_dma_tag_t lpe_rx_ring_tag; - bus_dmamap_t lpe_rx_ring_map; - bus_dma_tag_t lpe_rx_status_tag; - bus_dmamap_t lpe_rx_status_map; - bus_dma_tag_t lpe_rx_buf_tag; - struct lpe_rxdesc lpe_rx_desc[LPE_RXDESC_NUM]; - struct lpe_txdesc lpe_tx_desc[LPE_TXDESC_NUM]; - int lpe_tx_prod; - int lpe_tx_last; - int lpe_tx_used; -}; - -struct lpe_ring_data { - struct lpe_hwdesc * lpe_rx_ring; - struct lpe_hwstatus * lpe_rx_status; - bus_addr_t lpe_rx_ring_phys; - bus_addr_t lpe_rx_status_phys; - struct lpe_hwdesc * lpe_tx_ring; - struct lpe_hwstatus * lpe_tx_status; - bus_addr_t lpe_tx_ring_phys; - bus_addr_t lpe_tx_status_phys; -}; - -struct lpe_softc { - struct ifnet * lpe_ifp; - struct mtx lpe_mtx; -#ifndef __rtems__ - phandle_t lpe_ofw; -#endif /* __rtems__ */ - device_t lpe_dev; - device_t lpe_miibus; - uint8_t lpe_enaddr[6]; - struct resource * lpe_mem_res; - struct resource * lpe_irq_res; - void * lpe_intrhand; - bus_space_tag_t lpe_bst; - bus_space_handle_t lpe_bsh; -#define LPE_FLAG_LINK (1 << 0) - uint32_t lpe_flags; - int lpe_watchdog_timer; - struct callout lpe_tick; - struct lpe_chain_data lpe_cdata; - struct lpe_ring_data lpe_rdata; -}; - -static int lpe_probe(device_t); -static int lpe_attach(device_t); -static int lpe_detach(device_t); -static int lpe_miibus_readreg(device_t, int, int); -static int lpe_miibus_writereg(device_t, int, int, int); -static void lpe_miibus_statchg(device_t); - -static void lpe_reset(struct lpe_softc *); -static void lpe_init(void *); -static void lpe_init_locked(struct lpe_softc *); -static void lpe_start(struct ifnet *); -static void lpe_start_locked(struct ifnet *); -static void lpe_stop(struct lpe_softc *); -static void lpe_stop_locked(struct lpe_softc *); -static int lpe_ioctl(struct ifnet *, u_long, caddr_t); -static void lpe_set_rxmode(struct lpe_softc *); -static void lpe_set_rxfilter(struct lpe_softc *); -static void lpe_intr(void *); -static void lpe_rxintr(struct lpe_softc *); -static void lpe_txintr(struct lpe_softc *); -static void lpe_tick(void *); -static void lpe_watchdog(struct lpe_softc *); -static int lpe_encap(struct lpe_softc *, struct mbuf **); -static int lpe_dma_alloc(struct lpe_softc *); -static int lpe_dma_alloc_rx(struct lpe_softc *); -static int lpe_dma_alloc_tx(struct lpe_softc *); -static int lpe_init_rx(struct lpe_softc *); -static int lpe_init_rxbuf(struct lpe_softc *, int); -static void lpe_discard_rxbuf(struct lpe_softc *, int); -static void lpe_dmamap_cb(void *, bus_dma_segment_t *, int, int); -static int lpe_ifmedia_upd(struct ifnet *); -static void lpe_ifmedia_sts(struct ifnet *, struct ifmediareq *); - -#define lpe_lock(_sc) mtx_lock(&(_sc)->lpe_mtx) -#define lpe_unlock(_sc) mtx_unlock(&(_sc)->lpe_mtx) -#define lpe_lock_assert(_sc) mtx_assert(&(_sc)->lpe_mtx, MA_OWNED) - -#define lpe_read_4(_sc, _reg) \ - bus_space_read_4((_sc)->lpe_bst, (_sc)->lpe_bsh, (_reg)) -#define lpe_write_4(_sc, _reg, _val) \ - bus_space_write_4((_sc)->lpe_bst, (_sc)->lpe_bsh, (_reg), (_val)) - -#define LPE_HWDESC_RXERRS (LPE_HWDESC_CRCERROR | LPE_HWDESC_SYMBOLERROR | \ - LPE_HWDESC_LENGTHERROR | LPE_HWDESC_ALIGNERROR | LPE_HWDESC_OVERRUN | \ - LPE_HWDESC_RXNODESCR) - -#define LPE_HWDESC_TXERRS (LPE_HWDESC_EXCDEFER | LPE_HWDESC_EXCCOLL | \ - LPE_HWDESC_LATECOLL | LPE_HWDESC_UNDERRUN | LPE_HWDESC_TXNODESCR) - -static int -lpe_probe(device_t dev) -{ - -#ifndef __rtems__ - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "lpc,ethernet")) - return (ENXIO); -#endif /* __rtems__ */ - - device_set_desc(dev, "LPC32x0 10/100 Ethernet"); - return (BUS_PROBE_DEFAULT); -} - -static int -lpe_attach(device_t dev) -{ - struct lpe_softc *sc = device_get_softc(dev); - struct ifnet *ifp; - int rid, i; - uint32_t val; - - sc->lpe_dev = dev; -#ifndef __rtems__ - sc->lpe_ofw = ofw_bus_get_node(dev); - - i = OF_getprop(sc->lpe_ofw, "local-mac-address", (void *)&sc->lpe_enaddr, 6); - if (i != 6) { - sc->lpe_enaddr[0] = 0x00; - sc->lpe_enaddr[1] = 0x11; - sc->lpe_enaddr[2] = 0x22; - sc->lpe_enaddr[3] = 0x33; - sc->lpe_enaddr[4] = 0x44; - sc->lpe_enaddr[5] = 0x55; - } -#else /* __rtems__ */ - rtems_bsd_get_mac_address(device_get_name(sc->lpe_dev), device_get_unit(sc->lpe_dev), &sc->lpe_enaddr); -#endif /* __rtems__ */ - - mtx_init(&sc->lpe_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, - MTX_DEF); - - callout_init_mtx(&sc->lpe_tick, &sc->lpe_mtx, 0); - - rid = 0; - sc->lpe_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, - RF_ACTIVE); - if (!sc->lpe_mem_res) { - device_printf(dev, "cannot allocate memory window\n"); - goto fail; - } - - sc->lpe_bst = rman_get_bustag(sc->lpe_mem_res); - sc->lpe_bsh = rman_get_bushandle(sc->lpe_mem_res); - - rid = 0; - sc->lpe_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, - RF_ACTIVE); - if (!sc->lpe_irq_res) { - device_printf(dev, "cannot allocate interrupt\n"); - goto fail; - } - - sc->lpe_ifp = if_alloc(IFT_ETHER); - if (!sc->lpe_ifp) { - device_printf(dev, "cannot allocated ifnet\n"); - goto fail; - } - - ifp = sc->lpe_ifp; - - if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - ifp->if_softc = sc; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_start = lpe_start; - ifp->if_ioctl = lpe_ioctl; - ifp->if_init = lpe_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; - IFQ_SET_READY(&ifp->if_snd); - - ether_ifattach(ifp, sc->lpe_enaddr); - - if (bus_setup_intr(dev, sc->lpe_irq_res, INTR_TYPE_NET, NULL, - lpe_intr, sc, &sc->lpe_intrhand)) { - device_printf(dev, "cannot establish interrupt handler\n"); - ether_ifdetach(ifp); - goto fail; - } - - /* Enable Ethernet clock */ -#ifndef __rtems__ - lpc_pwr_write(dev, LPC_CLKPWR_MACCLK_CTRL, - LPC_CLKPWR_MACCLK_CTRL_REG | - LPC_CLKPWR_MACCLK_CTRL_SLAVE | - LPC_CLKPWR_MACCLK_CTRL_MASTER | - LPC_CLKPWR_MACCLK_CTRL_HDWINF(3)); -#else /* __rtems__ */ -#ifdef LPC32XX_ETHERNET_RMII - lpc_pwr_write(dev, LPC_CLKPWR_MACCLK_CTRL, - LPC_CLKPWR_MACCLK_CTRL_REG | - LPC_CLKPWR_MACCLK_CTRL_SLAVE | - LPC_CLKPWR_MACCLK_CTRL_MASTER | - LPC_CLKPWR_MACCLK_CTRL_HDWINF(3)); -#else - lpc_pwr_write(dev, LPC_CLKPWR_MACCLK_CTRL, - LPC_CLKPWR_MACCLK_CTRL_REG | - LPC_CLKPWR_MACCLK_CTRL_SLAVE | - LPC_CLKPWR_MACCLK_CTRL_MASTER | - LPC_CLKPWR_MACCLK_CTRL_HDWINF(1)); -#endif -#endif /* __rtems__ */ - - /* Reset chip */ - lpe_reset(sc); - - /* Initialize MII */ -#ifndef __rtems__ - val = lpe_read_4(sc, LPE_COMMAND); - lpe_write_4(sc, LPE_COMMAND, val | LPE_COMMAND_RMII); - - if (mii_attach(dev, &sc->lpe_miibus, ifp, lpe_ifmedia_upd, - lpe_ifmedia_sts, BMSR_DEFCAPMASK, 0x01, - MII_OFFSET_ANY, 0)) { - device_printf(dev, "cannot find PHY\n"); - goto fail; - } -#else /* __rtems__ */ - if (mii_attach(dev, &sc->lpe_miibus, ifp, lpe_ifmedia_upd, - lpe_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, - MII_OFFSET_ANY, 0)) { - device_printf(dev, "cannot find PHY\n"); - goto fail; - } -#endif /* __rtems__ */ - - lpe_dma_alloc(sc); - - return (0); - -fail: - if (sc->lpe_ifp) - if_free(sc->lpe_ifp); - if (sc->lpe_intrhand) - bus_teardown_intr(dev, sc->lpe_irq_res, sc->lpe_intrhand); - if (sc->lpe_irq_res) - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->lpe_irq_res); - if (sc->lpe_mem_res) - bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lpe_mem_res); - return (ENXIO); -} - -static int -lpe_detach(device_t dev) -{ - struct lpe_softc *sc = device_get_softc(dev); - - lpe_stop(sc); - - if_free(sc->lpe_ifp); - bus_teardown_intr(dev, sc->lpe_irq_res, sc->lpe_intrhand); - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->lpe_irq_res); - bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lpe_mem_res); - - return (0); -} - -static int -lpe_miibus_readreg(device_t dev, int phy, int reg) -{ - struct lpe_softc *sc = device_get_softc(dev); - uint32_t val; - int result; - - lpe_write_4(sc, LPE_MCMD, LPE_MCMD_READ); - lpe_write_4(sc, LPE_MADR, - (reg & LPE_MADR_REGMASK) << LPE_MADR_REGSHIFT | - (phy & LPE_MADR_PHYMASK) << LPE_MADR_PHYSHIFT); - - val = lpe_read_4(sc, LPE_MIND); - - /* Wait until request is completed */ - while (val & LPE_MIND_BUSY) { - val = lpe_read_4(sc, LPE_MIND); - DELAY(10); - } - - if (val & LPE_MIND_INVALID) - return (0); - - lpe_write_4(sc, LPE_MCMD, 0); - result = (lpe_read_4(sc, LPE_MRDD) & LPE_MRDD_DATAMASK); - debugf("phy=%d reg=%d result=0x%04x\n", phy, reg, result); - - return (result); -} - -static int -lpe_miibus_writereg(device_t dev, int phy, int reg, int data) -{ - struct lpe_softc *sc = device_get_softc(dev); - uint32_t val; - - debugf("phy=%d reg=%d data=0x%04x\n", phy, reg, data); - - lpe_write_4(sc, LPE_MCMD, LPE_MCMD_WRITE); - lpe_write_4(sc, LPE_MADR, - (reg & LPE_MADR_REGMASK) << LPE_MADR_REGSHIFT | - (phy & LPE_MADR_PHYMASK) << LPE_MADR_PHYSHIFT); - - lpe_write_4(sc, LPE_MWTD, (data & LPE_MWTD_DATAMASK)); - - val = lpe_read_4(sc, LPE_MIND); - - /* Wait until request is completed */ - while (val & LPE_MIND_BUSY) { - val = lpe_read_4(sc, LPE_MIND); - DELAY(10); - } - - return (0); -} - -static void -lpe_miibus_statchg(device_t dev) -{ - struct lpe_softc *sc = device_get_softc(dev); - struct mii_data *mii = device_get_softc(sc->lpe_miibus); - -#ifndef __rtems__ - lpe_lock(sc); -#endif /* __rtems__ */ - - if ((mii->mii_media_status & IFM_ACTIVE) && - (mii->mii_media_status & IFM_AVALID)) - sc->lpe_flags |= LPE_FLAG_LINK; - else - sc->lpe_flags &= ~LPE_FLAG_LINK; - -#ifndef __rtems__ - lpe_unlock(sc); -#endif /* __rtems__ */ -} - -static void -lpe_reset(struct lpe_softc *sc) -{ - uint32_t mac1; - -#ifndef __rtems__ - /* Enter soft reset mode */ - mac1 = lpe_read_4(sc, LPE_MAC1); - lpe_write_4(sc, LPE_MAC1, mac1 | LPE_MAC1_SOFTRESET | LPE_MAC1_RESETTX | - LPE_MAC1_RESETMCSTX | LPE_MAC1_RESETRX | LPE_MAC1_RESETMCSRX); - - /* Reset registers, Tx path and Rx path */ - lpe_write_4(sc, LPE_COMMAND, LPE_COMMAND_REGRESET | - LPE_COMMAND_TXRESET | LPE_COMMAND_RXRESET); - - /* Set station address */ - lpe_write_4(sc, LPE_SA2, sc->lpe_enaddr[1] << 8 | sc->lpe_enaddr[0]); - lpe_write_4(sc, LPE_SA1, sc->lpe_enaddr[3] << 8 | sc->lpe_enaddr[2]); - lpe_write_4(sc, LPE_SA0, sc->lpe_enaddr[5] << 8 | sc->lpe_enaddr[4]); - - /* Leave soft reset mode */ - mac1 = lpe_read_4(sc, LPE_MAC1); - lpe_write_4(sc, LPE_MAC1, mac1 & ~(LPE_MAC1_SOFTRESET | LPE_MAC1_RESETTX | - LPE_MAC1_RESETMCSTX | LPE_MAC1_RESETRX | LPE_MAC1_RESETMCSRX)); -#else /* __rtems__ */ - /* Reset registers, Tx path and Rx path */ - lpe_write_4(sc, LPE_COMMAND, LPE_COMMAND_REGRESET | LPE_COMMAND_TXRESET | LPE_COMMAND_RXRESET); - - /* Enter soft reset mode */ - mac1 = lpe_read_4(sc, LPE_MAC1); - lpe_write_4(sc, LPE_MAC1, mac1 | LPE_MAC1_SOFTRESET | LPE_MAC1_RESETTX | - LPE_MAC1_RESETMCSTX | LPE_MAC1_RESETRX | LPE_MAC1_RESETMCSRX); - - /* Leave soft reset mode */ - mac1 = lpe_read_4(sc, LPE_MAC1); - lpe_write_4(sc, LPE_MAC1, mac1 & ~(LPE_MAC1_SOFTRESET | LPE_MAC1_RESETTX | - LPE_MAC1_RESETMCSTX | LPE_MAC1_RESETRX | LPE_MAC1_RESETMCSRX)); - - /* Reinitialize registers */ - lpe_write_4(sc, LPE_MCFG, LPE_MCFG_CLKSEL(0x7)); - lpe_write_4(sc, LPE_MAC2, LPE_MAC2_PADCRCENABLE | LPE_MAC2_CRCENABLE | LPE_MAC2_FULLDUPLEX); - lpe_write_4(sc, LPE_IPGT, 0x15); - lpe_write_4(sc, LPE_IPGR, 0x12); - lpe_write_4(sc, LPE_CLRT, 0x370f); - lpe_write_4(sc, LPE_MAXF, 0x0600); - lpe_write_4(sc, LPE_SUPP, LPE_SUPP_SPEED); - lpe_write_4(sc, LPE_TEST, 0x0); -#ifdef LPC32XX_ETHERNET_RMII - lpe_write_4(sc, LPE_COMMAND, LPE_COMMAND_FULLDUPLEX | LPE_COMMAND_RMII); -#else - lpe_write_4(sc, LPE_COMMAND, LPE_COMMAND_FULLDUPLEX); -#endif - lpe_write_4(sc, LPE_INTENABLE, 0x0); - lpe_write_4(sc, LPE_INTCLEAR, 0x30ff); - lpe_write_4(sc, LPE_POWERDOWN, 0x0); - - /* Set station address */ - lpe_write_4(sc, LPE_SA2, sc->lpe_enaddr[1] << 8 | sc->lpe_enaddr[0]); - lpe_write_4(sc, LPE_SA1, sc->lpe_enaddr[3] << 8 | sc->lpe_enaddr[2]); - lpe_write_4(sc, LPE_SA0, sc->lpe_enaddr[5] << 8 | sc->lpe_enaddr[4]); -#endif /* __rtems__ */ -} - -static void -lpe_init(void *arg) -{ - struct lpe_softc *sc = (struct lpe_softc *)arg; - - lpe_lock(sc); - lpe_init_locked(sc); - lpe_unlock(sc); -} - -static void -lpe_init_locked(struct lpe_softc *sc) -{ - struct ifnet *ifp = sc->lpe_ifp; - uint32_t cmd, mac1; - - lpe_lock_assert(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - return; - - /* Enable Tx and Rx */ - cmd = lpe_read_4(sc, LPE_COMMAND); - lpe_write_4(sc, LPE_COMMAND, cmd | LPE_COMMAND_RXENABLE | - LPE_COMMAND_TXENABLE | LPE_COMMAND_PASSRUNTFRAME); - - /* Enable receive */ - mac1 = lpe_read_4(sc, LPE_MAC1); - lpe_write_4(sc, LPE_MAC1, /*mac1 |*/ LPE_MAC1_RXENABLE | LPE_MAC1_PASSALL); - - lpe_write_4(sc, LPE_MAC2, LPE_MAC2_CRCENABLE | LPE_MAC2_PADCRCENABLE | - LPE_MAC2_FULLDUPLEX); - - lpe_write_4(sc, LPE_MCFG, LPE_MCFG_CLKSEL(7)); - - /* Set up Rx filter */ - lpe_set_rxmode(sc); - - /* Enable interrupts */ - lpe_write_4(sc, LPE_INTENABLE, LPE_INT_RXOVERRUN | LPE_INT_RXERROR | - LPE_INT_RXFINISH | LPE_INT_RXDONE | LPE_INT_TXUNDERRUN | - LPE_INT_TXERROR | LPE_INT_TXFINISH | LPE_INT_TXDONE); - - sc->lpe_cdata.lpe_tx_prod = 0; - sc->lpe_cdata.lpe_tx_last = 0; - sc->lpe_cdata.lpe_tx_used = 0; - - lpe_init_rx(sc); - - /* Initialize Rx packet and status descriptor heads */ - lpe_write_4(sc, LPE_RXDESC, sc->lpe_rdata.lpe_rx_ring_phys); - lpe_write_4(sc, LPE_RXSTATUS, sc->lpe_rdata.lpe_rx_status_phys); - lpe_write_4(sc, LPE_RXDESC_NUMBER, LPE_RXDESC_NUM - 1); - lpe_write_4(sc, LPE_RXDESC_CONS, 0); - - /* Initialize Tx packet and status descriptor heads */ - lpe_write_4(sc, LPE_TXDESC, sc->lpe_rdata.lpe_tx_ring_phys); - lpe_write_4(sc, LPE_TXSTATUS, sc->lpe_rdata.lpe_tx_status_phys); - lpe_write_4(sc, LPE_TXDESC_NUMBER, LPE_TXDESC_NUM - 1); - lpe_write_4(sc, LPE_TXDESC_PROD, 0); - - ifp->if_drv_flags |= IFF_DRV_RUNNING; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - - callout_reset(&sc->lpe_tick, hz, lpe_tick, sc); -} - -static void -lpe_start(struct ifnet *ifp) -{ - struct lpe_softc *sc = (struct lpe_softc *)ifp->if_softc; - - lpe_lock(sc); - lpe_start_locked(ifp); - lpe_unlock(sc); -} - -static void -lpe_start_locked(struct ifnet *ifp) -{ - struct lpe_softc *sc = (struct lpe_softc *)ifp->if_softc; - struct mbuf *m_head; - int encap = 0; - - lpe_lock_assert(sc); - - while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { - if (lpe_read_4(sc, LPE_TXDESC_PROD) == - lpe_read_4(sc, LPE_TXDESC_CONS) - 5) - break; - - /* Dequeue first packet */ - IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); - if (!m_head) - break; - - lpe_encap(sc, &m_head); - - encap++; - } - - /* Submit new descriptor list */ - if (encap) { - lpe_write_4(sc, LPE_TXDESC_PROD, sc->lpe_cdata.lpe_tx_prod); - sc->lpe_watchdog_timer = 5; - } - -} - -#ifdef __rtems__ -static int -lpe_get_segs_for_tx(struct mbuf *m, bus_dma_segment_t segs[LPE_MAXFRAGS], - int *nsegs) -{ - int i = 0; - - do { - if (m->m_len > 0) { - segs[i].ds_addr = mtod(m, bus_addr_t); - segs[i].ds_len = m->m_len; -#ifdef CPU_DATA_CACHE_ALIGNMENT - rtems_cache_flush_multiple_data_lines(m->m_data, m->m_len); -#endif - ++i; - } - m = m->m_next; - if (m == NULL) { - *nsegs = i; - return (0); - } - } while (i < LPE_MAXFRAGS); - return (EFBIG); -} -#endif /* __rtems__ */ -static int -lpe_encap(struct lpe_softc *sc, struct mbuf **m_head) -{ - struct lpe_txdesc *txd; - struct lpe_hwdesc *hwd; - bus_dma_segment_t segs[LPE_MAXFRAGS]; - int i, err, nsegs, prod; - - lpe_lock_assert(sc); - M_ASSERTPKTHDR((*m_head)); - - prod = sc->lpe_cdata.lpe_tx_prod; - txd = &sc->lpe_cdata.lpe_tx_desc[prod]; - - debugf("starting with prod=%d\n", prod); - -#ifndef __rtems__ - err = bus_dmamap_load_mbuf_sg(sc->lpe_cdata.lpe_tx_buf_tag, - txd->lpe_txdesc_dmamap, *m_head, segs, &nsegs, BUS_DMA_NOWAIT); -#else /* __rtems__ */ - err = lpe_get_segs_for_tx(*m_head, segs, &nsegs); -#endif /* __rtems__ */ - - if (err) - return (err); - - if (nsegs == 0) { - m_freem(*m_head); - *m_head = NULL; - return (EIO); - } - -#ifndef __rtems__ - bus_dmamap_sync(sc->lpe_cdata.lpe_tx_buf_tag, txd->lpe_txdesc_dmamap, - BUS_DMASYNC_PREREAD); -#endif /* __rtems__ */ - bus_dmamap_sync(sc->lpe_cdata.lpe_tx_ring_tag, sc->lpe_cdata.lpe_tx_ring_map, - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - - txd->lpe_txdesc_first = 1; - txd->lpe_txdesc_mbuf = *m_head; - - for (i = 0; i < nsegs; i++) { - hwd = &sc->lpe_rdata.lpe_tx_ring[prod]; - hwd->lhr_data = segs[i].ds_addr; - hwd->lhr_control = segs[i].ds_len - 1; - - if (i == nsegs - 1) { - hwd->lhr_control |= LPE_HWDESC_LASTFLAG; - hwd->lhr_control |= LPE_HWDESC_INTERRUPT; - hwd->lhr_control |= LPE_HWDESC_CRC; - hwd->lhr_control |= LPE_HWDESC_PAD; - } - -#ifdef __rtems__ -#ifdef CPU_DATA_CACHE_ALIGNMENT - rtems_cache_flush_multiple_data_lines(hwd, sizeof(*hwd)); -#endif -#endif /* __rtems__ */ - LPE_INC(prod, LPE_TXDESC_NUM); - } - - bus_dmamap_sync(sc->lpe_cdata.lpe_tx_ring_tag, sc->lpe_cdata.lpe_tx_ring_map, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - - sc->lpe_cdata.lpe_tx_used += nsegs; - sc->lpe_cdata.lpe_tx_prod = prod; - - return (0); -} - -static void -lpe_stop(struct lpe_softc *sc) -{ - lpe_lock(sc); - lpe_stop_locked(sc); - lpe_unlock(sc); -} - -static void -lpe_stop_locked(struct lpe_softc *sc) -{ - lpe_lock_assert(sc); - - callout_stop(&sc->lpe_tick); - - /* Disable interrupts */ - lpe_write_4(sc, LPE_INTCLEAR, 0xffffffff); - - /* Stop EMAC */ - lpe_write_4(sc, LPE_MAC1, 0); - lpe_write_4(sc, LPE_MAC2, 0); - lpe_write_4(sc, LPE_COMMAND, 0); - - sc->lpe_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - sc->lpe_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; -} - -static int -lpe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct lpe_softc *sc = ifp->if_softc; - struct mii_data *mii = device_get_softc(sc->lpe_miibus); - struct ifreq *ifr = (struct ifreq *)data; - int err = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - lpe_lock(sc); - if (ifp->if_flags & IFF_UP) { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - lpe_set_rxmode(sc); - lpe_set_rxfilter(sc); - } else - lpe_init_locked(sc); - } else - lpe_stop(sc); - lpe_unlock(sc); - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - lpe_lock(sc); - lpe_set_rxfilter(sc); - lpe_unlock(sc); - } - break; - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - err = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); - break; - default: - err = ether_ioctl(ifp, cmd, data); - break; - } - - return (err); -} - -static void lpe_set_rxmode(struct lpe_softc *sc) -{ - struct ifnet *ifp = sc->lpe_ifp; - uint32_t rxfilt; - - rxfilt = LPE_RXFILTER_UNIHASH | LPE_RXFILTER_MULTIHASH | LPE_RXFILTER_PERFECT; - - if (ifp->if_flags & IFF_BROADCAST) - rxfilt |= LPE_RXFILTER_BROADCAST; - - if (ifp->if_flags & IFF_PROMISC) - rxfilt |= LPE_RXFILTER_UNICAST | LPE_RXFILTER_MULTICAST; - - if (ifp->if_flags & IFF_ALLMULTI) - rxfilt |= LPE_RXFILTER_MULTICAST; - - lpe_write_4(sc, LPE_RXFILTER_CTRL, rxfilt); -} - -static void lpe_set_rxfilter(struct lpe_softc *sc) -{ - struct ifnet *ifp = sc->lpe_ifp; - struct ifmultiaddr *ifma; - int index; - uint32_t hashl, hashh; - - hashl = 0; - hashh = 0; - - if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - - index = ether_crc32_be(LLADDR((struct sockaddr_dl *) - ifma->ifma_addr), ETHER_ADDR_LEN) >> 23 & 0x3f; - - if (index > 31) - hashh |= (1 << (index - 32)); - else - hashl |= (1 << index); - } - if_maddr_runlock(ifp); - - /* Program new hash filter */ - lpe_write_4(sc, LPE_HASHFILTER_L, hashl); - lpe_write_4(sc, LPE_HASHFILTER_H, hashh); -} - -static void -lpe_intr(void *arg) -{ - struct lpe_softc *sc = (struct lpe_softc *)arg; - uint32_t intstatus; - - debugf("status=0x%08x\n", lpe_read_4(sc, LPE_INTSTATUS)); - - lpe_lock(sc); - - while ((intstatus = lpe_read_4(sc, LPE_INTSTATUS))) { - if (intstatus & LPE_INT_RXDONE) - lpe_rxintr(sc); - -#ifndef __rtems__ - if (intstatus & LPE_INT_TXDONE) - lpe_txintr(sc); - -#else /* __rtems__ */ - if (intstatus & LPE_INT_TXUNDERRUN) { - if_inc_counter(sc->lpe_ifp, IFCOUNTER_OERRORS, 1); - lpe_stop_locked(sc); - lpe_init_locked(sc); - } - else if (intstatus & (LPE_INT_TXERROR | LPE_INT_TXFINISH | LPE_INT_TXDONE)) - lpe_txintr(sc); -#endif /* __rtems__ */ - lpe_write_4(sc, LPE_INTCLEAR, 0xffff); - } - - lpe_unlock(sc); -} - -static void -lpe_rxintr(struct lpe_softc *sc) -{ - struct ifnet *ifp = sc->lpe_ifp; - struct lpe_hwdesc *hwd; - struct lpe_hwstatus *hws; - struct lpe_rxdesc *rxd; - struct mbuf *m; - int prod, cons; - - for (;;) { - prod = lpe_read_4(sc, LPE_RXDESC_PROD); - cons = lpe_read_4(sc, LPE_RXDESC_CONS); - - if (prod == cons) - break; - - rxd = &sc->lpe_cdata.lpe_rx_desc[cons]; - hwd = &sc->lpe_rdata.lpe_rx_ring[cons]; - hws = &sc->lpe_rdata.lpe_rx_status[cons]; -#ifdef __rtems__ -#ifdef CPU_DATA_CACHE_ALIGNMENT - rtems_cache_invalidate_multiple_data_lines(rxd, sizeof(*rxd)); - rtems_cache_invalidate_multiple_data_lines(hwd, sizeof(*hwd)); - rtems_cache_invalidate_multiple_data_lines(hws, sizeof(*hws)); -#endif -#endif /* __rtems__ */ - - /* Check received frame for errors */ - if (hws->lhs_info & LPE_HWDESC_RXERRS) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - lpe_discard_rxbuf(sc, cons); - lpe_init_rxbuf(sc, cons); - goto skip; - } - - m = rxd->lpe_rxdesc_mbuf; -#ifdef __rtems__ -#ifdef CPU_DATA_CACHE_ALIGNMENT - rtems_cache_invalidate_multiple_data_lines(m->m_data, m->m_len); -#endif -#endif /* __rtems__ */ - m->m_pkthdr.rcvif = ifp; - m->m_data += 2; - - if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); - - lpe_unlock(sc); - (*ifp->if_input)(ifp, m); - lpe_lock(sc); - - lpe_init_rxbuf(sc, cons); -skip: - LPE_INC(cons, LPE_RXDESC_NUM); - lpe_write_4(sc, LPE_RXDESC_CONS, cons); - } -} - -static void -lpe_txintr(struct lpe_softc *sc) -{ - struct ifnet *ifp = sc->lpe_ifp; - struct lpe_hwdesc *hwd; - struct lpe_hwstatus *hws; - struct lpe_txdesc *txd; - int cons, last; - - for (;;) { - cons = lpe_read_4(sc, LPE_TXDESC_CONS); - last = sc->lpe_cdata.lpe_tx_last; - - if (cons == last) - break; - - txd = &sc->lpe_cdata.lpe_tx_desc[last]; - hwd = &sc->lpe_rdata.lpe_tx_ring[last]; - hws = &sc->lpe_rdata.lpe_tx_status[last]; - -#ifndef __rtems__ - bus_dmamap_sync(sc->lpe_cdata.lpe_tx_buf_tag, - txd->lpe_txdesc_dmamap, BUS_DMASYNC_POSTWRITE); -#else /* __rtems__ */ -#ifdef CPU_DATA_CACHE_ALIGNMENT - rtems_cache_invalidate_multiple_data_lines(txd, sizeof(*txd)); - rtems_cache_invalidate_multiple_data_lines(hwd, sizeof(*hwd)); - rtems_cache_invalidate_multiple_data_lines(hws, sizeof(*hws)); -#endif -#endif /* __rtems__ */ - - if_inc_counter(ifp, IFCOUNTER_COLLISIONS, LPE_HWDESC_COLLISIONS(hws->lhs_info)); - - if (hws->lhs_info & LPE_HWDESC_TXERRS) - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - else - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - - if (txd->lpe_txdesc_first) { -#ifndef __rtems__ - bus_dmamap_unload(sc->lpe_cdata.lpe_tx_buf_tag, - txd->lpe_txdesc_dmamap); -#endif /* __rtems__ */ - - m_freem(txd->lpe_txdesc_mbuf); - txd->lpe_txdesc_mbuf = NULL; - txd->lpe_txdesc_first = 0; - } - - sc->lpe_cdata.lpe_tx_used--; - LPE_INC(sc->lpe_cdata.lpe_tx_last, LPE_TXDESC_NUM); - } - - if (!sc->lpe_cdata.lpe_tx_used) - sc->lpe_watchdog_timer = 0; -} - -static void -lpe_tick(void *arg) -{ - struct lpe_softc *sc = (struct lpe_softc *)arg; - struct mii_data *mii = device_get_softc(sc->lpe_miibus); - - lpe_lock_assert(sc); - - mii_tick(mii); - lpe_watchdog(sc); - - callout_reset(&sc->lpe_tick, hz, lpe_tick, sc); -} - -static void -lpe_watchdog(struct lpe_softc *sc) -{ - struct ifnet *ifp = sc->lpe_ifp; - - lpe_lock_assert(sc); - - if (sc->lpe_watchdog_timer == 0 || sc->lpe_watchdog_timer--) - return; - - /* Chip has stopped responding */ - device_printf(sc->lpe_dev, "WARNING: chip hangup, restarting...\n"); - lpe_stop_locked(sc); - lpe_init_locked(sc); - - /* Try to resend packets */ - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - lpe_start_locked(ifp); -} - -static int -lpe_dma_alloc(struct lpe_softc *sc) -{ - int err; - - /* Create parent DMA tag */ - err = bus_dma_tag_create( - bus_get_dma_tag(sc->lpe_dev), - 1, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - BUS_SPACE_MAXSIZE_32BIT, 0, /* maxsize, nsegments */ - BUS_SPACE_MAXSIZE_32BIT, 0, /* maxsegsize, flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->lpe_cdata.lpe_parent_tag); - - if (err) { - device_printf(sc->lpe_dev, "cannot create parent DMA tag\n"); - return (err); - } - - err = lpe_dma_alloc_rx(sc); - if (err) - return (err); - - err = lpe_dma_alloc_tx(sc); - if (err) - return (err); - - return (0); -} - -static int -lpe_dma_alloc_rx(struct lpe_softc *sc) -{ - struct lpe_rxdesc *rxd; - struct lpe_dmamap_arg ctx; - int err, i; - - /* Create tag for Rx ring */ - err = bus_dma_tag_create( - sc->lpe_cdata.lpe_parent_tag, - LPE_DESC_ALIGN, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - LPE_RXDESC_SIZE, 1, /* maxsize, nsegments */ - LPE_RXDESC_SIZE, 0, /* maxsegsize, flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->lpe_cdata.lpe_rx_ring_tag); - - if (err) { - device_printf(sc->lpe_dev, "cannot create Rx ring DMA tag\n"); - goto fail; - } - - /* Create tag for Rx status ring */ - err = bus_dma_tag_create( - sc->lpe_cdata.lpe_parent_tag, - LPE_DESC_ALIGN, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - LPE_RXSTATUS_SIZE, 1, /* maxsize, nsegments */ - LPE_RXSTATUS_SIZE, 0, /* maxsegsize, flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->lpe_cdata.lpe_rx_status_tag); - - if (err) { - device_printf(sc->lpe_dev, "cannot create Rx status ring DMA tag\n"); - goto fail; - } - - /* Create tag for Rx buffers */ - err = bus_dma_tag_create( - sc->lpe_cdata.lpe_parent_tag, - LPE_DESC_ALIGN, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - MCLBYTES * LPE_RXDESC_NUM, /* maxsize */ - LPE_RXDESC_NUM, /* segments */ - MCLBYTES, 0, /* maxsegsize, flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->lpe_cdata.lpe_rx_buf_tag); - - if (err) { - device_printf(sc->lpe_dev, "cannot create Rx buffers DMA tag\n"); - goto fail; - } - - /* Allocate Rx DMA ring */ - err = bus_dmamem_alloc(sc->lpe_cdata.lpe_rx_ring_tag, - (void **)&sc->lpe_rdata.lpe_rx_ring, BUS_DMA_WAITOK | BUS_DMA_COHERENT | - BUS_DMA_ZERO, &sc->lpe_cdata.lpe_rx_ring_map); - - err = bus_dmamap_load(sc->lpe_cdata.lpe_rx_ring_tag, - sc->lpe_cdata.lpe_rx_ring_map, sc->lpe_rdata.lpe_rx_ring, - LPE_RXDESC_SIZE, lpe_dmamap_cb, &ctx, 0); - - sc->lpe_rdata.lpe_rx_ring_phys = ctx.lpe_dma_busaddr; - - /* Allocate Rx status ring */ - err = bus_dmamem_alloc(sc->lpe_cdata.lpe_rx_status_tag, - (void **)&sc->lpe_rdata.lpe_rx_status, BUS_DMA_WAITOK | BUS_DMA_COHERENT | - BUS_DMA_ZERO, &sc->lpe_cdata.lpe_rx_status_map); - - err = bus_dmamap_load(sc->lpe_cdata.lpe_rx_status_tag, - sc->lpe_cdata.lpe_rx_status_map, sc->lpe_rdata.lpe_rx_status, - LPE_RXDESC_SIZE, lpe_dmamap_cb, &ctx, 0); - - sc->lpe_rdata.lpe_rx_status_phys = ctx.lpe_dma_busaddr; - - - /* Create Rx buffers DMA map */ - for (i = 0; i < LPE_RXDESC_NUM; i++) { - rxd = &sc->lpe_cdata.lpe_rx_desc[i]; - rxd->lpe_rxdesc_mbuf = NULL; -#ifndef __rtems__ - rxd->lpe_rxdesc_dmamap = NULL; - - err = bus_dmamap_create(sc->lpe_cdata.lpe_rx_buf_tag, 0, - &rxd->lpe_rxdesc_dmamap); - - if (err) { - device_printf(sc->lpe_dev, "cannot create Rx DMA map\n"); - return (err); - } -#endif /* __rtems__ */ - } - - return (0); -fail: - return (err); -} - -static int -lpe_dma_alloc_tx(struct lpe_softc *sc) -{ - struct lpe_txdesc *txd; - struct lpe_dmamap_arg ctx; - int err, i; - - /* Create tag for Tx ring */ - err = bus_dma_tag_create( - sc->lpe_cdata.lpe_parent_tag, - LPE_DESC_ALIGN, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - LPE_TXDESC_SIZE, 1, /* maxsize, nsegments */ - LPE_TXDESC_SIZE, 0, /* maxsegsize, flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->lpe_cdata.lpe_tx_ring_tag); - - if (err) { - device_printf(sc->lpe_dev, "cannot create Tx ring DMA tag\n"); - goto fail; - } - - /* Create tag for Tx status ring */ - err = bus_dma_tag_create( - sc->lpe_cdata.lpe_parent_tag, - LPE_DESC_ALIGN, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - LPE_TXSTATUS_SIZE, 1, /* maxsize, nsegments */ - LPE_TXSTATUS_SIZE, 0, /* maxsegsize, flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->lpe_cdata.lpe_tx_status_tag); - - if (err) { - device_printf(sc->lpe_dev, "cannot create Tx status ring DMA tag\n"); - goto fail; - } - - /* Create tag for Tx buffers */ - err = bus_dma_tag_create( - sc->lpe_cdata.lpe_parent_tag, - LPE_DESC_ALIGN, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - MCLBYTES * LPE_TXDESC_NUM, /* maxsize */ - LPE_TXDESC_NUM, /* segments */ - MCLBYTES, 0, /* maxsegsize, flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->lpe_cdata.lpe_tx_buf_tag); - - if (err) { - device_printf(sc->lpe_dev, "cannot create Tx buffers DMA tag\n"); - goto fail; - } - - /* Allocate Tx DMA ring */ - err = bus_dmamem_alloc(sc->lpe_cdata.lpe_tx_ring_tag, - (void **)&sc->lpe_rdata.lpe_tx_ring, BUS_DMA_WAITOK | BUS_DMA_COHERENT | - BUS_DMA_ZERO, &sc->lpe_cdata.lpe_tx_ring_map); - - err = bus_dmamap_load(sc->lpe_cdata.lpe_tx_ring_tag, - sc->lpe_cdata.lpe_tx_ring_map, sc->lpe_rdata.lpe_tx_ring, - LPE_RXDESC_SIZE, lpe_dmamap_cb, &ctx, 0); - - sc->lpe_rdata.lpe_tx_ring_phys = ctx.lpe_dma_busaddr; - - /* Allocate Tx status ring */ - err = bus_dmamem_alloc(sc->lpe_cdata.lpe_tx_status_tag, - (void **)&sc->lpe_rdata.lpe_tx_status, BUS_DMA_WAITOK | BUS_DMA_COHERENT | - BUS_DMA_ZERO, &sc->lpe_cdata.lpe_tx_status_map); - - err = bus_dmamap_load(sc->lpe_cdata.lpe_tx_status_tag, - sc->lpe_cdata.lpe_tx_status_map, sc->lpe_rdata.lpe_tx_status, - LPE_RXDESC_SIZE, lpe_dmamap_cb, &ctx, 0); - - sc->lpe_rdata.lpe_tx_status_phys = ctx.lpe_dma_busaddr; - - - /* Create Tx buffers DMA map */ - for (i = 0; i < LPE_TXDESC_NUM; i++) { - txd = &sc->lpe_cdata.lpe_tx_desc[i]; - txd->lpe_txdesc_mbuf = NULL; -#ifndef __rtems__ - txd->lpe_txdesc_dmamap = NULL; -#endif /* __rtems__ */ - txd->lpe_txdesc_first = 0; - -#ifndef __rtems__ - err = bus_dmamap_create(sc->lpe_cdata.lpe_tx_buf_tag, 0, - &txd->lpe_txdesc_dmamap); -#endif /* __rtems__ */ - - if (err) { - device_printf(sc->lpe_dev, "cannot create Tx DMA map\n"); - return (err); - } - } - - return (0); -fail: - return (err); -} - -static int -lpe_init_rx(struct lpe_softc *sc) -{ - int i, err; - - for (i = 0; i < LPE_RXDESC_NUM; i++) { - err = lpe_init_rxbuf(sc, i); - if (err) - return (err); - } - - return (0); -} - -static int -lpe_init_rxbuf(struct lpe_softc *sc, int n) -{ - struct lpe_rxdesc *rxd; - struct lpe_hwdesc *hwd; - struct lpe_hwstatus *hws; - struct mbuf *m; - bus_dma_segment_t segs[1]; - int nsegs; - - rxd = &sc->lpe_cdata.lpe_rx_desc[n]; - hwd = &sc->lpe_rdata.lpe_rx_ring[n]; - hws = &sc->lpe_rdata.lpe_rx_status[n]; - m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); - - if (!m) { - device_printf(sc->lpe_dev, "WARNING: mbufs exhausted!\n"); - return (ENOBUFS); - } - - m->m_len = m->m_pkthdr.len = MCLBYTES; - -#ifndef __rtems__ - bus_dmamap_unload(sc->lpe_cdata.lpe_rx_buf_tag, rxd->lpe_rxdesc_dmamap); - - if (bus_dmamap_load_mbuf_sg(sc->lpe_cdata.lpe_rx_buf_tag, - rxd->lpe_rxdesc_dmamap, m, segs, &nsegs, 0)) { - m_freem(m); - return (ENOBUFS); - } - - bus_dmamap_sync(sc->lpe_cdata.lpe_rx_buf_tag, rxd->lpe_rxdesc_dmamap, - BUS_DMASYNC_PREREAD); -#else /* __rtems__ */ -#ifdef CPU_DATA_CACHE_ALIGNMENT - rtems_cache_invalidate_multiple_data_lines(m->m_data, m->m_len); -#endif - segs[0].ds_addr = mtod(m, bus_addr_t); -#endif /* __rtems__ */ - - rxd->lpe_rxdesc_mbuf = m; - hwd->lhr_data = segs[0].ds_addr + 2; - hwd->lhr_control = (segs[0].ds_len - 1) | LPE_HWDESC_INTERRUPT; -#ifdef __rtems__ -#ifdef CPU_DATA_CACHE_ALIGNMENT - rtems_cache_flush_multiple_data_lines(hwd, sizeof(*hwd)); -#endif -#endif /* __rtems__ */ - - return (0); -} - -static void -lpe_discard_rxbuf(struct lpe_softc *sc, int n) -{ - struct lpe_rxdesc *rxd; - struct lpe_hwdesc *hwd; - - rxd = &sc->lpe_cdata.lpe_rx_desc[n]; - hwd = &sc->lpe_rdata.lpe_rx_ring[n]; - -#ifndef __rtems__ - bus_dmamap_unload(sc->lpe_cdata.lpe_rx_buf_tag, rxd->lpe_rxdesc_dmamap); -#endif /* __rtems__ */ - - hwd->lhr_data = 0; - hwd->lhr_control = 0; - - if (rxd->lpe_rxdesc_mbuf) { - m_freem(rxd->lpe_rxdesc_mbuf); - rxd->lpe_rxdesc_mbuf = NULL; - } -} - -static void -lpe_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - struct lpe_dmamap_arg *ctx; - - if (error) - return; - - ctx = (struct lpe_dmamap_arg *)arg; - ctx->lpe_dma_busaddr = segs[0].ds_addr; -} - -static int -lpe_ifmedia_upd(struct ifnet *ifp) -{ - return (0); -} - -static void -lpe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct lpe_softc *sc = ifp->if_softc; - struct mii_data *mii = device_get_softc(sc->lpe_miibus); - - lpe_lock(sc); - mii_pollstat(mii); - ifmr->ifm_active = mii->mii_media_active; - ifmr->ifm_status = mii->mii_media_status; - lpe_unlock(sc); -} - -static device_method_t lpe_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, lpe_probe), - DEVMETHOD(device_attach, lpe_attach), - DEVMETHOD(device_detach, lpe_detach), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - - /* MII interface */ - DEVMETHOD(miibus_readreg, lpe_miibus_readreg), - DEVMETHOD(miibus_writereg, lpe_miibus_writereg), - DEVMETHOD(miibus_statchg, lpe_miibus_statchg), - { 0, 0 } -}; - -static driver_t lpe_driver = { - "lpe", - lpe_methods, - sizeof(struct lpe_softc), -}; - -static devclass_t lpe_devclass; - -#ifndef __rtems__ -DRIVER_MODULE(lpe, simplebus, lpe_driver, lpe_devclass, 0, 0); -#else /* __rtems__ */ -DRIVER_MODULE(lpe, nexus, lpe_driver, lpe_devclass, 0, 0); -#endif /* __rtems__ */ -DRIVER_MODULE(miibus, lpe, miibus_driver, miibus_devclass, 0, 0); -MODULE_DEPEND(lpe, obio, 1, 1, 1); -MODULE_DEPEND(lpe, miibus, 1, 1, 1); -MODULE_DEPEND(lpe, ether, 1, 1, 1); diff --git a/freebsd/sys/arm/lpc/if_lpereg.h b/freebsd/sys/arm/lpc/if_lpereg.h deleted file mode 100644 index a40bf8b5..00000000 --- a/freebsd/sys/arm/lpc/if_lpereg.h +++ /dev/null @@ -1,210 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2011 Jakub Wojciech Klama <jceel@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _ARM_LPC_IF_LPEREG_H -#define _ARM_LPC_IF_LPEREG_H - -#define LPE_MAC1 0x000 -#define LPE_MAC1_RXENABLE (1 << 0) -#define LPE_MAC1_PASSALL (1 << 1) -#define LPE_MAC1_RXFLOWCTRL (1 << 2) -#define LPE_MAC1_TXFLOWCTRL (1 << 3) -#define LPE_MAC1_LOOPBACK (1 << 4) -#define LPE_MAC1_RESETTX (1 << 8) -#define LPE_MAC1_RESETMCSTX (1 << 9) -#define LPE_MAC1_RESETRX (1 << 10) -#define LPE_MAC1_RESETMCSRX (1 << 11) -#define LPE_MAC1_SIMRESET (1 << 14) -#define LPE_MAC1_SOFTRESET (1 << 15) -#define LPE_MAC2 0x004 -#define LPE_MAC2_FULLDUPLEX (1 << 0) -#define LPE_MAC2_FRAMELENCHECK (1 << 1) -#define LPE_MAC2_HUGEFRAME (1 << 2) -#define LPE_MAC2_DELAYEDCRC (1 << 3) -#define LPE_MAC2_CRCENABLE (1 << 4) -#define LPE_MAC2_PADCRCENABLE (1 << 5) -#define LPE_MAC2_VLANPADENABLE (1 << 6) -#define LPE_MAC2_AUTOPADENABLE (1 << 7) -#define LPE_MAC2_PUREPREAMBLE (1 << 8) -#define LPE_MAC2_LONGPREAMBLE (1 << 9) -#define LPE_MAC2_NOBACKOFF (1 << 12) -#define LPE_MAC2_BACKPRESSURE (1 << 13) -#define LPE_MAC2_EXCESSDEFER (1 << 14) -#define LPE_IPGT 0x008 -#define LPE_IPGR 0x00c -#define LPE_CLRT 0x010 -#define LPE_MAXF 0x014 -#define LPE_SUPP 0x018 -#define LPE_SUPP_SPEED (1 << 8) -#define LPE_TEST 0x01c -#define LPE_MCFG 0x020 -#define LPE_MCFG_SCANINCR (1 << 0) -#define LPE_MCFG_SUPPREAMBLE (1 << 1) -#define LPE_MCFG_CLKSEL(_n) ((_n & 0x7) << 2) -#define LPC_MCFG_RESETMII (1 << 15) -#define LPE_MCMD 0x024 -#define LPE_MCMD_READ (1 << 0) -#define LPE_MCMD_WRITE (0 << 0) -#define LPE_MCMD_SCAN (1 << 1) -#define LPE_MADR 0x028 -#define LPE_MADR_REGMASK 0x1f -#define LPE_MADR_REGSHIFT 0 -#define LPE_MADR_PHYMASK 0x1f -#define LPE_MADR_PHYSHIFT 8 -#define LPE_MWTD 0x02c -#define LPE_MWTD_DATAMASK 0xffff -#define LPE_MRDD 0x030 -#define LPE_MRDD_DATAMASK 0xffff -#define LPE_MIND 0x034 -#define LPE_MIND_BUSY (1 << 0) -#define LPE_MIND_SCANNING (1 << 1) -#define LPE_MIND_INVALID (1 << 2) -#define LPE_MIND_MIIFAIL (1 << 3) -#define LPE_SA0 0x040 -#define LPE_SA1 0x044 -#define LPE_SA2 0x048 -#define LPE_COMMAND 0x100 -#define LPE_COMMAND_RXENABLE (1 << 0) -#define LPE_COMMAND_TXENABLE (1 << 1) -#define LPE_COMMAND_REGRESET (1 << 3) -#define LPE_COMMAND_TXRESET (1 << 4) -#define LPE_COMMAND_RXRESET (1 << 5) -#define LPE_COMMAND_PASSRUNTFRAME (1 << 6) -#define LPE_COMMAND_PASSRXFILTER (1 << 7) -#define LPE_COMMAND_TXFLOWCTL (1 << 8) -#define LPE_COMMAND_RMII (1 << 9) -#define LPE_COMMAND_FULLDUPLEX (1 << 10) -#define LPE_STATUS 0x104 -#define LPE_STATUS_RXACTIVE (1 << 0) -#define LPE_STATUS_TXACTIVE (1 << 1) -#define LPE_RXDESC 0x108 -#define LPE_RXSTATUS 0x10c -#define LPE_RXDESC_NUMBER 0x110 -#define LPE_RXDESC_PROD 0x114 -#define LPE_RXDESC_CONS 0x118 -#define LPE_TXDESC 0x11c -#define LPE_TXSTATUS 0x120 -#define LPE_TXDESC_NUMBER 0x124 -#define LPE_TXDESC_PROD 0x128 -#define LPE_TXDESC_CONS 0x12c -#define LPE_TSV0 0x158 -#define LPE_TSV1 0x15c -#define LPE_RSV 0x160 -#define LPE_FLOWCONTROL_COUNTER 0x170 -#define LPE_FLOWCONTROL_STATUS 0x174 -#define LPE_RXFILTER_CTRL 0x200 -#define LPE_RXFILTER_UNICAST (1 << 0) -#define LPE_RXFILTER_BROADCAST (1 << 1) -#define LPE_RXFILTER_MULTICAST (1 << 2) -#define LPE_RXFILTER_UNIHASH (1 << 3) -#define LPE_RXFILTER_MULTIHASH (1 << 4) -#define LPE_RXFILTER_PERFECT (1 << 5) -#define LPE_RXFILTER_WOL (1 << 12) -#define LPE_RXFILTER_FILTWOL (1 << 13) -#define LPE_RXFILTER_WOL_STATUS 0x204 -#define LPE_RXFILTER_WOL_CLEAR 0x208 -#define LPE_HASHFILTER_L 0x210 -#define LPE_HASHFILTER_H 0x214 -#define LPE_INTSTATUS 0xfe0 -#define LPE_INTENABLE 0xfe4 -#define LPE_INTCLEAR 0xfe8 -#define LPE_INTSET 0xfec -#define LPE_INT_RXOVERRUN (1 << 0) -#define LPE_INT_RXERROR (1 << 1) -#define LPE_INT_RXFINISH (1 << 2) -#define LPE_INT_RXDONE (1 << 3) -#define LPE_INT_TXUNDERRUN (1 << 4) -#define LPE_INT_TXERROR (1 << 5) -#define LPE_INT_TXFINISH (1 << 6) -#define LPE_INT_TXDONE (1 << 7) -#define LPE_INT_SOFTINT (1 << 12) -#define LPE_INTWAKEUPINT (1 << 13) -#define LPE_POWERDOWN 0xff4 - -#define LPE_DESC_ALIGN 8 -#define LPE_TXDESC_NUM 128 -#define LPE_RXDESC_NUM 128 -#define LPE_TXDESC_SIZE (LPE_TXDESC_NUM * sizeof(struct lpe_hwdesc)) -#define LPE_RXDESC_SIZE (LPE_RXDESC_NUM * sizeof(struct lpe_hwdesc)) -#define LPE_TXSTATUS_SIZE (LPE_TXDESC_NUM * sizeof(struct lpe_hwstatus)) -#define LPE_RXSTATUS_SIZE (LPE_RXDESC_NUM * sizeof(struct lpe_hwstatus)) -#define LPE_MAXFRAGS 8 - -struct lpe_hwdesc { - uint32_t lhr_data; - uint32_t lhr_control; -}; - -struct lpe_hwstatus { - uint32_t lhs_info; - uint32_t lhs_crc; -}; - -#define LPE_INC(x, y) (x) = ((x) == ((y)-1)) ? 0 : (x)+1 - -/* These are valid for both Rx and Tx descriptors */ -#define LPE_HWDESC_SIZE_MASK (1 << 10) -#define LPE_HWDESC_INTERRUPT (1U << 31) - -/* These are valid for Tx descriptors */ -#define LPE_HWDESC_LAST (1 << 30) -#define LPE_HWDESC_CRC (1 << 29) -#define LPE_HWDESC_PAD (1 << 28) -#define LPE_HWDESC_HUGE (1 << 27) -#define LPE_HWDESC_OVERRIDE (1 << 26) - -/* These are valid for Tx status descriptors */ -#define LPE_HWDESC_COLLISIONS(_n) (((_n) >> 21) & 0x7) -#define LPE_HWDESC_DEFER (1 << 25) -#define LPE_HWDESC_EXCDEFER (1 << 26) -#define LPE_HWDESC_EXCCOLL (1 << 27) -#define LPE_HWDESC_LATECOLL (1 << 28) -#define LPE_HWDESC_UNDERRUN (1 << 29) -#define LPE_HWDESC_TXNODESCR (1 << 30) -#define LPE_HWDESC_ERROR (1U << 31) - -/* These are valid for Rx status descriptors */ -#define LPE_HWDESC_CONTROL (1 << 18) -#define LPE_HWDESC_VLAN (1 << 19) -#define LPE_HWDESC_FAILFILTER (1 << 20) -#define LPE_HWDESC_MULTICAST (1 << 21) -#define LPE_HWDESC_BROADCAST (1 << 22) -#define LPE_HWDESC_CRCERROR (1 << 23) -#define LPE_HWDESC_SYMBOLERROR (1 << 24) -#define LPE_HWDESC_LENGTHERROR (1 << 25) -#define LPE_HWDESC_RANGEERROR (1 << 26) -#define LPE_HWDESC_ALIGNERROR (1 << 27) -#define LPE_HWDESC_OVERRUN (1 << 28) -#define LPE_HWDESC_RXNODESCR (1 << 29) -#define LPE_HWDESC_LASTFLAG (1 << 30) -#define LPE_HWDESC_ERROR (1U << 31) - - -#endif /* _ARM_LPC_IF_LPEREG_H */ diff --git a/freebsd/sys/arm/lpc/lpc_pwr.c b/freebsd/sys/arm/lpc/lpc_pwr.c deleted file mode 100755 index dd1064c8..00000000 --- a/freebsd/sys/arm/lpc/lpc_pwr.c +++ /dev/null @@ -1,141 +0,0 @@ -#include <machine/rtems-bsd-kernel-space.h> - -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2011 Jakub Wojciech Klama <jceel@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/malloc.h> -#include <sys/rman.h> -#include <machine/bus.h> -#ifndef __rtems__ -#include <machine/intr.h> - -#include <dev/ofw/ofw_bus.h> -#include <dev/ofw/ofw_bus_subr.h> -#endif /* __rtems__ */ - -#include <arm/lpc/lpcreg.h> -#include <arm/lpc/lpcvar.h> - -struct lpc_pwr_softc { - device_t dp_dev; - struct resource * dp_mem_res; - bus_space_tag_t dp_bst; - bus_space_handle_t dp_bsh; -}; - -static struct lpc_pwr_softc *lpc_pwr_sc = NULL; - -static int lpc_pwr_probe(device_t); -static int lpc_pwr_attach(device_t); - -#define lpc_pwr_read_4(_sc, _reg) \ - bus_space_read_4((_sc)->dp_bst, (_sc)->dp_bsh, _reg) -#define lpc_pwr_write_4(_sc, _reg, _val) \ - bus_space_write_4((_sc)->dp_bst, (_sc)->dp_bsh, _reg, _val) - -static int -lpc_pwr_probe(device_t dev) -{ - -#ifndef __rtems__ - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "lpc,pwr")) - return (ENXIO); -#endif /* __rtems__ */ - - device_set_desc(dev, "LPC32x0 Power Controller"); - return (BUS_PROBE_DEFAULT); -} - -static int -lpc_pwr_attach(device_t dev) -{ - struct lpc_pwr_softc *sc = device_get_softc(dev); - int rid; - - sc->dp_dev = dev; - - rid = 0; - sc->dp_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, - RF_ACTIVE); - if (!sc->dp_mem_res) { - device_printf(dev, "cannot allocate memory window\n"); - return (ENXIO); - } - - sc->dp_bst = rman_get_bustag(sc->dp_mem_res); - sc->dp_bsh = rman_get_bushandle(sc->dp_mem_res); - - lpc_pwr_sc = sc; - - return (0); -} - -uint32_t -lpc_pwr_read(device_t dev, int reg) -{ - return (lpc_pwr_read_4(lpc_pwr_sc, reg)); -} - -void -lpc_pwr_write(device_t dev, int reg, uint32_t value) -{ - lpc_pwr_write_4(lpc_pwr_sc, reg, value); -} - -static device_method_t lpc_pwr_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, lpc_pwr_probe), - DEVMETHOD(device_attach, lpc_pwr_attach), - { 0, 0 } -}; - -static devclass_t lpc_pwr_devclass; - -static driver_t lpc_pwr_driver = { - "pwr", - lpc_pwr_methods, - sizeof(struct lpc_pwr_softc), -}; - -#ifndef __rtems__ -DRIVER_MODULE(pwr, simplebus, lpc_pwr_driver, lpc_pwr_devclass, 0, 0); -#else /* __rtems__ */ -DRIVER_MODULE(pwr, nexus, lpc_pwr_driver, lpc_pwr_devclass, 0, 0); -#endif /* __rtems__ */ diff --git a/freebsd/sys/arm/lpc/lpcreg.h b/freebsd/sys/arm/lpc/lpcreg.h deleted file mode 100644 index d094e8f9..00000000 --- a/freebsd/sys/arm/lpc/lpcreg.h +++ /dev/null @@ -1,667 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2011 Jakub Wojciech Klama <jceel@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _ARM_LPC_LPCREG_H -#define _ARM_LPC_LPCREG_H - -#define LPC_DEV_PHYS_BASE 0x40000000 -#define LPC_DEV_P5_PHYS_BASE 0x20000000 -#define LPC_DEV_P6_PHYS_BASE 0x30000000 -#define LPC_DEV_SIZE 0x10000000 - -/* - * Interrupt controller (from UM10326: LPC32x0 User manual, page 87) - - */ -#define LPC_INTC_MIC_ER 0x0000 -#define LPC_INTC_MIC_RSR 0x0004 -#define LPC_INTC_MIC_SR 0x0008 -#define LPC_INTC_MIC_APR 0x000c -#define LPC_INTC_MIC_ATR 0x0010 -#define LPC_INTC_MIC_ITR 0x0014 -#define LPC_INTC_SIC1_ER 0x4000 -#define LPC_INTC_SIC1_RSR 0x4004 -#define LPC_INTC_SIC1_SR 0x4008 -#define LPC_INTC_SIC1_APR 0x400c -#define LPC_INTC_SIC1_ATR 0x4010 -#define LPC_INTC_SIC1_ITR 0x4014 -#define LPC_INTC_SIC2_ER 0x8000 -#define LPC_INTC_SIC2_RSR 0x8004 -#define LPC_INTC_SIC2_SR 0x8008 -#define LPC_INTC_SIC2_APR 0x800c -#define LPC_INTC_SIC2_ATR 0x8010 -#define LPC_INTC_SIC2_ITR 0x8014 - - -/* - * Timer 0|1|2|3|4|5. (from UM10326: LPC32x0 User manual, page 540) - */ -#define LPC_TIMER_IR 0x00 -#define LPC_TIMER_TCR 0x04 -#define LPC_TIMER_TCR_ENABLE (1 << 0) -#define LPC_TIMER_TCR_RESET (1 << 1) -#define LPC_TIMER_TC 0x08 -#define LPC_TIMER_PR 0x0c -#define LPC_TIMER_PC 0x10 -#define LPC_TIMER_MCR 0x14 -#define LPC_TIMER_MCR_MR0I (1 << 0) -#define LPC_TIMER_MCR_MR0R (1 << 1) -#define LPC_TIMER_MCR_MR0S (1 << 2) -#define LPC_TIMER_MCR_MR1I (1 << 3) -#define LPC_TIMER_MCR_MR1R (1 << 4) -#define LPC_TIMER_MCR_MR1S (1 << 5) -#define LPC_TIMER_MCR_MR2I (1 << 6) -#define LPC_TIMER_MCR_MR2R (1 << 7) -#define LPC_TIMER_MCR_MR2S (1 << 8) -#define LPC_TIMER_MCR_MR3I (1 << 9) -#define LPC_TIMER_MCR_MR3R (1 << 10) -#define LPC_TIMER_MCR_MR3S (1 << 11) -#define LPC_TIMER_MR0 0x18 -#define LPC_TIMER_CTCR 0x70 - -/* - * Watchdog timer. (from UM10326: LPC32x0 User manual, page 572) - */ -#define LPC_WDTIM_PHYS_BASE (LPC_DEV_PHYS_BASE + 0x3c000) -#define LPC_WDTIM_INT 0x00 -#define LPC_WDTIM_CTRL 0x04 -#define LPC_WDTIM_COUNTER 0x08 -#define LPC_WDTIM_MCTRL 0x0c -#define LPC_WDTIM_MATCH0 0x10 -#define LPC_WDTIM_EMR 0x14 -#define LPC_WDTIM_PULSE 0x18 -#define LPC_WDTIM_RES 0x1c -#define LPC_WDTIM_SIZE 0x20 - -/* - * Clocking and power control. (from UM10326: LPC32x0 User manual, page 58) - */ -#define LPC_CLKPWR_PHYS_BASE (LPC_DEV_PHYS_BASE + 0x4000) -#define LPC_CLKPWR_PWR_CTRL 0x44 -#define LPC_CLKPWR_OSC_CTRL 0x4c -#define LPC_CLKPWR_SYSCLK_CTRL 0x50 -#define LPC_CLKPWR_PLL397_CTRL 0x48 -#define LPC_CLKPWR_HCLKPLL_CTRL 0x58 -#define LPC_CLKPWR_HCLKDIV_CTRL 0x40 -#define LPC_CLKPWR_TEST_CTRL 0xa4 -#define LPC_CLKPWR_AUTOCLK_CTRL 0xec -#define LPC_CLKPWR_START_ER_PIN 0x30 -#define LPC_CLKPWR_START_ER_INT 0x20 -#define LPC_CLKPWR_P0_INTR_ER 0x18 -#define LPC_CLKPWR_START_SR_PIN 0x38 -#define LPC_CLKPWR_START_SR_INT 0x28 -#define LPC_CLKPWR_START_RSR_PIN 0x34 -#define LPC_CLKPWR_START_RSR_INT 0x24 -#define LPC_CLKPWR_START_APR_PIN 0x3c -#define LPC_CLKPWR_START_APR_INT 0x2c -#define LPC_CLKPWR_USB_CTRL 0x64 -#define LPC_CLKPWR_USB_CTRL_SLAVE_HCLK (1 << 24) -#define LPC_CLKPWR_USB_CTRL_I2C_EN (1 << 23) -#define LPC_CLKPWR_USB_CTRL_DEV_NEED_CLK_EN (1 << 22) -#define LPC_CLKPWR_USB_CTRL_HOST_NEED_CLK_EN (1 << 21) -#define LPC_CLKPWR_USB_CTRL_BUSKEEPER (1 << 19) -#define LPC_CLKPWR_USB_CTRL_CLK_EN2 (1 << 18) -#define LPC_CLKPWR_USB_CTRL_CLK_EN1 (1 << 17) -#define LPC_CLKPWR_USB_CTRL_PLL_PDOWN (1 << 16) -#define LPC_CLKPWR_USB_CTRL_BYPASS (1 << 15) -#define LPC_CLKPWR_USB_CTRL_DIRECT_OUT (1 << 14) -#define LPC_CLKPWR_USB_CTRL_FEEDBACK (1 << 13) -#define LPC_CLKPWR_USB_CTRL_POSTDIV(_x) ((_x & 0x3) << 11) -#define LPC_CLKPWR_USB_CTRL_PREDIV(_x) ((_x & 0x3) << 9) -#define LPC_CLKPWR_USB_CTRL_FDBKDIV(_x) (((_x-1) & 0xff) << 1) -#define LPC_CLKPWR_USB_CTRL_PLL_LOCK (1 << 0) -#define LPC_CLKPWR_USBDIV_CTRL 0x1c -#define LPC_CLKPWR_MS_CTRL 0x80 -#define LPC_CLKPWR_MS_CTRL_DISABLE_SD (1 << 10) -#define LPC_CLKPWR_MS_CTRL_CLOCK_EN (1 << 9) -#define LPC_CLKPWR_MS_CTRL_MSSDIO23_PAD (1 << 8) -#define LPC_CLKPWR_MS_CTRL_MSSDIO1_PAD (1 << 7) -#define LPC_CLKPWR_MS_CTRL_MSSDIO0_PAD (1 << 6) -#define LPC_CLKPWR_MS_CTRL_SD_CLOCK (1 << 5) -#define LPC_CLKPWR_MS_CTRL_CLKDIV_MASK 0xf -#define LPC_CLKPWR_DMACLK_CTRL 0xe8 -#define LPC_CLKPWR_DMACLK_CTRL_EN (1 << 0) -#define LPC_CLKPWR_FLASHCLK_CTRL 0xc8 -#define LPC_CLKPWR_MACCLK_CTRL 0x90 -#define LPC_CLKPWR_MACCLK_CTRL_REG (1 << 0) -#define LPC_CLKPWR_MACCLK_CTRL_SLAVE (1 << 1) -#define LPC_CLKPWR_MACCLK_CTRL_MASTER (1 << 2) -#define LPC_CLKPWR_MACCLK_CTRL_HDWINF(_n) ((_n & 0x3) << 3) -#define LPC_CLKPWR_LCDCLK_CTRL 0x54 -#define LPC_CLKPWR_LCDCLK_CTRL_DISPTYPE (1 << 8) -#define LPC_CLKPWR_LCDCLK_CTRL_MODE(_n) ((_n & 0x3) << 6) -#define LPC_CLKPWR_LCDCLK_CTRL_MODE_12 0x0 -#define LPC_CLKPWR_LCDCLK_CTRL_MODE_15 0x1 -#define LPC_CLKPWR_LCDCLK_CTRL_MODE_16 0x2 -#define LPC_CLKPWR_LCDCLK_CTRL_MODE_24 0x3 -#define LPC_CLKPWR_LCDCLK_CTRL_HCLKEN (1 << 5) -#define LPC_CLKPWR_LCDCLK_CTRL_CLKDIV(_n) ((_n) & 0x1f) -#define LPC_CLKPWR_I2S_CTRL 0x7c -#define LPC_CLKPWR_SSP_CTRL 0x78 -#define LPC_CLKPWR_SSP_CTRL_SSP1RXDMA (1 << 5) -#define LPC_CLKPWR_SSP_CTRL_SSP1TXDMA (1 << 4) -#define LPC_CLKPWR_SSP_CTRL_SSP0RXDMA (1 << 3) -#define LPC_CLKPWR_SSP_CTRL_SSP0TXDMA (1 << 2) -#define LPC_CLKPWR_SSP_CTRL_SSP1EN (1 << 1) -#define LPC_CLKPWR_SSP_CTRL_SSP0EN (1 << 0) -#define LPC_CLKPWR_SPI_CTRL 0xc4 -#define LPC_CLKPWR_I2CCLK_CTRL 0xac -#define LPC_CLKPWR_TIMCLK_CTRL1 0xc0 -#define LPC_CLKPWR_TIMCLK_CTRL1_TIMER4 (1 << 0) -#define LPC_CLKPWR_TIMCLK_CTRL1_TIMER5 (1 << 1) -#define LPC_CLKPWR_TIMCLK_CTRL1_TIMER0 (1 << 2) -#define LPC_CLKPWR_TIMCLK_CTRL1_TIMER1 (1 << 3) -#define LPC_CLKPWR_TIMCLK_CTRL1_TIMER2 (1 << 4) -#define LPC_CLKPWR_TIMCLK_CTRL1_TIMER3 (1 << 5) -#define LPC_CLKPWR_TIMCLK_CTRL1_MOTORCTL (1 << 6) -#define LPC_CLKPWR_TIMCLK_CTRL 0xbc -#define LPC_CLKPWR_TIMCLK_CTRL_WATCHDOG (1 << 0) -#define LPC_CLKPWR_TIMCLK_CTRL_HSTIMER (1 << 1) -#define LPC_CLKPWR_ADCLK_CTRL 0xb4 -#define LPC_CLKPWR_ADCLK_CTRL1 0x60 -#define LPC_CLKPWR_KEYCLK_CTRL 0xb0 -#define LPC_CLKPWR_PWMCLK_CTRL 0xb8 -#define LPC_CLKPWR_UARTCLK_CTRL 0xe4 -#define LPC_CLKPWR_POS0_IRAM_CTRL 0x110 -#define LPC_CLKPWR_POS1_IRAM_CTRL 0x114 -#define LPC_CLKPWR_SIZE 0x118 - -/* Additional UART registers in CLKPWR address space. */ -#define LPC_CLKPWR_UART_U3CLK 0xd0 -#define LPC_CLKPWR_UART_U4CLK 0xd4 -#define LPC_CLKPWR_UART_U5CLK 0xd8 -#define LPC_CLKPWR_UART_U6CLK 0xdc -#define LPC_CLKPWR_UART_UCLK_HCLK (1 << 16) -#define LPC_CLKPWR_UART_UCLK_X(_n) (((_n) & 0xff) << 8) -#define LPC_CLKPWR_UART_UCLK_Y(_n) ((_n) & 0xff) -#define LPC_CLKPWR_UART_IRDACLK 0xe0 - -/* Additional UART registers */ -#define LPC_UART_BASE 0x80000 -#define LPC_UART_CONTROL_BASE 0x54000 -#define LPC_UART5_BASE 0x90000 -#define LPC_UART_CTRL 0x00 -#define LPC_UART_CLKMODE 0x04 -#define LPC_UART_CLKMODE_UART3(_n) (((_n) & 0x3) << 4) -#define LPC_UART_CLKMODE_UART4(_n) (((_n) & 0x3) << 6) -#define LPC_UART_CLKMODE_UART5(_n) (((_n) & 0x3) << 8) -#define LPC_UART_CLKMODE_UART6(_n) (((_n) & 0x3) << 10) -#define LPC_UART_LOOP 0x08 -#define LPC_UART_CONTROL_SIZE 0x0c -#define LPC_UART_FIFOSIZE 64 - -/* - * Real time clock. (from UM10326: LPC32x0 User manual, page 566) - */ -#define LPC_RTC_UCOUNT 0x00 -#define LPC_RTC_DCOUNT 0x04 -#define LPC_RTC_MATCH0 0x08 -#define LPC_RTC_MATCH1 0x0c -#define LPC_RTC_CTRL 0x10 -#define LPC_RTC_CTRL_ONSW (1 << 7) -#define LPC_RTC_CTRL_DISABLE (1 << 6) -#define LPC_RTC_CTRL_RTCRESET (1 << 4) -#define LPC_RTC_CTRL_MATCH0ONSW (1 << 3) -#define LPC_RTC_CTRL_MATCH1ONSW (1 << 2) -#define LPC_RTC_CTRL_MATCH1INTR (1 << 1) -#define LPC_RTC_CTRL_MATCH0INTR (1 << 0) -#define LPC_RTC_INTSTAT 0x14 -#define LPC_RTC_KEY 0x18 -#define LPC_RTC_SRAM_BEGIN 0x80 -#define LPC_RTC_SRAM_END 0xff - -/* - * MMC/SD controller. (from UM10326: LPC32x0 User manual, page 436) - */ -#define LPC_SD_PHYS_BASE (LPC_DEV_P5_PHYS_BASE + 0x98000) -#define LPC_SD_CLK (13 * 1000 * 1000) // 13Mhz -#define LPC_SD_POWER 0x00 -#define LPC_SD_POWER_OPENDRAIN (1 << 6) -#define LPC_SD_POWER_CTRL_OFF 0x00 -#define LPC_SD_POWER_CTRL_UP 0x02 -#define LPC_SD_POWER_CTRL_ON 0x03 -#define LPC_SD_CLOCK 0x04 -#define LPC_SD_CLOCK_WIDEBUS (1 << 11) -#define LPC_SD_CLOCK_BYPASS (1 << 10) -#define LPC_SD_CLOCK_PWRSAVE (1 << 9) -#define LPC_SD_CLOCK_ENABLE (1 << 8) -#define LPC_SD_CLOCK_CLKDIVMASK 0xff -#define LPC_SD_ARGUMENT 0x08 -#define LPC_SD_COMMAND 0x0c -#define LPC_SD_COMMAND_ENABLE (1 << 10) -#define LPC_SD_COMMAND_PENDING (1 << 9) -#define LPC_SD_COMMAND_INTERRUPT (1 << 8) -#define LPC_SD_COMMAND_LONGRSP (1 << 7) -#define LPC_SD_COMMAND_RESPONSE (1 << 6) -#define LPC_SD_COMMAND_CMDINDEXMASK 0x3f -#define LPC_SD_RESPCMD 0x10 -#define LPC_SD_RESP0 0x14 -#define LPC_SD_RESP1 0x18 -#define LPC_SD_RESP2 0x1c -#define LPC_SD_RESP3 0x20 -#define LPC_SD_DATATIMER 0x24 -#define LPC_SD_DATALENGTH 0x28 -#define LPC_SD_DATACTRL 0x2c -#define LPC_SD_DATACTRL_BLOCKSIZESHIFT 4 -#define LPC_SD_DATACTRL_BLOCKSIZEMASK 0xf -#define LPC_SD_DATACTRL_DMAENABLE (1 << 3) -#define LPC_SD_DATACTRL_MODE (1 << 2) -#define LPC_SD_DATACTRL_WRITE (0 << 1) -#define LPC_SD_DATACTRL_READ (1 << 1) -#define LPC_SD_DATACTRL_ENABLE (1 << 0) -#define LPC_SD_DATACNT 0x30 -#define LPC_SD_STATUS 0x34 -#define LPC_SD_STATUS_RXDATAAVLBL (1 << 21) -#define LPC_SD_STATUS_TXDATAAVLBL (1 << 20) -#define LPC_SD_STATUS_RXFIFOEMPTY (1 << 19) -#define LPC_SD_STATUS_TXFIFOEMPTY (1 << 18) -#define LPC_SD_STATUS_RXFIFOFULL (1 << 17) -#define LPC_SD_STATUS_TXFIFOFULL (1 << 16) -#define LPC_SD_STATUS_RXFIFOHALFFULL (1 << 15) -#define LPC_SD_STATUS_TXFIFOHALFEMPTY (1 << 14) -#define LPC_SD_STATUS_RXACTIVE (1 << 13) -#define LPC_SD_STATUS_TXACTIVE (1 << 12) -#define LPC_SD_STATUS_CMDACTIVE (1 << 11) -#define LPC_SD_STATUS_DATABLOCKEND (1 << 10) -#define LPC_SD_STATUS_STARTBITERR (1 << 9) -#define LPC_SD_STATUS_DATAEND (1 << 8) -#define LPC_SD_STATUS_CMDSENT (1 << 7) -#define LPC_SD_STATUS_CMDRESPEND (1 << 6) -#define LPC_SD_STATUS_RXOVERRUN (1 << 5) -#define LPC_SD_STATUS_TXUNDERRUN (1 << 4) -#define LPC_SD_STATUS_DATATIMEOUT (1 << 3) -#define LPC_SD_STATUS_CMDTIMEOUT (1 << 2) -#define LPC_SD_STATUS_DATACRCFAIL (1 << 1) -#define LPC_SD_STATUS_CMDCRCFAIL (1 << 0) -#define LPC_SD_CLEAR 0x38 -#define LPC_SD_MASK0 0x03c -#define LPC_SD_MASK1 0x40 -#define LPC_SD_FIFOCNT 0x48 -#define LPC_SD_FIFO 0x80 - -/* - * USB OTG controller (from UM10326: LPC32x0 User manual, page 410) - */ -#define LPC_OTG_INT_STATUS 0x100 -#define LPC_OTG_INT_ENABLE 0x104 -#define LPC_OTG_INT_SET 0x108 -#define LPC_OTG_INT_CLEAR 0x10c -#define LPC_OTG_STATUS 0x110 -#define LPC_OTG_STATUS_ATOB_HNP_TRACK (1 << 9) -#define LPC_OTG_STATUS_BTOA_HNP_TACK (1 << 8) -#define LPC_OTG_STATUS_TRANSP_I2C_EN (1 << 7) -#define LPC_OTG_STATUS_TIMER_RESET (1 << 6) -#define LPC_OTG_STATUS_TIMER_EN (1 << 5) -#define LPC_OTG_STATUS_TIMER_MODE (1 << 4) -#define LPC_OTG_STATUS_TIMER_SCALE (1 << 2) -#define LPC_OTG_STATUS_HOST_EN (1 << 0) -#define LPC_OTG_TIMER 0x114 -#define LPC_OTG_I2C_TXRX 0x300 -#define LPC_OTG_I2C_STATUS 0x304 -#define LPC_OTG_I2C_STATUS_TFE (1 << 11) -#define LPC_OTG_I2C_STATUS_TFF (1 << 10) -#define LPC_OTG_I2C_STATUS_RFE (1 << 9) -#define LPC_OTG_I2C_STATUS_RFF (1 << 8) -#define LPC_OTG_I2C_STATUS_SDA (1 << 7) -#define LPC_OTG_I2C_STATUS_SCL (1 << 6) -#define LPC_OTG_I2C_STATUS_ACTIVE (1 << 5) -#define LPC_OTG_I2C_STATUS_DRSI (1 << 4) -#define LPC_OTG_I2C_STATUS_DRMI (1 << 3) -#define LPC_OTG_I2C_STATUS_NAI (1 << 2) -#define LPC_OTG_I2C_STATUS_AFI (1 << 1) -#define LPC_OTG_I2C_STATUS_TDI (1 << 0) -#define LPC_OTG_I2C_CTRL 0x308 -#define LPC_OTG_I2C_CTRL_SRST (1 << 8) -#define LPC_OTG_I2C_CTRL_TFFIE (1 << 7) -#define LPC_OTG_I2C_CTRL_RFDAIE (1 << 6) -#define LPC_OTG_I2C_CTRL_RFFIE (1 << 5) -#define LPC_OTG_I2C_CTRL_DRSIE (1 << 4) -#define LPC_OTG_I2C_CTRL_DRMIE (1 << 3) -#define LPC_OTG_I2C_CTRL_NAIE (1 << 2) -#define LPC_OTG_I2C_CTRL_AFIE (1 << 1) -#define LPC_OTG_I2C_CTRL_TDIE (1 << 0) -#define LPC_OTG_I2C_CLKHI 0x30c -#define LPC_OTG_I2C_CLKLO 0x310 -#define LPC_OTG_CLOCK_CTRL 0xff4 -#define LPC_OTG_CLOCK_CTRL_AHB_EN (1 << 4) -#define LPC_OTG_CLOCK_CTRL_OTG_EN (1 << 3) -#define LPC_OTG_CLOCK_CTRL_I2C_EN (1 << 2) -#define LPC_OTG_CLOCK_CTRL_DEV_EN (1 << 1) -#define LPC_OTG_CLOCK_CTRL_HOST_EN (1 << 0) -#define LPC_OTG_CLOCK_STATUS 0xff8 - -/* - * ISP3101 USB transceiver registers - */ -#define LPC_ISP3101_I2C_ADDR 0x2d -#define LPC_ISP3101_MODE_CONTROL_1 0x04 -#define LPC_ISP3101_MC1_SPEED_REG (1 << 0) -#define LPC_ISP3101_MC1_SUSPEND_REG (1 << 1) -#define LPC_ISP3101_MC1_DAT_SE0 (1 << 2) -#define LPC_ISP3101_MC1_TRANSPARENT (1 << 3) -#define LPC_ISP3101_MC1_BDIS_ACON_EN (1 << 4) -#define LPC_ISP3101_MC1_OE_INT_EN (1 << 5) -#define LPC_ISP3101_MC1_UART_EN (1 << 6) -#define LPC_ISP3101_MODE_CONTROL_2 0x12 -#define LPC_ISP3101_MC2_GLOBAL_PWR_DN (1 << 0) -#define LPC_ISP3101_MC2_SPD_SUSP_CTRL (1 << 1) -#define LPC_ISP3101_MC2_BI_DI (1 << 2) -#define LPC_ISP3101_MC2_TRANSP_BDIR0 (1 << 3) -#define LPC_ISP3101_MC2_TRANSP_BDIR1 (1 << 4) -#define LPC_ISP3101_MC2_AUDIO_EN (1 << 5) -#define LPC_ISP3101_MC2_PSW_EN (1 << 6) -#define LPC_ISP3101_MC2_EN2V7 (1 << 7) -#define LPC_ISP3101_OTG_CONTROL_1 0x06 -#define LPC_ISP3101_OTG1_DP_PULLUP (1 << 0) -#define LPC_ISP3101_OTG1_DM_PULLUP (1 << 1) -#define LPC_ISP3101_OTG1_DP_PULLDOWN (1 << 2) -#define LPC_ISP3101_OTG1_DM_PULLDOWN (1 << 3) -#define LPC_ISP3101_OTG1_ID_PULLDOWN (1 << 4) -#define LPC_ISP3101_OTG1_VBUS_DRV (1 << 5) -#define LPC_ISP3101_OTG1_VBUS_DISCHRG (1 << 6) -#define LPC_ISP3101_OTG1_VBUS_CHRG (1 << 7) -#define LPC_ISP3101_OTG_CONTROL_2 0x10 -#define LPC_ISP3101_OTG_INTR_LATCH 0x0a -#define LPC_ISP3101_OTG_INTR_FALLING 0x0c -#define LPC_ISP3101_OTG_INTR_RISING 0x0e -#define LPC_ISP3101_REG_CLEAR_ADDR 0x01 - -/* - * LCD Controller (from UM10326: LPC32x0 User manual, page 229) - */ -#define LPC_LCD_TIMH 0x00 -#define LPC_LCD_TIMH_HBP(_n) (((_n) & 0xff) << 24) -#define LPC_LCD_TIMH_HFP(_n) (((_n) & 0xff) << 16) -#define LPC_LCD_TIMH_HSW(_n) (((_n) & 0xff) << 8) -#define LPC_LCD_TIMH_PPL(_n) (((_n) / 16 - 1) << 2) -#define LPC_LCD_TIMV 0x04 -#define LPC_LCD_TIMV_VBP(_n) (((_n) & 0xff) << 24) -#define LPC_LCD_TIMV_VFP(_n) (((_n) & 0xff) << 16) -#define LPC_LCD_TIMV_VSW(_n) (((_n) & 0x3f) << 10) -#define LPC_LCD_TIMV_LPP(_n) ((_n) & 0x1ff) -#define LPC_LCD_POL 0x08 -#define LPC_LCD_POL_PCD_HI (((_n) & 0x1f) << 27) -#define LPC_LCD_POL_BCD (1 << 26) -#define LPC_LCD_POL_CPL(_n) (((_n) & 0x3ff) << 16) -#define LPC_LCD_POL_IOE (1 << 14) -#define LPC_LCD_POL_IPC (1 << 13) -#define LPC_LCD_POL_IHS (1 << 12) -#define LPC_LCD_POL_IVS (1 << 11) -#define LPC_LCD_POL_ACB(_n) ((_n & 0x1f) << 6) -#define LPC_LCD_POL_CLKSEL (1 << 5) -#define LPC_LCD_POL_PCD_LO(_n) ((_n) & 0x1f) -#define LPC_LCD_LE 0x0c -#define LPC_LCD_LE_LEE (1 << 16) -#define LPC_LCD_LE_LED ((_n) & 0x7f) -#define LPC_LCD_UPBASE 0x10 -#define LPC_LCD_LPBASE 0x14 -#define LPC_LCD_CTRL 0x18 -#define LPC_LCD_CTRL_WATERMARK (1 << 16) -#define LPC_LCD_CTRL_LCDVCOMP(_n) (((_n) & 0x3) << 12) -#define LPC_LCD_CTRL_LCDPWR (1 << 11) -#define LPC_LCD_CTRL_BEPO (1 << 10) -#define LPC_LCD_CTRL_BEBO (1 << 9) -#define LPC_LCD_CTRL_BGR (1 << 8) -#define LPC_LCD_CTRL_LCDDUAL (1 << 7) -#define LPC_LCD_CTRL_LCDMONO8 (1 << 6) -#define LPC_LCD_CTRL_LCDTFT (1 << 5) -#define LPC_LCD_CTRL_LCDBW (1 << 4) -#define LPC_LCD_CTRL_LCDBPP(_n) (((_n) & 0x7) << 1) -#define LPC_LCD_CTRL_BPP1 0 -#define LPC_LCD_CTRL_BPP2 1 -#define LPC_LCD_CTRL_BPP4 2 -#define LPC_LCD_CTRL_BPP8 3 -#define LPC_LCD_CTRL_BPP16 4 -#define LPC_LCD_CTRL_BPP24 5 -#define LPC_LCD_CTRL_BPP16_565 6 -#define LPC_LCD_CTRL_BPP12_444 7 -#define LPC_LCD_CTRL_LCDEN (1 << 0) -#define LPC_LCD_INTMSK 0x1c -#define LPC_LCD_INTRAW 0x20 -#define LPC_LCD_INTSTAT 0x24 -#define LPC_LCD_INTCLR 0x28 -#define LPC_LCD_UPCURR 0x2c -#define LPC_LCD_LPCURR 0x30 -#define LPC_LCD_PAL 0x200 -#define LPC_LCD_CRSR_IMG 0x800 -#define LPC_LCD_CRSR_CTRL 0xc00 -#define LPC_LCD_CRSR_CFG 0xc04 -#define LPC_LCD_CRSR_PAL0 0xc08 -#define LPC_LCD_CRSR_PAL1 0xc0c -#define LPC_LCD_CRSR_XY 0xc10 -#define LPC_LCD_CRSR_CLIP 0xc14 -#define LPC_LCD_CRSR_INTMSK 0xc20 -#define LPC_LCD_CRSR_INTCLR 0xc24 -#define LPC_LCD_CRSR_INTRAW 0xc28 -#define LPC_LCD_CRSR_INTSTAT 0xc2c - -/* - * SPI interface (from UM10326: LPC32x0 User manual, page 483) - */ -#define LPC_SPI_GLOBAL 0x00 -#define LPC_SPI_GLOBAL_RST (1 << 1) -#define LPC_SPI_GLOBAL_ENABLE (1 << 0) -#define LPC_SPI_CON 0x04 -#define LPC_SPI_CON_UNIDIR (1 << 23) -#define LPC_SPI_CON_BHALT (1 << 22) -#define LPC_SPI_CON_BPOL (1 << 21) -#define LPC_SPI_CON_MSB (1 << 19) -#define LPC_SPI_CON_MODE(_n) ((_n & 0x3) << 16) -#define LPC_SPI_CON_RXTX (1 << 15) -#define LPC_SPI_CON_THR (1 << 14) -#define LPC_SPI_CON_SHIFT_OFF (1 << 13) -#define LPC_SPI_CON_BITNUM(_n) ((_n & 0xf) << 9) -#define LPC_SPI_CON_MS (1 << 7) -#define LPC_SPI_CON_RATE(_n) (_n & 0x7f) -#define LPC_SPI_FRM 0x08 -#define LPC_SPI_IER 0x0c -#define LPC_SPI_IER_INTEOT (1 << 1) -#define LPC_SPI_IER_INTTHR (1 << 0) -#define LPC_SPI_STAT 0x10 -#define LPC_SPI_STAT_INTCLR (1 << 8) -#define LPC_SPI_STAT_EOT (1 << 7) -#define LPC_SPI_STAT_BUSYLEV (1 << 6) -#define LPC_SPI_STAT_SHIFTACT (1 << 3) -#define LPC_SPI_STAT_BF (1 << 2) -#define LPC_SPI_STAT_THR (1 << 1) -#define LPC_SPI_STAT_BE (1 << 0) -#define LPC_SPI_DAT 0x14 -#define LPC_SPI_TIM_CTRL 0x400 -#define LPC_SPI_TIM_COUNT 0x404 -#define LPC_SPI_TIM_STAT 0x408 - -/* - * SSP interface (from UM10326: LPC32x0 User manual, page 500) - */ -#define LPC_SSP0_BASE 0x4c00 -#define LPC_SSP1_BASE 0xc000 -#define LPC_SSP_CR0 0x00 -#define LPC_SSP_CR0_DSS(_n) ((_n-1) & 0xf) -#define LPC_SSP_CR0_TI (1 << 4) -#define LPC_SSP_CR0_MICROWIRE (1 << 5) -#define LPC_SSP_CR0_CPOL (1 << 6) -#define LPC_SSP_CR0_CPHA (1 << 7) -#define LPC_SSP_CR0_SCR(_n) ((_x & & 0xff) << 8) -#define LPC_SSP_CR1 0x04 -#define LPC_SSP_CR1_LBM (1 << 0) -#define LPC_SSP_CR1_SSE (1 << 1) -#define LPC_SSP_CR1_MS (1 << 2) -#define LPC_SSP_CR1_SOD (1 << 3) -#define LPC_SSP_DR 0x08 -#define LPC_SSP_SR 0x0c -#define LPC_SSP_SR_TFE (1 << 0) -#define LPC_SSP_SR_TNF (1 << 1) -#define LPC_SSP_SR_RNE (1 << 2) -#define LPC_SSP_SR_RFF (1 << 3) -#define LPC_SSP_SR_BSY (1 << 4) -#define LPC_SSP_CPSR 0x10 -#define LPC_SSP_IMSC 0x14 -#define LPC_SSP_IMSC_RORIM (1 << 0) -#define LPC_SSP_IMSC_RTIM (1 << 1) -#define LPC_SSP_IMSC_RXIM (1 << 2) -#define LPC_SSP_IMSC_TXIM (1 << 3) -#define LPC_SSP_RIS 0x18 -#define LPC_SSP_RIS_RORRIS (1 << 0) -#define LPC_SSP_RIS_RTRIS (1 << 1) -#define LPC_SSP_RIS_RXRIS (1 << 2) -#define LPC_SSP_RIS_TXRIS (1 << 3) -#define LPC_SSP_MIS 0x1c -#define LPC_SSP_ICR 0x20 -#define LPC_SSP_DMACR 0x24 - -/* - * GPIO (from UM10326: LPC32x0 User manual, page 606) - */ -#define LPC_GPIO_PHYS_BASE (LPC_DEV_PHYS_BASE + 0x28000) -#define LPC_GPIO_P0_COUNT 8 -#define LPC_GPIO_P1_COUNT 24 -#define LPC_GPIO_P2_COUNT 13 -#define LPC_GPIO_P3_COUNT 52 -#define LPC_GPIO_P0_INP_STATE 0x40 -#define LPC_GPIO_P0_OUTP_SET 0x44 -#define LPC_GPIO_P0_OUTP_CLR 0x48 -#define LPC_GPIO_P0_OUTP_STATE 0x4c -#define LPC_GPIO_P0_DIR_SET 0x50 -#define LPC_GPIO_P0_DIR_CLR 0x54 -#define LPC_GPIO_P0_DIR_STATE 0x58 -#define LPC_GPIO_P1_INP_STATE 0x60 -#define LPC_GPIO_P1_OUTP_SET 0x64 -#define LPC_GPIO_P1_OUTP_CLR 0x68 -#define LPC_GPIO_P1_OUTP_STATE 0x6c -#define LPC_GPIO_P1_DIR_SET 0x70 -#define LPC_GPIO_P1_DIR_CLR 0x74 -#define LPC_GPIO_P1_DIR_STATE 0x78 -#define LPC_GPIO_P2_INP_STATE 0x1c -#define LPC_GPIO_P2_OUTP_SET 0x20 -#define LPC_GPIO_P2_OUTP_CLR 0x24 -#define LPC_GPIO_P2_DIR_SET 0x10 -#define LPC_GPIO_P2_DIR_CLR 0x14 -#define LPC_GPIO_P2_DIR_STATE 0x14 -#define LPC_GPIO_P3_INP_STATE 0x00 -#define LPC_GPIO_P3_OUTP_SET 0x04 -#define LPC_GPIO_P3_OUTP_CLR 0x08 -#define LPC_GPIO_P3_OUTP_STATE 0x0c -#define LPC_GPIO_SIZE 0x80 - -/* Aliases for logical pin numbers: */ -#define LPC_GPIO_GPI_00(_n) (0 + _n) -#define LPC_GPIO_GPI_15(_n) (10 + _n) -#define LPC_GPIO_GPI_25 (19) -#define LPC_GPIO_GPI_27(_n) (20 + _n) -#define LPC_GPIO_GPO_00(_n) (22 + _n) -#define LPC_GPIO_GPIO_00(_n) (46 + _n) -/* SPI devices chip selects: */ -#define SSD1289_CS_PIN LPC_GPIO_GPO_00(4) -#define SSD1289_DC_PIN LPC_GPIO_GPO_00(5) -#define ADS7846_CS_PIN LPC_GPIO_GPO_00(11) -#define ADS7846_INTR_PIN LPC_GPIO_GPIO_00(0) - -/* - * GPDMA controller (from UM10326: LPC32x0 User manual, page 106) - */ -#define LPC_DMAC_INTSTAT 0x00 -#define LPC_DMAC_INTTCSTAT 0x04 -#define LPC_DMAC_INTTCCLEAR 0x08 -#define LPC_DMAC_INTERRSTAT 0x0c -#define LPC_DMAC_INTERRCLEAR 0x10 -#define LPC_DMAC_RAWINTTCSTAT 0x14 -#define LPC_DMAC_RAWINTERRSTAT 0x18 -#define LPC_DMAC_ENABLED_CHANNELS 0x1c -#define LPC_DMAC_SOFTBREQ 0x20 -#define LPC_DMAC_SOFTSREQ 0x24 -#define LPC_DMAC_SOFTLBREQ 0x28 -#define LPC_DMAC_SOFTLSREQ 0x2c -#define LPC_DMAC_CONFIG 0x30 -#define LPC_DMAC_CONFIG_M1 (1 << 2) -#define LPC_DMAC_CONFIG_M0 (1 << 1) -#define LPC_DMAC_CONFIG_ENABLE (1 << 0) -#define LPC_DMAC_CHADDR(_n) (0x100 + (_n * 0x20)) -#define LPC_DMAC_CHNUM 8 -#define LPC_DMAC_CHSIZE 0x20 -#define LPC_DMAC_CH_SRCADDR 0x00 -#define LPC_DMAC_CH_DSTADDR 0x04 -#define LPC_DMAC_CH_LLI 0x08 -#define LPC_DMAC_CH_LLI_AHB1 (1 << 0) -#define LPC_DMAC_CH_CONTROL 0x0c -#define LPC_DMAC_CH_CONTROL_I (1U << 31) -#define LPC_DMAC_CH_CONTROL_DI (1 << 27) -#define LPC_DMAC_CH_CONTROL_SI (1 << 26) -#define LPC_DMAC_CH_CONTROL_D (1 << 25) -#define LPC_DMAC_CH_CONTROL_S (1 << 24) -#define LPC_DMAC_CH_CONTROL_WIDTH_4 2 -#define LPC_DMAC_CH_CONTROL_DWIDTH(_n) ((_n & 0x7) << 21) -#define LPC_DMAC_CH_CONTROL_SWIDTH(_n) ((_n & 0x7) << 18) -#define LPC_DMAC_CH_CONTROL_BURST_8 2 -#define LPC_DMAC_CH_CONTROL_DBSIZE(_n) ((_n & 0x7) << 15) -#define LPC_DMAC_CH_CONTROL_SBSIZE(_n) ((_n & 0x7) << 12) -#define LPC_DMAC_CH_CONTROL_XFERLEN(_n) (_n & 0xfff) -#define LPC_DMAC_CH_CONFIG 0x10 -#define LPC_DMAC_CH_CONFIG_H (1 << 18) -#define LPC_DMAC_CH_CONFIG_A (1 << 17) -#define LPC_DMAC_CH_CONFIG_L (1 << 16) -#define LPC_DMAC_CH_CONFIG_ITC (1 << 15) -#define LPC_DMAC_CH_CONFIG_IE (1 << 14) -#define LPC_DMAC_CH_CONFIG_FLOWCNTL(_n) ((_n & 0x7) << 11) -#define LPC_DMAC_CH_CONFIG_DESTP(_n) ((_n & 0x1f) << 6) -#define LPC_DMAC_CH_CONFIG_SRCP(_n) ((_n & 0x1f) << 1) -#define LPC_DMAC_CH_CONFIG_E (1 << 0) - -/* DMA flow control values */ -#define LPC_DMAC_FLOW_D_M2M 0 -#define LPC_DMAC_FLOW_D_M2P 1 -#define LPC_DMAC_FLOW_D_P2M 2 -#define LPC_DMAC_FLOW_D_P2P 3 -#define LPC_DMAC_FLOW_DP_P2P 4 -#define LPC_DMAC_FLOW_P_M2P 5 -#define LPC_DMAC_FLOW_P_P2M 6 -#define LPC_DMAC_FLOW_SP_P2P 7 - -/* DMA peripheral ID's */ -#define LPC_DMAC_I2S0_DMA0_ID 0 -#define LPC_DMAC_NAND_ID 1 -#define LPC_DMAC_IS21_DMA0_ID 2 -#define LPC_DMAC_SSP1_ID 3 -#define LPC_DMAC_SPI2_ID 3 -#define LPC_DMAC_SD_ID 4 -#define LPC_DMAC_UART1_TX_ID 5 -#define LPC_DMAC_UART1_RX_ID 6 -#define LPC_DMAC_UART2_TX_ID 7 -#define LPC_DMAC_UART2_RX_ID 8 -#define LPC_DMAC_UART7_TX_ID 9 -#define LPC_DMAC_UART7_RX_ID 10 -#define LPC_DMAC_I2S1_DMA1_ID 10 -#define LPC_DMAC_SPI1_ID 11 -#define LPC_DMAC_SSP1_TX_ID 11 -#define LPC_DMAC_NAND2_ID 12 -#define LPC_DMAC_I2S0_DMA1_ID 13 -#define LPC_DMAC_SSP0_RX 14 -#define LPC_DMAC_SSP0_TX 15 - -#endif /* _ARM_LPC_LPCREG_H */ diff --git a/freebsd/sys/arm/lpc/lpcvar.h b/freebsd/sys/arm/lpc/lpcvar.h deleted file mode 100644 index dafbef08..00000000 --- a/freebsd/sys/arm/lpc/lpcvar.h +++ /dev/null @@ -1,71 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2011 Jakub Wojciech Klama <jceel@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _ARM_LPC_LPCVAR_H -#define _ARM_LPC_LPCVAR_H - -#include <sys/types.h> -#include <sys/bus.h> -#include <machine/bus.h> - -/* Clocking and power control */ -uint32_t lpc_pwr_read(device_t, int); -void lpc_pwr_write(device_t, int, uint32_t); - -/* GPIO */ -void lpc_gpio_init(void); -int lpc_gpio_set_flags(device_t, int, int); -int lpc_gpio_set_state(device_t, int, int); -int lpc_gpio_get_state(device_t, int, int *); - -/* DMA */ -struct lpc_dmac_channel_config -{ - int ldc_fcntl; - int ldc_src_periph; - int ldc_src_width; - int ldc_src_incr; - int ldc_src_burst; - int ldc_dst_periph; - int ldc_dst_width; - int ldc_dst_incr; - int ldc_dst_burst; - void (*ldc_success_handler)(void *); - void (*ldc_error_handler)(void *); - void * ldc_handler_arg; -}; - -int lpc_dmac_config_channel(device_t, int, struct lpc_dmac_channel_config *); -int lpc_dmac_setup_transfer(device_t, int, bus_addr_t, bus_addr_t, bus_size_t, int); -int lpc_dmac_enable_channel(device_t, int); -int lpc_dmac_disable_channel(device_t, int); -int lpc_dmac_start_burst(device_t, int); - -#endif /* _ARM_LPC_LPCVAR_H */ diff --git a/freebsd/sys/cam/cam_ccb.h b/freebsd/sys/cam/cam_ccb.h index 8e88b4a3..642e7862 100644 --- a/freebsd/sys/cam/cam_ccb.h +++ b/freebsd/sys/cam/cam_ccb.h @@ -519,7 +519,6 @@ struct device_match_result { struct scsi_inquiry_data inq_data; struct ata_params ident_data; dev_result_flags flags; - struct mmc_params mmc_ident_data; }; struct bus_match_result { @@ -646,6 +645,11 @@ struct ccb_pathinq_settings_sas { struct ccb_pathinq_settings_nvme { uint32_t nsid; /* Namespace ID for this path */ + uint32_t domain; + uint8_t bus; + uint8_t slot; + uint8_t function; + uint8_t extra; }; #define PATHINQ_SETTINGS_SIZE 128 @@ -1296,6 +1300,7 @@ struct ccb_dev_advinfo { #define CDAI_TYPE_EXT_INQ 5 #define CDAI_TYPE_NVME_CNTRL 6 /* NVMe Identify Controller data */ #define CDAI_TYPE_NVME_NS 7 /* NVMe Identify Namespace data */ +#define CDAI_TYPE_MMC_PARAMS 8 /* MMC/SD ident */ off_t bufsiz; /* IN: Size of external buffer */ #define CAM_SCSI_DEVID_MAXLEN 65536 /* length in buffer is an uint16_t */ off_t provsiz; /* OUT: Size required/used */ diff --git a/freebsd/sys/cam/cam_periph.h b/freebsd/sys/cam/cam_periph.h index b7f0618e..ee9a5fc0 100644 --- a/freebsd/sys/cam/cam_periph.h +++ b/freebsd/sys/cam/cam_periph.h @@ -197,12 +197,15 @@ void cam_periph_freeze_after_event(struct cam_periph *periph, struct timeval* event_time, u_int duration_ms); int cam_periph_error(union ccb *ccb, cam_flags camflags, - u_int32_t sense_flags, union ccb *save_ccb); + u_int32_t sense_flags); static __inline struct mtx * cam_periph_mtx(struct cam_periph *periph) { - return (xpt_path_mtx(periph->path)); + if (periph != NULL) + return (xpt_path_mtx(periph->path)); + else + return (NULL); } #define cam_periph_owned(periph) \ @@ -257,5 +260,8 @@ cam_periph_acquire_next(struct cam_periph *pperiph) (periph) != NULL; \ (periph) = cam_periph_acquire_next(periph)) +#define CAM_PERIPH_PRINT(p, msg, args...) \ + printf("%s%d:" msg, (periph)->periph_name, (periph)->unit_number, ##args) + #endif /* _KERNEL */ #endif /* _CAM_CAM_PERIPH_H */ diff --git a/freebsd/sys/cam/cam_xpt.h b/freebsd/sys/cam/cam_xpt.h index 8baec294..fb49c893 100644 --- a/freebsd/sys/cam/cam_xpt.h +++ b/freebsd/sys/cam/cam_xpt.h @@ -36,8 +36,10 @@ #ifdef _KERNEL #include <sys/cdefs.h> +#include <cam/cam_ccb.h> #endif + /* Forward Declarations */ union ccb; struct cam_periph; @@ -144,6 +146,22 @@ void xpt_copy_path(struct cam_path *new_path, void xpt_release_path(struct cam_path *path); const char * xpt_action_name(uint32_t action); +void xpt_pollwait(union ccb *start_ccb, uint32_t timeout); +uint32_t xpt_poll_setup(union ccb *start_ccb); + +/* + * Perform a path inquiry at the request priority. The bzero may be + * unnecessary. + */ +static inline void +xpt_path_inq(struct ccb_pathinq *cpi, struct cam_path *path) +{ + + bzero(cpi, sizeof(*cpi)); + xpt_setup_ccb(&cpi->ccb_h, path, CAM_PRIORITY_NORMAL); + cpi->ccb_h.func_code = XPT_PATH_INQ; + xpt_action((union ccb *)cpi); +} #endif /* _KERNEL */ diff --git a/freebsd/sys/cam/mmc/mmc.h b/freebsd/sys/cam/mmc/mmc.h index 2e31f029..9b9659fe 100644 --- a/freebsd/sys/cam/mmc/mmc.h +++ b/freebsd/sys/cam/mmc/mmc.h @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2014-2016 Ilya Bakulin. All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/freebsd/sys/cam/mmc/mmc_all.h b/freebsd/sys/cam/mmc/mmc_all.h index c2494894..cbc32c0d 100644 --- a/freebsd/sys/cam/mmc/mmc_all.h +++ b/freebsd/sys/cam/mmc/mmc_all.h @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2014-2016 Ilya Bakulin. All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/freebsd/sys/cam/nvme/nvme_all.h b/freebsd/sys/cam/nvme/nvme_all.h index b2db4833..fa229846 100644 --- a/freebsd/sys/cam/nvme/nvme_all.h +++ b/freebsd/sys/cam/nvme/nvme_all.h @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2015 Netflix, Inc * All rights reserved. * diff --git a/freebsd/sys/cam/scsi/scsi_all.c b/freebsd/sys/cam/scsi/scsi_all.c index d344cc14..1a469f32 100644 --- a/freebsd/sys/cam/scsi/scsi_all.c +++ b/freebsd/sys/cam/scsi/scsi_all.c @@ -1,10 +1,10 @@ #include <machine/rtems-bsd-kernel-space.h> /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * * Implementation of Utility functions for all SCSI device types. * + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 1997, 1998, 1999 Justin T. Gibbs. * Copyright (c) 1997, 1998, 2003 Kenneth D. Merry. * All rights reserved. diff --git a/freebsd/sys/dev/cadence/if_cgem.c b/freebsd/sys/dev/cadence/if_cgem.c index 42fd4213..191362c4 100644 --- a/freebsd/sys/dev/cadence/if_cgem.c +++ b/freebsd/sys/dev/cadence/if_cgem.c @@ -895,7 +895,7 @@ cgem_start_locked(if_t ifp) WR4(sc, CGEM_NET_CTRL, sc->net_ctl_shadow | CGEM_NET_CTRL_START_TX); - /* If there is a BPF listener, bounce a copy to to him. */ + /* If there is a BPF listener, bounce a copy to him. */ ETHER_BPF_MTAP(ifp, m); } } diff --git a/freebsd/sys/dev/e1000/e1000_82543.c b/freebsd/sys/dev/e1000/e1000_82543.c index dbaa4a6e..0bd0c6d5 100644 --- a/freebsd/sys/dev/e1000/e1000_82543.c +++ b/freebsd/sys/dev/e1000/e1000_82543.c @@ -1312,7 +1312,7 @@ static s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw) * turn it on. For compatibility with a TBI link * partner, we will store bad packets. Some * frames have an additional byte on the end and - * will look like CRC errors to to the hardware. + * will look like CRC errors to the hardware. */ if (!e1000_tbi_sbp_enabled_82543(hw)) { e1000_set_tbi_sbp_82543(hw, TRUE); diff --git a/freebsd/sys/dev/e1000/e1000_82575.h b/freebsd/sys/dev/e1000/e1000_82575.h index 7e127ed7..a96b25f4 100644 --- a/freebsd/sys/dev/e1000/e1000_82575.h +++ b/freebsd/sys/dev/e1000/e1000_82575.h @@ -385,7 +385,7 @@ struct e1000_adv_tx_context_desc { #define E1000_ETQF_FILTER_ENABLE (1 << 26) #define E1000_ETQF_IMM_INT (1 << 29) #define E1000_ETQF_1588 (1 << 30) -#define E1000_ETQF_QUEUE_ENABLE (1 << 31) +#define E1000_ETQF_QUEUE_ENABLE (1U << 31) /* * ETQF filter list: one static filter per filter consumer. This is * to avoid filter collisions later. Add new filters @@ -412,7 +412,7 @@ struct e1000_adv_tx_context_desc { #define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */ #define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8 #define E1000_DTXSWC_LLE_SHIFT 16 -#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */ +#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1U << 31) /* global VF LB enable */ /* Easy defines for setting default pool, would normally be left a zero */ #define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7 diff --git a/freebsd/sys/dev/e1000/e1000_api.c b/freebsd/sys/dev/e1000/e1000_api.c index 393a22e2..c351901c 100644 --- a/freebsd/sys/dev/e1000/e1000_api.c +++ b/freebsd/sys/dev/e1000/e1000_api.c @@ -313,6 +313,16 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_PCH_SPT_I219_V5: mac->type = e1000_pch_spt; break; + case E1000_DEV_ID_PCH_CNP_I219_LM6: + case E1000_DEV_ID_PCH_CNP_I219_V6: + case E1000_DEV_ID_PCH_CNP_I219_LM7: + case E1000_DEV_ID_PCH_CNP_I219_V7: + case E1000_DEV_ID_PCH_ICP_I219_LM8: + case E1000_DEV_ID_PCH_ICP_I219_V8: + case E1000_DEV_ID_PCH_ICP_I219_LM9: + case E1000_DEV_ID_PCH_ICP_I219_V9: + mac->type = e1000_pch_cnp; + break; case E1000_DEV_ID_82575EB_COPPER: case E1000_DEV_ID_82575EB_FIBER_SERDES: case E1000_DEV_ID_82575GB_QUAD_COPPER: @@ -464,6 +474,7 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device) case e1000_pch2lan: case e1000_pch_lpt: case e1000_pch_spt: + case e1000_pch_cnp: e1000_init_function_pointers_ich8lan(hw); break; case e1000_82575: diff --git a/freebsd/sys/dev/e1000/e1000_hw.h b/freebsd/sys/dev/e1000/e1000_hw.h index 82e783fe..2c17a022 100644 --- a/freebsd/sys/dev/e1000/e1000_hw.h +++ b/freebsd/sys/dev/e1000/e1000_hw.h @@ -147,6 +147,14 @@ struct e1000_hw; #define E1000_DEV_ID_PCH_SPT_I219_V4 0x15D8 #define E1000_DEV_ID_PCH_SPT_I219_LM5 0x15E3 #define E1000_DEV_ID_PCH_SPT_I219_V5 0x15D6 +#define E1000_DEV_ID_PCH_CNP_I219_LM6 0x15BD +#define E1000_DEV_ID_PCH_CNP_I219_V6 0x15BE +#define E1000_DEV_ID_PCH_CNP_I219_LM7 0x15BB +#define E1000_DEV_ID_PCH_CNP_I219_V7 0x15BC +#define E1000_DEV_ID_PCH_ICP_I219_LM8 0x15DF +#define E1000_DEV_ID_PCH_ICP_I219_V8 0x15E0 +#define E1000_DEV_ID_PCH_ICP_I219_LM9 0x15E1 +#define E1000_DEV_ID_PCH_ICP_I219_V9 0x15E2 #define E1000_DEV_ID_82576 0x10C9 #define E1000_DEV_ID_82576_FIBER 0x10E6 #define E1000_DEV_ID_82576_SERDES 0x10E7 @@ -233,6 +241,7 @@ enum e1000_mac_type { e1000_pch2lan, e1000_pch_lpt, e1000_pch_spt, + e1000_pch_cnp, e1000_82575, e1000_82576, e1000_82580, diff --git a/freebsd/sys/dev/e1000/e1000_ich8lan.c b/freebsd/sys/dev/e1000/e1000_ich8lan.c index b78b7283..bcd82c47 100644 --- a/freebsd/sys/dev/e1000/e1000_ich8lan.c +++ b/freebsd/sys/dev/e1000/e1000_ich8lan.c @@ -347,6 +347,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) switch (hw->mac.type) { case e1000_pch_lpt: case e1000_pch_spt: + case e1000_pch_cnp: if (e1000_phy_is_accessible_pchlan(hw)) break; @@ -495,6 +496,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) case e1000_pch2lan: case e1000_pch_lpt: case e1000_pch_spt: + case e1000_pch_cnp: /* In case the PHY needs to be in mdio slow mode, * set slow mode and try to get the PHY id again. */ @@ -796,6 +798,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) /* fall-through */ case e1000_pch_lpt: case e1000_pch_spt: + case e1000_pch_cnp: /* multicast address update for pch2 */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_pch2lan; @@ -1833,6 +1836,7 @@ void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw) case e1000_pch2lan: case e1000_pch_lpt: case e1000_pch_spt: + case e1000_pch_cnp: hw->phy.ops.init_params = e1000_init_phy_params_pchlan; break; default: @@ -2297,6 +2301,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) case e1000_pch2lan: case e1000_pch_lpt: case e1000_pch_spt: + case e1000_pch_cnp: sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; break; default: @@ -2657,6 +2662,8 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) e1000_phy_sw_reset_generic(hw); ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x3140); + if (ret_val) + return ret_val; } } @@ -3414,6 +3421,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) switch (hw->mac.type) { case e1000_pch_spt: + case e1000_pch_cnp: bank1_offset = nvm->flash_bank_size; act_offset = E1000_ICH_NVM_SIG_WORD; @@ -4389,6 +4397,7 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) switch (hw->mac.type) { case e1000_pch_lpt: case e1000_pch_spt: + case e1000_pch_cnp: word = NVM_COMPAT; valid_csum_mask = NVM_COMPAT_VALID_CSUM; break; @@ -5195,7 +5204,7 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) /* Device Status */ if (hw->mac.type == e1000_ich8lan) { reg = E1000_READ_REG(hw, E1000_STATUS); - reg &= ~(1 << 31); + reg &= ~(1U << 31); E1000_WRITE_REG(hw, E1000_STATUS, reg); } diff --git a/freebsd/sys/dev/e1000/e1000_ich8lan.h b/freebsd/sys/dev/e1000/e1000_ich8lan.h index d61f4df8..db37aab7 100644 --- a/freebsd/sys/dev/e1000/e1000_ich8lan.h +++ b/freebsd/sys/dev/e1000/e1000_ich8lan.h @@ -124,7 +124,8 @@ #define NVM_SIZE_MULTIPLIER 4096 /*multiplier for NVMS field*/ #define E1000_FLASH_BASE_ADDR 0xE000 /*offset of NVM access regs*/ #define E1000_CTRL_EXT_NVMVS 0x3 /*NVM valid sector */ -#define E1000_TARC0_CB_MULTIQ_3_REQ (1 << 28 | 1 << 29) +#define E1000_TARC0_CB_MULTIQ_3_REQ 0x30000000 +#define E1000_TARC0_CB_MULTIQ_2_REQ 0x20000000 #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL #define E1000_ICH_RAR_ENTRIES 7 diff --git a/freebsd/sys/dev/e1000/e1000_regs.h b/freebsd/sys/dev/e1000/e1000_regs.h index d9949817..246968e9 100644 --- a/freebsd/sys/dev/e1000/e1000_regs.h +++ b/freebsd/sys/dev/e1000/e1000_regs.h @@ -215,7 +215,7 @@ /* QAV Tx mode control register bitfields masks */ #define E1000_TQAVCC_IDLE_SLOPE 0xFFFF /* Idle slope */ #define E1000_TQAVCC_KEEP_CREDITS (1 << 30) /* Keep credits opt enable */ -#define E1000_TQAVCC_QUEUE_MODE (1 << 31) /* SP vs. SR Tx mode */ +#define E1000_TQAVCC_QUEUE_MODE (1U << 31) /* SP vs. SR Tx mode */ /* Good transmitted packets counter registers */ #define E1000_PQGPTC(_n) (0x010014 + (0x100 * (_n))) diff --git a/freebsd/sys/dev/e1000/em_txrx.c b/freebsd/sys/dev/e1000/em_txrx.c index 2183a8bd..9286f0ea 100644 --- a/freebsd/sys/dev/e1000/em_txrx.c +++ b/freebsd/sys/dev/e1000/em_txrx.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-kernel-space.h> /*- - * Copyright (c) 2016-2017 Matt Macy <mmacy@nextbsd.org> + * Copyright (c) 2016-2017 Matthew Macy <mmacy@mattmacy.io> * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/freebsd/sys/dev/e1000/if_em.c b/freebsd/sys/dev/e1000/if_em.c index 07acaad9..94159e31 100644 --- a/freebsd/sys/dev/e1000/if_em.c +++ b/freebsd/sys/dev/e1000/if_em.c @@ -3,7 +3,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2016 Matt Macy <mmacy@nextbsd.org> + * Copyright (c) 2016 Matthew Macy <mmacy@mattmacy.io> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -168,6 +168,14 @@ static pci_vendor_info_t em_vendor_info_array[] = PVID(0x8086, E1000_DEV_ID_PCH_SPT_I219_V4, "Intel(R) PRO/1000 Network Connection"), PVID(0x8086, E1000_DEV_ID_PCH_SPT_I219_LM5, "Intel(R) PRO/1000 Network Connection"), PVID(0x8086, E1000_DEV_ID_PCH_SPT_I219_V5, "Intel(R) PRO/1000 Network Connection"), + PVID(0x8086, E1000_DEV_ID_PCH_CNP_I219_LM6, "Intel(R) PRO/1000 Network Connection"), + PVID(0x8086, E1000_DEV_ID_PCH_CNP_I219_V6, "Intel(R) PRO/1000 Network Connection"), + PVID(0x8086, E1000_DEV_ID_PCH_CNP_I219_LM7, "Intel(R) PRO/1000 Network Connection"), + PVID(0x8086, E1000_DEV_ID_PCH_CNP_I219_V7, "Intel(R) PRO/1000 Network Connection"), + PVID(0x8086, E1000_DEV_ID_PCH_ICP_I219_LM8, "Intel(R) PRO/1000 Network Connection"), + PVID(0x8086, E1000_DEV_ID_PCH_ICP_I219_V8, "Intel(R) PRO/1000 Network Connection"), + PVID(0x8086, E1000_DEV_ID_PCH_ICP_I219_LM9, "Intel(R) PRO/1000 Network Connection"), + PVID(0x8086, E1000_DEV_ID_PCH_ICP_I219_V9, "Intel(R) PRO/1000 Network Connection"), /* required last entry */ PVID_END }; @@ -864,7 +872,7 @@ em_if_attach_pre(if_ctx_t ctx) ** so use the same tag and an offset handle for the ** FLASH read/write macros in the shared code. */ - else if (hw->mac.type == e1000_pch_spt) { + else if (hw->mac.type >= e1000_pch_spt) { adapter->osdep.flash_bus_space_tag = adapter->osdep.mem_bus_space_tag; adapter->osdep.flash_bus_space_handle = @@ -1134,6 +1142,7 @@ em_if_mtu_set(if_ctx_t ctx, uint32_t mtu) case e1000_pch2lan: case e1000_pch_lpt: case e1000_pch_spt: + case e1000_pch_cnp: case e1000_82574: case e1000_82583: case e1000_80003es2lan: @@ -2418,6 +2427,7 @@ em_reset(if_ctx_t ctx) case e1000_pch2lan: case e1000_pch_lpt: case e1000_pch_spt: + case e1000_pch_cnp: pba = E1000_PBA_26K; break; case e1000_82575: @@ -2526,6 +2536,7 @@ em_reset(if_ctx_t ctx) case e1000_pch2lan: case e1000_pch_lpt: case e1000_pch_spt: + case e1000_pch_cnp: hw->fc.high_water = 0x5C20; hw->fc.low_water = 0x5048; hw->fc.pause_time = 0x0650; @@ -3056,13 +3067,16 @@ em_initialize_transmit_unit(if_ctx_t ctx) /* This write will effectively turn on the transmit unit. */ E1000_WRITE_REG(&adapter->hw, E1000_TCTL, tctl); + /* SPT and KBL errata workarounds */ if (hw->mac.type == e1000_pch_spt) { u32 reg; reg = E1000_READ_REG(hw, E1000_IOSFPC); reg |= E1000_RCTL_RDMTS_HEX; E1000_WRITE_REG(hw, E1000_IOSFPC, reg); + /* i218-i219 Specification Update 1.5.4.5 */ reg = E1000_READ_REG(hw, E1000_TARC(0)); - reg |= E1000_TARC0_CB_MULTIQ_3_REQ; + reg &= ~E1000_TARC0_CB_MULTIQ_3_REQ; + reg |= E1000_TARC0_CB_MULTIQ_2_REQ; E1000_WRITE_REG(hw, E1000_TARC(0), reg); } } diff --git a/freebsd/sys/dev/e1000/if_em.h b/freebsd/sys/dev/e1000/if_em.h index 4f9d34b8..0a6a09ca 100644 --- a/freebsd/sys/dev/e1000/if_em.h +++ b/freebsd/sys/dev/e1000/if_em.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2016 Matt Macy <mmacy@nextbsd.org> + * Copyright (c) 2016 Matthew Macy <mmacy@mattmacy.io> * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/freebsd/sys/dev/e1000/igb_txrx.c b/freebsd/sys/dev/e1000/igb_txrx.c index 2ed24e2d..05b2fff2 100644 --- a/freebsd/sys/dev/e1000/igb_txrx.c +++ b/freebsd/sys/dev/e1000/igb_txrx.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-kernel-space.h> /*- - * Copyright (c) 2016 Matt Macy <mmacy@nextbsd.org> + * Copyright (c) 2016 Matthew Macy <mmacy@mattmacy.io> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -239,7 +239,7 @@ igb_isc_txd_encap(void *arg, if_pkt_info_t pi) int nsegs = pi->ipi_nsegs; bus_dma_segment_t *segs = pi->ipi_segs; union e1000_adv_tx_desc *txd = NULL; - int i, j, first, pidx_last; + int i, j, pidx_last; u32 olinfo_status, cmd_type_len, txd_flags; qidx_t ntxd; @@ -251,7 +251,7 @@ igb_isc_txd_encap(void *arg, if_pkt_info_t pi) if (pi->ipi_mflags & M_VLANTAG) cmd_type_len |= E1000_ADVTXD_DCMD_VLE; - first = i = pi->ipi_pidx; + i = pi->ipi_pidx; ntxd = scctx->isc_ntxd[0]; txd_flags = pi->ipi_flags & IPI_TX_INTR ? E1000_ADVTXD_DCMD_RS : 0; /* Consume the first descriptor */ diff --git a/freebsd/sys/dev/fdt/fdt_common.c b/freebsd/sys/dev/fdt/fdt_common.c index 26f73bc3..daa45832 100644 --- a/freebsd/sys/dev/fdt/fdt_common.c +++ b/freebsd/sys/dev/fdt/fdt_common.c @@ -157,7 +157,7 @@ fdt_get_range(phandle_t node, int range_id, u_long *base, u_long *size) pcell_t ranges[FDT_RANGES_SIZE], *rangesptr; pcell_t addr_cells, size_cells, par_addr_cells; u_long par_bus_addr, pbase, psize; - int err, len, tuple_size, tuples; + int err, len; if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0) return (ENXIO); @@ -183,10 +183,6 @@ fdt_get_range(phandle_t node, int range_id, u_long *base, u_long *size) if (OF_getprop(node, "ranges", ranges, sizeof(ranges)) <= 0) return (EINVAL); - tuple_size = sizeof(pcell_t) * (addr_cells + par_addr_cells + - size_cells); - tuples = len / tuple_size; - if (par_addr_cells > 2 || addr_cells > 2 || size_cells > 2) return (ERANGE); @@ -602,11 +598,9 @@ fdt_get_reserved_regions(struct mem_region *mr, int *mrcnt) pcell_t reserve[FDT_REG_CELLS * FDT_MEM_REGIONS]; pcell_t *reservep; phandle_t memory, root; - uint32_t memory_size; int addr_cells, size_cells; - int i, max_size, res_len, rv, tuple_size, tuples; + int i, res_len, rv, tuple_size, tuples; - max_size = sizeof(reserve); root = OF_finddevice("/"); memory = OF_finddevice("/memory"); if (memory == -1) { @@ -636,7 +630,6 @@ fdt_get_reserved_regions(struct mem_region *mr, int *mrcnt) goto out; } - memory_size = 0; tuples = res_len / tuple_size; reservep = (pcell_t *)&reserve; for (i = 0; i < tuples; i++) { @@ -664,9 +657,8 @@ fdt_get_mem_regions(struct mem_region *mr, int *mrcnt, uint64_t *memsize) phandle_t memory; uint64_t memory_size; int addr_cells, size_cells; - int i, max_size, reg_len, rv, tuple_size, tuples; + int i, reg_len, rv, tuple_size, tuples; - max_size = sizeof(reg); memory = OF_finddevice("/memory"); if (memory == -1) { rv = ENXIO; diff --git a/freebsd/sys/dev/mmc/mmc.c b/freebsd/sys/dev/mmc/mmc.c index 32599383..2c3cba3d 100644 --- a/freebsd/sys/dev/mmc/mmc.c +++ b/freebsd/sys/dev/mmc/mmc.c @@ -1573,17 +1573,14 @@ mmc_host_timing(device_t dev, enum mmc_bus_timing timing) static void mmc_log_card(device_t dev, struct mmc_ivars *ivar, int newcard) { - enum mmc_bus_timing max_timing, timing; + enum mmc_bus_timing timing; device_printf(dev, "Card at relative address 0x%04x%s:\n", ivar->rca, newcard ? " added" : ""); device_printf(dev, " card: %s\n", ivar->card_id_string); - max_timing = bus_timing_normal; for (timing = bus_timing_max; timing > bus_timing_normal; timing--) { - if (isset(&ivar->timings, timing)) { - max_timing = timing; + if (isset(&ivar->timings, timing)) break; - } } device_printf(dev, " quirks: %b\n", ivar->quirks, MMC_QUIRKS_FMT); device_printf(dev, " bus: %ubit, %uMHz (%s timing)\n", @@ -1885,7 +1882,7 @@ mmc_discover_cards(struct mmc_softc *sc) * units of 10 ms), defaulting to 500 ms. */ ivar->cmd6_time = 500 * 1000; - if (ivar->csd.spec_vers >= 6) + if (ivar->raw_ext_csd[EXT_CSD_REV] >= 6) ivar->cmd6_time = 10 * ivar->raw_ext_csd[EXT_CSD_GEN_CMD6_TIME]; /* Handle HC erase sector size. */ diff --git a/freebsd/sys/dev/mmc/mmcsd.c b/freebsd/sys/dev/mmc/mmcsd.c index df29b544..94e6e73f 100644 --- a/freebsd/sys/dev/mmc/mmcsd.c +++ b/freebsd/sys/dev/mmc/mmcsd.c @@ -1005,11 +1005,9 @@ mmcsd_close(struct disk *dp __unused) static void mmcsd_strategy(struct bio *bp) { - struct mmcsd_softc *sc; struct mmcsd_part *part; part = bp->bio_disk->d_drv1; - sc = part->sc; MMCSD_DISK_LOCK(part); if (part->running > 0 || part->suspend > 0) { bioq_disksort(&part->bio_queue, bp); @@ -1169,6 +1167,16 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag) default: break; } + /* + * No partition switching in userland; it's almost impossible + * to recover from that, especially if things go wrong. + */ + if (cmd.opcode == MMC_SWITCH_FUNC && dp != NULL && + (((uint8_t *)dp)[EXT_CSD_PART_CONFIG] & + EXT_CSD_PART_CONFIG_ACC_MASK) != part->type) { + err = EINVAL; + goto out; + } } dev = sc->dev; mmcbus = sc->mmcbus; @@ -1189,7 +1197,7 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag) if (part->type == EXT_CSD_PART_CONFIG_ACC_RPMB) { /* * If the request went to the RPMB partition, try to ensure - * that the command actually has completed ... + * that the command actually has completed. */ retries = MMCSD_CMD_RETRIES; do { @@ -1201,13 +1209,6 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag) break; DELAY(1000); } while (retries-- > 0); - -switch_back: - /* ... and always switch back to the default partition. */ - err = mmcsd_switch_part(mmcbus, dev, rca, - EXT_CSD_PART_CONFIG_ACC_DEFAULT); - if (err != MMC_ERR_NONE) - goto release; } /* * If EXT_CSD was changed, our copy is outdated now. Specifically, @@ -1219,6 +1220,17 @@ switch_back: if (err != MMC_ERR_NONE) goto release; } +switch_back: + if (part->type == EXT_CSD_PART_CONFIG_ACC_RPMB) { + /* + * If the request went to the RPMB partition, always switch + * back to the default partition (see mmcsd_switch_part()). + */ + err = mmcsd_switch_part(mmcbus, dev, rca, + EXT_CSD_PART_CONFIG_ACC_DEFAULT); + if (err != MMC_ERR_NONE) + goto release; + } MMCBUS_RELEASE_BUS(mmcbus, dev); if (cmd.error != MMC_ERR_NONE) { switch (cmd.error) { diff --git a/freebsd/sys/dev/ofw/ofw_bus_subr.c b/freebsd/sys/dev/ofw/ofw_bus_subr.c index c655e668..8406988f 100644 --- a/freebsd/sys/dev/ofw/ofw_bus_subr.c +++ b/freebsd/sys/dev/ofw/ofw_bus_subr.c @@ -92,6 +92,7 @@ ofw_bus_gen_child_pnpinfo_str(device_t cbdev, device_t child, char *buf, size_t buflen) { + *buf = '\0'; if (ofw_bus_get_name(child) != NULL) { strlcat(buf, "name=", buflen); strlcat(buf, ofw_bus_get_name(child), buflen); @@ -388,9 +389,8 @@ ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz, uint8_t *mptr; pcell_t paddrsz; pcell_t pintrsz; - int i, rsz, tsz; + int i, tsz; - rsz = -1; if (imapmsk != NULL) { for (i = 0; i < physsz; i++) ref[i] = uiregs[i] & uiimapmsk[i]; @@ -447,7 +447,7 @@ ofw_bus_msimap(phandle_t node, uint16_t pci_rid, phandle_t *msi_parent, { pcell_t *map, mask, msi_base, rid_base, rid_length; ssize_t len; - uint32_t masked_rid, rid; + uint32_t masked_rid; int err, i; /* TODO: This should be OF_searchprop_alloc if we had it */ @@ -464,7 +464,6 @@ ofw_bus_msimap(phandle_t node, uint16_t pci_rid, phandle_t *msi_parent, } err = ENOENT; - rid = 0; mask = 0xffffffff; OF_getencprop(node, "msi-map-mask", &mask, sizeof(mask)); diff --git a/freebsd/sys/dev/ofw/ofw_fdt.c b/freebsd/sys/dev/ofw/ofw_fdt.c index 7bdf447b..b9266eb5 100644 --- a/freebsd/sys/dev/ofw/ofw_fdt.c +++ b/freebsd/sys/dev/ofw/ofw_fdt.c @@ -256,7 +256,7 @@ ofw_fdt_instance_to_package(ofw_t ofw, ihandle_t instance) static ssize_t ofw_fdt_getproplen(ofw_t ofw, phandle_t package, const char *propname) { - const struct fdt_property *prop; + const void *prop; int offset, len; offset = fdt_phandle_offset(package); @@ -264,7 +264,7 @@ ofw_fdt_getproplen(ofw_t ofw, phandle_t package, const char *propname) return (-1); len = -1; - prop = fdt_get_property(fdtp, offset, propname, &len); + prop = fdt_getprop(fdtp, offset, propname, &len); if (prop == NULL && strcmp(propname, "name") == 0) { /* Emulate the 'name' property */ @@ -341,7 +341,7 @@ static int ofw_fdt_nextprop(ofw_t ofw, phandle_t package, const char *previous, char *buf, size_t size) { - const struct fdt_property *prop; + const void *prop; const char *name; int offset; @@ -356,7 +356,7 @@ ofw_fdt_nextprop(ofw_t ofw, phandle_t package, const char *previous, char *buf, if (previous != NULL) { while (offset >= 0) { - prop = fdt_get_property_by_offset(fdtp, offset, NULL); + prop = fdt_getprop_by_offset(fdtp, offset, &name, NULL); if (prop == NULL) return (-1); /* Internal error */ @@ -365,17 +365,16 @@ ofw_fdt_nextprop(ofw_t ofw, phandle_t package, const char *previous, char *buf, return (0); /* No more properties */ /* Check if the last one was the one we wanted */ - name = fdt_string(fdtp, fdt32_to_cpu(prop->nameoff)); if (strcmp(name, previous) == 0) break; } } - prop = fdt_get_property_by_offset(fdtp, offset, &offset); + prop = fdt_getprop_by_offset(fdtp, offset, &name, &offset); if (prop == NULL) return (-1); /* Internal error */ - strncpy(buf, fdt_string(fdtp, fdt32_to_cpu(prop->nameoff)), size); + strncpy(buf, name, size); return (1); } @@ -439,8 +438,7 @@ ofw_fdt_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len) return (-1); } -#ifndef __rtems__ -#if defined(FDT_MARVELL) || defined(__powerpc__) +#if defined(FDT_MARVELL) static int ofw_fdt_fixup(ofw_t ofw) { @@ -483,13 +481,11 @@ ofw_fdt_fixup(ofw_t ofw) return (0); } #endif -#endif /* __rtems__ */ static int ofw_fdt_interpret(ofw_t ofw, const char *cmd, int nret, cell_t *retvals) { -#if defined(FDT_MARVELL) || defined(__powerpc__) -#ifndef __rtems__ +#if defined(FDT_MARVELL) int rv; /* @@ -508,9 +504,6 @@ ofw_fdt_interpret(ofw_t ofw, const char *cmd, int nret, cell_t *retvals) retvals[0] = rv; return (rv); -#else /* __rtems__ */ - return (0); -#endif /* __rtems__ */ #else return (0); #endif diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c index e492846d..7fbdc693 100644 --- a/freebsd/sys/dev/pci/pci.c +++ b/freebsd/sys/dev/pci/pci.c @@ -125,6 +125,8 @@ static void pci_resume_msi(device_t dev); static void pci_resume_msix(device_t dev); static int pci_remap_intr_method(device_t bus, device_t dev, u_int irq); +static void pci_hint_device_unit(device_t acdev, device_t child, + const char *name, int *unitp); static int pci_get_id_method(device_t dev, device_t child, enum pci_id_type type, uintptr_t *rid); @@ -164,6 +166,7 @@ static device_method_t pci_methods[] = { DEVMETHOD(bus_child_detached, pci_child_detached), DEVMETHOD(bus_child_pnpinfo_str, pci_child_pnpinfo_str_method), DEVMETHOD(bus_child_location_str, pci_child_location_str_method), + DEVMETHOD(bus_hint_device_unit, pci_hint_device_unit), DEVMETHOD(bus_remap_intr, pci_remap_intr_method), DEVMETHOD(bus_suspend_child, pci_suspend_child), DEVMETHOD(bus_resume_child, pci_resume_child), @@ -3987,7 +3990,6 @@ pci_rescan_method(device_t dev) { #define REG(n, w) PCIB_READ_CONFIG(pcib, busno, s, f, n, w) device_t pcib = device_get_parent(dev); - struct pci_softc *sc; device_t child, *devlist, *unchanged; int devcount, error, i, j, maxslots, oldcount; int busno, domain, s, f, pcifunchigh; @@ -4007,7 +4009,6 @@ pci_rescan_method(device_t dev) } else unchanged = NULL; - sc = device_get_softc(dev); domain = pcib_get_domain(dev); busno = pcib_get_bus(dev); maxslots = PCIB_MAXSLOTS(pcib); @@ -4084,12 +4085,10 @@ device_t pci_add_iov_child(device_t bus, device_t pf, uint16_t rid, uint16_t vid, uint16_t did) { - struct pci_devinfo *pf_dinfo, *vf_dinfo; + struct pci_devinfo *vf_dinfo; device_t pcib; int busno, slot, func; - pf_dinfo = device_get_ivars(pf); - pcib = device_get_parent(bus); PCIB_DECODE_RID(pcib, rid, &busno, &slot, &func); @@ -4231,6 +4230,31 @@ pci_detach(device_t dev) } static void +pci_hint_device_unit(device_t dev, device_t child, const char *name, int *unitp) +{ + int line, unit; + const char *at; + char me1[24], me2[32]; + uint8_t b, s, f; + uint32_t d; + + d = pci_get_domain(child); + b = pci_get_bus(child); + s = pci_get_slot(child); + f = pci_get_function(child); + snprintf(me1, sizeof(me1), "pci%u:%u:%u", b, s, f); + snprintf(me2, sizeof(me2), "pci%u:%u:%u:%u", d, b, s, f); + line = 0; + while (resource_find_dev(&line, name, &unit, "at", NULL) == 0) { + resource_string_value(name, unit, "at", &at); + if (strcmp(at, me1) != 0 && strcmp(at, me2) != 0) + continue; /* No match, try next candidate */ + *unitp = unit; + return; + } +} + +static void pci_set_power_child(device_t dev, device_t child, int state) { device_t pcib; diff --git a/freebsd/sys/dev/pci/pci_pci.c b/freebsd/sys/dev/pci/pci_pci.c index 5585bd32..20364cf9 100644 --- a/freebsd/sys/dev/pci/pci_pci.c +++ b/freebsd/sys/dev/pci/pci_pci.c @@ -1243,10 +1243,8 @@ static void pcib_pcie_ab_timeout(void *arg) { struct pcib_softc *sc; - device_t dev; sc = arg; - dev = sc->dev; mtx_assert(&Giant, MA_OWNED); if (sc->flags & PCIB_DETACH_PENDING) { sc->flags |= PCIB_DETACHING; @@ -1486,16 +1484,14 @@ pcib_cfg_save(struct pcib_softc *sc) static void pcib_cfg_restore(struct pcib_softc *sc) { - device_t dev; #ifndef NEW_PCIB uint16_t command; #endif - dev = sc->dev; #ifdef NEW_PCIB pcib_write_windows(sc, WIN_IO | WIN_MEM | WIN_PMEM); #else - command = pci_read_config(dev, PCIR_COMMAND, 2); + command = pci_read_config(sc->dev, PCIR_COMMAND, 2); if (command & PCIM_CMD_PORTEN) pcib_set_io_decode(sc); if (command & PCIM_CMD_MEMEN) diff --git a/freebsd/sys/dev/rtwn/if_rtwn.c b/freebsd/sys/dev/rtwn/if_rtwn.c index 1f057dad..79868dc0 100644 --- a/freebsd/sys/dev/rtwn/if_rtwn.c +++ b/freebsd/sys/dev/rtwn/if_rtwn.c @@ -1576,17 +1576,19 @@ rtwn_set_channel(struct ieee80211com *ic) static int rtwn_wme_update(struct ieee80211com *ic) { + struct chanAccParams chp; struct ieee80211_channel *c = ic->ic_curchan; struct rtwn_softc *sc = ic->ic_softc; struct wmeParams *wmep = sc->cap_wmeParams; uint8_t aifs, acm, slottime; int ac; + ieee80211_wme_ic_getparams(ic, &chp); + /* Prevent possible races. */ IEEE80211_LOCK(ic); /* XXX */ RTWN_LOCK(sc); - memcpy(wmep, ic->ic_wme.wme_chanParams.cap_wmeParams, - sizeof(sc->cap_wmeParams)); + memcpy(wmep, chp.cap_wmeParams, sizeof(sc->cap_wmeParams)); RTWN_UNLOCK(sc); IEEE80211_UNLOCK(ic); diff --git a/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h b/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h index 6bbdf5bc..e30ae6be 100644 --- a/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h +++ b/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h @@ -134,6 +134,7 @@ static const STRUCT_USB_HOST_ID rtwn_devs[] = { RTWN_RTL8812AU_DEV(MELCO, WIU3866D), RTWN_RTL8812AU_DEV(NEC, WL900U), RTWN_RTL8812AU_DEV(PLANEX2, GW900D), + RTWN_RTL8812AU_DEV(REALTEK, RTL8812AU), RTWN_RTL8812AU_DEV(SENAO, EUB1200AC), RTWN_RTL8812AU_DEV(SITECOMEU, WLA7100), RTWN_RTL8812AU_DEV(TPLINK, T4U), diff --git a/freebsd/sys/dev/sdhci/sdhci.c b/freebsd/sys/dev/sdhci/sdhci.c index 496e8fac..39b9dc91 100644 --- a/freebsd/sys/dev/sdhci/sdhci.c +++ b/freebsd/sys/dev/sdhci/sdhci.c @@ -275,7 +275,7 @@ sdhci_tuning_intmask(struct sdhci_slot *slot) uint32_t intmask; intmask = 0; - if (slot->opt & SDHCI_TUNING_SUPPORTED) { + if (slot->opt & SDHCI_TUNING_ENABLED) { intmask |= SDHCI_INT_TUNEERR; if (slot->retune_mode == SDHCI_RETUNE_MODE_2 || slot->retune_mode == SDHCI_RETUNE_MODE_3) @@ -303,7 +303,7 @@ sdhci_init(struct sdhci_slot *slot) slot->intmask |= SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT; } - WR4(slot, SDHCI_INT_ENABLE, slot->intmask | sdhci_tuning_intmask(slot)); + WR4(slot, SDHCI_INT_ENABLE, slot->intmask); WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); } @@ -656,6 +656,7 @@ sdhci_card_task(void *arg, int pending __unused) xpt_rescan(ccb); #else slot->intmask &= ~sdhci_tuning_intmask(slot); + WR4(slot, SDHCI_INT_ENABLE, slot->intmask); WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); slot->opt &= ~SDHCI_TUNING_ENABLED; SDHCI_UNLOCK(slot); @@ -1340,6 +1341,7 @@ sdhci_generic_tune(device_t brdev __unused, device_t reqdev, bool hs400) if (err == 0) { slot->opt |= SDHCI_TUNING_ENABLED; slot->intmask |= sdhci_tuning_intmask(slot); + WR4(slot, SDHCI_INT_ENABLE, slot->intmask); WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); if (slot->retune_ticks) { callout_reset(&slot->retune_callout, slot->retune_ticks, @@ -1408,6 +1410,7 @@ sdhci_exec_tuning(struct sdhci_slot *slot, bool reset) */ intmask = slot->intmask; slot->intmask = SDHCI_INT_DATA_AVAIL; + WR4(slot, SDHCI_INT_ENABLE, SDHCI_INT_DATA_AVAIL); WR4(slot, SDHCI_SIGNAL_ENABLE, SDHCI_INT_DATA_AVAIL); hostctrl2 = RD2(slot, SDHCI_HOST_CONTROL2); @@ -1447,8 +1450,17 @@ sdhci_exec_tuning(struct sdhci_slot *slot, bool reset) DELAY(1000); } + /* + * Restore DMA usage and interrupts. + * Note that the interrupt aggregation code might have cleared + * SDHCI_INT_DMA_END and/or SDHCI_INT_RESPONSE in slot->intmask + * and SDHCI_SIGNAL_ENABLE respectively so ensure SDHCI_INT_ENABLE + * doesn't lose these. + */ slot->opt = opt; slot->intmask = intmask; + WR4(slot, SDHCI_INT_ENABLE, intmask | SDHCI_INT_DMA_END | + SDHCI_INT_RESPONSE); WR4(slot, SDHCI_SIGNAL_ENABLE, intmask); if ((hostctrl2 & (SDHCI_CTRL2_EXEC_TUNING | diff --git a/freebsd/sys/dev/smc/if_smc.c b/freebsd/sys/dev/smc/if_smc.c index 6b087a85..ac2fdf88 100644 --- a/freebsd/sys/dev/smc/if_smc.c +++ b/freebsd/sys/dev/smc/if_smc.c @@ -1224,7 +1224,6 @@ smc_stop(struct smc_softc *sc) #ifdef DEVICE_POLLING ether_poll_deregister(sc->smc_ifp); sc->smc_ifp->if_capenable &= ~IFCAP_POLLING; - sc->smc_ifp->if_capenable &= ~IFCAP_POLLING_NOCOUNT; #endif /* @@ -1284,7 +1283,6 @@ smc_init_locked(struct smc_softc *sc) ether_poll_register(smc_poll, ifp); SMC_LOCK(sc); ifp->if_capenable |= IFCAP_POLLING; - ifp->if_capenable |= IFCAP_POLLING_NOCOUNT; #endif } diff --git a/freebsd/sys/dev/usb/controller/dwc_otg_fdt.c b/freebsd/sys/dev/usb/controller/dwc_otg_fdt.c index 1cf96f4c..a7110887 100644 --- a/freebsd/sys/dev/usb/controller/dwc_otg_fdt.c +++ b/freebsd/sys/dev/usb/controller/dwc_otg_fdt.c @@ -175,7 +175,6 @@ int dwc_otg_detach(device_t dev) { struct dwc_otg_fdt_softc *sc = device_get_softc(dev); - int err; /* during module unload there are lots of children leftover */ device_delete_children(dev); @@ -186,7 +185,7 @@ dwc_otg_detach(device_t dev) */ dwc_otg_uninit(&sc->sc_otg); - err = bus_teardown_intr(dev, sc->sc_otg.sc_irq_res, + bus_teardown_intr(dev, sc->sc_otg.sc_irq_res, sc->sc_otg.sc_intr_hdl); sc->sc_otg.sc_intr_hdl = NULL; } diff --git a/freebsd/sys/dev/usb/controller/ehci.c b/freebsd/sys/dev/usb/controller/ehci.c index 557698f6..6e7c05f4 100644 --- a/freebsd/sys/dev/usb/controller/ehci.c +++ b/freebsd/sys/dev/usb/controller/ehci.c @@ -1204,9 +1204,7 @@ ehci_non_isoc_done_sub(struct usb_xfer *xfer) static void ehci_non_isoc_done(struct usb_xfer *xfer) { - ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus); ehci_qh_t *qh; - uint32_t status; usb_error_t err = 0; DPRINTFN(13, "xfer=%p endpoint=%p transfer done\n", @@ -1226,8 +1224,6 @@ ehci_non_isoc_done(struct usb_xfer *xfer) usb_pc_cpu_invalidate(qh->page_cache); - status = hc32toh(sc, qh->qh_qtd.qtd_status); - /* reset scanner */ xfer->td_transfer_cache = xfer->td_transfer_first; diff --git a/freebsd/sys/dev/usb/controller/ohci.c b/freebsd/sys/dev/usb/controller/ohci.c index df1981cc..48db76f0 100644 --- a/freebsd/sys/dev/usb/controller/ohci.c +++ b/freebsd/sys/dev/usb/controller/ohci.c @@ -2387,7 +2387,6 @@ ohci_xfer_setup(struct usb_setup_params *parm) { struct usb_page_search page_info; struct usb_page_cache *pc; - ohci_softc_t *sc; struct usb_xfer *xfer; void *last_obj; uint32_t ntd; @@ -2395,7 +2394,6 @@ ohci_xfer_setup(struct usb_setup_params *parm) uint32_t nqh; uint32_t n; - sc = OHCI_BUS2SC(parm->udev->bus); xfer = parm->curr_xfer; parm->hc_max_packet_size = 0x500; diff --git a/freebsd/sys/dev/usb/net/if_cdce.c b/freebsd/sys/dev/usb/net/if_cdce.c index ececc5b3..9a15da69 100644 --- a/freebsd/sys/dev/usb/net/if_cdce.c +++ b/freebsd/sys/dev/usb/net/if_cdce.c @@ -288,6 +288,9 @@ static const STRUCT_USB_HOST_ID cdce_host_devs[] = { {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR), USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x76), USB_DRIVER_INFO(0)}, + {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR), + USB_IFACE_SUBCLASS(0x03), USB_IFACE_PROTOCOL(0x16), + USB_DRIVER_INFO(0)}, }; static const STRUCT_USB_DUAL_ID cdce_dual_devs[] = { diff --git a/freebsd/sys/dev/usb/net/if_mos.c b/freebsd/sys/dev/usb/net/if_mos.c index a25e9df6..ad7bfcce 100644 --- a/freebsd/sys/dev/usb/net/if_mos.c +++ b/freebsd/sys/dev/usb/net/if_mos.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-kernel-space.h> /*- - * SPDX-License-Identifier: 0BSD AND BSD-4-Clause + * SPDX-License-Identifier: (BSD-1-Clause AND BSD-4-Clause) * * Copyright (c) 2011 Rick van der Zwet <info@rickvanderzwet.nl> * diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.c b/freebsd/sys/dev/usb/quirk/usb_quirk.c index 8c9e91cb..3ae4a557 100644 --- a/freebsd/sys/dev/usb/quirk/usb_quirk.c +++ b/freebsd/sys/dev/usb/quirk/usb_quirk.c @@ -246,6 +246,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(IOMEGA, ZIP100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_TEST_UNIT_READY), /* XXX ZIP drives can also use ATAPI */ + USB_QUIRK(JMICRON, JMS567, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN), USB_QUIRK(JMICRON, JM20337, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_SYNC_CACHE), diff --git a/freebsd/sys/dev/usb/serial/u3g.c b/freebsd/sys/dev/usb/serial/u3g.c index 0f3933e6..6f1cfdb1 100644 --- a/freebsd/sys/dev/usb/serial/u3g.c +++ b/freebsd/sys/dev/usb/serial/u3g.c @@ -202,6 +202,7 @@ static driver_t u3g_driver = { static const STRUCT_USB_HOST_ID u3g_devs[] = { #define U3G_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) } + U3G_DEV(ABIT, AK_020, 0), U3G_DEV(ACERP, H10, 0), U3G_DEV(AIRPLUS, MCD650, 0), U3G_DEV(AIRPRIME, PC5220, 0), @@ -310,7 +311,7 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = { U3G_DEV(HUAWEI, E173, 0), U3G_DEV(HUAWEI, E173_INIT, U3GINIT_HUAWEISCSI), U3G_DEV(HUAWEI, E3131, 0), - U3G_DEV(HUAWEI, E3131_INIT, U3GINIT_HUAWEISCSI), + U3G_DEV(HUAWEI, E3131_INIT, U3GINIT_HUAWEISCSI2), U3G_DEV(HUAWEI, E180V, U3GINIT_HUAWEI), U3G_DEV(HUAWEI, E220, U3GINIT_HUAWEI), U3G_DEV(HUAWEI, E220BIS, U3GINIT_HUAWEI), @@ -331,6 +332,8 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = { U3G_DEV(HUAWEI, K4505, U3GINIT_HUAWEI), U3G_DEV(HUAWEI, K4505_INIT, U3GINIT_HUAWEISCSI), U3G_DEV(HUAWEI, ETS2055, U3GINIT_HUAWEI), + U3G_DEV(HUAWEI, E3272_INIT, U3GINIT_HUAWEISCSI2), + U3G_DEV(HUAWEI, E3272, 0), U3G_DEV(KYOCERA2, CDMA_MSM_K, 0), U3G_DEV(KYOCERA2, KPC680, 0), U3G_DEV(LONGCHEER, WM66, U3GINIT_HUAWEI), @@ -493,6 +496,7 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = { U3G_DEV(QUANTA, GLX, 0), U3G_DEV(QUANTA, Q101, 0), U3G_DEV(QUANTA, Q111, 0), + U3G_DEV(QUECTEL, EC25, 0), U3G_DEV(SIERRA, AC402, 0), U3G_DEV(SIERRA, AC595U, 0), U3G_DEV(SIERRA, AC313U, 0), @@ -632,6 +636,45 @@ u3g_huawei_init(struct usb_device *udev) return (0); } +static int +u3g_huawei_is_cdce(uint16_t idVendor, uint8_t bInterfaceSubClass, + uint8_t bInterfaceProtocol) +{ + /* + * This function returns non-zero if the interface being + * probed is of type CDC ethernet, which the U3G driver should + * not attach to. See sys/dev/usb/net/if_cdce.c for matching + * entries. + */ + if (idVendor != USB_VENDOR_HUAWEI) + goto done; + + switch (bInterfaceSubClass) { + case 0x02: + switch (bInterfaceProtocol) { + case 0x16: + case 0x46: + case 0x76: + return (1); + default: + break; + } + break; + case 0x03: + switch (bInterfaceProtocol) { + case 0x16: + return (1); + default: + break; + } + break; + default: + break; + } +done: + return (0); +} + static void u3g_sael_m460_init(struct usb_device *udev) { @@ -845,6 +888,10 @@ u3g_probe(device_t self) if (uaa->info.bInterfaceClass != UICLASS_VENDOR) { return (ENXIO); } + if (u3g_huawei_is_cdce(uaa->info.idVendor, uaa->info.bInterfaceSubClass, + uaa->info.bInterfaceProtocol)) { + return (ENXIO); + } return (usbd_lookup_id_by_uaa(u3g_devs, sizeof(u3g_devs), uaa)); } @@ -888,6 +935,9 @@ u3g_attach(device_t dev) id = usbd_get_interface_descriptor(iface); if (id == NULL || id->bInterfaceClass != UICLASS_VENDOR) continue; + if (u3g_huawei_is_cdce(uaa->info.idVendor, + id->bInterfaceSubClass, id->bInterfaceProtocol)) + continue; usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex); iface_valid |= (1<<i); } diff --git a/freebsd/sys/dev/usb/serial/umodem.c b/freebsd/sys/dev/usb/serial/umodem.c index c64600c8..ac1e35c8 100644 --- a/freebsd/sys/dev/usb/serial/umodem.c +++ b/freebsd/sys/dev/usb/serial/umodem.c @@ -133,6 +133,18 @@ static const STRUCT_USB_DUAL_ID umodem_dual_devs[] = { static const STRUCT_USB_HOST_ID umodem_host_devs[] = { /* Huawei Modem class match */ + {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR), + USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x01)}, + {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR), + USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x02)}, + {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR), + USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x10)}, + {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR), + USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x12)}, + {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR), + USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x61)}, + {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR), + USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x62)}, {USB_VENDOR(USB_VENDOR_HUAWEI),USB_IFACE_CLASS(UICLASS_CDC), USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL), USB_IFACE_PROTOCOL(0xFF)}, diff --git a/freebsd/sys/dev/usb/storage/umass.c b/freebsd/sys/dev/usb/storage/umass.c index 6b488cf7..c74a8403 100644 --- a/freebsd/sys/dev/usb/storage/umass.c +++ b/freebsd/sys/dev/usb/storage/umass.c @@ -1097,7 +1097,6 @@ static void umass_init_shuttle(struct umass_softc *sc) { struct usb_device_request req; - usb_error_t err; uint8_t status[2] = {0, 0}; /* @@ -1110,7 +1109,7 @@ umass_init_shuttle(struct umass_softc *sc) req.wIndex[0] = sc->sc_iface_no; req.wIndex[1] = 0; USETW(req.wLength, sizeof(status)); - err = usbd_do_request(sc->sc_udev, NULL, &req, &status); + usbd_do_request(sc->sc_udev, NULL, &req, &status); DPRINTF(sc, UDMASS_GEN, "Shuttle init returned 0x%02x%02x\n", status[0], status[1]); diff --git a/freebsd/sys/dev/usb/usb_dev.c b/freebsd/sys/dev/usb/usb_dev.c index 2b244d80..94f306d4 100644 --- a/freebsd/sys/dev/usb/usb_dev.c +++ b/freebsd/sys/dev/usb/usb_dev.c @@ -882,7 +882,7 @@ usb_open(struct cdev *dev, int fflags, int devtype, struct thread *td) struct usb_fs_privdata* pd = (struct usb_fs_privdata*)dev->si_drv1; struct usb_cdev_refdata refs; struct usb_cdev_privdata *cpd; - int err, ep; + int err; DPRINTFN(2, "%s fflags=0x%08x\n", devtoname(dev), fflags); @@ -894,7 +894,6 @@ usb_open(struct cdev *dev, int fflags, int devtype, struct thread *td) } cpd = malloc(sizeof(*cpd), M_USBDEV, M_WAITOK | M_ZERO); - ep = cpd->ep_addr = pd->ep_addr; usb_loc_fill(pd, cpd); err = usb_ref_device(cpd, &refs, 1); @@ -1422,8 +1421,6 @@ usb_read(struct cdev *dev, struct uio *uio, int ioflag) struct usb_cdev_privdata* cpd; struct usb_fifo *f; struct usb_mbuf *m; - int fflags; - int resid; int io_len; int err; uint8_t tr_data = 0; @@ -1436,8 +1433,6 @@ usb_read(struct cdev *dev, struct uio *uio, int ioflag) if (err) return (ENXIO); - fflags = cpd->fflags; - f = refs.rxfifo; if (f == NULL) { /* should not happen */ @@ -1445,8 +1440,6 @@ usb_read(struct cdev *dev, struct uio *uio, int ioflag) return (EPERM); } - resid = uio->uio_resid; - mtx_lock(f->priv_mtx); /* check for permanent read error */ @@ -1546,8 +1539,6 @@ usb_write(struct cdev *dev, struct uio *uio, int ioflag) struct usb_fifo *f; struct usb_mbuf *m; uint8_t *pdata; - int fflags; - int resid; int io_len; int err; uint8_t tr_data = 0; @@ -1562,15 +1553,12 @@ usb_write(struct cdev *dev, struct uio *uio, int ioflag) if (err) return (ENXIO); - fflags = cpd->fflags; - f = refs.txfifo; if (f == NULL) { /* should not happen */ usb_unref_device(cpd, &refs); return (EPERM); } - resid = uio->uio_resid; mtx_lock(f->priv_mtx); diff --git a/freebsd/sys/dev/usb/usb_device.c b/freebsd/sys/dev/usb/usb_device.c index 861f6029..5f1cf409 100644 --- a/freebsd/sys/dev/usb/usb_device.c +++ b/freebsd/sys/dev/usb/usb_device.c @@ -89,6 +89,7 @@ /* function prototypes */ +static int sysctl_hw_usb_template(SYSCTL_HANDLER_ARGS); static void usb_init_endpoint(struct usb_device *, uint8_t, struct usb_endpoint_descriptor *, struct usb_endpoint_ss_comp_descriptor *, @@ -123,8 +124,137 @@ int usb_template; #endif #ifndef __rtems__ -SYSCTL_INT(_hw_usb, OID_AUTO, template, CTLFLAG_RWTUN, - &usb_template, 0, "Selected USB device side template"); +SYSCTL_PROC(_hw_usb, OID_AUTO, template, + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, + NULL, 0, sysctl_hw_usb_template, + "I", "Selected USB device side template"); + +/*------------------------------------------------------------------------* + * usb_trigger_reprobe_on_off + * + * This function sets the pull up resistors for all ports currently + * operating in device mode either on (when on_not_off is 1), or off + * (when it's 0). + *------------------------------------------------------------------------*/ +static void +usb_trigger_reprobe_on_off(int on_not_off) +{ + struct usb_port_status ps; + struct usb_bus *bus; + struct usb_device *udev; + usb_error_t err; + int do_unlock, max; + + max = devclass_get_maxunit(usb_devclass_ptr); + while (max >= 0) { + mtx_lock(&usb_ref_lock); + bus = devclass_get_softc(usb_devclass_ptr, max); + max--; + + if (bus == NULL || bus->devices == NULL || + bus->devices[USB_ROOT_HUB_ADDR] == NULL) { + mtx_unlock(&usb_ref_lock); + continue; + } + + udev = bus->devices[USB_ROOT_HUB_ADDR]; + + if (udev->refcount == USB_DEV_REF_MAX) { + mtx_unlock(&usb_ref_lock); + continue; + } + + udev->refcount++; + mtx_unlock(&usb_ref_lock); + + do_unlock = usbd_enum_lock(udev); + if (do_unlock > 1) { + do_unlock = 0; + goto next; + } + + err = usbd_req_get_port_status(udev, NULL, &ps, 1); + if (err != 0) { + DPRINTF("usbd_req_get_port_status() " + "failed: %s\n", usbd_errstr(err)); + goto next; + } + + if ((UGETW(ps.wPortStatus) & UPS_PORT_MODE_DEVICE) == 0) + goto next; + + if (on_not_off) { + err = usbd_req_set_port_feature(udev, NULL, 1, + UHF_PORT_POWER); + if (err != 0) { + DPRINTF("usbd_req_set_port_feature() " + "failed: %s\n", usbd_errstr(err)); + } + } else { + err = usbd_req_clear_port_feature(udev, NULL, 1, + UHF_PORT_POWER); + if (err != 0) { + DPRINTF("usbd_req_clear_port_feature() " + "failed: %s\n", usbd_errstr(err)); + } + } + +next: + mtx_lock(&usb_ref_lock); + if (do_unlock) + usbd_enum_unlock(udev); + if (--(udev->refcount) == 0) + cv_broadcast(&udev->ref_cv); + mtx_unlock(&usb_ref_lock); + } +} + +/*------------------------------------------------------------------------* + * usb_trigger_reprobe_all + * + * This function toggles the pull up resistors for all ports currently + * operating in device mode, causing the host machine to reenumerate them. + *------------------------------------------------------------------------*/ +static void +usb_trigger_reprobe_all(void) +{ + + /* + * Set the pull up resistors off for all ports in device mode. + */ + usb_trigger_reprobe_on_off(0); + + /* + * According to the DWC OTG spec this must be at least 3ms. + */ + usb_pause_mtx(NULL, USB_MS_TO_TICKS(USB_POWER_DOWN_TIME)); + + /* + * Set the pull up resistors back on. + */ + usb_trigger_reprobe_on_off(1); +} + +static int +sysctl_hw_usb_template(SYSCTL_HANDLER_ARGS) +{ + int error, val; + + val = usb_template; + error = sysctl_handle_int(oidp, &val, 0, req); + if (error != 0 || req->newptr == NULL || usb_template == val) + return (error); + + usb_template = val; + + if (usb_template < 0) { + usb_trigger_reprobe_on_off(0); + } else { + usb_trigger_reprobe_all(); + } + + return (0); +} #endif /* __rtems__ */ /* English is default language */ diff --git a/freebsd/sys/dev/usb/wlan/if_rum.c b/freebsd/sys/dev/usb/wlan/if_rum.c index 9996576e..dbb12335 100644 --- a/freebsd/sys/dev/usb/wlan/if_rum.c +++ b/freebsd/sys/dev/usb/wlan/if_rum.c @@ -2303,11 +2303,14 @@ rum_update_slot(struct ieee80211com *ic) static int rum_wme_update(struct ieee80211com *ic) { - const struct wmeParams *chanp = - ic->ic_wme.wme_chanParams.cap_wmeParams; + struct chanAccParams chp; + const struct wmeParams *chanp; struct rum_softc *sc = ic->ic_softc; int error = 0; + ieee80211_wme_ic_getparams(ic, &chp); + chanp = chp.cap_wmeParams; + RUM_LOCK(sc); error = rum_write(sc, RT2573_AIFSN_CSR, chanp[WME_AC_VO].wmep_aifsn << 12 | diff --git a/freebsd/sys/dev/usb/wlan/if_run.c b/freebsd/sys/dev/usb/wlan/if_run.c index d9bda8c8..71f53dd3 100644 --- a/freebsd/sys/dev/usb/wlan/if_run.c +++ b/freebsd/sys/dev/usb/wlan/if_run.c @@ -2219,11 +2219,14 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) static int run_wme_update(struct ieee80211com *ic) { + struct chanAccParams chp; struct run_softc *sc = ic->ic_softc; - const struct wmeParams *ac = - ic->ic_wme.wme_chanParams.cap_wmeParams; + const struct wmeParams *ac; int aci, error = 0; + ieee80211_wme_ic_getparams(ic, &chp); + ac = chp.cap_wmeParams; + /* update MAC TX configuration registers */ RUN_LOCK(sc); for (aci = 0; aci < WME_NUM_AC; aci++) { diff --git a/freebsd/sys/dev/usb/wlan/if_uath.c b/freebsd/sys/dev/usb/wlan/if_uath.c index e1aa5ec0..e001d9ed 100644 --- a/freebsd/sys/dev/usb/wlan/if_uath.c +++ b/freebsd/sys/dev/usb/wlan/if_uath.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-kernel-space.h> /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND 0BSD + * SPDX-License-Identifier: (BSD-2-Clause-FreeBSD AND BSD-1-Clause) * * Copyright (c) 2006 Sam Leffler, Errno Consulting * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org> diff --git a/freebsd/sys/fs/devfs/devfs_vnops.c b/freebsd/sys/fs/devfs/devfs_vnops.c index 4a1c0675..dfa8413b 100644 --- a/freebsd/sys/fs/devfs/devfs_vnops.c +++ b/freebsd/sys/fs/devfs/devfs_vnops.c @@ -911,6 +911,7 @@ devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock) struct devfs_dirent *de, *dd; struct devfs_dirent **dde; struct devfs_mount *dmp; + struct mount *mp; struct cdev *cdev; int error, flags, nameiop, dvplocked; char specname[SPECNAMELEN + 1], *pname; @@ -922,7 +923,8 @@ devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock) td = cnp->cn_thread; flags = cnp->cn_flags; nameiop = cnp->cn_nameiop; - dmp = VFSTODEVFS(dvp->v_mount); + mp = dvp->v_mount; + dmp = VFSTODEVFS(mp); dd = dvp->v_data; *vpp = NULLVP; @@ -955,8 +957,8 @@ devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock) return (ENOENT); dvplocked = VOP_ISLOCKED(dvp); VOP_UNLOCK(dvp, 0); - error = devfs_allocv(de, dvp->v_mount, - cnp->cn_lkflags & LK_TYPE_MASK, vpp); + error = devfs_allocv(de, mp, cnp->cn_lkflags & LK_TYPE_MASK, + vpp); *dm_unlock = 0; vn_lock(dvp, dvplocked | LK_RETRY); return (error); @@ -1041,8 +1043,7 @@ devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock) return (0); } } - error = devfs_allocv(de, dvp->v_mount, cnp->cn_lkflags & LK_TYPE_MASK, - vpp); + error = devfs_allocv(de, mp, cnp->cn_lkflags & LK_TYPE_MASK, vpp); *dm_unlock = 0; return (error); } @@ -1195,6 +1196,18 @@ devfs_pathconf(struct vop_pathconf_args *ap) { switch (ap->a_name) { + case _PC_FILESIZEBITS: + *ap->a_retval = 64; + return (0); + case _PC_NAME_MAX: + *ap->a_retval = NAME_MAX; + return (0); + case _PC_LINK_MAX: + *ap->a_retval = INT_MAX; + return (0); + case _PC_SYMLINK_MAX: + *ap->a_retval = MAXPATHLEN; + return (0); case _PC_MAX_CANON: if (ap->a_vp->v_vflag & VV_ISTTY) { *ap->a_retval = MAX_CANON; @@ -1224,6 +1237,9 @@ devfs_pathconf(struct vop_pathconf_args *ap) *ap->a_retval = 0; #endif return (0); + case _PC_CHOWN_RESTRICTED: + *ap->a_retval = 1; + return (0); default: return (vop_stdpathconf(ap)); } diff --git a/freebsd/sys/isa/isavar.h b/freebsd/sys/isa/isavar.h index 28d13505..30fd1f8d 100644 --- a/freebsd/sys/isa/isavar.h +++ b/freebsd/sys/isa/isavar.h @@ -142,6 +142,10 @@ enum isa_device_ivars { #define ISACFGATTR_DYNAMIC (1 << 1) /* dynamic configuration */ #define ISACFGATTR_HINTS (1 << 3) /* source of config is hints */ +#define ISA_PNP_DESCR "E:pnpid;D:#" +#define ISA_PNP_INFO(t) \ + MODULE_PNP_INFO(ISA_PNP_DESCR, isa, t, t, sizeof(t[0]), nitems(t) - 1); \ + /* * Simplified accessors for isa devices */ diff --git a/freebsd/sys/kern/init_main.c b/freebsd/sys/kern/init_main.c index b8961ab6..ea827ebe 100644 --- a/freebsd/sys/kern/init_main.c +++ b/freebsd/sys/kern/init_main.c @@ -91,7 +91,6 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_param.h> #include <vm/pmap.h> #include <vm/vm_map.h> -#include <vm/vm_domain.h> #include <sys/copyright.h> #include <ddb/ddb.h> @@ -235,6 +234,8 @@ mi_startup(void) int verbose; #endif + TSENTER(); + #ifndef __rtems__ if (boothowto & RB_VERBOSE) bootverbose++; @@ -334,6 +335,8 @@ restart: #endif /* __rtems__ */ } + TSEXIT(); /* Here so we don't overlap with start_init. */ + mtx_assert(&Giant, MA_OWNED | MA_NOTRECURSED); mtx_unlock(&Giant); @@ -517,10 +520,7 @@ proc0_init(void *dummy __unused) td->td_flags = TDF_INMEM; td->td_pflags = TDP_KTHREAD; td->td_cpuset = cpuset_thread0(); - vm_domain_policy_init(&td->td_vm_dom_policy); - vm_domain_policy_set(&td->td_vm_dom_policy, VM_POLICY_NONE, -1); - vm_domain_policy_init(&p->p_vm_dom_policy); - vm_domain_policy_set(&p->p_vm_dom_policy, VM_POLICY_NONE, -1); + td->td_domain.dr_policy = td->td_cpuset->cs_domain; prison0_init(); p->p_peers = 0; p->p_leader = p; @@ -730,6 +730,8 @@ start_init(void *dummy) GIANT_REQUIRED; + TSENTER(); /* Here so we don't overlap with mi_startup. */ + td = curthread; p = td->td_proc; @@ -823,6 +825,7 @@ start_init(void *dummy) */ if ((error = sys_execve(td, &args)) == EJUSTRETURN) { mtx_unlock(&Giant); + TSEXIT(); return; } if (error != ENOENT) diff --git a/freebsd/sys/kern/kern_mbuf.c b/freebsd/sys/kern/kern_mbuf.c index 0f46259a..78e3528f 100644 --- a/freebsd/sys/kern/kern_mbuf.c +++ b/freebsd/sys/kern/kern_mbuf.c @@ -295,7 +295,7 @@ static void mb_dtor_pack(void *, int, void *); static int mb_zinit_pack(void *, int, int); static void mb_zfini_pack(void *, int); static void mb_reclaim(uma_zone_t, int); -static void *mbuf_jumbo_alloc(uma_zone_t, vm_size_t, uint8_t *, int); +static void *mbuf_jumbo_alloc(uma_zone_t, vm_size_t, int, uint8_t *, int); /* Ensure that MSIZE is a power of 2. */ CTASSERT((((MSIZE - 1) ^ MSIZE) + 1) >> 1 == MSIZE); @@ -400,13 +400,14 @@ SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbuf_init, NULL); * pages. */ static void * -mbuf_jumbo_alloc(uma_zone_t zone, vm_size_t bytes, uint8_t *flags, int wait) +mbuf_jumbo_alloc(uma_zone_t zone, vm_size_t bytes, int domain, uint8_t *flags, + int wait) { /* Inform UMA that this allocator uses kernel_map/object. */ *flags = UMA_SLAB_KERNEL; #ifndef __rtems__ - return ((void *)kmem_alloc_contig(kernel_arena, bytes, wait, + return ((void *)kmem_alloc_contig_domain(domain, bytes, wait, (vm_paddr_t)0, ~(vm_paddr_t)0, 1, 0, VM_MEMATTR_DEFAULT)); #else /* __rtems__ */ return ((void *)malloc(bytes, M_TEMP, wait)); diff --git a/freebsd/sys/kern/kern_synch.c b/freebsd/sys/kern/kern_synch.c index d96954c7..f6485a86 100644 --- a/freebsd/sys/kern/kern_synch.c +++ b/freebsd/sys/kern/kern_synch.c @@ -139,18 +139,12 @@ _sleep(void *ident, struct lock_object *lock, int priority, const char *wmesg, sbintime_t sbt, sbintime_t pr, int flags) { struct thread *td; -#ifndef __rtems__ - struct proc *p; -#endif /* __rtems__ */ struct lock_class *class; uintptr_t lock_state; int catch, pri, rval, sleepq_flags; WITNESS_SAVE_DECL(lock_witness); td = curthread; -#ifndef __rtems__ - p = td->td_proc; -#endif /* __rtems__ */ #ifdef KTRACE if (KTRPOINT(td, KTR_CSW)) ktrcsw(1, 0, wmesg); @@ -198,7 +192,7 @@ _sleep(void *ident, struct lock_object *lock, int priority, sleepq_lock(ident); CTR5(KTR_PROC, "sleep: thread %ld (pid %ld, %s) on %s (%p)", - td->td_tid, p->p_pid, td->td_name, wmesg, ident); + td->td_tid, td->td_proc->p_pid, td->td_name, wmesg, ident); if (lock == &Giant.lock_object) mtx_assert(&Giant, MA_OWNED); @@ -263,12 +257,10 @@ msleep_spin_sbt(void *ident, struct mtx *mtx, const char *wmesg, sbintime_t sbt, sbintime_t pr, int flags) { struct thread *td; - struct proc *p; int rval; WITNESS_SAVE_DECL(mtx); td = curthread; - p = td->td_proc; KASSERT(mtx != NULL, ("sleeping without a mutex")); KASSERT(ident != NULL, ("msleep_spin_sbt: NULL ident")); KASSERT(TD_IS_RUNNING(td), ("msleep_spin_sbt: curthread not running")); @@ -278,7 +270,7 @@ msleep_spin_sbt(void *ident, struct mtx *mtx, const char *wmesg, sleepq_lock(ident); CTR5(KTR_PROC, "msleep_spin: thread %ld (pid %ld, %s) on %s (%p)", - td->td_tid, p->p_pid, td->td_name, wmesg, ident); + td->td_tid, td->td_proc->p_pid, td->td_name, wmesg, ident); DROP_GIANT(); mtx_assert(mtx, MA_OWNED | MA_NOTRECURSED); diff --git a/freebsd/sys/kern/subr_bus.c b/freebsd/sys/kern/subr_bus.c index 09a459aa..8076e7e3 100644 --- a/freebsd/sys/kern/subr_bus.c +++ b/freebsd/sys/kern/subr_bus.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/conf.h> +#include <sys/eventhandler.h> #include <sys/filio.h> #include <sys/lock.h> #include <sys/kernel.h> @@ -149,6 +150,10 @@ static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures"); static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc"); #ifndef __rtems__ +EVENTHANDLER_LIST_DEFINE(device_attach); +EVENTHANDLER_LIST_DEFINE(device_detach); +EVENTHANDLER_LIST_DEFINE(dev_lookup); + static void devctl2_init(void); #endif /* __rtems__ */ @@ -2981,6 +2986,7 @@ device_attach(device_t dev) dev->flags &= ~DF_DONENOMATCH; #ifndef __rtems__ EVENTHANDLER_INVOKE(device_attach, dev); + EVENTHANDLER_DIRECT_INVOKE(device_attach, dev); #endif /* __rtems__ */ devadded(dev); return (0); @@ -3016,16 +3022,18 @@ device_detach(device_t dev) return (0); #ifndef __rtems__ - EVENTHANDLER_INVOKE(device_detach, dev, EVHDEV_DETACH_BEGIN); + EVENTHANDLER_DIRECT_INVOKE(device_detach, dev, EVHDEV_DETACH_BEGIN); #endif /* __rtems__ */ if ((error = DEVICE_DETACH(dev)) != 0) { #ifndef __rtems__ - EVENTHANDLER_INVOKE(device_detach, dev, EVHDEV_DETACH_FAILED); + EVENTHANDLER_DIRECT_INVOKE(device_detach, dev, + EVHDEV_DETACH_FAILED); #endif /* __rtems__ */ return (error); } else { #ifndef __rtems__ - EVENTHANDLER_INVOKE(device_detach, dev, EVHDEV_DETACH_COMPLETE); + EVENTHANDLER_DIRECT_INVOKE(device_detach, dev, + EVHDEV_DETACH_COMPLETE); #endif /* __rtems__ */ } devremoved(dev); @@ -5099,7 +5107,7 @@ print_device_short(device_t dev, int indent) if (!dev) return; - indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%s%s,%sivars,%ssoftc,busy=%d\n", + indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%s%s%s,%sivars,%ssoftc,busy=%d\n", dev->unit, dev->desc, (dev->parent? "":"no "), (TAILQ_EMPTY(&dev->children)? "no ":""), @@ -5108,6 +5116,7 @@ print_device_short(device_t dev, int indent) (dev->flags&DF_WILDCARD? "wildcard,":""), (dev->flags&DF_DESCMALLOCED? "descmalloced,":""), (dev->flags&DF_REBID? "rebiddable,":""), + (dev->flags&DF_SUSPENDED? "suspended,":""), (dev->ivars? "":"no "), (dev->softc? "":"no "), dev->busy)); @@ -5388,7 +5397,7 @@ find_device(struct devreq *req, device_t *devp) /* Finally, give device enumerators a chance. */ dev = NULL; - EVENTHANDLER_INVOKE(dev_lookup, req->dr_name, &dev); + EVENTHANDLER_DIRECT_INVOKE(dev_lookup, req->dr_name, &dev); if (dev == NULL) return (ENOENT); *devp = dev; @@ -5655,6 +5664,56 @@ devctl2_init(void) UID_ROOT, GID_WHEEL, 0600, "devctl2"); } +/* + * APIs to manage deprecation and obsolescence. + */ +static int obsolete_panic = 0; +SYSCTL_INT(_debug, OID_AUTO, obsolete_panic, CTLFLAG_RWTUN, &obsolete_panic, 0, + "Bus debug level"); +/* 0 - don't panic, 1 - panic if already obsolete, 2 - panic if deprecated */ +static void +gone_panic(int major, int running, const char *msg) +{ + + switch (obsolete_panic) + { + case 0: + return; + case 1: + if (running < major) + return; + /* FALLTHROUGH */ + default: + panic("%s", msg); + } +} + +void +_gone_in(int major, const char *msg) +{ + + gone_panic(major, P_OSREL_MAJOR(__FreeBSD_version), msg); + if (P_OSREL_MAJOR(__FreeBSD_version) >= major) + printf("Obsolete code will removed soon: %s\n", msg); + else if (P_OSREL_MAJOR(__FreeBSD_version) + 1 == major) + printf("Deprecated code (to be removed in FreeBSD %d): %s\n", + major, msg); +} + +void +_gone_in_dev(device_t dev, int major, const char *msg) +{ + + gone_panic(major, P_OSREL_MAJOR(__FreeBSD_version), msg); + if (P_OSREL_MAJOR(__FreeBSD_version) >= major) + device_printf(dev, + "Obsolete code will removed soon: %s\n", msg); + else if (P_OSREL_MAJOR(__FreeBSD_version) + 1 == major) + device_printf(dev, + "Deprecated code (to be removed in FreeBSD %d): %s\n", + major, msg); +} + #ifdef DDB DB_SHOW_COMMAND(device, db_show_device) { diff --git a/freebsd/sys/kern/subr_hash.c b/freebsd/sys/kern/subr_hash.c index 488d8bcd..dd442931 100644 --- a/freebsd/sys/kern/subr_hash.c +++ b/freebsd/sys/kern/subr_hash.c @@ -59,9 +59,8 @@ void * hashinit_flags(int elements, struct malloc_type *type, u_long *hashmask, int flags) { - long hashsize; + long hashsize, i; LIST_HEAD(generic, generic) *hashtbl; - int i; KASSERT(elements > 0, ("%s: bad elements", __func__)); /* Exactly one of HASH_WAITOK and HASH_NOWAIT must be set. */ @@ -116,9 +115,8 @@ static const int primes[] = { 1, 13, 31, 61, 127, 251, 509, 761, 1021, 1531, void * phashinit_flags(int elements, struct malloc_type *type, u_long *nentries, int flags) { - long hashsize; + long hashsize, i; LIST_HEAD(generic, generic) *hashtbl; - int i; KASSERT(elements > 0, ("%s: bad elements", __func__)); /* Exactly one of HASH_WAITOK and HASH_NOWAIT must be set. */ diff --git a/freebsd/sys/kern/subr_prf.c b/freebsd/sys/kern/subr_prf.c index 0405b369..12a0825d 100644 --- a/freebsd/sys/kern/subr_prf.c +++ b/freebsd/sys/kern/subr_prf.c @@ -137,6 +137,7 @@ static void snprintf_func(int ch, void *arg); #ifndef __rtems__ static int msgbufmapped; /* Set when safe to use msgbuf */ int msgbuftrigger; +struct msgbuf *msgbufp; static int log_console_output = 1; SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RWTUN, @@ -290,6 +291,7 @@ _vprintf(int level, int flags, const char *fmt, va_list ap) char bufr[PRINTF_BUFR_SIZE]; #endif + TSENTER(); pca.tty = NULL; pca.pri = level; pca.flags = flags; @@ -317,6 +319,7 @@ _vprintf(int level, int flags, const char *fmt, va_list ap) } #endif + TSEXIT(); return (retval); } #else /* __rtems__ */ diff --git a/freebsd/sys/kern/subr_sleepqueue.c b/freebsd/sys/kern/subr_sleepqueue.c index fa33af86..6ecefc70 100644 --- a/freebsd/sys/kern/subr_sleepqueue.c +++ b/freebsd/sys/kern/subr_sleepqueue.c @@ -1441,11 +1441,10 @@ sleepq_sbuf_print_stacks(struct sbuf *sb, void *wchan, int queue, struct stack **st; struct sbuf **td_infos; int i, stack_idx, error, stacks_to_allocate; - bool finished, partial_print; + bool finished; error = 0; finished = false; - partial_print = false; KASSERT(wchan != NULL, ("%s: invalid NULL wait channel", __func__)); MPASS((queue >= 0) && (queue < NR_SLEEPQS)); diff --git a/freebsd/sys/kern/sys_generic.c b/freebsd/sys/kern/sys_generic.c index 118b4c77..1c46bd29 100644 --- a/freebsd/sys/kern/sys_generic.c +++ b/freebsd/sys/kern/sys_generic.c @@ -2004,6 +2004,8 @@ seltdfini(struct thread *td) if (stp->st_free2) uma_zfree(selfd_zone, stp->st_free2); td->td_sel = NULL; + cv_destroy(&stp->st_wait); + mtx_destroy(&stp->st_mtx); free(stp, M_SELECT); } diff --git a/freebsd/sys/kern/sys_socket.c b/freebsd/sys/kern/sys_socket.c index 974f7eec..4f4ce99e 100644 --- a/freebsd/sys/kern/sys_socket.c +++ b/freebsd/sys/kern/sys_socket.c @@ -585,6 +585,7 @@ soo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) kif->kf_type = KF_TYPE_SOCKET; so = fp->f_data; + CURVNET_SET(so->so_vnet); kif->kf_un.kf_sock.kf_sock_domain0 = so->so_proto->pr_domain->dom_family; kif->kf_un.kf_sock.kf_sock_type0 = so->so_type; @@ -637,6 +638,7 @@ soo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) } strncpy(kif->kf_path, so->so_proto->pr_domain->dom_name, sizeof(kif->kf_path)); + CURVNET_RESTORE(); return (0); } diff --git a/freebsd/sys/kern/uipc_usrreq.c b/freebsd/sys/kern/uipc_usrreq.c index 9f7e545f..7849be9d 100644 --- a/freebsd/sys/kern/uipc_usrreq.c +++ b/freebsd/sys/kern/uipc_usrreq.c @@ -1724,13 +1724,13 @@ unp_disconnect(struct unpcb *unp, struct unpcb *unp2) static int unp_pcblist(SYSCTL_HANDLER_ARGS) { - int error, i, n; - int freeunp; struct unpcb *unp, **unp_list; unp_gen_t gencnt; struct xunpgen *xug; struct unp_head *head; struct xunpcb *xu; + u_int i; + int error, freeunp, n; switch ((intptr_t)arg1) { case SOCK_STREAM: diff --git a/freebsd/sys/net/altq/altq_hfsc.h b/freebsd/sys/net/altq/altq_hfsc.h index de5e89b8..0a9fcf95 100644 --- a/freebsd/sys/net/altq/altq_hfsc.h +++ b/freebsd/sys/net/altq/altq_hfsc.h @@ -192,7 +192,7 @@ struct hfsc_class_stats { * representation. * the slope values are scaled to avoid overflow. * the inverse slope values as well as the y-projection of the 1st - * segment are kept in order to to avoid 64-bit divide operations + * segment are kept in order to avoid 64-bit divide operations * that are expensive on 32-bit architectures. * * note: Intel Pentium TSC never wraps around in several thousands of years. diff --git a/freebsd/sys/net/bpf.c b/freebsd/sys/net/bpf.c index 6fc6b435..e6ad9e25 100644 --- a/freebsd/sys/net/bpf.c +++ b/freebsd/sys/net/bpf.c @@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sockio.h> #include <sys/ttycom.h> #include <sys/uio.h> +#include <sys/sysent.h> #include <sys/event.h> #include <sys/file.h> @@ -728,7 +729,7 @@ bpf_check_upgrade(u_long cmd, struct bpf_d *d, struct bpf_insn *fcode, int flen) * Check if cmd looks like snaplen setting from * pcap_bpf.c:pcap_open_live(). * Note we're not checking .k value here: - * while pcap_open_live() definitely sets to to non-zero value, + * while pcap_open_live() definitely sets to non-zero value, * we'd prefer to treat k=0 (deny ALL) case the same way: e.g. * do not consider upgrading immediately */ @@ -1396,9 +1397,11 @@ bpfioctl(struct bpf_d *d, u_long cmd, caddr_t addr, int flags, case BIOCGDLTLIST32: case BIOCGRTIMEOUT32: case BIOCSRTIMEOUT32: - BPFD_LOCK(d); - d->bd_compat32 = 1; - BPFD_UNLOCK(d); + if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) { + BPFD_LOCK(d); + d->bd_compat32 = 1; + BPFD_UNLOCK(d); + } } #endif diff --git a/freebsd/sys/net/ieee8023ad_lacp.c b/freebsd/sys/net/ieee8023ad_lacp.c index 1778193d..2a30f4a3 100644 --- a/freebsd/sys/net/ieee8023ad_lacp.c +++ b/freebsd/sys/net/ieee8023ad_lacp.c @@ -203,8 +203,8 @@ SYSCTL_INT(_net_link_lagg_lacp, OID_AUTO, debug, CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(lacp_debug), 0, "Enable LACP debug logging (1=debug, 2=trace)"); static VNET_DEFINE(int, lacp_default_strict_mode) = 1; -SYSCTL_INT(_net_link_lagg_lacp, OID_AUTO, default_strict_mode, CTLFLAG_RWTUN, - &VNET_NAME(lacp_default_strict_mode), 0, +SYSCTL_INT(_net_link_lagg_lacp, OID_AUTO, default_strict_mode, + CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(lacp_default_strict_mode), 0, "LACP strict protocol compliance default"); #define LACP_DPRINTF(a) if (V_lacp_debug & 0x01) { lacp_dprintf a ; } diff --git a/freebsd/sys/net/if_clone.c b/freebsd/sys/net/if_clone.c index 99faa05f..295bddf4 100644 --- a/freebsd/sys/net/if_clone.c +++ b/freebsd/sys/net/if_clone.c @@ -357,7 +357,7 @@ if_clone_alloc(const char *name, int maxunit) return (ifc); } - + static int if_clone_attach(struct if_clone *ifc) { @@ -389,10 +389,8 @@ if_clone_advanced(const char *name, u_int maxunit, ifc_match_t match, ifc->ifc_create = create; ifc->ifc_destroy = destroy; - if (if_clone_attach(ifc) != 0) { - if_clone_free(ifc); + if (if_clone_attach(ifc) != 0) return (NULL); - } EVENTHANDLER_INVOKE(if_clone_event, ifc); @@ -412,10 +410,8 @@ if_clone_simple(const char *name, ifcs_create_t create, ifcs_destroy_t destroy, ifc->ifcs_destroy = destroy; ifc->ifcs_minifs = minifs; - if (if_clone_attach(ifc) != 0) { - if_clone_free(ifc); + if (if_clone_attach(ifc) != 0) return (NULL); - } for (unit = 0; unit < minifs; unit++) { char name[IFNAMSIZ]; @@ -452,7 +448,7 @@ if_clone_detach(struct if_clone *ifc) /* destroy all interfaces for this cloner */ while (!LIST_EMPTY(&ifc->ifc_iflist)) if_clone_destroyif(ifc, LIST_FIRST(&ifc->ifc_iflist)); - + IF_CLONE_REMREF(ifc); } @@ -514,7 +510,7 @@ if_clone_list(struct if_clonereq *ifcr) done: IF_CLONERS_UNLOCK(); - if (err == 0) + if (err == 0 && dst != NULL) err = copyout(outbuf, dst, buf_count*IFNAMSIZ); if (outbuf != NULL) free(outbuf, M_CLONE); diff --git a/freebsd/sys/net/if_ethersubr.c b/freebsd/sys/net/if_ethersubr.c index 9b927511..24f11436 100644 --- a/freebsd/sys/net/if_ethersubr.c +++ b/freebsd/sys/net/if_ethersubr.c @@ -292,7 +292,6 @@ ether_output(struct ifnet *ifp, struct mbuf *m, int hlen; /* link layer header length */ uint32_t pflags; struct llentry *lle = NULL; - struct rtentry *rt0 = NULL; int addref = 0; phdr = NULL; @@ -322,7 +321,6 @@ ether_output(struct ifnet *ifp, struct mbuf *m, pflags = lle->r_flags; } } - rt0 = ro->ro_rt; } #ifdef MAC diff --git a/freebsd/sys/net/if_gif.c b/freebsd/sys/net/if_gif.c index fdbccbb6..bd33ab75 100644 --- a/freebsd/sys/net/if_gif.c +++ b/freebsd/sys/net/if_gif.c @@ -526,7 +526,6 @@ gif_input(struct mbuf *m, struct ifnet *ifp, int proto, uint8_t ecn) struct ip6_hdr *ip6; uint32_t t; #endif - struct gif_softc *sc; struct ether_header *eh; struct ifnet *oldifp; int isr, n, af; @@ -536,7 +535,6 @@ gif_input(struct mbuf *m, struct ifnet *ifp, int proto, uint8_t ecn) m_freem(m); return; } - sc = ifp->if_softc; m->m_pkthdr.rcvif = ifp; m_clrprotoflags(m); switch (proto) { diff --git a/freebsd/sys/net/if_lagg.c b/freebsd/sys/net/if_lagg.c index ce696fb2..36c8095a 100644 --- a/freebsd/sys/net/if_lagg.c +++ b/freebsd/sys/net/if_lagg.c @@ -246,7 +246,7 @@ SYSCTL_INT(_net_link_lagg, OID_AUTO, failover_rx_all, CTLFLAG_RW | CTLFLAG_VNET, "Accept input from any interface in a failover lagg"); /* Default value for using flowid */ -static VNET_DEFINE(int, def_use_flowid) = 1; +static VNET_DEFINE(int, def_use_flowid) = 0; #define V_def_use_flowid VNET(def_use_flowid) SYSCTL_INT(_net_link_lagg, OID_AUTO, default_use_flowid, CTLFLAG_RWTUN, &VNET_NAME(def_use_flowid), 0, diff --git a/freebsd/sys/net/iflib.h b/freebsd/sys/net/iflib.h index 70992fdd..3730f0ea 100644 --- a/freebsd/sys/net/iflib.h +++ b/freebsd/sys/net/iflib.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2014-2017, Matthew Macy (mmacy@nextbsd.org) + * Copyright (c) 2014-2017, Matthew Macy (mmacy@mattmacy.io) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -174,9 +174,9 @@ typedef struct pci_vendor_info { #define PVID_END {0, 0, 0, 0, 0, 0, NULL} #define IFLIB_PNP_DESCR "U32:vendor;U32:device;U32:subvendor;U32:subdevice;" \ - "U32:revision;U32:class;D:human" + "U32:revision;U32:class;D:#" #define IFLIB_PNP_INFO(b, u, t) \ - MODULE_PNP_INFO(IFLIB_PNP_DESCR, b, u, t, sizeof(t[0]), nitems(t)) + MODULE_PNP_INFO(IFLIB_PNP_DESCR, b, u, t, sizeof(t[0]), nitems(t) - 1) typedef struct if_txrx { int (*ift_txd_encap) (void *, if_pkt_info_t); @@ -217,6 +217,8 @@ typedef struct if_softc_ctx { iflib_intr_mode_t isc_intr; uint16_t isc_max_frame_size; /* set at init time by driver */ + uint16_t isc_min_frame_size; /* set at init time by driver, only used if + IFLIB_NEED_ETHER_PAD is set. */ uint32_t isc_pause_frames; /* set by driver for iflib_timer to detect */ pci_vendor_info_t isc_vendor_info; /* set by iflib prior to attach_pre */ int isc_disable_msix; @@ -314,6 +316,10 @@ typedef enum { * Driver needs csum zeroed for offloading */ #define IFLIB_NEED_ZERO_CSUM 0x80 +/* + * Driver needs frames padded to some minimum length + */ +#define IFLIB_NEED_ETHER_PAD 0x100 diff --git a/freebsd/sys/net/pfvar.h b/freebsd/sys/net/pfvar.h index 4bc84d94..c9b1d1db 100644 --- a/freebsd/sys/net/pfvar.h +++ b/freebsd/sys/net/pfvar.h @@ -1619,6 +1619,7 @@ int pf_normalize_tcp_stateful(struct mbuf *, int, struct pf_pdesc *, u_int32_t pf_state_expires(const struct pf_state *); void pf_purge_expired_fragments(void); +void pf_purge_fragments(uint32_t); int pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *, int); int pf_socket_lookup(int, struct pf_pdesc *, struct mbuf *); diff --git a/freebsd/sys/net/route.c b/freebsd/sys/net/route.c index 1be39753..ade738a2 100644 --- a/freebsd/sys/net/route.c +++ b/freebsd/sys/net/route.c @@ -1765,6 +1765,8 @@ rtrequest1_fib_change(struct rib_head *rnh, struct rt_addrinfo *info, int family, mtu; struct if_mtuinfo ifmtu; + RIB_WLOCK_ASSERT(rnh); + rt = (struct rtentry *)rnh->rnh_lookup(info->rti_info[RTAX_DST], info->rti_info[RTAX_NETMASK], &rnh->head); @@ -1813,8 +1815,9 @@ rtrequest1_fib_change(struct rib_head *rnh, struct rt_addrinfo *info, /* Check if outgoing interface has changed */ if (info->rti_ifa != NULL && info->rti_ifa != rt->rt_ifa && - rt->rt_ifa != NULL && rt->rt_ifa->ifa_rtrequest != NULL) { - rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, info); + rt->rt_ifa != NULL) { + if (rt->rt_ifa->ifa_rtrequest != NULL) + rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, info); ifa_free(rt->rt_ifa); } /* Update gateway address */ @@ -1854,6 +1857,13 @@ rtrequest1_fib_change(struct rib_head *rnh, struct rt_addrinfo *info, } } + /* + * This route change may have modified the route's gateway. In that + * case, any inpcbs that have cached this route need to invalidate their + * llentry cache. + */ + rnh->rnh_gen++; + if (ret_nrt) { *ret_nrt = rt; RT_ADDREF(rt); diff --git a/freebsd/sys/net/route.h b/freebsd/sys/net/route.h index 8835433e..28f1db01 100644 --- a/freebsd/sys/net/route.h +++ b/freebsd/sys/net/route.h @@ -416,6 +416,14 @@ struct rt_addrinfo { } \ } while (0) +#define RO_INVALIDATE_CACHE(ro) do { \ + RO_RTFREE(ro); \ + if ((ro)->ro_lle != NULL) { \ + LLE_FREE((ro)->ro_lle); \ + (ro)->ro_lle = NULL; \ + } \ + } while (0) + /* * Validate a cached route based on a supplied cookie. If there is an * out-of-date cache, simply free it. Update the generation number @@ -424,10 +432,7 @@ struct rt_addrinfo { #define RT_VALIDATE(ro, cookiep, fibnum) do { \ rt_gen_t cookie = RT_GEN(fibnum, (ro)->ro_dst.sa_family); \ if (*(cookiep) != cookie) { \ - if ((ro)->ro_rt != NULL) { \ - RTFREE((ro)->ro_rt); \ - (ro)->ro_rt = NULL; \ - } \ + RO_INVALIDATE_CACHE(ro); \ *(cookiep) = cookie; \ } \ } while (0) diff --git a/freebsd/sys/net/rtsock.c b/freebsd/sys/net/rtsock.c index fe608d70..851c30c9 100644 --- a/freebsd/sys/net/rtsock.c +++ b/freebsd/sys/net/rtsock.c @@ -114,6 +114,12 @@ struct ifa_msghdrl32 { int32_t ifam_metric; struct if_data ifam_data; }; + +#define SA_SIZE32(sa) \ + ( (((struct sockaddr *)(sa))->sa_len == 0) ? \ + sizeof(int) : \ + 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(int) - 1) ) ) + #endif /* COMPAT_FREEBSD32 */ MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables"); @@ -1128,6 +1134,9 @@ rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, struct walkarg *w, int * struct sockaddr_storage ss; struct sockaddr_in6 *sin6; #endif +#ifdef COMPAT_FREEBSD32 + bool compat32 = false; +#endif switch (type) { @@ -1135,9 +1144,10 @@ rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, struct walkarg *w, int * case RTM_NEWADDR: if (w != NULL && w->w_op == NET_RT_IFLISTL) { #ifdef COMPAT_FREEBSD32 - if (w->w_req->flags & SCTL_MASK32) + if (w->w_req->flags & SCTL_MASK32) { len = sizeof(struct ifa_msghdrl32); - else + compat32 = true; + } else #endif len = sizeof(struct ifa_msghdrl); } else @@ -1151,6 +1161,7 @@ rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, struct walkarg *w, int * len = sizeof(struct if_msghdrl32); else len = sizeof(struct if_msghdr32); + compat32 = true; break; } #endif @@ -1181,7 +1192,12 @@ rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, struct walkarg *w, int * if ((sa = rtinfo->rti_info[i]) == NULL) continue; rtinfo->rti_addrs |= (1 << i); - dlen = SA_SIZE(sa); +#ifdef COMPAT_FREEBSD32 + if (compat32) + dlen = SA_SIZE32(sa); + else +#endif + dlen = SA_SIZE(sa); if (cp != NULL && buflen >= dlen) { #ifdef INET6 if (V_deembed_scopeid && sa->sa_family == AF_INET6) { diff --git a/freebsd/sys/net/sff8472.h b/freebsd/sys/net/sff8472.h index e67aa7f6..d38fcfc0 100644 --- a/freebsd/sys/net/sff8472.h +++ b/freebsd/sys/net/sff8472.h @@ -379,7 +379,7 @@ enum { /* * Table 3.2 Identifier values. - * Identifier constants has taken from SFF-8024 rev 2.9 table 4.1 + * Identifier constants has taken from SFF-8024 rev 4.2 table 4.1 * (as referenced by table 3.2 footer) * */ enum { @@ -400,13 +400,15 @@ enum { SFF_8024_ID_CXP = 0xE, /* CXP */ SFF_8024_ID_HD4X = 0xF, /* Shielded Mini Multilane HD 4X */ SFF_8024_ID_HD8X = 0x10, /* Shielded Mini Multilane HD 8X */ - SFF_8024_ID_QSFP28 = 0x11, /* QSFP28 */ + SFF_8024_ID_QSFP28 = 0x11, /* QSFP28 or later */ SFF_8024_ID_CXP2 = 0x12, /* CXP2 (aka CXP28) */ SFF_8024_ID_CDFP = 0x13, /* CDFP (Style 1/Style 2) */ SFF_8024_ID_SMM4 = 0x14, /* Shielded Mini Multilate HD 4X Fanout */ SFF_8024_ID_SMM8 = 0x15, /* Shielded Mini Multilate HD 8X Fanout */ SFF_8024_ID_CDFP3 = 0x16, /* CDFP (Style3) */ - SFF_8024_ID_LAST = SFF_8024_ID_CDFP3 + SFF_8024_ID_MICROQSFP = 0x17, /* microQSFP */ + SFF_8024_ID_QSFP_DD = 0x18, /* QSFP-DD 8X Pluggable Transceiver */ + SFF_8024_ID_LAST = SFF_8024_ID_QSFP_DD }; static const char *sff_8024_id[SFF_8024_ID_LAST + 1] = {"Unknown", @@ -431,7 +433,9 @@ static const char *sff_8024_id[SFF_8024_ID_LAST + 1] = {"Unknown", "CDFP", "SMM4", "SMM8", - "CDFP3"}; + "CDFP3", + "microQSFP", + "QSFP-DD"}; /* Keep compatibility with old definitions */ #define SFF_8472_ID_UNKNOWN SFF_8024_ID_UNKNOWN diff --git a/freebsd/sys/net80211/ieee80211_ht.c b/freebsd/sys/net80211/ieee80211_ht.c index 21d85fb3..c6a3a200 100644 --- a/freebsd/sys/net80211/ieee80211_ht.c +++ b/freebsd/sys/net80211/ieee80211_ht.c @@ -3356,7 +3356,7 @@ ieee80211_add_htinfo_body(uint8_t *frm, struct ieee80211_node *ni) } /* - * Add 802.11n HT information information element. + * Add 802.11n HT information element. */ uint8_t * ieee80211_add_htinfo(uint8_t *frm, struct ieee80211_node *ni) diff --git a/freebsd/sys/net80211/ieee80211_node.c b/freebsd/sys/net80211/ieee80211_node.c index 023fb128..45d6fa73 100644 --- a/freebsd/sys/net80211/ieee80211_node.c +++ b/freebsd/sys/net80211/ieee80211_node.c @@ -245,7 +245,12 @@ ieee80211_node_setuptxparms(struct ieee80211_node *ni) struct ieee80211vap *vap = ni->ni_vap; enum ieee80211_phymode mode; - if (ni->ni_flags & IEEE80211_NODE_HT) { + if (ni->ni_flags & IEEE80211_NODE_VHT) { + if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) + mode = IEEE80211_MODE_VHT_5GHZ; + else + mode = IEEE80211_MODE_VHT_2GHZ; + } else if (ni->ni_flags & IEEE80211_NODE_HT) { if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) mode = IEEE80211_MODE_11NA; else diff --git a/freebsd/sys/net80211/ieee80211_output.c b/freebsd/sys/net80211/ieee80211_output.c index 51a75af2..a49c8a16 100644 --- a/freebsd/sys/net80211/ieee80211_output.c +++ b/freebsd/sys/net80211/ieee80211_output.c @@ -553,6 +553,59 @@ ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni, return (error); } +static int +ieee80211_validate_frame(struct mbuf *m, + const struct ieee80211_bpf_params *params) +{ + struct ieee80211_frame *wh; + int type; + + if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_ack)) + return (EINVAL); + + wh = mtod(m, struct ieee80211_frame *); + if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != + IEEE80211_FC0_VERSION_0) + return (EINVAL); + + type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + if (type != IEEE80211_FC0_TYPE_DATA) { + if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) != + IEEE80211_FC1_DIR_NODS) + return (EINVAL); + + if (type != IEEE80211_FC0_TYPE_MGT && + (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) != 0) + return (EINVAL); + + /* XXX skip other field checks? */ + } + + if ((params && (params->ibp_flags & IEEE80211_BPF_CRYPTO) != 0) || + (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) != 0) { + int subtype; + + subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + + /* + * See IEEE Std 802.11-2012, + * 8.2.4.1.9 'Protected Frame field' + */ + /* XXX no support for robust management frames yet. */ + if (!(type == IEEE80211_FC0_TYPE_DATA || + (type == IEEE80211_FC0_TYPE_MGT && + subtype == IEEE80211_FC0_SUBTYPE_AUTH))) + return (EINVAL); + + wh->i_fc[1] |= IEEE80211_FC1_PROTECTED; + } + + if (m->m_pkthdr.len < ieee80211_anyhdrsize(wh)) + return (EINVAL); + + return (0); +} + /* * 802.11 output routine. This is (currently) used only to * connect bpf write calls to the 802.11 layer for injecting @@ -563,6 +616,7 @@ ieee80211_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct route *ro) { #define senderr(e) do { error = (e); goto bad;} while (0) + const struct ieee80211_bpf_params *params = NULL; struct ieee80211_node *ni = NULL; struct ieee80211vap *vap; struct ieee80211_frame *wh; @@ -608,14 +662,20 @@ ieee80211_output(struct ifnet *ifp, struct mbuf *m, senderr(EIO); /* XXX bypass bridge, pfil, carp, etc. */ - if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_ack)) - senderr(EIO); /* XXX */ + /* + * NB: DLT_IEEE802_11_RADIO identifies the parameters are + * present by setting the sa_len field of the sockaddr (yes, + * this is a hack). + * NB: we assume sa_data is suitably aligned to cast. + */ + if (dst->sa_len != 0) + params = (const struct ieee80211_bpf_params *)dst->sa_data; + + error = ieee80211_validate_frame(m, params); + if (error != 0) + senderr(error); + wh = mtod(m, struct ieee80211_frame *); - if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != - IEEE80211_FC0_VERSION_0) - senderr(EIO); /* XXX */ - if (m->m_pkthdr.len < ieee80211_anyhdrsize(wh)) - senderr(EIO); /* XXX */ /* locate destination node */ switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { @@ -628,7 +688,7 @@ ieee80211_output(struct ifnet *ifp, struct mbuf *m, ni = ieee80211_find_txnode(vap, wh->i_addr3); break; default: - senderr(EIO); /* XXX */ + senderr(EDOOFUS); } if (ni == NULL) { /* @@ -647,11 +707,18 @@ ieee80211_output(struct ifnet *ifp, struct mbuf *m, * it marks EAPOL in frames with M_EAPOL. */ m->m_flags &= ~M_80211_TX; + m->m_flags |= M_ENCAP; /* mark encapsulated */ - /* calculate priority so drivers can find the tx queue */ - /* XXX assumes an 802.3 frame */ - if (ieee80211_classify(ni, m)) - senderr(EIO); /* XXX */ + if (IEEE80211_IS_DATA(wh)) { + /* calculate priority so drivers can find the tx queue */ + if (ieee80211_classify(ni, m)) + senderr(EIO); /* XXX */ + + /* NB: ieee80211_encap does not include 802.11 header */ + IEEE80211_NODE_STAT_ADD(ni, tx_bytes, + m->m_pkthdr.len - ieee80211_hdrsize(wh)); + } else + M_WME_SETAC(m, WME_AC_BE); IEEE80211_NODE_STAT(ni, tx_data); if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { @@ -659,20 +726,9 @@ ieee80211_output(struct ifnet *ifp, struct mbuf *m, m->m_flags |= M_MCAST; } else IEEE80211_NODE_STAT(ni, tx_ucast); - /* NB: ieee80211_encap does not include 802.11 header */ - IEEE80211_NODE_STAT_ADD(ni, tx_bytes, m->m_pkthdr.len); IEEE80211_TX_LOCK(ic); - - /* - * NB: DLT_IEEE802_11_RADIO identifies the parameters are - * present by setting the sa_len field of the sockaddr (yes, - * this is a hack). - * NB: we assume sa_data is suitably aligned to cast. - */ - ret = ieee80211_raw_output(vap, ni, m, - (const struct ieee80211_bpf_params *)(dst->sa_len ? - dst->sa_data : NULL)); + ret = ieee80211_raw_output(vap, ni, m, params); IEEE80211_TX_UNLOCK(ic); return (ret); bad: @@ -1008,13 +1064,44 @@ ieee80211_send_nulldata(struct ieee80211_node *ni) int ieee80211_classify(struct ieee80211_node *ni, struct mbuf *m) { - const struct ether_header *eh = mtod(m, struct ether_header *); + const struct ether_header *eh = NULL; + uint16_t ether_type; int v_wme_ac, d_wme_ac, ac; + if (__predict_false(m->m_flags & M_ENCAP)) { + struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *); + struct llc *llc; + int hdrlen, subtype; + + subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + if (subtype & IEEE80211_FC0_SUBTYPE_NODATA) { + ac = WME_AC_BE; + goto done; + } + + hdrlen = ieee80211_hdrsize(wh); + if (m->m_pkthdr.len < hdrlen + sizeof(*llc)) + return 1; + + llc = (struct llc *)mtodo(m, hdrlen); + if (llc->llc_dsap != LLC_SNAP_LSAP || + llc->llc_ssap != LLC_SNAP_LSAP || + llc->llc_control != LLC_UI || + llc->llc_snap.org_code[0] != 0 || + llc->llc_snap.org_code[1] != 0 || + llc->llc_snap.org_code[2] != 0) + return 1; + + ether_type = llc->llc_snap.ether_type; + } else { + eh = mtod(m, struct ether_header *); + ether_type = eh->ether_type; + } + /* * Always promote PAE/EAPOL frames to high priority. */ - if (eh->ether_type == htons(ETHERTYPE_PAE)) { + if (ether_type == htons(ETHERTYPE_PAE)) { /* NB: mark so others don't need to check header */ m->m_flags |= M_EAPOL; ac = WME_AC_VO; @@ -1049,7 +1136,7 @@ ieee80211_classify(struct ieee80211_node *ni, struct mbuf *m) /* XXX m_copydata may be too slow for fast path */ #ifdef INET - if (eh->ether_type == htons(ETHERTYPE_IP)) { + if (eh && eh->ether_type == htons(ETHERTYPE_IP)) { uint8_t tos; /* * IP frame, map the DSCP bits from the TOS field. @@ -1062,7 +1149,7 @@ ieee80211_classify(struct ieee80211_node *ni, struct mbuf *m) } else { #endif /* INET */ #ifdef INET6 - if (eh->ether_type == htons(ETHERTYPE_IPV6)) { + if (eh && eh->ether_type == htons(ETHERTYPE_IPV6)) { uint32_t flow; uint8_t tos; /* diff --git a/freebsd/sys/net80211/ieee80211_proto.c b/freebsd/sys/net80211/ieee80211_proto.c index 73410d70..129e11e2 100644 --- a/freebsd/sys/net80211/ieee80211_proto.c +++ b/freebsd/sys/net80211/ieee80211_proto.c @@ -1310,6 +1310,12 @@ ieee80211_wme_updateparams(struct ieee80211vap *vap) } } +/* + * Fetch the WME parameters for the given VAP. + * + * When net80211 grows p2p, etc support, this may return different + * parameters for each VAP. + */ void ieee80211_wme_vap_getparams(struct ieee80211vap *vap, struct chanAccParams *wp) { @@ -1317,6 +1323,12 @@ ieee80211_wme_vap_getparams(struct ieee80211vap *vap, struct chanAccParams *wp) memcpy(wp, &vap->iv_ic->ic_wme.wme_chanParams, sizeof(*wp)); } +/* + * For NICs which only support one set of WME paramaters (ie, softmac NICs) + * there may be different VAP WME parameters but only one is "active". + * This returns the "NIC" WME parameters for the currently active + * context. + */ void ieee80211_wme_ic_getparams(struct ieee80211com *ic, struct chanAccParams *wp) { @@ -1324,6 +1336,26 @@ ieee80211_wme_ic_getparams(struct ieee80211com *ic, struct chanAccParams *wp) memcpy(wp, &ic->ic_wme.wme_chanParams, sizeof(*wp)); } +/* + * Return whether to use QoS on a given WME queue. + * + * This is intended to be called from the transmit path of softmac drivers + * which are setting NoAck bits in transmit descriptors. + * + * Ideally this would be set in some transmit field before the packet is + * queued to the driver but net80211 isn't quite there yet. + */ +int +ieee80211_wme_vap_ac_is_noack(struct ieee80211vap *vap, int ac) +{ + /* Bounds/sanity check */ + if (ac < 0 || ac >= WME_NUM_AC) + return (0); + + /* Again, there's only one global context for now */ + return (!! vap->iv_ic->ic_wme.wme_chanParams.cap_wmeParams[ac].wmep_noackPolicy); +} + static void parent_updown(void *arg, int npending) { diff --git a/freebsd/sys/net80211/ieee80211_proto.h b/freebsd/sys/net80211/ieee80211_proto.h index 187f7018..28238ce8 100644 --- a/freebsd/sys/net80211/ieee80211_proto.h +++ b/freebsd/sys/net80211/ieee80211_proto.h @@ -298,6 +298,7 @@ void ieee80211_wme_vap_getparams(struct ieee80211vap *vap, struct chanAccParams *); void ieee80211_wme_ic_getparams(struct ieee80211com *ic, struct chanAccParams *); +int ieee80211_wme_vap_ac_is_noack(struct ieee80211vap *vap, int ac); /* * Return the WME TID from a QoS frame. If no TID diff --git a/freebsd/sys/net80211/ieee80211_scan_sta.c b/freebsd/sys/net80211/ieee80211_scan_sta.c index ed069ed8..a7a1fc29 100644 --- a/freebsd/sys/net80211/ieee80211_scan_sta.c +++ b/freebsd/sys/net80211/ieee80211_scan_sta.c @@ -121,7 +121,7 @@ static void sta_flush_table(struct sta_table *); /* * match_bss returns a bitmask describing if an entry is suitable * for use. If non-zero the entry was deemed not suitable and it's - * contents explains why. The following flags are or'd to to this + * contents explains why. The following flags are or'd to this * mask and can be used to figure out why the entry was rejected. */ #define MATCH_CHANNEL 0x00001 /* channel mismatch */ diff --git a/freebsd/sys/netinet/icmp6.h b/freebsd/sys/netinet/icmp6.h index b0ae67fe..310684b8 100644 --- a/freebsd/sys/netinet/icmp6.h +++ b/freebsd/sys/netinet/icmp6.h @@ -628,7 +628,7 @@ struct icmp6stat { uint64_t icp6s_nd_badopt; /* bad ND options */ uint64_t icp6s_badns; /* bad neighbor solicitation */ uint64_t icp6s_badna; /* bad neighbor advertisement */ - uint64_t icp6s_badrs; /* bad router advertisement */ + uint64_t icp6s_badrs; /* bad router solicitation */ uint64_t icp6s_badra; /* bad router advertisement */ uint64_t icp6s_badredirect; /* bad redirect message */ }; diff --git a/freebsd/sys/netinet/in_pcb.c b/freebsd/sys/netinet/in_pcb.c index 2783a276..2803126d 100644 --- a/freebsd/sys/netinet/in_pcb.c +++ b/freebsd/sys/netinet/in_pcb.c @@ -1331,9 +1331,7 @@ in_pcbfree(struct inpcb *inp) if (inp->inp_moptions != NULL) inp_freemoptions(inp->inp_moptions); #endif - RO_RTFREE(&inp->inp_route); - if (inp->inp_route.ro_lle) - LLE_FREE(inp->inp_route.ro_lle); /* zeros ro_lle */ + RO_INVALIDATE_CACHE(&inp->inp_route); inp->inp_vflag = 0; inp->inp_flags2 |= INP_FREED; @@ -2271,9 +2269,7 @@ void in_losing(struct inpcb *inp) { - RO_RTFREE(&inp->inp_route); - if (inp->inp_route.ro_lle) - LLE_FREE(inp->inp_route.ro_lle); /* zeros ro_lle */ + RO_INVALIDATE_CACHE(&inp->inp_route); return; } diff --git a/freebsd/sys/netinet/ip_mroute.c b/freebsd/sys/netinet/ip_mroute.c index eba4af63..3bf4fa91 100644 --- a/freebsd/sys/netinet/ip_mroute.c +++ b/freebsd/sys/netinet/ip_mroute.c @@ -2820,7 +2820,7 @@ static void vnet_mroute_init(const void *unused __unused) { - MALLOC(V_nexpire, u_char *, mfchashsize, M_MRTABLE, M_WAITOK|M_ZERO); + V_nexpire = malloc(mfchashsize, M_MRTABLE, M_WAITOK|M_ZERO); bzero(V_bw_meter_timers, sizeof(V_bw_meter_timers)); callout_init(&V_expire_upcalls_ch, 1); callout_init(&V_bw_upcalls_ch, 1); @@ -2834,7 +2834,7 @@ static void vnet_mroute_uninit(const void *unused __unused) { - FREE(V_nexpire, M_MRTABLE); + free(V_nexpire, M_MRTABLE); V_nexpire = NULL; } diff --git a/freebsd/sys/netinet/ip_output.c b/freebsd/sys/netinet/ip_output.c index 62110ed1..4944c035 100644 --- a/freebsd/sys/netinet/ip_output.c +++ b/freebsd/sys/netinet/ip_output.c @@ -304,11 +304,8 @@ again: !RT_LINK_IS_UP(rte->rt_ifp) || dst->sin_family != AF_INET || dst->sin_addr.s_addr != ip->ip_dst.s_addr)) { - RTFREE(rte); - rte = ro->ro_rt = (struct rtentry *)NULL; - if (ro->ro_lle) - LLE_FREE(ro->ro_lle); /* zeros ro_lle */ - ro->ro_lle = (struct llentry *)NULL; + RO_INVALIDATE_CACHE(ro); + rte = NULL; } ia = NULL; have_ia_ref = 0; diff --git a/freebsd/sys/netinet/ip_reass.c b/freebsd/sys/netinet/ip_reass.c index 30cf3ba4..64660228 100644 --- a/freebsd/sys/netinet/ip_reass.c +++ b/freebsd/sys/netinet/ip_reass.c @@ -379,6 +379,7 @@ ip_reass(struct mbuf *m) q->m_nextpkt = NULL; m->m_pkthdr.csum_flags &= q->m_pkthdr.csum_flags; m->m_pkthdr.csum_data += q->m_pkthdr.csum_data; + m_demote_pkthdr(q); m_cat(m, q); } /* diff --git a/freebsd/sys/netinet/libalias/alias_mod.h b/freebsd/sys/netinet/libalias/alias_mod.h index d57798f7..c646f794 100644 --- a/freebsd/sys/netinet/libalias/alias_mod.h +++ b/freebsd/sys/netinet/libalias/alias_mod.h @@ -43,7 +43,7 @@ MALLOC_DECLARE(M_ALIAS); #if defined(_SYS_MALLOC_H_) #ifndef __rtems__ #define malloc(x) malloc(x, M_ALIAS, M_NOWAIT|M_ZERO) -#define calloc(x, n) malloc(x*n) +#define calloc(n, x) mallocarray((n), (x), M_ALIAS, M_NOWAIT|M_ZERO) #define free(x) free(x, M_ALIAS) #else /* __rtems__ */ #undef malloc diff --git a/freebsd/sys/netinet/libalias/alias_sctp.c b/freebsd/sys/netinet/libalias/alias_sctp.c index f7fda7bf..4f7d4940 100644 --- a/freebsd/sys/netinet/libalias/alias_sctp.c +++ b/freebsd/sys/netinet/libalias/alias_sctp.c @@ -29,7 +29,7 @@ */ /* - * Alias_sctp forms part of the libalias kernel module to handle + * Alias_sctp forms part of the libalias kernel module to handle * Network Address Translation (NAT) for the SCTP protocol. * * This software was developed by David A. Hayes and Jason But @@ -41,13 +41,13 @@ * proposed by Jason But and Grenville Armitage: * http://caia.swin.edu.au/urp/sonata/ * - * + * * This project has been made possible in part by a grant from * the Cisco University Research Program Fund at Community * Foundation Silicon Valley. * */ -/** @mainpage +/** @mainpage * Alias_sctp is part of the SONATA (http://caia.swin.edu.au/urp/sonata) project * to develop and release a BSD licensed implementation of a Network Address * Translation (NAT) module that supports the Stream Control Transmission @@ -178,7 +178,7 @@ static void SctpAliasLog(const char *format, ...); * * Calls the higher level ShowAliasStats() in alias_db.c which logs all current * statistics about the libalias instance - including SCTP statistics - * + * * @param la Pointer to the libalias instance */ void SctpShowAliasStats(struct libalias *la); @@ -189,7 +189,7 @@ static MALLOC_DEFINE(M_SCTPNAT, "sctpnat", "sctp nat dbs"); /* Use kernel allocator. */ #ifdef _SYS_MALLOC_H_ #define sn_malloc(x) malloc(x, M_SCTPNAT, M_NOWAIT|M_ZERO) -#define sn_calloc(n,x) sn_malloc(x * n) +#define sn_calloc(n,x) mallocarray((n), (x), M_SCTPNAT, M_NOWAIT|M_ZERO) #define sn_free(x) free(x, M_SCTPNAT) #endif// #ifdef _SYS_MALLOC_H_ @@ -263,7 +263,7 @@ static MALLOC_DEFINE(M_SCTPNAT, "sctpnat", "sctp nat dbs"); * Define various log levels and a macro to call specified log functions only if * the current log level (sysctl_log_level) matches the specified level @{ */ -#define SN_LOG_LOW 0 +#define SN_LOG_LOW 0 #define SN_LOG_EVENT 1 #define SN_LOG_INFO 2 #define SN_LOG_DETAIL 3 @@ -424,9 +424,9 @@ int sysctl_chg_loglevel(SYSCTL_HANDLER_ARGS) error = sysctl_handle_int(oidp, &level, 0, req); if (error) return (error); - sysctl_log_level = (level > SN_LOG_DEBUG_MAX)?(SN_LOG_DEBUG_MAX):(level); - sysctl_log_level = (level < SN_LOG_LOW)?(SN_LOG_LOW):(level); - + level = (level > SN_LOG_DEBUG_MAX) ? (SN_LOG_DEBUG_MAX) : (level); + level = (level < SN_LOG_LOW) ? (SN_LOG_LOW) : (level); + sysctl_log_level = level; return (0); } @@ -445,12 +445,11 @@ int sysctl_chg_timer(SYSCTL_HANDLER_ARGS) error = sysctl_handle_int(oidp, &timer, 0, req); if (error) return (error); - timer = (timer > SN_MAX_TIMER)?(SN_MAX_TIMER):(timer); + timer = (timer > SN_MAX_TIMER) ? (SN_MAX_TIMER) : (timer); - if (((u_int *)arg1) != &sysctl_holddown_timer) - { - timer = (timer < SN_MIN_TIMER)?(SN_MIN_TIMER):(timer); - } + if (((u_int *)arg1) != &sysctl_holddown_timer) { + timer = (timer < SN_MIN_TIMER) ? (SN_MIN_TIMER) : (timer); + } *(u_int *)arg1 = timer; @@ -474,11 +473,11 @@ int sysctl_chg_hashtable_size(SYSCTL_HANDLER_ARGS) error = sysctl_handle_int(oidp, &size, 0, req); if (error) return (error); - size = (size < SN_MIN_HASH_SIZE)?(SN_MIN_HASH_SIZE):((size > SN_MAX_HASH_SIZE)?(SN_MAX_HASH_SIZE):(size)); + size = (size < SN_MIN_HASH_SIZE) ? (SN_MIN_HASH_SIZE) : ((size > SN_MAX_HASH_SIZE) ? (SN_MAX_HASH_SIZE) : (size)); size |= 0x00000001; /* make odd */ - for(;(((size % 3) == 0) || ((size % 5) == 0) || ((size % 7) == 0) || ((size % 11) == 0)); size+=2); + for (;(((size % 3) == 0) || ((size % 5) == 0) || ((size % 7) == 0) || ((size % 11) == 0)); size+=2); sysctl_hashtable_size = size; return (0); @@ -487,7 +486,7 @@ int sysctl_chg_hashtable_size(SYSCTL_HANDLER_ARGS) /** @ingroup sysctl * @brief sysctl callback for changing net.inet.ip.alias.sctp.error_on_ootb * - * Updates the error_on_clash sysctl variable. + * Updates the error_on_clash sysctl variable. * If set to 0, no ErrorM will be sent if there is a look up table clash * If set to 1, an ErrorM is sent only to the local side * If set to 2, an ErrorM is sent to the local side and global side if there is @@ -542,16 +541,16 @@ int sysctl_chg_initialising_chunk_proc_limit(SYSCTL_HANDLER_ARGS) if (error) return (error); sysctl_initialising_chunk_proc_limit = (proclimit < 1) ? 1: proclimit; - sysctl_chunk_proc_limit = + sysctl_chunk_proc_limit = (sysctl_chunk_proc_limit < sysctl_initialising_chunk_proc_limit) ? sysctl_initialising_chunk_proc_limit : sysctl_chunk_proc_limit; - + return (0); } /** @ingroup sysctl * @brief sysctl callback for changing net.inet.ip.alias.sctp.chunk_proc_limit * - * Updates the chunk_proc_limit sysctl variable. + * Updates the chunk_proc_limit sysctl variable. * Number of chunks that should be processed to find key chunk: * >= initialising_chunk_proc_limit (A high value is a DoS risk) */ @@ -563,7 +562,7 @@ int sysctl_chg_chunk_proc_limit(SYSCTL_HANDLER_ARGS) error = sysctl_handle_int(oidp, &proclimit, 0, req); if (error) return (error); - sysctl_chunk_proc_limit = + sysctl_chunk_proc_limit = (proclimit < sysctl_initialising_chunk_proc_limit) ? sysctl_initialising_chunk_proc_limit : proclimit; return (0); @@ -573,7 +572,7 @@ int sysctl_chg_chunk_proc_limit(SYSCTL_HANDLER_ARGS) /** @ingroup sysctl * @brief sysctl callback for changing net.inet.ip.alias.sctp.param_proc_limit * - * Updates the param_proc_limit sysctl variable. + * Updates the param_proc_limit sysctl variable. * Number of parameters that should be processed to find key parameters: * > 1 (A high value is a DoS risk) */ @@ -585,7 +584,7 @@ int sysctl_chg_param_proc_limit(SYSCTL_HANDLER_ARGS) error = sysctl_handle_int(oidp, &proclimit, 0, req); if (error) return (error); - sysctl_param_proc_limit = + sysctl_param_proc_limit = (proclimit < 2) ? 2 : proclimit; return (0); @@ -616,9 +615,9 @@ int sysctl_chg_track_global_addresses(SYSCTL_HANDLER_ARGS) * CODE BEGINS HERE * ---------------------------------------------------------------------- */ -/** +/** * @brief Initialises the SCTP NAT Implementation - * + * * Creates the look-up tables and the timer queue and initialises all state * variables * @@ -652,7 +651,7 @@ void AliasSctpInit(struct libalias *la) la->sctpLinkCount = 0; } -/** +/** * @brief Cleans-up the SCTP NAT Implementation prior to unloading * * Removes all entries from the timer queue, freeing associations as it goes. @@ -707,7 +706,7 @@ void AliasSctpTerm(struct libalias *la) * @param la Pointer to the relevant libalias instance * @param pip Pointer to IP packet to process * @param direction SN_TO_LOCAL | SN_TO_GLOBAL - * + * * @return PKT_ALIAS_OK | PKT_ALIAS_IGNORE | PKT_ALIAS_ERROR */ int @@ -719,10 +718,10 @@ SctpAlias(struct libalias *la, struct ip *pip, int direction) if ((direction != SN_TO_LOCAL) && (direction != SN_TO_GLOBAL)) { SctpAliasLog("ERROR: Invalid direction\n"); - return(PKT_ALIAS_ERROR); + return (PKT_ALIAS_ERROR); } - sctp_CheckTimers(la); /* Check timers */ + sctp_CheckTimers(la); /* Check timers */ /* Parse the packet */ rtnval = sctp_PktParser(la, direction, pip, &msg, &assoc); //using *char (change to mbuf when get code from paolo) @@ -737,24 +736,24 @@ SctpAlias(struct libalias *la, struct ip *pip, int direction) } SN_LOG(SN_LOG_EVENT, logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction)); - return(PKT_ALIAS_ERROR); + return (PKT_ALIAS_ERROR); case SN_PARSE_ERROR_PARTIALLOOKUP: if (sysctl_error_on_ootb > SN_LOCALandPARTIAL_ERROR_ON_OOTB) { SN_LOG(SN_LOG_EVENT, logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction)); - return(PKT_ALIAS_ERROR); + return (PKT_ALIAS_ERROR); } case SN_PARSE_ERROR_LOOKUP: if (sysctl_error_on_ootb == SN_ERROR_ON_OOTB || (sysctl_error_on_ootb == SN_LOCALandPARTIAL_ERROR_ON_OOTB && direction == SN_TO_LOCAL) || (sysctl_error_on_ootb == SN_LOCAL_ERROR_ON_OOTB && direction == SN_TO_GLOBAL)) { TxAbortErrorM(la, &msg, assoc, SN_REFLECT_ERROR, direction); /*NB assoc=NULL */ - return(PKT_ALIAS_RESPOND); + return (PKT_ALIAS_RESPOND); } default: SN_LOG(SN_LOG_EVENT, logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction)); - return(PKT_ALIAS_ERROR); + return (PKT_ALIAS_ERROR); } SN_LOG(SN_LOG_DETAIL, @@ -772,9 +771,9 @@ SctpAlias(struct libalias *la, struct ip *pip, int direction) ); SN_LOG(SN_LOG_DEBUG, logTimerQ(la)); - switch(rtnval){ + switch (rtnval) { case SN_NAT_PKT: - switch(direction) { + switch (direction) { case SN_TO_LOCAL: DifferentialChecksum(&(msg.ip_hdr->ip_sum), &(assoc->l_addr), &(msg.ip_hdr->ip_dst), 2); @@ -796,7 +795,7 @@ SctpAlias(struct libalias *la, struct ip *pip, int direction) break; case SN_REPLY_ABORT: case SN_REPLY_ERROR: - case SN_SEND_ABORT: + case SN_SEND_ABORT: TxAbortErrorM(la, &msg, assoc, rtnval, direction); break; default: @@ -816,22 +815,22 @@ SctpAlias(struct libalias *la, struct ip *pip, int direction) freeGlobalAddressList(assoc); sn_free(assoc); } - switch(rtnval) { + switch (rtnval) { case SN_NAT_PKT: - return(PKT_ALIAS_OK); + return (PKT_ALIAS_OK); case SN_SEND_ABORT: - return(PKT_ALIAS_OK); + return (PKT_ALIAS_OK); case SN_REPLY_ABORT: case SN_REPLY_ERROR: case SN_REFLECT_ERROR: - return(PKT_ALIAS_RESPOND); + return (PKT_ALIAS_RESPOND); case SN_DROP_PKT: default: - return(PKT_ALIAS_ERROR); + return (PKT_ALIAS_ERROR); } } -/** +/** * @brief Send an AbortM or ErrorM * * We construct the new SCTP packet to send in place of the existing packet we @@ -867,7 +866,7 @@ SctpAlias(struct libalias *la, struct ip *pip, int direction) static uint32_t local_sctp_finalize_crc32(uint32_t crc32c) { - /* This routine is duplicated from SCTP + /* This routine is duplicated from SCTP * we need to do that since it MAY be that SCTP * is NOT compiled into the kernel. The CRC32C routines * however are always available in libkern. @@ -926,7 +925,7 @@ TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm, struct sctp_nat_asso ip->ip_hl = 5; /* 5*32 bit words */ ip->ip_tos = 0; ip->ip_len = htons(ip_size); - ip->ip_id = sm->ip_hdr->ip_id; + ip->ip_id = sm->ip_hdr->ip_id; ip->ip_off = 0; ip->ip_ttl = 255; ip->ip_p = IPPROTO_SCTP; @@ -939,7 +938,7 @@ TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm, struct sctp_nat_asso chunk_hdr->chunk_type = (sndrply & SN_TX_ABORT) ? SCTP_ABORT_ASSOCIATION : SCTP_OPERATION_ERROR; chunk_hdr->chunk_flags = SCTP_MIDDLEBOX_FLAG; if (include_error_cause) { - error_cause->code = htons((sndrply & SN_REFLECT_ERROR) ? SCTP_MISSING_NAT : SCTP_NAT_TABLE_COLLISION); + error_cause->code = htons((sndrply & SN_REFLECT_ERROR) ? SCTP_MISSING_NAT : SCTP_NAT_TABLE_COLLISION); error_cause->length = htons(sizeof(struct sctp_error_cause)); chunk_hdr->chunk_length = htons(sizeof(*chunk_hdr) + sizeof(struct sctp_error_cause)); } else { @@ -947,22 +946,22 @@ TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm, struct sctp_nat_asso } /* set specific values */ - switch(sndrply) { + switch (sndrply) { case SN_REFLECT_ERROR: chunk_hdr->chunk_flags |= SCTP_HAD_NO_TCB; /* set Tbit */ - sctp_hdr->v_tag = sm->sctp_hdr->v_tag; + sctp_hdr->v_tag = sm->sctp_hdr->v_tag; break; case SN_REPLY_ERROR: - sctp_hdr->v_tag = (direction == SN_TO_LOCAL) ? assoc->g_vtag : assoc->l_vtag ; + sctp_hdr->v_tag = (direction == SN_TO_LOCAL) ? assoc->g_vtag : assoc->l_vtag ; break; case SN_SEND_ABORT: - sctp_hdr->v_tag = sm->sctp_hdr->v_tag; + sctp_hdr->v_tag = sm->sctp_hdr->v_tag; break; case SN_REPLY_ABORT: sctp_hdr->v_tag = sm->sctpchnk.Init->initiate_tag; break; } - + /* Set send/reply values */ if (sndrply == SN_SEND_ABORT) { /*pass through NAT */ ip->ip_src = (direction == SN_TO_LOCAL) ? sm->ip_hdr->ip_src : assoc->a_addr; @@ -975,10 +974,10 @@ TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm, struct sctp_nat_asso sctp_hdr->src_port = sm->sctp_hdr->dest_port; sctp_hdr->dest_port = sm->sctp_hdr->src_port; } - + /* Calculate IP header checksum */ ip->ip_sum = in_cksum_hdr(ip); - + /* calculate SCTP header CRC32 */ sctp_hdr->checksum = 0; sctp_hdr->checksum = local_sctp_finalize_crc32(calculate_crc32c(0xffffffff, (unsigned char *) sctp_hdr, sctp_size)); @@ -1005,18 +1004,18 @@ TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm, struct sctp_nat_asso */ /** @ingroup packet_parser * @brief Parses SCTP packets for the key SCTP chunk that will be processed - * + * * This module parses SCTP packets for the key SCTP chunk that will be processed * The module completes the sctp_nat_msg structure and either retrieves the * relevant (existing) stored association from the Hash Tables or creates a new * association entity with state SN_ID * * @param la Pointer to the relevant libalias instance - * @param direction SN_TO_LOCAL | SN_TO_GLOBAL - * @param pip + * @param direction SN_TO_LOCAL | SN_TO_GLOBAL + * @param pip * @param sm Pointer to sctp message information * @param passoc Pointer to the association this SCTP Message belongs to - * + * * @return SN_PARSE_OK | SN_PARSE_ERROR_* */ static int @@ -1051,26 +1050,26 @@ sctp_PktParser(struct libalias *la, int direction, struct ip *pip, /* Check SCTP header length and move to first chunk */ if (bytes_left < sizeof(struct sctphdr)) { sm->sctp_hdr = NULL; - return(SN_PARSE_ERROR_IPSHL); /* packet not long enough*/ + return (SN_PARSE_ERROR_IPSHL); /* packet not long enough*/ } sm->sctp_hdr = sctp_hdr = (struct sctphdr *) ip_next(pip); bytes_left -= sizeof(struct sctphdr); - + /* Check for valid ports (zero valued ports would find partially initialised associations */ if (sctp_hdr->src_port == 0 || sctp_hdr->dest_port == 0) - return(SN_PARSE_ERROR_PORT); + return (SN_PARSE_ERROR_PORT); /* Check length of first chunk */ if (bytes_left < SN_MIN_CHUNK_SIZE) /* malformed chunk - could cause endless loop*/ - return(SN_PARSE_ERROR_CHHL); /* packet not long enough for this chunk */ - + return (SN_PARSE_ERROR_CHHL); /* packet not long enough for this chunk */ + /* First chunk */ chunk_hdr = SN_SCTP_FIRSTCHUNK(sctp_hdr); - + chunk_length = SCTP_SIZE32(ntohs(chunk_hdr->chunk_length)); if ((chunk_length < SN_MIN_CHUNK_SIZE) || (chunk_length > bytes_left)) /* malformed chunk - could cause endless loop*/ - return(SN_PARSE_ERROR_CHHL); + return (SN_PARSE_ERROR_CHHL); if ((chunk_hdr->chunk_flags & SCTP_HAD_NO_TCB) && ((chunk_hdr->chunk_type == SCTP_ABORT_ASSOCIATION) || @@ -1093,43 +1092,43 @@ sctp_PktParser(struct libalias *la, int direction, struct ip *pip, sm->msg = SN_SCTP_OTHER;/* Initialise to largest value*/ sm->chunk_length = 0; /* only care about length for key chunks */ while (IS_SCTP_CONTROL(chunk_hdr)) { - switch(chunk_hdr->chunk_type) { + switch (chunk_hdr->chunk_type) { case SCTP_INITIATION: if (chunk_length < sizeof(struct sctp_init_chunk)) /* malformed chunk*/ - return(SN_PARSE_ERROR_CHHL); + return (SN_PARSE_ERROR_CHHL); sm->msg = SN_SCTP_INIT; sm->sctpchnk.Init = (struct sctp_init *) ((char *) chunk_hdr + sizeof(struct sctp_chunkhdr)); sm->chunk_length = chunk_length; /* if no existing association, create a new one */ if (*passoc == NULL) { - if (sctp_hdr->v_tag == 0){ //Init requires vtag=0 + if (sctp_hdr->v_tag == 0) { //Init requires vtag=0 *passoc = (struct sctp_nat_assoc *) sn_malloc(sizeof(struct sctp_nat_assoc)); - if (*passoc == NULL) {/* out of resources */ - return(SN_PARSE_ERROR_AS_MALLOC); + if (*passoc == NULL) {/* out of resources */ + return (SN_PARSE_ERROR_AS_MALLOC); } - /* Initialise association - malloc initialises memory to zeros */ + /* Initialize association - sn_malloc initializes memory to zeros */ (*passoc)->state = SN_ID; LIST_INIT(&((*passoc)->Gaddr)); /* always initialise to avoid memory problems */ (*passoc)->TableRegister = SN_NULL_TBL; - return(SN_PARSE_OK); + return (SN_PARSE_OK); } - return(SN_PARSE_ERROR_VTAG); + return (SN_PARSE_ERROR_VTAG); } - return(SN_PARSE_ERROR_LOOKUP); + return (SN_PARSE_ERROR_LOOKUP); case SCTP_INITIATION_ACK: if (chunk_length < sizeof(struct sctp_init_ack_chunk)) /* malformed chunk*/ - return(SN_PARSE_ERROR_CHHL); + return (SN_PARSE_ERROR_CHHL); sm->msg = SN_SCTP_INITACK; sm->sctpchnk.InitAck = (struct sctp_init_ack *) ((char *) chunk_hdr + sizeof(struct sctp_chunkhdr)); sm->chunk_length = chunk_length; - return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP):(SN_PARSE_OK)); + return ((*passoc == NULL) ? (SN_PARSE_ERROR_LOOKUP) : (SN_PARSE_OK)); case SCTP_ABORT_ASSOCIATION: /* access only minimum sized chunk */ sm->msg = SN_SCTP_ABORT; sm->chunk_length = chunk_length; - return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP_ABORT):(SN_PARSE_OK)); + return ((*passoc == NULL) ? (SN_PARSE_ERROR_LOOKUP_ABORT) : (SN_PARSE_OK)); case SCTP_SHUTDOWN_ACK: if (chunk_length < sizeof(struct sctp_shutdown_ack_chunk)) /* malformed chunk*/ - return(SN_PARSE_ERROR_CHHL); + return (SN_PARSE_ERROR_CHHL); if (sm->msg > SN_SCTP_SHUTACK) { sm->msg = SN_SCTP_SHUTACK; sm->chunk_length = chunk_length; @@ -1140,11 +1139,11 @@ sctp_PktParser(struct libalias *la, int direction, struct ip *pip, sm->msg = SN_SCTP_SHUTCOMP; sm->chunk_length = chunk_length; } - return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP):(SN_PARSE_OK)); + return ((*passoc == NULL) ? (SN_PARSE_ERROR_LOOKUP) : (SN_PARSE_OK)); case SCTP_ASCONF: if (sm->msg > SN_SCTP_ASCONF) { if (chunk_length < (sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv4addr_param))) /* malformed chunk*/ - return(SN_PARSE_ERROR_CHHL); + return (SN_PARSE_ERROR_CHHL); //leave parameter searching to later, if required param_hdr = (struct sctp_paramhdr *) ((char *) chunk_hdr + sizeof(struct sctp_asconf_chunk)); /*compulsory IP parameter*/ if (ntohs(param_hdr->param_type) == SCTP_IPV4_ADDRESS) { @@ -1153,38 +1152,38 @@ sctp_PktParser(struct libalias *la, int direction, struct ip *pip, ipv4addr.s_addr = ((struct sctp_ipv4addr_param *) param_hdr)->addr; *passoc = FindSctpGlobal(la, ipv4addr, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port, &partial_match); } - param_hdr = (struct sctp_paramhdr *) + param_hdr = (struct sctp_paramhdr *) ((char *) param_hdr + sizeof(struct sctp_ipv4addr_param)); /*asconf's compulsory address parameter */ sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_chunk) - sizeof(struct sctp_ipv4addr_param); /* rest of chunk */ } else { if (chunk_length < (sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv6addr_param))) /* malformed chunk*/ - return(SN_PARSE_ERROR_CHHL); - param_hdr = (struct sctp_paramhdr *) - ((char *) param_hdr + sizeof(struct sctp_ipv6addr_param)); /*asconf's compulsory address parameter */ + return (SN_PARSE_ERROR_CHHL); + param_hdr = (struct sctp_paramhdr *) + ((char *) param_hdr + sizeof(struct sctp_ipv6addr_param)); /*asconf's compulsory address parameter */ sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_chunk) - sizeof(struct sctp_ipv6addr_param); /* rest of chunk */ } sm->msg = SN_SCTP_ASCONF; sm->sctpchnk.Asconf = param_hdr; - + if (*passoc == NULL) { /* AddIP with no association */ *passoc = (struct sctp_nat_assoc *) sn_malloc(sizeof(struct sctp_nat_assoc)); - if (*passoc == NULL) {/* out of resources */ - return(SN_PARSE_ERROR_AS_MALLOC); + if (*passoc == NULL) {/* out of resources */ + return (SN_PARSE_ERROR_AS_MALLOC); } - /* Initialise association - malloc initialises memory to zeros */ + /* Initialize association - sn_malloc initializes memory to zeros */ (*passoc)->state = SN_ID; LIST_INIT(&((*passoc)->Gaddr)); /* always initialise to avoid memory problems */ (*passoc)->TableRegister = SN_NULL_TBL; - return(SN_PARSE_OK); + return (SN_PARSE_OK); } } break; case SCTP_ASCONF_ACK: if (sm->msg > SN_SCTP_ASCONFACK) { if (chunk_length < sizeof(struct sctp_asconf_ack_chunk)) /* malformed chunk*/ - return(SN_PARSE_ERROR_CHHL); + return (SN_PARSE_ERROR_CHHL); //leave parameter searching to later, if required - param_hdr = (struct sctp_paramhdr *) ((char *) chunk_hdr + param_hdr = (struct sctp_paramhdr *) ((char *) chunk_hdr + sizeof(struct sctp_asconf_ack_chunk)); sm->msg = SN_SCTP_ASCONFACK; sm->sctpchnk.Asconf = param_hdr; @@ -1197,33 +1196,33 @@ sctp_PktParser(struct libalias *la, int direction, struct ip *pip, /* if no association is found exit - we need to find an Init or AddIP within sysctl_initialising_chunk_proc_limit */ if ((*passoc == NULL) && (chunk_count >= sysctl_initialising_chunk_proc_limit)) - return(SN_PARSE_ERROR_LOOKUP); + return (SN_PARSE_ERROR_LOOKUP); /* finished with this chunk, on to the next chunk*/ bytes_left-= chunk_length; /* Is this the end of the packet ? */ if (bytes_left == 0) - return (*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP):(SN_PARSE_OK); + return (*passoc == NULL) ? (SN_PARSE_ERROR_LOOKUP) : (SN_PARSE_OK); /* Are there enough bytes in packet to at least retrieve length of next chunk ? */ if (bytes_left < SN_MIN_CHUNK_SIZE) - return(SN_PARSE_ERROR_CHHL); + return (SN_PARSE_ERROR_CHHL); chunk_hdr = SN_SCTP_NEXTCHUNK(chunk_hdr); /* Is the chunk long enough to not cause endless look and are there enough bytes in packet to read the chunk ? */ chunk_length = SCTP_SIZE32(ntohs(chunk_hdr->chunk_length)); if ((chunk_length < SN_MIN_CHUNK_SIZE) || (chunk_length > bytes_left)) - return(SN_PARSE_ERROR_CHHL); - if(++chunk_count > sysctl_chunk_proc_limit) - return(SN_PARSE_OK); /* limit for processing chunks, take what we get */ + return (SN_PARSE_ERROR_CHHL); + if (++chunk_count > sysctl_chunk_proc_limit) + return (SN_PARSE_OK); /* limit for processing chunks, take what we get */ } if (*passoc == NULL) - return (partial_match)?(SN_PARSE_ERROR_PARTIALLOOKUP):(SN_PARSE_ERROR_LOOKUP); + return (partial_match) ? (SN_PARSE_ERROR_PARTIALLOOKUP) : (SN_PARSE_ERROR_LOOKUP); else - return(SN_PARSE_OK); + return (SN_PARSE_OK); } /** @ingroup packet_parser @@ -1231,7 +1230,7 @@ sctp_PktParser(struct libalias *la, int direction, struct ip *pip, * * GetAsconfVtags scans an Asconf Chunk for the vtags parameter, and then * extracts the vtags. - * + * * GetAsconfVtags is not called from within sctp_PktParser. It is called only * from within ID_process when an AddIP has been received. * @@ -1239,9 +1238,9 @@ sctp_PktParser(struct libalias *la, int direction, struct ip *pip, * @param sm Pointer to sctp message information * @param l_vtag Pointer to the local vtag in the association this SCTP Message belongs to * @param g_vtag Pointer to the local vtag in the association this SCTP Message belongs to - * @param direction SN_TO_LOCAL | SN_TO_GLOBAL - * - * @return 1 - success | 0 - fail + * @param direction SN_TO_LOCAL | SN_TO_GLOBAL + * + * @return 1 - success | 0 - fail */ static int GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm, uint32_t *l_vtag, uint32_t *g_vtag, int direction) @@ -1253,7 +1252,7 @@ GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm, uint32_t *l_vtag, u uint32_t local_vtag; uint32_t remote_vtag; } __attribute__((packed)); - + struct sctp_vtag_param *vtag_param; struct sctp_paramhdr *param; int bytes_left; @@ -1268,7 +1267,7 @@ GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm, uint32_t *l_vtag, u while((bytes_left >= param_size) && (bytes_left >= SN_VTAG_PARAM_SIZE)) { if (ntohs(param->param_type) == SCTP_VTAG_PARAM) { vtag_param = (struct sctp_vtag_param *) param; - switch(direction) { + switch (direction) { /* The Internet draft is a little ambigious as to order of these vtags. We think it is this way around. If we are wrong, the order will need to be changed. */ @@ -1281,11 +1280,11 @@ GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm, uint32_t *l_vtag, u *l_vtag = vtag_param->local_vtag; break; } - return(1); /* found */ + return (1); /* found */ } bytes_left -= param_size; - if (bytes_left < SN_MIN_PARAM_SIZE) return(0); + if (bytes_left < SN_MIN_PARAM_SIZE) return (0); param = SN_SCTP_NEXTPARAM(param); param_size = SCTP_SIZE32(ntohs(param->param_length)); @@ -1293,22 +1292,22 @@ GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm, uint32_t *l_vtag, u SN_LOG(SN_LOG_EVENT, logsctperror("Parameter parse limit exceeded (GetAsconfVtags)", sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction)); - return(0); /* not found limit exceeded*/ + return (0); /* not found limit exceeded*/ } } - return(0); /* not found */ + return (0); /* not found */ } /** @ingroup packet_parser * @brief AddGlobalIPAddresses from Init,InitAck,or AddIP packets - * + * * AddGlobalIPAddresses scans an SCTP chunk (in sm) for Global IP addresses, and * adds them. * * @param sm Pointer to sctp message information * @param assoc Pointer to the association this SCTP Message belongs to - * @param direction SN_TO_LOCAL | SN_TO_GLOBAL - * + * @param direction SN_TO_LOCAL | SN_TO_GLOBAL + * */ static void AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction) @@ -1321,7 +1320,7 @@ AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int int param_size; int param_count, addr_param_count = 0; - switch(direction) { + switch (direction) { case SN_TO_GLOBAL: /* does not contain global addresses */ g_addr = sm->ip_hdr->ip_dst; bytes_left = 0; /* force exit */ @@ -1329,7 +1328,7 @@ AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int case SN_TO_LOCAL: g_addr = sm->ip_hdr->ip_src; param_count = 1; - switch(sm->msg) { + switch (sm->msg) { case SN_SCTP_INIT: bytes_left = sm->chunk_length - sizeof(struct sctp_init_chunk); param = (struct sctp_paramhdr *)((char *)sm->sctpchnk.Init + sizeof(struct sctp_init)); @@ -1344,16 +1343,16 @@ AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int break; } } - if (bytes_left >= SN_MIN_PARAM_SIZE) + if (bytes_left >= SN_MIN_PARAM_SIZE) param_size = SCTP_SIZE32(ntohs(param->param_length)); else param_size = bytes_left+1; /* force skip loop */ - - if ((assoc->state == SN_ID) && ((sm->msg == SN_SCTP_INIT) || (bytes_left < SN_MIN_PARAM_SIZE))) {/* add pkt address */ + + if ((assoc->state == SN_ID) && ((sm->msg == SN_SCTP_INIT) || (bytes_left < SN_MIN_PARAM_SIZE))) {/* add pkt address */ G_Addr = (struct sctp_GlobalAddress *) sn_malloc(sizeof(struct sctp_GlobalAddress)); - if (G_Addr == NULL) {/* out of resources */ + if (G_Addr == NULL) {/* out of resources */ SN_LOG(SN_LOG_EVENT, - logsctperror("AddGlobalIPAddress: No resources for adding global address - revert to no tracking", + logsctperror("AddGlobalIPAddress: No resources for adding global address - revert to no tracking", sm->sctp_hdr->v_tag, 0, direction)); assoc->num_Gaddr = 0; /* don't track any more for this assoc*/ sysctl_track_global_addresses=0; @@ -1362,7 +1361,7 @@ AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int G_Addr->g_addr = g_addr; if (!Add_Global_Address_to_List(assoc, G_Addr)) SN_LOG(SN_LOG_EVENT, - logsctperror("AddGlobalIPAddress: Address already in list", + logsctperror("AddGlobalIPAddress: Address already in list", sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction)); } @@ -1370,21 +1369,22 @@ AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int while((bytes_left >= param_size) && (bytes_left >= sizeof(struct sctp_ipv4addr_param))) { if (assoc->num_Gaddr >= sysctl_track_global_addresses) { SN_LOG(SN_LOG_EVENT, - logsctperror("AddGlobalIPAddress: Maximum Number of addresses reached", + logsctperror("AddGlobalIPAddress: Maximum Number of addresses reached", sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction)); return; } - switch(ntohs(param->param_type)) { + switch (ntohs(param->param_type)) { case SCTP_ADD_IP_ADDRESS: /* skip to address parameter - leave param_size so bytes left will be calculated properly*/ param = (struct sctp_paramhdr *) &((struct sctp_asconf_addrv4_param *) param)->addrp; + /* FALLTHROUGH */ case SCTP_IPV4_ADDRESS: ipv4_param = (struct sctp_ipv4addr_param *) param; /* add addresses to association */ G_Addr = (struct sctp_GlobalAddress *) sn_malloc(sizeof(struct sctp_GlobalAddress)); - if (G_Addr == NULL) {/* out of resources */ + if (G_Addr == NULL) {/* out of resources */ SN_LOG(SN_LOG_EVENT, - logsctperror("AddGlobalIPAddress: No resources for adding global address - revert to no tracking", + logsctperror("AddGlobalIPAddress: No resources for adding global address - revert to no tracking", sm->sctp_hdr->v_tag, 0, direction)); assoc->num_Gaddr = 0; /* don't track any more for this assoc*/ sysctl_track_global_addresses=0; @@ -1396,22 +1396,22 @@ AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int G_Addr->g_addr = g_addr; if (!Add_Global_Address_to_List(assoc, G_Addr)) SN_LOG(SN_LOG_EVENT, - logsctperror("AddGlobalIPAddress: Address already in list", + logsctperror("AddGlobalIPAddress: Address already in list", sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction)); return; /*shouldn't be any other addresses if the zero address is given*/ } else { G_Addr->g_addr.s_addr = ipv4_param->addr; if (!Add_Global_Address_to_List(assoc, G_Addr)) SN_LOG(SN_LOG_EVENT, - logsctperror("AddGlobalIPAddress: Address already in list", + logsctperror("AddGlobalIPAddress: Address already in list", sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction)); } - } - + } + bytes_left -= param_size; if (bytes_left < SN_MIN_PARAM_SIZE) break; - + param = SN_SCTP_NEXTPARAM(param); param_size = SCTP_SIZE32(ntohs(param->param_length)); if (++param_count > sysctl_param_proc_limit) { @@ -1423,39 +1423,39 @@ AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int } if (addr_param_count == 0) { SN_LOG(SN_LOG_DETAIL, - logsctperror("AddGlobalIPAddress: no address parameters to add", + logsctperror("AddGlobalIPAddress: no address parameters to add", sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction)); } } -/** +/** * @brief Add_Global_Address_to_List * * Adds a global IP address to an associations address list, if it is not * already there. The first address added us usually the packet's address, and * is most likely to be used, so it is added at the beginning. Subsequent * addresses are added after this one. - * + * * @param assoc Pointer to the association this SCTP Message belongs to * @param G_addr Pointer to the global address to add * - * @return 1 - success | 0 - fail + * @return 1 - success | 0 - fail */ static int Add_Global_Address_to_List(struct sctp_nat_assoc *assoc, struct sctp_GlobalAddress *G_addr) { - struct sctp_GlobalAddress *iter_G_Addr = NULL, *first_G_Addr = NULL; - first_G_Addr = LIST_FIRST(&(assoc->Gaddr)); + struct sctp_GlobalAddress *iter_G_Addr = NULL, *first_G_Addr = NULL; + first_G_Addr = LIST_FIRST(&(assoc->Gaddr)); if (first_G_Addr == NULL) { LIST_INSERT_HEAD(&(assoc->Gaddr), G_addr, list_Gaddr); /* add new address to beginning of list*/ } else { LIST_FOREACH(iter_G_Addr, &(assoc->Gaddr), list_Gaddr) { if (G_addr->g_addr.s_addr == iter_G_Addr->g_addr.s_addr) - return(0); /* already exists, so don't add */ + return (0); /* already exists, so don't add */ } LIST_INSERT_AFTER(first_G_Addr, G_addr, list_Gaddr); /* add address to end of list*/ } - assoc->num_Gaddr++; - return(1); /* success */ + assoc->num_Gaddr++; + return (1); /* success */ } /** @ingroup packet_parser @@ -1468,8 +1468,8 @@ static int Add_Global_Address_to_List(struct sctp_nat_assoc *assoc, struct sct * * @param sm Pointer to sctp message information * @param assoc Pointer to the association this SCTP Message belongs to - * @param direction SN_TO_LOCAL | SN_TO_GLOBAL - * + * @param direction SN_TO_LOCAL | SN_TO_GLOBAL + * */ static void RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction) @@ -1482,7 +1482,7 @@ RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int d int param_size; int param_count; - if(direction == SN_TO_GLOBAL) + if (direction == SN_TO_GLOBAL) g_addr = sm->ip_hdr->ip_dst; else g_addr = sm->ip_hdr->ip_src; @@ -1490,29 +1490,29 @@ RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int d bytes_left = sm->chunk_length; param_count = 1; param = sm->sctpchnk.Asconf; - if (bytes_left >= SN_MIN_PARAM_SIZE) { + if (bytes_left >= SN_MIN_PARAM_SIZE) { param_size = SCTP_SIZE32(ntohs(param->param_length)); } else { SN_LOG(SN_LOG_EVENT, - logsctperror("RmGlobalIPAddress: truncated packet - cannot remove IP addresses", + logsctperror("RmGlobalIPAddress: truncated packet - cannot remove IP addresses", sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction)); return; } - + /* step through Asconf parameters */ while((bytes_left >= param_size) && (bytes_left >= sizeof(struct sctp_ipv4addr_param))) { if (ntohs(param->param_type) == SCTP_DEL_IP_ADDRESS) { asconf_ipv4_param = (struct sctp_asconf_addrv4_param *) param; if (asconf_ipv4_param->addrp.addr == INADDR_ANY) { /* remove all bar pkt address */ LIST_FOREACH_SAFE(G_Addr, &(assoc->Gaddr), list_Gaddr, G_Addr_tmp) { - if(G_Addr->g_addr.s_addr != sm->ip_hdr->ip_src.s_addr) { + if (G_Addr->g_addr.s_addr != sm->ip_hdr->ip_src.s_addr) { if (assoc->num_Gaddr > 1) { /* only delete if more than one */ LIST_REMOVE(G_Addr, list_Gaddr); sn_free(G_Addr); assoc->num_Gaddr--; } else { SN_LOG(SN_LOG_EVENT, - logsctperror("RmGlobalIPAddress: Request to remove last IP address (didn't)", + logsctperror("RmGlobalIPAddress: Request to remove last IP address (didn't)", sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction)); } } @@ -1520,7 +1520,7 @@ RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int d return; /*shouldn't be any other addresses if the zero address is given*/ } else { LIST_FOREACH_SAFE(G_Addr, &(assoc->Gaddr), list_Gaddr, G_Addr_tmp) { - if(G_Addr->g_addr.s_addr == asconf_ipv4_param->addrp.addr) { + if (G_Addr->g_addr.s_addr == asconf_ipv4_param->addrp.addr) { if (assoc->num_Gaddr > 1) { /* only delete if more than one */ LIST_REMOVE(G_Addr, list_Gaddr); sn_free(G_Addr); @@ -1528,22 +1528,22 @@ RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int d break; /* Since add only adds new addresses, there should be no double entries */ } else { SN_LOG(SN_LOG_EVENT, - logsctperror("RmGlobalIPAddress: Request to remove last IP address (didn't)", + logsctperror("RmGlobalIPAddress: Request to remove last IP address (didn't)", sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction)); } } } } - } + } bytes_left -= param_size; if (bytes_left == 0) return; else if (bytes_left < SN_MIN_PARAM_SIZE) { SN_LOG(SN_LOG_EVENT, - logsctperror("RmGlobalIPAddress: truncated packet - may not have removed all IP addresses", + logsctperror("RmGlobalIPAddress: truncated packet - may not have removed all IP addresses", sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction)); return; } - + param = SN_SCTP_NEXTPARAM(param); param_size = SCTP_SIZE32(ntohs(param->param_length)); if (++param_count > sysctl_param_proc_limit) { @@ -1570,11 +1570,11 @@ RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int d * Since there is currently no connection on this path, there should be no other * ASCONF configuration parameters outstanding, so we presume that if there is * an ACK that it is responding to the AddIP and activate the new association. - * + * * @param la Pointer to the relevant libalias instance * @param sm Pointer to sctp message information - * @param direction SN_TO_LOCAL | SN_TO_GLOBAL - * + * @param direction SN_TO_LOCAL | SN_TO_GLOBAL + * * @return 1 - success | 0 - fail */ static int @@ -1589,45 +1589,45 @@ IsASCONFack(struct libalias *la, struct sctp_nat_msg *sm, int direction) param = sm->sctpchnk.Asconf; param_size = SCTP_SIZE32(ntohs(param->param_length)); if (param_size == 8) - return(1); /*success - default acknowledgement of everything */ + return (1); /*success - default acknowledgement of everything */ bytes_left = sm->chunk_length; if (bytes_left < param_size) - return(0); /* not found */ + return (0); /* not found */ /* step through Asconf parameters */ while(bytes_left >= SN_ASCONFACK_PARAM_SIZE) { if (ntohs(param->param_type) == SCTP_SUCCESS_REPORT) - return(1); /* success - but can't match correlation IDs - should only be one */ + return (1); /* success - but can't match correlation IDs - should only be one */ /* check others just in case */ bytes_left -= param_size; if (bytes_left >= SN_MIN_PARAM_SIZE) { param = SN_SCTP_NEXTPARAM(param); } else { - return(0); + return (0); } param_size = SCTP_SIZE32(ntohs(param->param_length)); - if (bytes_left < param_size) return(0); + if (bytes_left < param_size) return (0); if (++param_count > sysctl_param_proc_limit) { SN_LOG(SN_LOG_EVENT, - logsctperror("Parameter parse limit exceeded (IsASCONFack)", + logsctperror("Parameter parse limit exceeded (IsASCONFack)", sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction)); - return(0); /* not found limit exceeded*/ + return (0); /* not found limit exceeded*/ } } - return(0); /* not success */ + return (0); /* not success */ } /** @ingroup packet_parser - * @brief Check to see if ASCONF contains an Add IP or Del IP parameter - * + * @brief Check to see if ASCONF contains an Add IP or Del IP parameter + * * IsADDorDEL scans an ASCONF packet to see if it contains an AddIP or DelIP * parameter * * @param la Pointer to the relevant libalias instance * @param sm Pointer to sctp message information - * @param direction SN_TO_LOCAL | SN_TO_GLOBAL - * + * @param direction SN_TO_LOCAL | SN_TO_GLOBAL + * * @return SCTP_ADD_IP_ADDRESS | SCTP_DEL_IP_ADDRESS | 0 - fail */ static int @@ -1644,31 +1644,31 @@ IsADDorDEL(struct libalias *la, struct sctp_nat_msg *sm, int direction) bytes_left = sm->chunk_length; if (bytes_left < param_size) - return(0); /* not found */ + return (0); /* not found */ /* step through Asconf parameters */ while(bytes_left >= SN_ASCONFACK_PARAM_SIZE) { if (ntohs(param->param_type) == SCTP_ADD_IP_ADDRESS) - return(SCTP_ADD_IP_ADDRESS); - else if (ntohs(param->param_type) == SCTP_DEL_IP_ADDRESS) - return(SCTP_DEL_IP_ADDRESS); + return (SCTP_ADD_IP_ADDRESS); + else if (ntohs(param->param_type) == SCTP_DEL_IP_ADDRESS) + return (SCTP_DEL_IP_ADDRESS); /* check others just in case */ bytes_left -= param_size; if (bytes_left >= SN_MIN_PARAM_SIZE) { param = SN_SCTP_NEXTPARAM(param); } else { - return(0); /*Neither found */ + return (0); /*Neither found */ } param_size = SCTP_SIZE32(ntohs(param->param_length)); - if (bytes_left < param_size) return(0); + if (bytes_left < param_size) return (0); if (++param_count > sysctl_param_proc_limit) { SN_LOG(SN_LOG_EVENT, - logsctperror("Parameter parse limit exceeded IsADDorDEL)", + logsctperror("Parameter parse limit exceeded IsADDorDEL)", sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction)); - return(0); /* not found limit exceeded*/ + return (0); /* not found limit exceeded*/ } } - return(0); /*Neither found */ + return (0); /*Neither found */ } /* ---------------------------------------------------------------------- @@ -1691,7 +1691,7 @@ IsADDorDEL(struct libalias *la, struct sctp_nat_msg *sm, int direction) * each state. * * @param la Pointer to the relevant libalias instance - * @param direction SN_TO_LOCAL | SN_TO_GLOBAL + * @param direction SN_TO_LOCAL | SN_TO_GLOBAL * @param sm Pointer to sctp message information * @param assoc Pointer to the association this SCTP Message belongs to * @@ -1708,17 +1708,17 @@ ProcessSctpMsg(struct libalias *la, int direction, struct sctp_nat_msg *sm, stru if (rtnval != SN_NAT_PKT) { assoc->state = SN_RM;/* Mark for removal*/ } - return(rtnval); + return (rtnval); case SN_INi: /* Initialising - Init */ - return(INi_process(la, direction, assoc, sm)); + return (INi_process(la, direction, assoc, sm)); case SN_INa: /* Initialising - AddIP */ - return(INa_process(la, direction, assoc, sm)); + return (INa_process(la, direction, assoc, sm)); case SN_UP: /* Association UP */ - return(UP_process(la, direction, assoc, sm)); + return (UP_process(la, direction, assoc, sm)); case SN_CL: /* Association Closing */ - return(CL_process(la, direction, assoc, sm)); + return (CL_process(la, direction, assoc, sm)); } - return(SN_PROCESSING_ERROR); + return (SN_PROCESSING_ERROR); } /** @ingroup state_machine @@ -1738,56 +1738,57 @@ ProcessSctpMsg(struct libalias *la, int direction, struct sctp_nat_msg *sm, stru static int ID_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm) { - switch(sm->msg) { + switch (sm->msg) { case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk with ADDIP */ if (!sysctl_accept_global_ootb_addip && (direction == SN_TO_LOCAL)) - return(SN_DROP_PKT); + return (SN_DROP_PKT); /* if this Asconf packet does not contain the Vtag parameters it is of no use in Idle state */ if (!GetAsconfVtags(la, sm, &(assoc->l_vtag), &(assoc->g_vtag), direction)) - return(SN_DROP_PKT); + return (SN_DROP_PKT); + /* FALLTHROUGH */ case SN_SCTP_INIT: /* a packet containing an INIT chunk or an ASCONF AddIP */ if (sysctl_track_global_addresses) AddGlobalIPAddresses(sm, assoc, direction); - switch(direction){ + switch (direction) { case SN_TO_GLOBAL: assoc->l_addr = sm->ip_hdr->ip_src; assoc->a_addr = FindAliasAddress(la, assoc->l_addr); assoc->l_port = sm->sctp_hdr->src_port; assoc->g_port = sm->sctp_hdr->dest_port; - if(sm->msg == SN_SCTP_INIT) + if (sm->msg == SN_SCTP_INIT) assoc->g_vtag = sm->sctpchnk.Init->initiate_tag; if (AddSctpAssocGlobal(la, assoc)) /* DB clash *///**** need to add dst address - return((sm->msg == SN_SCTP_INIT) ? SN_REPLY_ABORT : SN_REPLY_ERROR); - if(sm->msg == SN_SCTP_ASCONF) { + return ((sm->msg == SN_SCTP_INIT) ? SN_REPLY_ABORT : SN_REPLY_ERROR); + if (sm->msg == SN_SCTP_ASCONF) { if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_dst)) /* DB clash */ - return(SN_REPLY_ERROR); + return (SN_REPLY_ERROR); assoc->TableRegister |= SN_WAIT_TOLOCAL; /* wait for tolocal ack */ } break; case SN_TO_LOCAL: assoc->l_addr = FindSctpRedirectAddress(la, sm); - assoc->a_addr = sm->ip_hdr->ip_dst; + assoc->a_addr = sm->ip_hdr->ip_dst; assoc->l_port = sm->sctp_hdr->dest_port; assoc->g_port = sm->sctp_hdr->src_port; - if(sm->msg == SN_SCTP_INIT) + if (sm->msg == SN_SCTP_INIT) assoc->l_vtag = sm->sctpchnk.Init->initiate_tag; if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_src)) /* DB clash */ - return((sm->msg == SN_SCTP_INIT) ? SN_REPLY_ABORT : SN_REPLY_ERROR); - if(sm->msg == SN_SCTP_ASCONF) { + return ((sm->msg == SN_SCTP_INIT) ? SN_REPLY_ABORT : SN_REPLY_ERROR); + if (sm->msg == SN_SCTP_ASCONF) { if (AddSctpAssocGlobal(la, assoc)) /* DB clash */ //**** need to add src address - return(SN_REPLY_ERROR); + return (SN_REPLY_ERROR); assoc->TableRegister |= SN_WAIT_TOGLOBAL; /* wait for toglobal ack */ } break; } - assoc->state = (sm->msg == SN_SCTP_INIT) ? SN_INi : SN_INa; - assoc->exp = SN_I_T(la); - sctp_AddTimeOut(la,assoc); - return(SN_NAT_PKT); + assoc->state = (sm->msg == SN_SCTP_INIT) ? SN_INi : SN_INa; + assoc->exp = SN_I_T(la); + sctp_AddTimeOut(la,assoc); + return (SN_NAT_PKT); default: /* Any other type of SCTP message is not valid in Idle */ - return(SN_DROP_PKT); + return (SN_DROP_PKT); } -return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */ + return (SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */ } /** @ingroup state_machine @@ -1795,30 +1796,30 @@ return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the b * * Only an INIT-ACK, resent INIT, or an ABORT SCTP packet are valid in this * state, all other packets are dropped. - * + * * @param la Pointer to the relevant libalias instance - * @param direction SN_TO_LOCAL | SN_TO_GLOBAL + * @param direction SN_TO_LOCAL | SN_TO_GLOBAL * @param sm Pointer to sctp message information * @param assoc Pointer to the association this SCTP Message belongs to - * - * @return SN_NAT_PKT | SN_DROP_PKT | SN_REPLY_ABORT + * + * @return SN_NAT_PKT | SN_DROP_PKT | SN_REPLY_ABORT */ static int INi_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm) { - switch(sm->msg) { + switch (sm->msg) { case SN_SCTP_INIT: /* a packet containing a retransmitted INIT chunk */ sctp_ResetTimeOut(la, assoc, SN_I_T(la)); - return(SN_NAT_PKT); + return (SN_NAT_PKT); case SN_SCTP_INITACK: /* a packet containing an INIT-ACK chunk */ - switch(direction){ + switch (direction) { case SN_TO_LOCAL: if (assoc->num_Gaddr) /*If tracking global addresses for this association */ AddGlobalIPAddresses(sm, assoc, direction); assoc->l_vtag = sm->sctpchnk.Init->initiate_tag; if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_src)) { /* DB clash */ assoc->state = SN_RM;/* Mark for removal*/ - return(SN_SEND_ABORT); + return (SN_SEND_ABORT); } break; case SN_TO_GLOBAL: @@ -1826,97 +1827,97 @@ INi_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, st assoc->g_vtag = sm->sctpchnk.Init->initiate_tag; if (AddSctpAssocGlobal(la, assoc)) { /* DB clash */ assoc->state = SN_RM;/* Mark for removal*/ - return(SN_SEND_ABORT); + return (SN_SEND_ABORT); } break; } assoc->state = SN_UP;/* association established for NAT */ sctp_ResetTimeOut(la,assoc, SN_U_T(la)); - return(SN_NAT_PKT); + return (SN_NAT_PKT); case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */ assoc->state = SN_RM;/* Mark for removal*/ - return(SN_NAT_PKT); + return (SN_NAT_PKT); default: - return(SN_DROP_PKT); + return (SN_DROP_PKT); } - return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */ + return (SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */ } /** @ingroup state_machine * @brief Process SCTP message while waiting for an AddIp-ACK message - * + * * Only an AddIP-ACK, resent AddIP, or an ABORT message are valid, all other * SCTP packets are dropped * * @param la Pointer to the relevant libalias instance - * @param direction SN_TO_LOCAL | SN_TO_GLOBAL + * @param direction SN_TO_LOCAL | SN_TO_GLOBAL * @param sm Pointer to sctp message information * @param assoc Pointer to the association this SCTP Message belongs to - * - * @return SN_NAT_PKT | SN_DROP_PKT + * + * @return SN_NAT_PKT | SN_DROP_PKT */ static int INa_process(struct libalias *la, int direction,struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm) { - switch(sm->msg) { + switch (sm->msg) { case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk*/ sctp_ResetTimeOut(la,assoc, SN_I_T(la)); - return(SN_NAT_PKT); + return (SN_NAT_PKT); case SN_SCTP_ASCONFACK: /* a packet containing an ASCONF chunk with a ADDIP-ACK */ - switch(direction){ + switch (direction) { case SN_TO_LOCAL: if (!(assoc->TableRegister & SN_WAIT_TOLOCAL)) /* wrong direction */ - return(SN_DROP_PKT); + return (SN_DROP_PKT); break; case SN_TO_GLOBAL: if (!(assoc->TableRegister & SN_WAIT_TOGLOBAL)) /* wrong direction */ - return(SN_DROP_PKT); + return (SN_DROP_PKT); } if (IsASCONFack(la,sm,direction)) { assoc->TableRegister &= SN_BOTH_TBL; /* remove wait flags */ assoc->state = SN_UP; /* association established for NAT */ sctp_ResetTimeOut(la,assoc, SN_U_T(la)); - return(SN_NAT_PKT); + return (SN_NAT_PKT); } else { assoc->state = SN_RM;/* Mark for removal*/ - return(SN_NAT_PKT); + return (SN_NAT_PKT); } case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */ assoc->state = SN_RM;/* Mark for removal*/ - return(SN_NAT_PKT); + return (SN_NAT_PKT); default: - return(SN_DROP_PKT); + return (SN_DROP_PKT); } - return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */ + return (SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */ } /** @ingroup state_machine * @brief Process SCTP messages while association is UP redirecting packets - * + * * While in the SN_UP state, all packets for the particular association * are passed. Only a SHUT-ACK or an ABORT will cause a change of state. * * @param la Pointer to the relevant libalias instance - * @param direction SN_TO_LOCAL | SN_TO_GLOBAL + * @param direction SN_TO_LOCAL | SN_TO_GLOBAL * @param sm Pointer to sctp message information * @param assoc Pointer to the association this SCTP Message belongs to - * - * @return SN_NAT_PKT | SN_DROP_PKT + * + * @return SN_NAT_PKT | SN_DROP_PKT */ static int UP_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm) { - switch(sm->msg) { + switch (sm->msg) { case SN_SCTP_SHUTACK: /* a packet containing a SHUTDOWN-ACK chunk */ assoc->state = SN_CL; sctp_ResetTimeOut(la,assoc, SN_C_T(la)); - return(SN_NAT_PKT); + return (SN_NAT_PKT); case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */ assoc->state = SN_RM;/* Mark for removal*/ - return(SN_NAT_PKT); + return (SN_NAT_PKT); case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk*/ if ((direction == SN_TO_LOCAL) && assoc->num_Gaddr) /*If tracking global addresses for this association & from global side */ - switch(IsADDorDEL(la,sm,direction)) { + switch (IsADDorDEL(la,sm,direction)) { case SCTP_ADD_IP_ADDRESS: AddGlobalIPAddresses(sm, assoc, direction); break; @@ -1926,9 +1927,9 @@ UP_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, str } /* fall through to default */ default: sctp_ResetTimeOut(la,assoc, SN_U_T(la)); - return(SN_NAT_PKT); /* forward packet */ + return (SN_NAT_PKT); /* forward packet */ } - return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */ + return (SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */ } /** @ingroup state_machine @@ -1940,34 +1941,34 @@ UP_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, str * ABORT packets are permitted in this state. All other packets are dropped. * * @param la Pointer to the relevant libalias instance - * @param direction SN_TO_LOCAL | SN_TO_GLOBAL + * @param direction SN_TO_LOCAL | SN_TO_GLOBAL * @param sm Pointer to sctp message information * @param assoc Pointer to the association this SCTP Message belongs to - * - * @return SN_NAT_PKT | SN_DROP_PKT + * + * @return SN_NAT_PKT | SN_DROP_PKT */ static int CL_process(struct libalias *la, int direction,struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm) { - switch(sm->msg) { + switch (sm->msg) { case SN_SCTP_SHUTCOMP: /* a packet containing a SHUTDOWN-COMPLETE chunk */ assoc->state = SN_CL; /* Stay in Close state until timeout */ if (sysctl_holddown_timer > 0) sctp_ResetTimeOut(la, assoc, SN_X_T(la));/* allow to stay open for Tbit packets*/ else assoc->state = SN_RM;/* Mark for removal*/ - return(SN_NAT_PKT); + return (SN_NAT_PKT); case SN_SCTP_SHUTACK: /* a packet containing a SHUTDOWN-ACK chunk */ assoc->state = SN_CL; /* Stay in Close state until timeout */ sctp_ResetTimeOut(la, assoc, SN_C_T(la)); - return(SN_NAT_PKT); + return (SN_NAT_PKT); case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */ assoc->state = SN_RM;/* Mark for removal*/ - return(SN_NAT_PKT); + return (SN_NAT_PKT); default: - return(SN_DROP_PKT); + return (SN_DROP_PKT); } - return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */ + return (SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */ } /* ---------------------------------------------------------------------- @@ -1981,7 +1982,7 @@ CL_process(struct libalias *la, int direction,struct sctp_nat_assoc *assoc, stru */ /** @ingroup Hash * @brief Find the SCTP association given the local address, port and vtag - * + * * Searches the local look-up table for the association entry matching the * provided local <address:ports:vtag> tuple * @@ -1991,7 +1992,7 @@ CL_process(struct libalias *la, int direction,struct sctp_nat_assoc *assoc, stru * @param l_vtag local Vtag * @param l_port local Port * @param g_port global Port - * + * * @return pointer to association or NULL */ static struct sctp_nat_assoc* @@ -2000,7 +2001,7 @@ FindSctpLocal(struct libalias *la, struct in_addr l_addr, struct in_addr g_addr, u_int i; struct sctp_nat_assoc *assoc = NULL; struct sctp_GlobalAddress *G_Addr = NULL; - + if (l_vtag != 0) { /* an init packet, vtag==0 */ i = SN_TABLE_HASH(l_vtag, l_port, la->sctpNatTableSize); LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) { @@ -2008,27 +2009,27 @@ FindSctpLocal(struct libalias *la, struct in_addr l_addr, struct in_addr g_addr, && (assoc->l_addr.s_addr == l_addr.s_addr)) { if (assoc->num_Gaddr) { LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) { - if(G_Addr->g_addr.s_addr == g_addr.s_addr) - return(assoc); + if (G_Addr->g_addr.s_addr == g_addr.s_addr) + return (assoc); } } else { - return(assoc); + return (assoc); } } } } - return(NULL); + return (NULL); } /** @ingroup Hash * @brief Check for Global Clash - * + * * Searches the global look-up table for the association entry matching the * provided global <(addresses):ports:vtag> tuple * * @param la Pointer to the relevant libalias instance * @param Cassoc association being checked for a clash - * + * * @return pointer to association or NULL */ static struct sctp_nat_assoc* @@ -2038,7 +2039,7 @@ FindSctpGlobalClash(struct libalias *la, struct sctp_nat_assoc *Cassoc) struct sctp_nat_assoc *assoc = NULL; struct sctp_GlobalAddress *G_Addr = NULL; struct sctp_GlobalAddress *G_AddrC = NULL; - + if (Cassoc->g_vtag != 0) { /* an init packet, vtag==0 */ i = SN_TABLE_HASH(Cassoc->g_vtag, Cassoc->g_port, la->sctpNatTableSize); LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) { @@ -2046,22 +2047,22 @@ FindSctpGlobalClash(struct libalias *la, struct sctp_nat_assoc *Cassoc) if (assoc->num_Gaddr) { LIST_FOREACH(G_AddrC, &(Cassoc->Gaddr), list_Gaddr) { LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) { - if(G_Addr->g_addr.s_addr == G_AddrC->g_addr.s_addr) - return(assoc); + if (G_Addr->g_addr.s_addr == G_AddrC->g_addr.s_addr) + return (assoc); } } } else { - return(assoc); + return (assoc); } } } } - return(NULL); + return (NULL); } /** @ingroup Hash * @brief Find the SCTP association given the global port and vtag - * + * * Searches the global look-up table for the association entry matching the * provided global <address:ports:vtag> tuple * @@ -2075,7 +2076,7 @@ FindSctpGlobalClash(struct libalias *la, struct sctp_nat_assoc *Cassoc) * @param g_vtag global vtag * @param g_port global port * @param l_port local port - * + * * @return pointer to association or NULL */ static struct sctp_nat_assoc* @@ -2084,7 +2085,7 @@ FindSctpGlobal(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint u_int i; struct sctp_nat_assoc *assoc = NULL; struct sctp_GlobalAddress *G_Addr = NULL; - + *partial_match = 0; if (g_vtag != 0) { /* an init packet, vtag==0 */ i = SN_TABLE_HASH(g_vtag, g_port, la->sctpNatTableSize); @@ -2093,21 +2094,21 @@ FindSctpGlobal(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint *partial_match = 1; if (assoc->num_Gaddr) { LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) { - if(G_Addr->g_addr.s_addr == g_addr.s_addr) - return(assoc); + if (G_Addr->g_addr.s_addr == g_addr.s_addr) + return (assoc); } } else { - return(assoc); + return (assoc); } } } } - return(NULL); + return (NULL); } /** @ingroup Hash * @brief Find the SCTP association for a T-Flag message (given the global port and local vtag) - * + * * Searches the local look-up table for a unique association entry matching the * provided global port and local vtag information * @@ -2116,40 +2117,40 @@ FindSctpGlobal(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint * @param l_vtag local Vtag * @param g_port global Port * @param l_port local Port - * + * * @return pointer to association or NULL */ static struct sctp_nat_assoc* -FindSctpLocalT(struct libalias *la, struct in_addr g_addr, uint32_t l_vtag, uint16_t g_port, uint16_t l_port) +FindSctpLocalT(struct libalias *la, struct in_addr g_addr, uint32_t l_vtag, uint16_t g_port, uint16_t l_port) { u_int i; struct sctp_nat_assoc *assoc = NULL, *lastmatch = NULL; struct sctp_GlobalAddress *G_Addr = NULL; int cnt = 0; - + if (l_vtag != 0) { /* an init packet, vtag==0 */ i = SN_TABLE_HASH(l_vtag, g_port, la->sctpNatTableSize); LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) { if ((assoc->g_vtag == l_vtag) && (assoc->g_port == g_port) && (assoc->l_port == l_port)) { if (assoc->num_Gaddr) { LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) { - if(G_Addr->g_addr.s_addr == G_Addr->g_addr.s_addr) - return(assoc); /* full match */ + if (G_Addr->g_addr.s_addr == g_addr.s_addr) + return (assoc); /* full match */ } } else { - if (++cnt > 1) return(NULL); + if (++cnt > 1) return (NULL); lastmatch = assoc; } } } } /* If there is more than one match we do not know which local address to send to */ - return( cnt ? lastmatch : NULL ); + return (cnt ? lastmatch : NULL); } /** @ingroup Hash * @brief Find the SCTP association for a T-Flag message (given the local port and global vtag) - * + * * Searches the global look-up table for a unique association entry matching the * provided local port and global vtag information * @@ -2158,7 +2159,7 @@ FindSctpLocalT(struct libalias *la, struct in_addr g_addr, uint32_t l_vtag, uin * @param g_vtag global vtag * @param l_port local port * @param g_port global port - * + * * @return pointer to association or NULL */ static struct sctp_nat_assoc* @@ -2167,28 +2168,28 @@ FindSctpGlobalT(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uin u_int i; struct sctp_nat_assoc *assoc = NULL; struct sctp_GlobalAddress *G_Addr = NULL; - + if (g_vtag != 0) { /* an init packet, vtag==0 */ i = SN_TABLE_HASH(g_vtag, l_port, la->sctpNatTableSize); LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) { if ((assoc->l_vtag == g_vtag) && (assoc->l_port == l_port) && (assoc->g_port == g_port)) { if (assoc->num_Gaddr) { LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) { - if(G_Addr->g_addr.s_addr == g_addr.s_addr) - return(assoc); + if (G_Addr->g_addr.s_addr == g_addr.s_addr) + return (assoc); } } else { - return(assoc); + return (assoc); } } } } - return(NULL); + return (NULL); } /** @ingroup Hash * @brief Add the sctp association information to the local look up table - * + * * Searches the local look-up table for an existing association with the same * details. If a match exists and is ONLY in the local look-up table then this * is a repeated INIT packet, we need to remove this association from the @@ -2199,7 +2200,7 @@ FindSctpGlobalT(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uin * @param la Pointer to the relevant libalias instance * @param assoc pointer to sctp association * @param g_addr global address - * + * * @return SN_ADD_OK | SN_ADD_CLASH */ static int @@ -2225,9 +2226,9 @@ AddSctpAssocLocal(struct libalias *la, struct sctp_nat_assoc *assoc, struct in_a freeGlobalAddressList(found); sn_free(found); } else - return(SN_ADD_CLASH); + return (SN_ADD_CLASH); } - + LIST_INSERT_HEAD(&la->sctpTableLocal[SN_TABLE_HASH(assoc->l_vtag, assoc->l_port, la->sctpNatTableSize)], assoc, list_L); assoc->TableRegister |= SN_LOCAL_TBL; @@ -2241,7 +2242,7 @@ AddSctpAssocLocal(struct libalias *la, struct sctp_nat_assoc *assoc, struct in_a SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "^")); } - return(SN_ADD_OK); + return (SN_ADD_OK); } /** @ingroup Hash @@ -2274,9 +2275,9 @@ AddSctpAssocGlobal(struct libalias *la, struct sctp_nat_assoc *assoc) freeGlobalAddressList(found); sn_free(found); } else - return(SN_ADD_CLASH); + return (SN_ADD_CLASH); } - + LIST_INSERT_HEAD(&la->sctpTableGlobal[SN_TABLE_HASH(assoc->g_vtag, assoc->g_port, la->sctpNatTableSize)], assoc, list_G); assoc->TableRegister |= SN_GLOBAL_TBL; @@ -2290,12 +2291,12 @@ AddSctpAssocGlobal(struct libalias *la, struct sctp_nat_assoc *assoc) SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "^")); } - return(SN_ADD_OK); + return (SN_ADD_OK); } /** @ingroup Hash * @brief Remove the sctp association information from the look up table - * + * * For each of the two (local/global) look-up tables, remove the association * from that table IF it has been registered in that table. * @@ -2327,7 +2328,7 @@ RmSctpAssoc(struct libalias *la, struct sctp_nat_assoc *assoc) la->sctpLinkCount--; //decrement link count LIST_REMOVE(assoc, list_L); } - + if (assoc->TableRegister & SN_GLOBAL_TBL) { assoc->TableRegister ^= SN_GLOBAL_TBL; la->sctpLinkCount--; //decrement link count @@ -2339,20 +2340,20 @@ RmSctpAssoc(struct libalias *la, struct sctp_nat_assoc *assoc) SctpShowAliasStats(la); } -/** +/** * @ingroup Hash * @brief free the Global Address List memory - * + * * freeGlobalAddressList deletes all global IP addresses in an associations * global IP address list. * - * @param assoc + * @param assoc */ static void freeGlobalAddressList(struct sctp_nat_assoc *assoc) { struct sctp_GlobalAddress *gaddr1=NULL,*gaddr2=NULL; /*free global address list*/ - gaddr1 = LIST_FIRST(&(assoc->Gaddr)); + gaddr1 = LIST_FIRST(&(assoc->Gaddr)); while (gaddr1 != NULL) { gaddr2 = LIST_NEXT(gaddr1, list_Gaddr); sn_free(gaddr1); @@ -2383,8 +2384,8 @@ static void freeGlobalAddressList(struct sctp_nat_assoc *assoc) * Determine the location in the queue to add the timeout and insert the * association into the list at that queue position * - * @param la - * @param assoc + * @param la + * @param assoc */ static void sctp_AddTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc) @@ -2440,7 +2441,7 @@ sctp_ResetTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc, int newexp) /** @ingroup Timer * @brief Check timer Q against current time - * + * * Loop through each entry in the timer queue since the last time we processed * the timer queue until now (the current time). For each association in the * event list, we remove it from that position in the timer queue and check if @@ -2451,22 +2452,22 @@ sctp_ResetTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc, int newexp) * * If the timer hasn't really expired we place the association into its new * correct position in the timer queue. - * + * * @param la Pointer to the relevant libalias instance */ void sctp_CheckTimers(struct libalias *la) { struct sctp_nat_assoc *assoc; - + LIBALIAS_LOCK_ASSERT(la); while(la->timeStamp >= la->sctpNatTimer.loc_time) { - while (!LIST_EMPTY(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc])) { + while (!LIST_EMPTY(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc])) { assoc = LIST_FIRST(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc]); //SLIST_REMOVE_HEAD(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc], timer_Q); LIST_REMOVE(assoc, timer_Q); if (la->timeStamp >= assoc->exp) { /* state expired */ - SN_LOG(((assoc->state == SN_CL)?(SN_LOG_DEBUG):(SN_LOG_INFO)), + SN_LOG(((assoc->state == SN_CL) ? (SN_LOG_DEBUG) : (SN_LOG_INFO)), logsctperror("Timer Expired", assoc->g_vtag, assoc->state, SN_TO_NODIR)); RmSctpAssoc(la, assoc); freeGlobalAddressList(assoc); @@ -2483,7 +2484,7 @@ sctp_CheckTimers(struct libalias *la) } /* ---------------------------------------------------------------------- - * LOGGING CODE + * LOGGING CODE * ---------------------------------------------------------------------- */ /** @addtogroup Logging @@ -2494,7 +2495,7 @@ sctp_CheckTimers(struct libalias *la) */ /** @ingroup Logging * @brief Log sctp nat errors - * + * * @param errormsg Error message to be logged * @param vtag Current Vtag * @param error Error number @@ -2504,7 +2505,7 @@ static void logsctperror(char* errormsg, uint32_t vtag, int error, int direction) { char dir; - switch(direction) { + switch (direction) { case SN_TO_LOCAL: dir = 'L'; break; @@ -2520,7 +2521,7 @@ logsctperror(char* errormsg, uint32_t vtag, int error, int direction) /** @ingroup Logging * @brief Log what the parser parsed - * + * * @param direction Direction of packet * @param sm Pointer to sctp message information */ @@ -2528,7 +2529,7 @@ static void logsctpparse(int direction, struct sctp_nat_msg *sm) { char *ploc, *pstate; - switch(direction) { + switch (direction) { case SN_TO_LOCAL: ploc = "TO_LOCAL -"; break; @@ -2538,7 +2539,7 @@ logsctpparse(int direction, struct sctp_nat_msg *sm) default: ploc = ""; } - switch(sm->msg) { + switch (sm->msg) { case SN_SCTP_INIT: pstate = "Init"; break; @@ -2572,7 +2573,7 @@ logsctpparse(int direction, struct sctp_nat_msg *sm) /** @ingroup Logging * @brief Log an SCTP association's details - * + * * @param assoc pointer to sctp association * @param s Character that indicates the state of processing for this packet */ @@ -2582,7 +2583,7 @@ static void logsctpassoc(struct sctp_nat_assoc *assoc, char* s) char *sp; char addrbuf[INET_ADDRSTRLEN]; - switch(assoc->state) { + switch (assoc->state) { case SN_ID: sp = "ID "; break; @@ -2618,15 +2619,15 @@ static void logsctpassoc(struct sctp_nat_assoc *assoc, char* s) } /** @ingroup Logging - * @brief Output Global table to log - * + * @brief Output Global table to log + * * @param la Pointer to the relevant libalias instance */ static void logSctpGlobal(struct libalias *la) { u_int i; struct sctp_nat_assoc *assoc = NULL; - + SctpAliasLog("G->\n"); for (i=0; i < la->sctpNatTableSize; i++) { LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) { @@ -2636,15 +2637,15 @@ static void logSctpGlobal(struct libalias *la) } /** @ingroup Logging - * @brief Output Local table to log - * + * @brief Output Local table to log + * * @param la Pointer to the relevant libalias instance */ static void logSctpLocal(struct libalias *la) { u_int i; struct sctp_nat_assoc *assoc = NULL; - + SctpAliasLog("L->\n"); for (i=0; i < la->sctpNatTableSize; i++) { LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) { @@ -2655,7 +2656,7 @@ static void logSctpLocal(struct libalias *la) /** @ingroup Logging * @brief Output timer queue to log - * + * * @param la Pointer to the relevant libalias instance */ static void logTimerQ(struct libalias *la) @@ -2674,12 +2675,12 @@ static void logTimerQ(struct libalias *la) } } -/** @ingroup Logging +/** @ingroup Logging * @brief Sctp NAT logging function - * + * * This function is based on a similar function in alias_db.c * - * @param str/stream logging descriptor + * @param str/stream logging descriptor * @param format printf type string */ #ifdef _KERNEL diff --git a/freebsd/sys/netinet/sctp_constants.h b/freebsd/sys/netinet/sctp_constants.h index 94378799..018cd282 100644 --- a/freebsd/sys/netinet/sctp_constants.h +++ b/freebsd/sys/netinet/sctp_constants.h @@ -400,43 +400,34 @@ __FBSDID("$FreeBSD$"); #define SCTP_HOSTNAME_ADDRESS 0x000b #define SCTP_SUPPORTED_ADDRTYPE 0x000c -/* draft-ietf-stewart-tsvwg-strreset-xxx */ +/* RFC 6525 */ #define SCTP_STR_RESET_OUT_REQUEST 0x000d #define SCTP_STR_RESET_IN_REQUEST 0x000e #define SCTP_STR_RESET_TSN_REQUEST 0x000f #define SCTP_STR_RESET_RESPONSE 0x0010 #define SCTP_STR_RESET_ADD_OUT_STREAMS 0x0011 -#define SCTP_STR_RESET_ADD_IN_STREAMS 0x0012 +#define SCTP_STR_RESET_ADD_IN_STREAMS 0x0012 #define SCTP_MAX_RESET_PARAMS 2 -#define SCTP_STREAM_RESET_TSN_DELTA 0x1000 +#define SCTP_STREAM_RESET_TSN_DELTA 0x1000 /*************0x4000 series*************/ /*************0x8000 series*************/ #define SCTP_ECN_CAPABLE 0x8000 -/* draft-ietf-tsvwg-auth-xxx */ +/* RFC 4895 */ #define SCTP_RANDOM 0x8002 #define SCTP_CHUNK_LIST 0x8003 #define SCTP_HMAC_LIST 0x8004 -/* - * draft-ietf-tsvwg-addip-sctp-xx param=0x8008 len=0xNNNN Byte | Byte | Byte - * | Byte Byte | Byte ... - * - * Where each byte is a chunk type extension supported. For example, to support - * all chunks one would have (in hex): - * - * 80 01 00 09 C0 C1 80 81 82 00 00 00 - * - * Has the parameter. C0 = PR-SCTP (RFC3758) C1, 80 = ASCONF (addip draft) 81 - * = Packet Drop 82 = Stream Reset 83 = Authentication - */ -#define SCTP_SUPPORTED_CHUNK_EXT 0x8008 +/* RFC 4820 */ +#define SCTP_PAD 0x8005 +/* RFC 5061 */ +#define SCTP_SUPPORTED_CHUNK_EXT 0x8008 /*************0xC000 series*************/ #define SCTP_PRSCTP_SUPPORTED 0xc000 -/* draft-ietf-tsvwg-addip-sctp */ +/* RFC 5061 */ #define SCTP_ADD_IP_ADDRESS 0xc001 #define SCTP_DEL_IP_ADDRESS 0xc002 #define SCTP_ERROR_CAUSE_IND 0xc003 @@ -444,8 +435,8 @@ __FBSDID("$FreeBSD$"); #define SCTP_SUCCESS_REPORT 0xc005 #define SCTP_ULP_ADAPTATION 0xc006 /* behave-nat-draft */ -#define SCTP_HAS_NAT_SUPPORT 0xc007 -#define SCTP_NAT_VTAGS 0xc008 +#define SCTP_HAS_NAT_SUPPORT 0xc007 +#define SCTP_NAT_VTAGS 0xc008 /* bits for TOS field */ #define SCTP_ECT0_BIT 0x02 @@ -624,7 +615,7 @@ __FBSDID("$FreeBSD$"); #define SCTP_RTO_INITIAL (3000) /* 3 sec in ms */ -#define SCTP_INP_KILL_TIMEOUT 20/* number of ms to retry kill of inpcb */ +#define SCTP_INP_KILL_TIMEOUT 20 /* number of ms to retry kill of inpcb */ #define SCTP_ASOC_KILL_TIMEOUT 10 /* number of ms to retry kill of inpcb */ #define SCTP_DEF_MAX_INIT 8 diff --git a/freebsd/sys/netinet/sctp_crc32.c b/freebsd/sys/netinet/sctp_crc32.c index 82e361e1..e22abeb6 100644 --- a/freebsd/sys/netinet/sctp_crc32.c +++ b/freebsd/sys/netinet/sctp_crc32.c @@ -37,30 +37,36 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <rtems/bsd/local/opt_sctp.h> + +#ifdef SCTP #include <netinet/sctp_os.h> #include <netinet/sctp.h> #include <netinet/sctp_crc32.h> #include <netinet/sctp_pcb.h> +#else +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> - -#if !defined(SCTP_WITH_NO_CSUM) +#include <netinet/sctp_crc32.h> +#endif static uint32_t sctp_finalize_crc32c(uint32_t crc32c) { uint32_t result; - #if BYTE_ORDER == BIG_ENDIAN uint8_t byte0, byte1, byte2, byte3; - #endif + /* Complement the result */ result = ~crc32c; #if BYTE_ORDER == BIG_ENDIAN /* - * For BIG-ENDIAN.. aka Motorola byte order the result is in - * little-endian form. So we must manually swap the bytes. Then we - * can call htonl() which does nothing... + * For BIG-ENDIAN platforms the result is in little-endian form. So + * we must swap the bytes to return the result in network byte + * order. */ byte0 = result & 0x000000ff; byte1 = (result >> 8) & 0x000000ff; @@ -69,65 +75,57 @@ sctp_finalize_crc32c(uint32_t crc32c) crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); #else /* - * For INTEL platforms the result comes out in network order. No - * htonl is required or the swap above. So we optimize out both the - * htonl and the manual swap above. + * For LITTLE ENDIAN platforms the result is in already in network + * byte order. */ crc32c = result; #endif return (crc32c); } +/* + * Compute the SCTP checksum in network byte order for a given mbuf chain m + * which contains an SCTP packet starting at offset. + * Since this function is also called by ipfw, don't assume that + * it is compiled on a kernel with SCTP support. + */ uint32_t sctp_calculate_cksum(struct mbuf *m, uint32_t offset) { - /* - * given a mbuf chain with a packetheader offset by 'offset' - * pointing at a sctphdr (with csum set to 0) go through the chain - * of SCTP_BUF_NEXT()'s and calculate the SCTP checksum. This also - * has a side bonus as it will calculate the total length of the - * mbuf chain. Note: if offset is greater than the total mbuf - * length, checksum=1, pktlen=0 is returned (ie. no real error code) - */ uint32_t base = 0xffffffff; - struct mbuf *at; - at = m; - /* find the correct mbuf and offset into mbuf */ - while ((at != NULL) && (offset > (uint32_t)SCTP_BUF_LEN(at))) { - offset -= SCTP_BUF_LEN(at); /* update remaining offset - * left */ - at = SCTP_BUF_NEXT(at); - } - while (at != NULL) { - if ((SCTP_BUF_LEN(at) - offset) > 0) { - base = calculate_crc32c(base, - (unsigned char *)(SCTP_BUF_AT(at, offset)), - (unsigned int)(SCTP_BUF_LEN(at) - offset)); - } - if (offset) { - /* we only offset once into the first mbuf */ - if (offset < (uint32_t)SCTP_BUF_LEN(at)) - offset = 0; - else - offset -= SCTP_BUF_LEN(at); + while (offset > 0) { + KASSERT(m != NULL, ("sctp_calculate_cksum, offset > length of mbuf chain")); + if (offset < (uint32_t)m->m_len) { + break; } - at = SCTP_BUF_NEXT(at); + offset -= m->m_len; + m = m->m_next; + } + if (offset > 0) { + base = calculate_crc32c(base, + (unsigned char *)(m->m_data + offset), + (unsigned int)(m->m_len - offset)); + m = m->m_next; + } + while (m != NULL) { + base = calculate_crc32c(base, + (unsigned char *)m->m_data, + (unsigned int)m->m_len); + m = m->m_next; } base = sctp_finalize_crc32c(base); return (base); } -#endif /* !defined(SCTP_WITH_NO_CSUM) */ - +#ifdef SCTP +/* + * Compute and insert the SCTP checksum in network byte order for a given + * mbuf chain m which contains an SCTP packet starting at offset. + */ void sctp_delayed_cksum(struct mbuf *m, uint32_t offset) { -#if defined(SCTP_WITH_NO_CSUM) -#ifdef INVARIANTS - panic("sctp_delayed_cksum() called when using no SCTP CRC."); -#endif -#else uint32_t checksum; checksum = sctp_calculate_cksum(m, offset); @@ -136,15 +134,15 @@ sctp_delayed_cksum(struct mbuf *m, uint32_t offset) offset += offsetof(struct sctphdr, checksum); if (offset + sizeof(uint32_t) > (uint32_t)(m->m_len)) { - SCTP_PRINTF("sctp_delayed_cksum(): m->len: %d, off: %d.\n", - (uint32_t)m->m_len, offset); - /* - * XXX this shouldn't happen, but if it does, the correct - * behavior may be to insert the checksum in the appropriate - * next mbuf in the chain. - */ +#ifdef INVARIANTS + panic("sctp_delayed_cksum(): m->m_len: %d, offset: %u.", + m->m_len, offset); +#else + SCTP_PRINTF("sctp_delayed_cksum(): m->m_len: %d, offset: %u.\n", + m->m_len, offset); +#endif return; } *(uint32_t *)(m->m_data + offset) = checksum; -#endif } +#endif diff --git a/freebsd/sys/netinet/sctp_crc32.h b/freebsd/sys/netinet/sctp_crc32.h index adc38afc..4bdf8265 100644 --- a/freebsd/sys/netinet/sctp_crc32.h +++ b/freebsd/sys/netinet/sctp_crc32.h @@ -39,9 +39,9 @@ __FBSDID("$FreeBSD$"); #define _NETINET_SCTP_CRC32_H_ #if defined(_KERNEL) -#if !defined(SCTP_WITH_NO_CSUM) uint32_t sctp_calculate_cksum(struct mbuf *, uint32_t); -#endif +#ifdef SCTP void sctp_delayed_cksum(struct mbuf *, uint32_t offset); +#endif #endif /* _KERNEL */ #endif /* __crc32c_h__ */ diff --git a/freebsd/sys/netinet/sctp_indata.c b/freebsd/sys/netinet/sctp_indata.c index c4522a39..3325dd03 100644 --- a/freebsd/sys/netinet/sctp_indata.c +++ b/freebsd/sys/netinet/sctp_indata.c @@ -3366,7 +3366,8 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, } } } - if (SCTP_TSN_GT(tp1->rec.data.tsn, asoc->this_sack_highest_gap)) { + if (SCTP_TSN_GT(tp1->rec.data.tsn, asoc->this_sack_highest_gap) && + !(accum_moved && asoc->fast_retran_loss_recovery)) { /* we are beyond the tsn in the sack */ break; } @@ -3390,8 +3391,10 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, * FR using this SACK. */ continue; - } else if (tp1->whoTo && SCTP_TSN_GT(tp1->rec.data.tsn, - tp1->whoTo->this_sack_highest_newack)) { + } else if (tp1->whoTo && + SCTP_TSN_GT(tp1->rec.data.tsn, + tp1->whoTo->this_sack_highest_newack) && + !(accum_moved && asoc->fast_retran_loss_recovery)) { /* * CMT: New acks were receieved for data sent to * this dest. But no new acks were seen for data @@ -3676,7 +3679,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, tp1->whoTo->find_pseudo_cumack = 1; tp1->whoTo->find_rtx_pseudo_cumack = 1; } - } else {/* CMT is OFF */ + } else { /* CMT is OFF */ #ifdef SCTP_FR_TO_ALTERNATE /* Can we find an alternate? */ @@ -4605,6 +4608,13 @@ hopeless_peer: if (stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack) { (*stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack) (stcb, net); } + /* + * CMT: SFR algo (and HTNA) - this_sack_highest_newack has + * to be greater than the cumack. Also reset saw_newack to 0 + * for all dests. + */ + net->saw_newack = 0; + net->this_sack_highest_newack = last_tsn; } /* process the new consecutive TSN first */ TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { @@ -4732,16 +4742,6 @@ hopeless_peer: if ((num_seg > 0) || (num_nr_seg > 0)) { /* - * CMT: SFR algo (and HTNA) - this_sack_highest_newack has - * to be greater than the cumack. Also reset saw_newack to 0 - * for all dests. - */ - TAILQ_FOREACH(net, &asoc->nets, sctp_next) { - net->saw_newack = 0; - net->this_sack_highest_newack = last_tsn; - } - - /* * thisSackHighestGap will increase while handling NEW * segments this_sack_highest_newack will increase while * handling NEWLY ACKED chunks. this_sack_lowest_newack is diff --git a/freebsd/sys/netinet/sctp_input.c b/freebsd/sys/netinet/sctp_input.c index 9c552ff5..9a74ef4b 100644 --- a/freebsd/sys/netinet/sctp_input.c +++ b/freebsd/sys/netinet/sctp_input.c @@ -3209,9 +3209,9 @@ sctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb, struct sct stcb->asoc.ecn_echo_cnt_onq--; TAILQ_REMOVE(&stcb->asoc.control_send_queue, chk, sctp_next); + stcb->asoc.ctrl_queue_cnt--; sctp_m_freem(chk->data); chk->data = NULL; - stcb->asoc.ctrl_queue_cnt--; sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); if (override == 0) { break; @@ -3643,26 +3643,23 @@ static void sctp_clean_up_stream_reset(struct sctp_tcb *stcb) { struct sctp_association *asoc; - struct sctp_tmit_chunk *chk = stcb->asoc.str_reset; + struct sctp_tmit_chunk *chk; - if (stcb->asoc.str_reset == NULL) { + asoc = &stcb->asoc; + chk = asoc->str_reset; + if (chk == NULL) { return; } - asoc = &stcb->asoc; - + asoc->str_reset = NULL; sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_28); - TAILQ_REMOVE(&asoc->control_send_queue, - chk, - sctp_next); + TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next); + asoc->ctrl_queue_cnt--; if (chk->data) { sctp_m_freem(chk->data); chk->data = NULL; } - asoc->ctrl_queue_cnt--; sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); - /* sa_ignore NO_NULL_CHK */ - stcb->asoc.str_reset = NULL; } @@ -5509,9 +5506,7 @@ void sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int length, struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, struct sctp_chunkhdr *ch, -#if !defined(SCTP_WITH_NO_CSUM) uint8_t compute_crc, -#endif uint8_t ecn_bits, uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, uint32_t vrf_id, uint16_t port) @@ -5531,7 +5526,6 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt sctp_audit_log(0xE0, 1); sctp_auditing(0, inp, stcb, net); #endif -#if !defined(SCTP_WITH_NO_CSUM) if (compute_crc != 0) { uint32_t check, calc_check; @@ -5576,7 +5570,6 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt goto out; } } -#endif /* Destination port of 0 is illegal, based on RFC4960. */ if (sh->dest_port == 0) { SCTP_STAT_INCR(sctps_hdrops); @@ -5894,9 +5887,7 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port) struct sctphdr *sh; struct sctp_chunkhdr *ch; int length, offset; -#if !defined(SCTP_WITH_NO_CSUM) uint8_t compute_crc; -#endif uint32_t mflowid; uint8_t mflowtype; uint16_t fibnum; @@ -5966,9 +5957,6 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port) goto out; } ecn_bits = ip->ip_tos; -#if defined(SCTP_WITH_NO_CSUM) - SCTP_STAT_INCR(sctps_recvnocrc); -#else if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) { SCTP_STAT_INCR(sctps_recvhwcrc); compute_crc = 0; @@ -5976,14 +5964,11 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port) SCTP_STAT_INCR(sctps_recvswcrc); compute_crc = 1; } -#endif sctp_common_input_processing(&m, iphlen, offset, length, (struct sockaddr *)&src, (struct sockaddr *)&dst, sh, ch, -#if !defined(SCTP_WITH_NO_CSUM) compute_crc, -#endif ecn_bits, mflowtype, mflowid, fibnum, vrf_id, port); diff --git a/freebsd/sys/netinet/sctp_input.h b/freebsd/sys/netinet/sctp_input.h index ff0916e7..f393ad89 100644 --- a/freebsd/sys/netinet/sctp_input.h +++ b/freebsd/sys/netinet/sctp_input.h @@ -43,9 +43,7 @@ void sctp_common_input_processing(struct mbuf **, int, int, int, struct sockaddr *, struct sockaddr *, struct sctphdr *, struct sctp_chunkhdr *, -#if !defined(SCTP_WITH_NO_CSUM) uint8_t, -#endif uint8_t, uint8_t, uint32_t, uint16_t, uint32_t, uint16_t); diff --git a/freebsd/sys/netinet/sctp_output.c b/freebsd/sys/netinet/sctp_output.c index bc54ee96..9dd2e0fa 100644 --- a/freebsd/sys/netinet/sctp_output.c +++ b/freebsd/sys/netinet/sctp_output.c @@ -4228,23 +4228,15 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, } SCTP_ATTACH_CHAIN(o_pak, m, packet_length); if (port) { -#if defined(SCTP_WITH_NO_CSUM) - SCTP_STAT_INCR(sctps_sendnocrc); -#else sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip) + sizeof(struct udphdr)); SCTP_STAT_INCR(sctps_sendswcrc); -#endif if (V_udp_cksum) { SCTP_ENABLE_UDP_CSUM(o_pak); } } else { -#if defined(SCTP_WITH_NO_CSUM) - SCTP_STAT_INCR(sctps_sendnocrc); -#else m->m_pkthdr.csum_flags = CSUM_SCTP; m->m_pkthdr.csum_data = offsetof(struct sctphdr, checksum); SCTP_STAT_INCR(sctps_sendhwcrc); -#endif } #ifdef SCTP_PACKET_LOGGING if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) @@ -4568,23 +4560,15 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, } SCTP_ATTACH_CHAIN(o_pak, m, packet_length); if (port) { -#if defined(SCTP_WITH_NO_CSUM) - SCTP_STAT_INCR(sctps_sendnocrc); -#else sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip6_hdr) + sizeof(struct udphdr)); SCTP_STAT_INCR(sctps_sendswcrc); -#endif if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), packet_length - sizeof(struct ip6_hdr))) == 0) { udp->uh_sum = 0xffff; } } else { -#if defined(SCTP_WITH_NO_CSUM) - SCTP_STAT_INCR(sctps_sendnocrc); -#else m->m_pkthdr.csum_flags = CSUM_SCTP_IPV6; m->m_pkthdr.csum_data = offsetof(struct sctphdr, checksum); SCTP_STAT_INCR(sctps_sendhwcrc); -#endif } /* send it out. table id is taken from stcb */ #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) @@ -6916,11 +6900,11 @@ sctp_toss_old_cookies(struct sctp_tcb *stcb, struct sctp_association *asoc) TAILQ_FOREACH_SAFE(chk, &asoc->control_send_queue, sctp_next, nchk) { if (chk->rec.chunk_id.id == SCTP_COOKIE_ECHO) { TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next); + asoc->ctrl_queue_cnt--; if (chk->data) { sctp_m_freem(chk->data); chk->data = NULL; } - asoc->ctrl_queue_cnt--; sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); } } @@ -6945,11 +6929,11 @@ sctp_toss_old_asconf(struct sctp_tcb *stcb) } } TAILQ_REMOVE(&asoc->asconf_send_queue, chk, sctp_next); + asoc->ctrl_queue_cnt--; if (chk->data) { sctp_m_freem(chk->data); chk->data = NULL; } - asoc->ctrl_queue_cnt--; sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); } } @@ -7073,13 +7057,14 @@ sctp_clean_up_ctl(struct sctp_tcb *stcb, struct sctp_association *asoc, int so_l /* Stray chunks must be cleaned up */ clean_up_anyway: TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next); + asoc->ctrl_queue_cnt--; if (chk->data) { sctp_m_freem(chk->data); chk->data = NULL; } - asoc->ctrl_queue_cnt--; - if (chk->rec.chunk_id.id == SCTP_FORWARD_CUM_TSN) + if (chk->rec.chunk_id.id == SCTP_FORWARD_CUM_TSN) { asoc->fwd_tsn_cnt--; + } sctp_free_a_chunk(stcb, chk, so_locked); } else if (chk->rec.chunk_id.id == SCTP_STREAM_RESET) { /* special handling, we must look into the param */ @@ -11229,23 +11214,15 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, } ip->ip_len = htons(len); if (port) { -#if defined(SCTP_WITH_NO_CSUM) - SCTP_STAT_INCR(sctps_sendnocrc); -#else shout->checksum = sctp_calculate_cksum(mout, sizeof(struct ip) + sizeof(struct udphdr)); SCTP_STAT_INCR(sctps_sendswcrc); -#endif if (V_udp_cksum) { SCTP_ENABLE_UDP_CSUM(o_pak); } } else { -#if defined(SCTP_WITH_NO_CSUM) - SCTP_STAT_INCR(sctps_sendnocrc); -#else mout->m_pkthdr.csum_flags = CSUM_SCTP; mout->m_pkthdr.csum_data = offsetof(struct sctphdr, checksum); SCTP_STAT_INCR(sctps_sendhwcrc); -#endif } #ifdef SCTP_PACKET_LOGGING if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { @@ -11259,23 +11236,15 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, case AF_INET6: ip6->ip6_plen = (uint16_t)(len - sizeof(struct ip6_hdr)); if (port) { -#if defined(SCTP_WITH_NO_CSUM) - SCTP_STAT_INCR(sctps_sendnocrc); -#else shout->checksum = sctp_calculate_cksum(mout, sizeof(struct ip6_hdr) + sizeof(struct udphdr)); SCTP_STAT_INCR(sctps_sendswcrc); -#endif if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), len - sizeof(struct ip6_hdr))) == 0) { udp->uh_sum = 0xffff; } } else { -#if defined(SCTP_WITH_NO_CSUM) - SCTP_STAT_INCR(sctps_sendnocrc); -#else mout->m_pkthdr.csum_flags = CSUM_SCTP_IPV6; mout->m_pkthdr.csum_data = offsetof(struct sctphdr, checksum); SCTP_STAT_INCR(sctps_sendhwcrc); -#endif } #ifdef SCTP_PACKET_LOGGING if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { diff --git a/freebsd/sys/netinet/sctp_sysctl.c b/freebsd/sys/netinet/sctp_sysctl.c index 8259140f..f1a8d1d5 100644 --- a/freebsd/sys/netinet/sctp_sysctl.c +++ b/freebsd/sys/netinet/sctp_sysctl.c @@ -718,7 +718,6 @@ sctp_sysctl_handle_stats(SYSCTL_HANDLER_ARGS) sb.sctps_recvauthfailed += sarry->sctps_recvauthfailed; sb.sctps_recvexpress += sarry->sctps_recvexpress; sb.sctps_recvexpressm += sarry->sctps_recvexpressm; - sb.sctps_recvnocrc += sarry->sctps_recvnocrc; sb.sctps_recvswcrc += sarry->sctps_recvswcrc; sb.sctps_recvhwcrc += sarry->sctps_recvhwcrc; sb.sctps_sendpackets += sarry->sctps_sendpackets; @@ -731,7 +730,6 @@ sctp_sysctl_handle_stats(SYSCTL_HANDLER_ARGS) sb.sctps_sendecne += sarry->sctps_sendecne; sb.sctps_sendauth += sarry->sctps_sendauth; sb.sctps_senderrors += sarry->sctps_senderrors; - sb.sctps_sendnocrc += sarry->sctps_sendnocrc; sb.sctps_sendswcrc += sarry->sctps_sendswcrc; sb.sctps_sendhwcrc += sarry->sctps_sendhwcrc; sb.sctps_pdrpfmbox += sarry->sctps_pdrpfmbox; diff --git a/freebsd/sys/netinet/sctp_uio.h b/freebsd/sys/netinet/sctp_uio.h index 93274a70..8732219c 100644 --- a/freebsd/sys/netinet/sctp_uio.h +++ b/freebsd/sys/netinet/sctp_uio.h @@ -986,7 +986,7 @@ struct sctpstat { uint32_t sctps_recvexpress; /* total fast path receives all one * chunk */ uint32_t sctps_recvexpressm; /* total fast path multi-part data */ - uint32_t sctps_recvnocrc; + uint32_t sctps_recv_spare; /* formerly sctps_recvnocrc */ uint32_t sctps_recvswcrc; uint32_t sctps_recvhwcrc; @@ -1006,7 +1006,7 @@ struct sctpstat { uint32_t sctps_sendecne;/* total output ECNE chunks */ uint32_t sctps_sendauth;/* total output AUTH chunks FIXME */ uint32_t sctps_senderrors; /* ip_output error counter */ - uint32_t sctps_sendnocrc; + uint32_t sctps_send_spare; /* formerly sctps_sendnocrc */ uint32_t sctps_sendswcrc; uint32_t sctps_sendhwcrc; /* PCKDROPREP statistics: */ diff --git a/freebsd/sys/netinet/sctputil.c b/freebsd/sys/netinet/sctputil.c index 98c2a708..5511df64 100644 --- a/freebsd/sys/netinet/sctputil.c +++ b/freebsd/sys/netinet/sctputil.c @@ -49,7 +49,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_output.h> #include <netinet/sctp_uio.h> #include <netinet/sctp_timer.h> -#include <netinet/sctp_indata.h>/* for sctp_deliver_data() */ +#include <netinet/sctp_indata.h> #include <netinet/sctp_auth.h> #include <netinet/sctp_asconf.h> #include <netinet/sctp_bsd_addr.h> @@ -6096,7 +6096,7 @@ sctp_m_free(struct mbuf *m) return (m_free(m)); } -void +void sctp_m_freem(struct mbuf *mb) { while (mb != NULL) @@ -6166,6 +6166,7 @@ sctp_soreceive(struct socket *so, struct sockaddr *from; struct sctp_extrcvinfo sinfo; int filling_sinfo = 1; + int flags; struct sctp_inpcb *inp; inp = (struct sctp_inpcb *)so->so_pcb; @@ -6193,15 +6194,24 @@ sctp_soreceive(struct socket *so, if (filling_sinfo) { memset(&sinfo, 0, sizeof(struct sctp_extrcvinfo)); } - error = sctp_sorecvmsg(so, uio, mp0, from, fromlen, flagsp, + if (flagsp != NULL) { + flags = *flagsp; + } else { + flags = 0; + } + error = sctp_sorecvmsg(so, uio, mp0, from, fromlen, &flags, (struct sctp_sndrcvinfo *)&sinfo, filling_sinfo); + if (flagsp != NULL) { + *flagsp = flags; + } if (controlp != NULL) { /* copy back the sinfo in a CMSG format */ - if (filling_sinfo) + if (filling_sinfo && ((flags & MSG_NOTIFICATION) == 0)) { *controlp = sctp_build_ctl_nchunk(inp, (struct sctp_sndrcvinfo *)&sinfo); - else + } else { *controlp = NULL; + } } if (psa) { /* copy back the address info */ diff --git a/freebsd/sys/netinet/tcp_output.c b/freebsd/sys/netinet/tcp_output.c index 1cb622ac..d0f08e3a 100644 --- a/freebsd/sys/netinet/tcp_output.c +++ b/freebsd/sys/netinet/tcp_output.c @@ -200,7 +200,9 @@ tcp_output(struct tcpcb *tp) int off, flags, error = 0; /* Keep compiler happy */ struct mbuf *m; struct ip *ip = NULL; +#ifdef TCPDEBUG struct ipovly *ipov = NULL; +#endif struct tcphdr *th; u_char opt[TCP_MAXOLEN]; unsigned ipoptlen, optlen, hdrlen; @@ -489,59 +491,7 @@ after_sack_rexmit: /* len will be >= 0 after this point. */ KASSERT(len >= 0, ("[%s:%d]: len < 0", __func__, __LINE__)); - /* - * Automatic sizing of send socket buffer. Often the send buffer - * size is not optimally adjusted to the actual network conditions - * at hand (delay bandwidth product). Setting the buffer size too - * small limits throughput on links with high bandwidth and high - * delay (eg. trans-continental/oceanic links). Setting the - * buffer size too big consumes too much real kernel memory, - * especially with many connections on busy servers. - * - * The criteria to step up the send buffer one notch are: - * 1. receive window of remote host is larger than send buffer - * (with a fudge factor of 5/4th); - * 2. send buffer is filled to 7/8th with data (so we actually - * have data to make use of it); - * 3. send buffer fill has not hit maximal automatic size; - * 4. our send window (slow start and cogestion controlled) is - * larger than sent but unacknowledged data in send buffer. - * - * The remote host receive window scaling factor may limit the - * growing of the send buffer before it reaches its allowed - * maximum. - * - * It scales directly with slow start or congestion window - * and does at most one step per received ACK. This fast - * scaling has the drawback of growing the send buffer beyond - * what is strictly necessary to make full use of a given - * delay*bandwidth product. However testing has shown this not - * to be much of an problem. At worst we are trading wasting - * of available bandwidth (the non-use of it) for wasting some - * socket buffer memory. - * - * TODO: Shrink send buffer during idle periods together - * with congestion window. Requires another timer. Has to - * wait for upcoming tcp timer rewrite. - * - * XXXGL: should there be used sbused() or sbavail()? - */ - if (V_tcp_do_autosndbuf && so->so_snd.sb_flags & SB_AUTOSIZE) { - int lowat; - - lowat = V_tcp_sendbuf_auto_lowat ? so->so_snd.sb_lowat : 0; - if ((tp->snd_wnd / 4 * 5) >= so->so_snd.sb_hiwat - lowat && - sbused(&so->so_snd) >= - (so->so_snd.sb_hiwat / 8 * 7) - lowat && - sbused(&so->so_snd) < V_tcp_autosndbuf_max && - sendwin >= (sbused(&so->so_snd) - - (tp->snd_nxt - tp->snd_una))) { - if (!sbreserve_locked(&so->so_snd, - min(so->so_snd.sb_hiwat + V_tcp_autosndbuf_inc, - V_tcp_autosndbuf_max), so, curthread)) - so->so_snd.sb_flags &= ~SB_AUTOSIZE; - } - } + tcp_sndbuf_autoscale(tp, so, sendwin); /* * Decide if we can use TCP Segmentation Offloading (if supported by @@ -1145,7 +1095,9 @@ send: #endif /* INET6 */ { ip = mtod(m, struct ip *); +#ifdef TCPDEBUG ipov = (struct ipovly *)ip; +#endif th = (struct tcphdr *)(ip + 1); tcpip_fillheaders(tp->t_inpcb, ip, th); } @@ -1293,12 +1245,13 @@ send: * NOTE: since TCP options buffer doesn't point into * mbuf's data, calculate offset and use it. */ - if (!TCPMD5_ENABLED() || TCPMD5_OUTPUT(m, th, - (u_char *)(th + 1) + (to.to_signature - opt)) != 0) { + if (!TCPMD5_ENABLED() || (error = TCPMD5_OUTPUT(m, th, + (u_char *)(th + 1) + (to.to_signature - opt))) != 0) { /* * Do not send segment if the calculation of MD5 * digest has failed. */ + m_freem(m); goto out; } } @@ -1860,3 +1813,62 @@ tcp_addoptions(struct tcpopt *to, u_char *optp) KASSERT(optlen <= TCP_MAXOLEN, ("%s: TCP options too long", __func__)); return (optlen); } + +void +tcp_sndbuf_autoscale(struct tcpcb *tp, struct socket *so, uint32_t sendwin) +{ + + /* + * Automatic sizing of send socket buffer. Often the send buffer + * size is not optimally adjusted to the actual network conditions + * at hand (delay bandwidth product). Setting the buffer size too + * small limits throughput on links with high bandwidth and high + * delay (eg. trans-continental/oceanic links). Setting the + * buffer size too big consumes too much real kernel memory, + * especially with many connections on busy servers. + * + * The criteria to step up the send buffer one notch are: + * 1. receive window of remote host is larger than send buffer + * (with a fudge factor of 5/4th); + * 2. send buffer is filled to 7/8th with data (so we actually + * have data to make use of it); + * 3. send buffer fill has not hit maximal automatic size; + * 4. our send window (slow start and cogestion controlled) is + * larger than sent but unacknowledged data in send buffer. + * + * The remote host receive window scaling factor may limit the + * growing of the send buffer before it reaches its allowed + * maximum. + * + * It scales directly with slow start or congestion window + * and does at most one step per received ACK. This fast + * scaling has the drawback of growing the send buffer beyond + * what is strictly necessary to make full use of a given + * delay*bandwidth product. However testing has shown this not + * to be much of an problem. At worst we are trading wasting + * of available bandwidth (the non-use of it) for wasting some + * socket buffer memory. + * + * TODO: Shrink send buffer during idle periods together + * with congestion window. Requires another timer. Has to + * wait for upcoming tcp timer rewrite. + * + * XXXGL: should there be used sbused() or sbavail()? + */ + if (V_tcp_do_autosndbuf && so->so_snd.sb_flags & SB_AUTOSIZE) { + int lowat; + + lowat = V_tcp_sendbuf_auto_lowat ? so->so_snd.sb_lowat : 0; + if ((tp->snd_wnd / 4 * 5) >= so->so_snd.sb_hiwat - lowat && + sbused(&so->so_snd) >= + (so->so_snd.sb_hiwat / 8 * 7) - lowat && + sbused(&so->so_snd) < V_tcp_autosndbuf_max && + sendwin >= (sbused(&so->so_snd) - + (tp->snd_nxt - tp->snd_una))) { + if (!sbreserve_locked(&so->so_snd, + min(so->so_snd.sb_hiwat + V_tcp_autosndbuf_inc, + V_tcp_autosndbuf_max), so, curthread)) + so->so_snd.sb_flags &= ~SB_AUTOSIZE; + } + } +} diff --git a/freebsd/sys/netinet/tcp_timer.c b/freebsd/sys/netinet/tcp_timer.c index a2f854d7..539913f4 100644 --- a/freebsd/sys/netinet/tcp_timer.c +++ b/freebsd/sys/netinet/tcp_timer.c @@ -120,9 +120,9 @@ SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_slop, CTLTYPE_INT|CTLFLAG_RW, &tcp_rexmit_slop, 0, sysctl_msec_to_ticks, "I", "Retransmission Timer Slop"); -static int always_keepalive = 1; +int tcp_always_keepalive = 1; SYSCTL_INT(_net_inet_tcp, OID_AUTO, always_keepalive, CTLFLAG_RW, - &always_keepalive , 0, "Assume SO_KEEPALIVE on all TCP connections"); + &tcp_always_keepalive , 0, "Assume SO_KEEPALIVE on all TCP connections"); int tcp_fast_finwait2_recycle = 0; SYSCTL_INT(_net_inet_tcp, OID_AUTO, fast_finwait2_recycle, CTLFLAG_RW, @@ -473,7 +473,8 @@ tcp_timer_keep(void *xtp) TCPSTAT_INC(tcps_keeptimeo); if (tp->t_state < TCPS_ESTABLISHED) goto dropit; - if ((always_keepalive || inp->inp_socket->so_options & SO_KEEPALIVE) && + if ((tcp_always_keepalive || + inp->inp_socket->so_options & SO_KEEPALIVE) && tp->t_state <= TCPS_CLOSING) { if (ticks - tp->t_rcvtime >= TP_KEEPIDLE(tp) + TP_MAXIDLE(tp)) goto dropit; diff --git a/freebsd/sys/netinet/tcp_timer.h b/freebsd/sys/netinet/tcp_timer.h index 9a26c95d..b0ff3809 100644 --- a/freebsd/sys/netinet/tcp_timer.h +++ b/freebsd/sys/netinet/tcp_timer.h @@ -197,6 +197,7 @@ extern int tcp_ttl; /* time to live for TCP segs */ extern int tcp_backoff[]; extern int tcp_syn_backoff[]; +extern int tcp_always_keepalive; extern int tcp_finwait2_timeout; extern int tcp_fast_finwait2_recycle; diff --git a/freebsd/sys/netinet/tcp_var.h b/freebsd/sys/netinet/tcp_var.h index 0bcb3dc6..35b44410 100644 --- a/freebsd/sys/netinet/tcp_var.h +++ b/freebsd/sys/netinet/tcp_var.h @@ -884,6 +884,7 @@ void tcp_sack_partialack(struct tcpcb *, struct tcphdr *); void tcp_free_sackholes(struct tcpcb *tp); int tcp_newreno(struct tcpcb *, struct tcphdr *); int tcp_compute_pipe(struct tcpcb *); +void tcp_sndbuf_autoscale(struct tcpcb *, struct socket *, uint32_t); static inline void tcp_fields_to_host(struct tcphdr *th) diff --git a/freebsd/sys/netinet6/frag6.c b/freebsd/sys/netinet6/frag6.c index 1224aeaa..5b405ebb 100644 --- a/freebsd/sys/netinet6/frag6.c +++ b/freebsd/sys/netinet6/frag6.c @@ -229,6 +229,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto) IP6STAT_INC(ip6s_reassembled); in6_ifstat_inc(dstifp, ifs6_reass_ok); *offp = offset; + m->m_flags |= M_FRAGMENTED; return (ip6f->ip6f_nxt); } @@ -542,6 +543,7 @@ insert: while (t->m_next) t = t->m_next; m_adj(IP6_REASS_MBUF(af6), af6->ip6af_offset); + m_demote_pkthdr(IP6_REASS_MBUF(af6)); m_cat(t, IP6_REASS_MBUF(af6)); free(af6, M_FTABLE); af6 = af6dwn; @@ -829,5 +831,6 @@ ip6_deletefraghdr(struct mbuf *m, int offset, int wait) m_cat(m, t); } + m->m_flags |= M_FRAGMENTED; return (0); } diff --git a/freebsd/sys/netinet6/icmp6.c b/freebsd/sys/netinet6/icmp6.c index fb537170..38f14461 100644 --- a/freebsd/sys/netinet6/icmp6.c +++ b/freebsd/sys/netinet6/icmp6.c @@ -2266,6 +2266,10 @@ icmp6_redirect_input(struct mbuf *m, int off) if (!V_icmp6_rediraccept) goto freeit; + /* RFC 6980: Nodes MUST silently ignore fragments */ + if(m->m_flags & M_FRAGMENTED) + goto freeit; + #ifndef PULLDOWN_TEST IP6_EXTHDR_CHECK(m, off, icmp6len,); nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off); diff --git a/freebsd/sys/netinet6/in6.c b/freebsd/sys/netinet6/in6.c index 2046043d..6fc29892 100644 --- a/freebsd/sys/netinet6/in6.c +++ b/freebsd/sys/netinet6/in6.c @@ -1458,7 +1458,7 @@ in6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags) /* - * find the internet address corresponding to a given address. + * find the interface address corresponding to a given IPv6 address. * ifaddr is returned referenced. */ struct in6_ifaddr * diff --git a/freebsd/sys/netinet6/in6_ifattach.c b/freebsd/sys/netinet6/in6_ifattach.c index d89581e4..26a682ad 100644 --- a/freebsd/sys/netinet6/in6_ifattach.c +++ b/freebsd/sys/netinet6/in6_ifattach.c @@ -700,7 +700,6 @@ void in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) { struct in6_ifaddr *ia; - struct in6_addr in6; if (ifp->if_afdata[AF_INET6] == NULL) return; @@ -733,18 +732,16 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) /* * assign loopback address for loopback interface. - * XXX multiple loopback interface case. */ if ((ifp->if_flags & IFF_LOOPBACK) != 0) { - struct ifaddr *ifa; - - in6 = in6addr_loopback; - ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &in6); - if (ifa == NULL) { - if (in6_ifattach_loopback(ifp) != 0) - return; - } else - ifa_free(ifa); + /* + * check that loopback address doesn't exist yet. + */ + ia = in6ifa_ifwithaddr(&in6addr_loopback, 0); + if (ia == NULL) + in6_ifattach_loopback(ifp); + else + ifa_free(&ia->ia_ifa); } /* @@ -752,18 +749,10 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) */ if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) && ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL) { - int error; - ia = in6ifa_ifpforlinklocal(ifp, 0); - if (ia == NULL) { - error = in6_ifattach_linklocal(ifp, altifp); -#if 0 - if (error) - log(LOG_NOTICE, "in6_ifattach_linklocal: " - "failed to add a link-local addr to %s\n", - if_name(ifp)); -#endif - } else + if (ia == NULL) + in6_ifattach_linklocal(ifp, altifp); + else ifa_free(&ia->ia_ifa); } diff --git a/freebsd/sys/netinet6/in6_mcast.c b/freebsd/sys/netinet6/in6_mcast.c index 4119d1d9..a634b18b 100644 --- a/freebsd/sys/netinet6/in6_mcast.c +++ b/freebsd/sys/netinet6/in6_mcast.c @@ -1240,11 +1240,8 @@ out_in6m_release: int in6_mc_leave(struct in6_multi *inm, /*const*/ struct in6_mfilter *imf) { - struct ifnet *ifp; int error; - ifp = inm->in6m_ifp; - IN6_MULTI_LOCK(); error = in6_mc_leave_locked(inm, imf); IN6_MULTI_UNLOCK(); diff --git a/freebsd/sys/netinet6/in6_src.c b/freebsd/sys/netinet6/in6_src.c index a13c1a06..5b110274 100644 --- a/freebsd/sys/netinet6/in6_src.c +++ b/freebsd/sys/netinet6/in6_src.c @@ -162,7 +162,6 @@ static struct in6_addrpolicy *match_addrsel_policy(struct sockaddr_in6 *); */ #define REPLACE(r) do {\ IP6STAT_INC(ip6s_sources_rule[(r)]); \ - rule = (r); \ /* { \ char ip6buf[INET6_ADDRSTRLEN], ip6b[INET6_ADDRSTRLEN]; \ printf("in6_selectsrc: replace %s with %s by %d\n", ia_best ? ip6_sprintf(ip6buf, &ia_best->ia_addr.sin6_addr) : "none", ip6_sprintf(ip6b, &ia->ia_addr.sin6_addr), (r)); \ @@ -178,7 +177,6 @@ static struct in6_addrpolicy *match_addrsel_policy(struct sockaddr_in6 *); } while(0) #define BREAK(r) do { \ IP6STAT_INC(ip6s_sources_rule[(r)]); \ - rule = (r); \ goto out; /* XXX: we can't use 'break' here */ \ } while(0) @@ -196,7 +194,7 @@ in6_selectsrc(uint32_t fibnum, struct sockaddr_in6 *dstsock, struct in6_addrpolicy *dst_policy = NULL, *best_policy = NULL; u_int32_t odstzone; int prefer_tempaddr; - int error, rule; + int error; struct ip6_moptions *mopts; KASSERT(srcp != NULL, ("%s: srcp is NULL", __func__)); @@ -312,7 +310,6 @@ in6_selectsrc(uint32_t fibnum, struct sockaddr_in6 *dstsock, if (error) return (error); - rule = 0; IN6_IFADDR_RLOCK(&in6_ifa_tracker); TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) { int new_scope = -1, new_matchlen = -1; diff --git a/freebsd/sys/netinet6/ip6_id.c b/freebsd/sys/netinet6/ip6_id.c index cf0f3a4c..0905ab3f 100644 --- a/freebsd/sys/netinet6/ip6_id.c +++ b/freebsd/sys/netinet6/ip6_id.c @@ -1,6 +1,8 @@ #include <machine/rtems-bsd-kernel-space.h> /*- + * SPDX-License-Identifier: (BSD-3-Clause AND BSD-2-Clause) + * * Copyright (C) 2003 WIDE Project. * All rights reserved. * @@ -32,8 +34,6 @@ */ /*- - * SPDX-License-Identifier: BSD-4-Clause AND BSD-3-Clause - * * Copyright 1998 Niels Provos <provos@citi.umich.edu> * All rights reserved. * @@ -50,11 +50,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -67,7 +62,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $OpenBSD: ip_id.c,v 1.6 2002/03/15 18:19:52 millert Exp $ + * $OpenBSD: ip6_id.c,v 1.3 2003/12/12 06:57:12 itojun Exp $ */ #include <sys/cdefs.h> @@ -88,7 +83,7 @@ __FBSDID("$FreeBSD$"); * The transaction id is determined by: * id[n] = seed xor (g^X[n] mod n) * - * Effectivly the id is restricted to the lower (bits - 1) bits, thus + * Effectively the id is restricted to the lower (bits - 1) bits, thus * yielding two different cycles by toggling the msb on and off. * This avoids reuse issues caused by reseeding. */ @@ -179,7 +174,7 @@ pmod(u_int32_t gen, u_int32_t expo, u_int32_t mod) } /* - * Initalizes the seed and chooses a suitable generator. Also toggles + * Initializes the seed and chooses a suitable generator. Also toggles * the msb flag. The msb flag is used to generate two distinct * cycles of random numbers and thus avoiding reuse of ids. * @@ -234,15 +229,12 @@ static u_int32_t randomid(struct randomtab *p) { int i, n; - u_int32_t tmp; if (p->ru_counter >= p->ru_max || time_uptime > p->ru_reseed) initid(p); - tmp = arc4random(); - /* Skip a random number of ids */ - n = tmp & 0x3; tmp = tmp >> 2; + n = arc4random() & 0x3; if (p->ru_counter + n >= p->ru_max) initid(p); @@ -253,7 +245,7 @@ randomid(struct randomtab *p) p->ru_counter += i; - return (p->ru_seed ^ pmod(p->ru_g, p->ru_seed2 ^ p->ru_x, p->ru_n)) | + return (p->ru_seed ^ pmod(p->ru_g, p->ru_seed2 + p->ru_x, p->ru_n)) | p->ru_msb; } diff --git a/freebsd/sys/netinet6/ip6_input.c b/freebsd/sys/netinet6/ip6_input.c index c22f2015..78d941ae 100644 --- a/freebsd/sys/netinet6/ip6_input.c +++ b/freebsd/sys/netinet6/ip6_input.c @@ -575,10 +575,8 @@ ip6_input(struct mbuf *m) /* * Firewall changed destination to local. */ - m->m_flags &= ~M_FASTFWD_OURS; - ours = 1; ip6 = mtod(m, struct ip6_hdr *); - goto hbhcheck; + goto passin; } /* @@ -739,10 +737,8 @@ ip6_input(struct mbuf *m) if ((m = ip6_tryforward(m)) == NULL) return; if (m->m_flags & M_FASTFWD_OURS) { - m->m_flags &= ~M_FASTFWD_OURS; - ours = 1; ip6 = mtod(m, struct ip6_hdr *); - goto hbhcheck; + goto passin; } } #if defined(IPSEC) || defined(IPSEC_SUPPORT) @@ -773,13 +769,7 @@ ip6_input(struct mbuf *m) return; ip6 = mtod(m, struct ip6_hdr *); srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst); - - if (m->m_flags & M_FASTFWD_OURS) { - m->m_flags &= ~M_FASTFWD_OURS; - ours = 1; - goto hbhcheck; - } - if ((m->m_flags & M_IP6_NEXTHOP) && + if ((m->m_flags & (M_IP6_NEXTHOP | M_FASTFWD_OURS)) == M_IP6_NEXTHOP && m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL) { /* * Directly ship the packet on. This allows forwarding @@ -810,6 +800,11 @@ passin: IP6STAT_INC(ip6s_badscope); goto bad; } + if (m->m_flags & M_FASTFWD_OURS) { + m->m_flags &= ~M_FASTFWD_OURS; + ours = 1; + goto hbhcheck; + } /* * Multicast check. Assume packet is for us to avoid * prematurely taking locks. diff --git a/freebsd/sys/netinet6/mld6.c b/freebsd/sys/netinet6/mld6.c index 26fb21f7..c1dff0c3 100644 --- a/freebsd/sys/netinet6/mld6.c +++ b/freebsd/sys/netinet6/mld6.c @@ -2288,7 +2288,7 @@ mld_v2_enqueue_group_record(struct mbufq *mq, struct in6_multi *inm, struct ifnet *ifp; struct ip6_msource *ims, *nims; struct mbuf *m0, *m, *md; - int error, is_filter_list_change; + int is_filter_list_change; int minrec0len, m0srcs, msrcs, nbytes, off; int record_has_sources; int now; @@ -2300,7 +2300,6 @@ mld_v2_enqueue_group_record(struct mbufq *mq, struct in6_multi *inm, IN6_MULTI_LOCK_ASSERT(); - error = 0; ifp = inm->in6m_ifp; is_filter_list_change = 0; m = NULL; diff --git a/freebsd/sys/netinet6/nd6.c b/freebsd/sys/netinet6/nd6.c index 30672e23..6235b808 100644 --- a/freebsd/sys/netinet6/nd6.c +++ b/freebsd/sys/netinet6/nd6.c @@ -2034,10 +2034,11 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr, if (ln_tmp == NULL) { /* No existing lle, mark as new entry (6,7) */ is_newentry = 1; - nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); - if (lladdr != NULL) /* (7) */ + if (lladdr != NULL) { /* (7) */ + nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED); + } } else { lltable_free_entry(LLTABLE6(ifp), ln); ln = ln_tmp; @@ -2115,7 +2116,7 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr, LLE_RUNLOCK(ln); if (chain != NULL) - nd6_flush_holdchain(ifp, ifp, chain, &sin6); + nd6_flush_holdchain(ifp, chain, &sin6); /* * When the link-layer address of a router changes, select the @@ -2504,23 +2505,18 @@ nd6_resolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst, } int -nd6_flush_holdchain(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *chain, +nd6_flush_holdchain(struct ifnet *ifp, struct mbuf *chain, struct sockaddr_in6 *dst) { struct mbuf *m, *m_head; - struct ifnet *outifp; int error = 0; m_head = chain; - if ((ifp->if_flags & IFF_LOOPBACK) != 0) - outifp = origifp; - else - outifp = ifp; - + while (m_head) { m = m_head; m_head = m_head->m_nextpkt; - error = nd6_output_ifp(ifp, origifp, m, dst, NULL); + error = nd6_output_ifp(ifp, ifp, m, dst, NULL); } /* @@ -2528,7 +2524,7 @@ nd6_flush_holdchain(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *chain * note that intermediate errors are blindly ignored */ return (error); -} +} static int nd6_need_cache(struct ifnet *ifp) diff --git a/freebsd/sys/netinet6/nd6.h b/freebsd/sys/netinet6/nd6.h index 30990637..cabfeec0 100644 --- a/freebsd/sys/netinet6/nd6.h +++ b/freebsd/sys/netinet6/nd6.h @@ -448,7 +448,7 @@ void nd6_cache_lladdr(struct ifnet *, struct in6_addr *, char *, int, int, int); void nd6_grab_holdchain(struct llentry *, struct mbuf **, struct sockaddr_in6 *); -int nd6_flush_holdchain(struct ifnet *, struct ifnet *, struct mbuf *, +int nd6_flush_holdchain(struct ifnet *, struct mbuf *, struct sockaddr_in6 *); int nd6_add_ifa_lle(struct in6_ifaddr *); void nd6_rem_ifa_lle(struct in6_ifaddr *, int); diff --git a/freebsd/sys/netinet6/nd6_nbr.c b/freebsd/sys/netinet6/nd6_nbr.c index 5e55fc2b..0c875324 100644 --- a/freebsd/sys/netinet6/nd6_nbr.c +++ b/freebsd/sys/netinet6/nd6_nbr.c @@ -139,6 +139,10 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len) struct sockaddr_dl proxydl; char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; + /* RFC 6980: Nodes MUST silently ignore fragments */ + if(m->m_flags & M_FRAGMENTED) + goto freeit; + rflag = (V_ip6_forwarding) ? ND_NA_FLAG_ROUTER : 0; if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV && V_ip6_norbit_raif) rflag = 0; @@ -633,6 +637,10 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len) int lladdr_off; char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; + /* RFC 6980: Nodes MUST silently ignore fragments */ + if(m->m_flags & M_FRAGMENTED) + goto freeit; + if (ip6->ip6_hlim != 255) { nd6log((LOG_ERR, "nd6_na_input: invalid hlim (%d) from %s to %s on %s\n", @@ -888,7 +896,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len) LLE_WUNLOCK(ln); if (chain != NULL) - nd6_flush_holdchain(ifp, ifp, chain, &sin6); + nd6_flush_holdchain(ifp, chain, &sin6); if (checklink) pfxlist_onlink_check(); @@ -1301,7 +1309,8 @@ nd6_dad_stop(struct ifaddr *ifa) * we were waiting for it to stop, so re-do the lookup. */ nd6_dad_rele(dp); - if (nd6_dad_find(ifa, NULL) == NULL) + dp = nd6_dad_find(ifa, NULL); + if (dp == NULL) return; nd6_dad_del(dp); @@ -1508,17 +1517,11 @@ nd6_dad_ns_output(struct dadq *dp) static void nd6_dad_ns_input(struct ifaddr *ifa, struct nd_opt_nonce *ndopt_nonce) { - struct in6_ifaddr *ia; - struct ifnet *ifp; - const struct in6_addr *taddr6; struct dadq *dp; if (ifa == NULL) panic("ifa == NULL in nd6_dad_ns_input"); - ia = (struct in6_ifaddr *)ifa; - ifp = ifa->ifa_ifp; - taddr6 = &ia->ia_addr.sin6_addr; /* Ignore Nonce option when Enhanced DAD is disabled. */ if (V_dad_enhanced == 0) ndopt_nonce = NULL; diff --git a/freebsd/sys/netinet6/nd6_rtr.c b/freebsd/sys/netinet6/nd6_rtr.c index 47fc497e..2affacbf 100644 --- a/freebsd/sys/netinet6/nd6_rtr.c +++ b/freebsd/sys/netinet6/nd6_rtr.c @@ -141,6 +141,10 @@ nd6_rs_input(struct mbuf *m, int off, int icmp6len) if (!V_ip6_forwarding || ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) goto freeit; + /* RFC 6980: Nodes MUST silently ignore fragments */ + if(m->m_flags & M_FRAGMENTED) + goto freeit; + /* Sanity checks */ if (ip6->ip6_hlim != 255) { nd6log((LOG_ERR, @@ -231,6 +235,10 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len) if (!(ndi->flags & ND6_IFF_ACCEPT_RTADV)) goto freeit; + /* RFC 6980: Nodes MUST silently ignore fragments */ + if(m->m_flags & M_FRAGMENTED) + goto freeit; + if (ip6->ip6_hlim != 255) { nd6log((LOG_ERR, "nd6_ra_input: invalid hlim (%d) from %s to %s on %s\n", diff --git a/freebsd/sys/netinet6/raw_ip6.c b/freebsd/sys/netinet6/raw_ip6.c index 743fe787..b68077ef 100644 --- a/freebsd/sys/netinet6/raw_ip6.c +++ b/freebsd/sys/netinet6/raw_ip6.c @@ -341,9 +341,6 @@ rip6_input(struct mbuf **mp, int *offp, int proto) void rip6_ctlinput(int cmd, struct sockaddr *sa, void *d) { - struct ip6_hdr *ip6; - struct mbuf *m; - int off = 0; struct ip6ctlparam *ip6cp = NULL; const struct sockaddr_in6 *sa6_src = NULL; void *cmdarg; @@ -367,14 +364,9 @@ rip6_ctlinput(int cmd, struct sockaddr *sa, void *d) */ if (d != NULL) { ip6cp = (struct ip6ctlparam *)d; - m = ip6cp->ip6c_m; - ip6 = ip6cp->ip6c_ip6; - off = ip6cp->ip6c_off; cmdarg = ip6cp->ip6c_cmdarg; sa6_src = ip6cp->ip6c_src; } else { - m = NULL; - ip6 = NULL; cmdarg = NULL; sa6_src = &sa6_any; } @@ -393,7 +385,6 @@ rip6_output(struct mbuf *m, struct socket *so, ...) struct mbuf *control; struct m_tag *mtag; struct sockaddr_in6 *dstsock; - struct in6_addr *dst; struct ip6_hdr *ip6; struct inpcb *in6p; u_int plen = m->m_pkthdr.len; @@ -415,7 +406,6 @@ rip6_output(struct mbuf *m, struct socket *so, ...) in6p = sotoinpcb(so); INP_WLOCK(in6p); - dst = &dstsock->sin6_addr; if (control != NULL) { if ((error = ip6_setpktopts(control, &opt, in6p->in6p_outputopts, so->so_cred, diff --git a/freebsd/sys/netinet6/scope6.c b/freebsd/sys/netinet6/scope6.c index a4c56769..40218287 100644 --- a/freebsd/sys/netinet6/scope6.c +++ b/freebsd/sys/netinet6/scope6.c @@ -413,7 +413,7 @@ in6_setscope(struct in6_addr *in6, struct ifnet *ifp, u_int32_t *ret_id) if (scope == IPV6_ADDR_SCOPE_INTFACELOCAL || scope == IPV6_ADDR_SCOPE_LINKLOCAL) { /* - * Currently we use interface indeces as the + * Currently we use interface indices as the * zone IDs for interface-local and link-local * scopes. */ diff --git a/freebsd/sys/netinet6/sctp6_usrreq.c b/freebsd/sys/netinet6/sctp6_usrreq.c index 619a30dc..a79e6f53 100644 --- a/freebsd/sys/netinet6/sctp6_usrreq.c +++ b/freebsd/sys/netinet6/sctp6_usrreq.c @@ -73,9 +73,7 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port) struct sctphdr *sh; struct sctp_chunkhdr *ch; int length, offset; -#if !defined(SCTP_WITH_NO_CSUM) uint8_t compute_crc; -#endif uint32_t mflowid; uint8_t mflowtype; uint16_t fibnum; @@ -146,9 +144,6 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port) goto out; } ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff); -#if defined(SCTP_WITH_NO_CSUM) - SCTP_STAT_INCR(sctps_recvnocrc); -#else if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) { SCTP_STAT_INCR(sctps_recvhwcrc); compute_crc = 0; @@ -156,14 +151,11 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port) SCTP_STAT_INCR(sctps_recvswcrc); compute_crc = 1; } -#endif sctp_common_input_processing(&m, iphlen, offset, length, (struct sockaddr *)&src, (struct sockaddr *)&dst, sh, ch, -#if !defined(SCTP_WITH_NO_CSUM) compute_crc, -#endif ecn_bits, mflowtype, mflowid, fibnum, vrf_id, port); diff --git a/freebsd/sys/netinet6/udp6_usrreq.c b/freebsd/sys/netinet6/udp6_usrreq.c index ae57ac79..98d097f7 100644 --- a/freebsd/sys/netinet6/udp6_usrreq.c +++ b/freebsd/sys/netinet6/udp6_usrreq.c @@ -1192,7 +1192,6 @@ udp6_disconnect(struct socket *so) { struct inpcb *inp; struct inpcbinfo *pcbinfo; - int error; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); @@ -1214,8 +1213,8 @@ udp6_disconnect(struct socket *so) #endif if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { - error = ENOTCONN; - goto out; + INP_WUNLOCK(inp); + return (ENOTCONN); } INP_HASH_WLOCK(pcbinfo); @@ -1225,7 +1224,6 @@ udp6_disconnect(struct socket *so) SOCK_LOCK(so); so->so_state &= ~SS_ISCONNECTED; /* XXX */ SOCK_UNLOCK(so); -out: INP_WUNLOCK(inp); return (0); } diff --git a/freebsd/sys/netipsec/key.c b/freebsd/sys/netipsec/key.c index 3652524c..31269058 100644 --- a/freebsd/sys/netipsec/key.c +++ b/freebsd/sys/netipsec/key.c @@ -5746,7 +5746,6 @@ static int key_setident(struct secashead *sah, const struct sadb_msghdr *mhp) { const struct sadb_ident *idsrc, *iddst; - int idsrclen, iddstlen; IPSEC_ASSERT(sah != NULL, ("null secashead")); IPSEC_ASSERT(mhp != NULL, ("null msghdr")); @@ -5768,8 +5767,6 @@ key_setident(struct secashead *sah, const struct sadb_msghdr *mhp) idsrc = (const struct sadb_ident *)mhp->ext[SADB_EXT_IDENTITY_SRC]; iddst = (const struct sadb_ident *)mhp->ext[SADB_EXT_IDENTITY_DST]; - idsrclen = mhp->extlen[SADB_EXT_IDENTITY_SRC]; - iddstlen = mhp->extlen[SADB_EXT_IDENTITY_DST]; /* validity check */ if (idsrc->sadb_ident_type != iddst->sadb_ident_type) { @@ -7466,7 +7463,6 @@ key_dump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) SAHTREE_RLOCK_TRACKER; struct secashead *sah; struct secasvar *sav; - struct sadb_msg *newmsg; struct mbuf *n; uint32_t cnt; uint8_t proto, satype; @@ -7503,7 +7499,6 @@ key_dump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) } /* send this to the userland, one at a time. */ - newmsg = NULL; TAILQ_FOREACH(sah, &V_sahtree, chain) { if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC && proto != sah->saidx.proto) @@ -8149,7 +8144,10 @@ key_destroy(void) TAILQ_CONCAT(&drainq, &V_sptree[i], chain); TAILQ_CONCAT(&drainq, &V_sptree_ifnet[i], chain); } + for (i = 0; i < V_sphash_mask + 1; i++) + LIST_INIT(&V_sphashtbl[i]); SPTREE_WUNLOCK(); + sp = TAILQ_FIRST(&drainq); while (sp != NULL) { nextsp = TAILQ_NEXT(sp, chain); @@ -8200,6 +8198,10 @@ key_destroy(void) free(acq, M_IPSEC_SAQ); acq = nextacq; } + for (i = 0; i < V_acqaddrhash_mask + 1; i++) + LIST_INIT(&V_acqaddrhashtbl[i]); + for (i = 0; i < V_acqseqhash_mask + 1; i++) + LIST_INIT(&V_acqseqhashtbl[i]); ACQ_UNLOCK(); SPACQ_LOCK(); @@ -8215,6 +8217,18 @@ key_destroy(void) hashdestroy(V_acqaddrhashtbl, M_IPSEC_SAQ, V_acqaddrhash_mask); hashdestroy(V_acqseqhashtbl, M_IPSEC_SAQ, V_acqseqhash_mask); uma_zdestroy(V_key_lft_zone); + + if (!IS_DEFAULT_VNET(curvnet)) + return; +#ifndef IPSEC_DEBUG2 + callout_drain(&key_timer); +#endif + XFORMS_LOCK_DESTROY(); + SPTREE_LOCK_DESTROY(); + REGTREE_LOCK_DESTROY(); + SAHTREE_LOCK_DESTROY(); + ACQ_LOCK_DESTROY(); + SPACQ_LOCK_DESTROY(); } #endif diff --git a/freebsd/sys/netipsec/xform_ah.c b/freebsd/sys/netipsec/xform_ah.c index 5667f78f..9125ba40 100644 --- a/freebsd/sys/netipsec/xform_ah.c +++ b/freebsd/sys/netipsec/xform_ah.c @@ -266,7 +266,7 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out) #ifdef INET6 struct ip6_ext *ip6e; struct ip6_hdr ip6; - int alloc, len, ad; + int ad, alloc, nxt, noff; #endif /* INET6 */ switch (proto) { @@ -295,7 +295,7 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out) else ip->ip_off = htons(0); - ptr = mtod(m, unsigned char *) + sizeof(struct ip); + ptr = mtod(m, unsigned char *); /* IPv4 option processing */ for (off = sizeof(struct ip); off < skip;) { @@ -376,7 +376,7 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out) /* Zeroize all other options. */ count = ptr[off + 1]; - bcopy(ipseczeroes, ptr, count); + bcopy(ipseczeroes, ptr + off, count); off += count; break; } @@ -449,61 +449,44 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out) } else break; - off = ip6.ip6_nxt & 0xff; /* Next header type. */ + nxt = ip6.ip6_nxt & 0xff; /* Next header type. */ - for (len = 0; len < skip - sizeof(struct ip6_hdr);) - switch (off) { + for (off = 0; off < skip - sizeof(struct ip6_hdr);) + switch (nxt) { case IPPROTO_HOPOPTS: case IPPROTO_DSTOPTS: - ip6e = (struct ip6_ext *) (ptr + len); + ip6e = (struct ip6_ext *)(ptr + off); + noff = off + ((ip6e->ip6e_len + 1) << 3); + + /* Sanity check. */ + if (noff > skip - sizeof(struct ip6_hdr)) + goto error6; /* - * Process the mutable/immutable - * options -- borrows heavily from the - * KAME code. + * Zero out mutable options. */ - for (count = len + sizeof(struct ip6_ext); - count < len + ((ip6e->ip6e_len + 1) << 3);) { + for (count = off + sizeof(struct ip6_ext); + count < noff;) { if (ptr[count] == IP6OPT_PAD1) { count++; continue; /* Skip padding. */ } - /* Sanity check. */ - if (count > len + - ((ip6e->ip6e_len + 1) << 3)) { - m_freem(m); - - /* Free, if we allocated. */ - if (alloc) - free(ptr, M_XDATA); - return EINVAL; - } - - ad = ptr[count + 1]; + ad = ptr[count + 1] + 2; + if (count + ad > noff) + goto error6; - /* If mutable option, zeroize. */ if (ptr[count] & IP6OPT_MUTABLE) - bcopy(ipseczeroes, ptr + count, - ptr[count + 1]); - + memset(ptr + count, 0, ad); count += ad; - - /* Sanity check. */ - if (count > - skip - sizeof(struct ip6_hdr)) { - m_freem(m); - - /* Free, if we allocated. */ - if (alloc) - free(ptr, M_XDATA); - return EINVAL; - } } + if (count != noff) + goto error6; + /* Advance. */ - len += ((ip6e->ip6e_len + 1) << 3); - off = ip6e->ip6e_nxt; + off += ((ip6e->ip6e_len + 1) << 3); + nxt = ip6e->ip6e_nxt; break; case IPPROTO_ROUTING: @@ -511,14 +494,15 @@ ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out) * Always include routing headers in * computation. */ - ip6e = (struct ip6_ext *) (ptr + len); - len += ((ip6e->ip6e_len + 1) << 3); - off = ip6e->ip6e_nxt; + ip6e = (struct ip6_ext *) (ptr + off); + off += ((ip6e->ip6e_len + 1) << 3); + nxt = ip6e->ip6e_nxt; break; default: DPRINTF(("%s: unexpected IPv6 header type %d", __func__, off)); +error6: if (alloc) free(ptr, M_XDATA); m_freem(m); @@ -687,9 +671,7 @@ ah_input_cb(struct cryptop *crp) { IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); unsigned char calc[AH_ALEN_MAX]; - const struct auth_hash *ahx; struct mbuf *m; - struct cryptodesc *crd; struct xform_data *xd; struct secasvar *sav; struct secasindex *saidx; @@ -698,7 +680,6 @@ ah_input_cb(struct cryptop *crp) int authsize, rplen, error, skip, protoff; uint8_t nxt; - crd = crp->crp_desc; m = (struct mbuf *) crp->crp_buf; xd = (struct xform_data *) crp->crp_opaque; sav = xd->sav; @@ -711,8 +692,6 @@ ah_input_cb(struct cryptop *crp) saidx->dst.sa.sa_family == AF_INET6, ("unexpected protocol family %u", saidx->dst.sa.sa_family)); - ahx = sav->tdb_authalgxform; - /* Check for crypto errors. */ if (crp->crp_etype) { if (crp->crp_etype == EAGAIN) { diff --git a/freebsd/sys/netipsec/xform_esp.c b/freebsd/sys/netipsec/xform_esp.c index 8af95f7d..f26b8ae7 100644 --- a/freebsd/sys/netipsec/xform_esp.c +++ b/freebsd/sys/netipsec/xform_esp.c @@ -443,7 +443,6 @@ esp_input_cb(struct cryptop *crp) IPSEC_DEBUG_DECLARE(char buf[128]); u_int8_t lastthree[3], aalg[AH_HMAC_MAXHASHLEN]; const struct auth_hash *esph; - const struct enc_xform *espx; struct mbuf *m; struct cryptodesc *crd; struct xform_data *xd; @@ -464,7 +463,6 @@ esp_input_cb(struct cryptop *crp) cryptoid = xd->cryptoid; saidx = &sav->sah->saidx; esph = sav->tdb_authalgxform; - espx = sav->tdb_encalgxform; /* Check for crypto errors */ if (crp->crp_etype) { diff --git a/freebsd/sys/netipsec/xform_ipcomp.c b/freebsd/sys/netipsec/xform_ipcomp.c index 4764e609..956383d5 100644 --- a/freebsd/sys/netipsec/xform_ipcomp.c +++ b/freebsd/sys/netipsec/xform_ipcomp.c @@ -276,7 +276,6 @@ static int ipcomp_input_cb(struct cryptop *crp) { IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]); - struct cryptodesc *crd; struct xform_data *xd; struct mbuf *m; struct secasvar *sav; @@ -287,8 +286,6 @@ ipcomp_input_cb(struct cryptop *crp) int skip, protoff; uint8_t nproto; - crd = crp->crp_desc; - m = (struct mbuf *) crp->crp_buf; xd = (struct xform_data *) crp->crp_opaque; sav = xd->sav; diff --git a/freebsd/sys/netpfil/pf/if_pflog.c b/freebsd/sys/netpfil/pf/if_pflog.c index 1ad6a774..53cf94c8 100644 --- a/freebsd/sys/netpfil/pf/if_pflog.c +++ b/freebsd/sys/netpfil/pf/if_pflog.c @@ -1,6 +1,8 @@ #include <machine/rtems-bsd-kernel-space.h> /*- + * SPDX-License-Identifier: ISC + * * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and * Niels Provos (provos@physnet.uni-hamburg.de). diff --git a/freebsd/sys/netpfil/pf/in4_cksum.c b/freebsd/sys/netpfil/pf/in4_cksum.c index 509c33cd..242909cc 100644 --- a/freebsd/sys/netpfil/pf/in4_cksum.c +++ b/freebsd/sys/netpfil/pf/in4_cksum.c @@ -5,7 +5,7 @@ /* $KAME: in4_cksum.c,v 1.10 2001/11/30 10:06:15 itojun Exp $ */ /* $NetBSD: in_cksum.c,v 1.13 1996/10/13 02:03:03 christos Exp $ */ -/* +/*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (C) 1999 WIDE Project. diff --git a/freebsd/sys/netpfil/pf/pf.c b/freebsd/sys/netpfil/pf/pf.c index d94966b9..a904a0db 100644 --- a/freebsd/sys/netpfil/pf/pf.c +++ b/freebsd/sys/netpfil/pf/pf.c @@ -1500,7 +1500,7 @@ pf_unload_vnet_purge(void) * Now purge everything. */ pf_purge_expired_states(0, pf_hashmask); - pf_purge_expired_fragments(); + pf_purge_fragments(UINT_MAX); pf_purge_expired_src_nodes(); /* @@ -1615,6 +1615,7 @@ int pf_unlink_state(struct pf_state *s, u_int flags) { struct pf_idhash *ih = &V_pf_idhash[PF_IDHASH(s)]; + int last; if ((flags & PF_ENTER_LOCKED) == 0) PF_HASHROW_LOCK(ih); @@ -1655,7 +1656,8 @@ pf_unlink_state(struct pf_state *s, u_int flags) PF_HASHROW_UNLOCK(ih); pf_detach_state(s); - refcount_release(&s->refs); + last = refcount_release(&s->refs); + KASSERT(last == 0, ("Incorrect state reference count")); return (pf_release_state(s)); } diff --git a/freebsd/sys/netpfil/pf/pf.h b/freebsd/sys/netpfil/pf/pf.h index 333faea3..69472782 100644 --- a/freebsd/sys/netpfil/pf/pf.h +++ b/freebsd/sys/netpfil/pf/pf.h @@ -1,4 +1,4 @@ -/* +/*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2001 Daniel Hartmeier diff --git a/freebsd/sys/netpfil/pf/pf_ioctl.c b/freebsd/sys/netpfil/pf/pf_ioctl.c index 98f190e7..a1b0b5e5 100644 --- a/freebsd/sys/netpfil/pf/pf_ioctl.c +++ b/freebsd/sys/netpfil/pf/pf_ioctl.c @@ -2543,7 +2543,12 @@ DIOCCHANGEADDR_error: break; } totlen = io->pfrio_size * sizeof(struct pfr_table); - pfrts = malloc(totlen, M_TEMP, M_WAITOK); + pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), + M_TEMP, M_WAITOK); + if (! pfrts) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP); @@ -2567,7 +2572,12 @@ DIOCCHANGEADDR_error: break; } totlen = io->pfrio_size * sizeof(struct pfr_table); - pfrts = malloc(totlen, M_TEMP, M_WAITOK); + pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), + M_TEMP, M_WAITOK); + if (! pfrts) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP); @@ -2591,7 +2601,12 @@ DIOCCHANGEADDR_error: break; } totlen = io->pfrio_size * sizeof(struct pfr_table); - pfrts = malloc(totlen, M_TEMP, M_WAITOK); + pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), + M_TEMP, M_WAITOK); + if (! pfrts) { + error = ENOMEM; + break; + } PF_RULES_RLOCK(); error = pfr_get_tables(&io->pfrio_table, pfrts, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); @@ -2612,7 +2627,12 @@ DIOCCHANGEADDR_error: break; } totlen = io->pfrio_size * sizeof(struct pfr_tstats); - pfrtstats = malloc(totlen, M_TEMP, M_WAITOK); + pfrtstats = mallocarray(io->pfrio_size, + sizeof(struct pfr_tstats), M_TEMP, M_WAITOK); + if (! pfrtstats) { + error = ENOMEM; + break; + } PF_RULES_WLOCK(); error = pfr_get_tstats(&io->pfrio_table, pfrtstats, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); @@ -2633,7 +2653,12 @@ DIOCCHANGEADDR_error: break; } totlen = io->pfrio_size * sizeof(struct pfr_table); - pfrts = malloc(totlen, M_TEMP, M_WAITOK); + pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), + M_TEMP, M_WAITOK); + if (! pfrts) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP); @@ -2657,7 +2682,12 @@ DIOCCHANGEADDR_error: break; } totlen = io->pfrio_size * sizeof(struct pfr_table); - pfrts = malloc(totlen, M_TEMP, M_WAITOK); + pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), + M_TEMP, M_WAITOK); + if (! pfrts) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP); @@ -2696,7 +2726,12 @@ DIOCCHANGEADDR_error: break; } totlen = io->pfrio_size * sizeof(struct pfr_addr); - pfras = malloc(totlen, M_TEMP, M_WAITOK); + pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), + M_TEMP, M_WAITOK); + if (! pfras) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); @@ -2723,7 +2758,12 @@ DIOCCHANGEADDR_error: break; } totlen = io->pfrio_size * sizeof(struct pfr_addr); - pfras = malloc(totlen, M_TEMP, M_WAITOK); + pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), + M_TEMP, M_WAITOK); + if (! pfras) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); @@ -2751,7 +2791,12 @@ DIOCCHANGEADDR_error: } count = max(io->pfrio_size, io->pfrio_size2); totlen = count * sizeof(struct pfr_addr); - pfras = malloc(totlen, M_TEMP, M_WAITOK); + pfras = mallocarray(count, sizeof(struct pfr_addr), M_TEMP, + M_WAITOK); + if (! pfras) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); @@ -2779,7 +2824,12 @@ DIOCCHANGEADDR_error: break; } totlen = io->pfrio_size * sizeof(struct pfr_addr); - pfras = malloc(totlen, M_TEMP, M_WAITOK); + pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), + M_TEMP, M_WAITOK); + if (! pfras) { + error = ENOMEM; + break; + } PF_RULES_RLOCK(); error = pfr_get_addrs(&io->pfrio_table, pfras, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); @@ -2800,7 +2850,12 @@ DIOCCHANGEADDR_error: break; } totlen = io->pfrio_size * sizeof(struct pfr_astats); - pfrastats = malloc(totlen, M_TEMP, M_WAITOK); + pfrastats = mallocarray(io->pfrio_size, + sizeof(struct pfr_astats), M_TEMP, M_WAITOK); + if (! pfrastats) { + error = ENOMEM; + break; + } PF_RULES_RLOCK(); error = pfr_get_astats(&io->pfrio_table, pfrastats, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); @@ -2821,7 +2876,12 @@ DIOCCHANGEADDR_error: break; } totlen = io->pfrio_size * sizeof(struct pfr_addr); - pfras = malloc(totlen, M_TEMP, M_WAITOK); + pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), + M_TEMP, M_WAITOK); + if (! pfras) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); @@ -2848,7 +2908,12 @@ DIOCCHANGEADDR_error: break; } totlen = io->pfrio_size * sizeof(struct pfr_addr); - pfras = malloc(totlen, M_TEMP, M_WAITOK); + pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), + M_TEMP, M_WAITOK); + if (! pfras) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); @@ -2875,7 +2940,12 @@ DIOCCHANGEADDR_error: break; } totlen = io->pfrio_size * sizeof(struct pfr_addr); - pfras = malloc(totlen, M_TEMP, M_WAITOK); + pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), + M_TEMP, M_WAITOK); + if (! pfras) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); @@ -2917,7 +2987,12 @@ DIOCCHANGEADDR_error: break; } totlen = sizeof(struct pfioc_trans_e) * io->size; - ioes = malloc(totlen, M_TEMP, M_WAITOK); + ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e), + M_TEMP, M_WAITOK); + if (! ioes) { + error = ENOMEM; + break; + } error = copyin(io->array, ioes, totlen); if (error) { free(ioes, M_TEMP); @@ -2983,7 +3058,12 @@ DIOCCHANGEADDR_error: break; } totlen = sizeof(struct pfioc_trans_e) * io->size; - ioes = malloc(totlen, M_TEMP, M_WAITOK); + ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e), + M_TEMP, M_WAITOK); + if (! ioes) { + error = ENOMEM; + break; + } error = copyin(io->array, ioes, totlen); if (error) { free(ioes, M_TEMP); @@ -3049,7 +3129,12 @@ DIOCCHANGEADDR_error: break; } totlen = sizeof(struct pfioc_trans_e) * io->size; - ioes = malloc(totlen, M_TEMP, M_WAITOK); + ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e), + M_TEMP, M_WAITOK); + if (! ioes) { + error = ENOMEM; + break; + } error = copyin(io->array, ioes, totlen); if (error) { free(ioes, M_TEMP); @@ -3250,7 +3335,12 @@ DIOCCHANGEADDR_error: } bufsiz = io->pfiio_size * sizeof(struct pfi_kif); - ifstore = malloc(bufsiz, M_TEMP, M_WAITOK); + ifstore = mallocarray(io->pfiio_size, sizeof(struct pfi_kif), + M_TEMP, M_WAITOK); + if (! ifstore) { + error = ENOMEM; + break; + } PF_RULES_RLOCK(); pfi_get_ifaces(io->pfiio_name, ifstore, &io->pfiio_size); PF_RULES_RUNLOCK(); @@ -3845,12 +3935,6 @@ pf_modevent(module_t mod, int type, void *data) case MOD_LOAD: error = pf_load(); break; - case MOD_QUIESCE: - /* - * Module should not be unloaded due to race conditions. - */ - error = EBUSY; - break; case MOD_UNLOAD: /* Handled in SYSUNINIT(pf_unload) to ensure it's done after * the vnet_pf_uninit()s */ diff --git a/freebsd/sys/netpfil/pf/pf_norm.c b/freebsd/sys/netpfil/pf/pf_norm.c index e3a00971..4f0966ed 100644 --- a/freebsd/sys/netpfil/pf/pf_norm.c +++ b/freebsd/sys/netpfil/pf/pf_norm.c @@ -221,9 +221,16 @@ pf_frag_compare(struct pf_fragment *a, struct pf_fragment *b) void pf_purge_expired_fragments(void) { + u_int32_t expire = time_uptime - + V_pf_default_rule.timeout[PFTM_FRAG]; + + pf_purge_fragments(expire); +} + +void +pf_purge_fragments(uint32_t expire) +{ struct pf_fragment *frag; - u_int32_t expire = time_uptime - - V_pf_default_rule.timeout[PFTM_FRAG]; PF_FRAG_LOCK(); while ((frag = TAILQ_LAST(&V_pf_fragqueue, pf_fragqueue)) != NULL) { diff --git a/freebsd/sys/netpfil/pf/pf_osfp.c b/freebsd/sys/netpfil/pf/pf_osfp.c index 7b55d20a..1ee16df5 100644 --- a/freebsd/sys/netpfil/pf/pf_osfp.c +++ b/freebsd/sys/netpfil/pf/pf_osfp.c @@ -1,6 +1,8 @@ #include <machine/rtems-bsd-kernel-space.h> /*- + * SPDX-License-Identifier: ISC + * * Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org> * * Permission to use, copy, modify, and distribute this software for any diff --git a/freebsd/sys/opencrypto/crypto.c b/freebsd/sys/opencrypto/crypto.c index 2631ca5b..f6943be2 100644 --- a/freebsd/sys/opencrypto/crypto.c +++ b/freebsd/sys/opencrypto/crypto.c @@ -903,11 +903,12 @@ crypto_dispatch(struct cryptop *crp) binuptime(&crp->crp_tstamp); #endif + crp->crp_retw_id = crp->crp_sid % crypto_workers_num; + if (CRYPTOP_ASYNC(crp)) { if (crp->crp_flags & CRYPTO_F_ASYNC_KEEPORDER) { struct crypto_ret_worker *ret_worker; - crp->crp_retw_id = crp->crp_sid % crypto_workers_num; ret_worker = CRYPTO_RETW(crp->crp_retw_id); CRYPTO_RETW_LOCK(ret_worker); @@ -1001,7 +1002,7 @@ kdriver_suitable(const struct cryptocap *cap, const struct cryptkop *krp) static struct cryptocap * crypto_select_kdriver(const struct cryptkop *krp, int flags) { - struct cryptocap *cap, *best, *blocked; + struct cryptocap *cap, *best; int match, hid; CRYPTO_DRIVER_ASSERT(); @@ -1014,7 +1015,6 @@ crypto_select_kdriver(const struct cryptkop *krp, int flags) else match = CRYPTOCAP_F_SOFTWARE; best = NULL; - blocked = NULL; again: for (hid = 0; hid < crypto_drivers_num; hid++) { cap = &crypto_drivers[hid]; diff --git a/freebsd/sys/opencrypto/cryptodev.c b/freebsd/sys/opencrypto/cryptodev.c index 9d8b23dc..c24af195 100644 --- a/freebsd/sys/opencrypto/cryptodev.c +++ b/freebsd/sys/opencrypto/cryptodev.c @@ -280,14 +280,17 @@ struct csession { caddr_t key; int keylen; - u_char tmp_iv[EALG_MAX_BLOCK_LEN]; caddr_t mackey; int mackeylen; +}; + +struct cryptop_data { + struct csession *cse; - struct iovec iovec; + struct iovec iovec[1]; struct uio uio; - int error; + bool done; }; struct fcrypt { @@ -449,6 +452,7 @@ cryptof_ioctl( default: CRYPTDEB("invalid cipher"); + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); } @@ -496,6 +500,7 @@ cryptof_ioctl( break; default: CRYPTDEB("invalid mac"); + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); } @@ -509,6 +514,8 @@ cryptof_ioctl( sop->keylen < txform->minkey) { CRYPTDEB("invalid cipher parameters"); error = EINVAL; + SDT_PROBE1(opencrypto, dev, ioctl, error, + __LINE__); goto bail; } @@ -517,6 +524,8 @@ cryptof_ioctl( if ((error = copyin(sop->key, crie.cri_key, crie.cri_klen / 8))) { CRYPTDEB("invalid key"); + SDT_PROBE1(opencrypto, dev, ioctl, error, + __LINE__); goto bail; } if (thash) @@ -530,6 +539,8 @@ cryptof_ioctl( sop->mackeylen > thash->keysize) { CRYPTDEB("invalid mac key length"); error = EINVAL; + SDT_PROBE1(opencrypto, dev, ioctl, error, + __LINE__); goto bail; } @@ -539,6 +550,8 @@ cryptof_ioctl( if ((error = copyin(sop->mackey, cria.cri_key, cria.cri_klen / 8))) { CRYPTDEB("invalid mac key"); + SDT_PROBE1(opencrypto, dev, ioctl, + error, __LINE__); goto bail; } } @@ -554,6 +567,8 @@ cryptof_ioctl( error = checkforsoftware(&crid); if (error) { CRYPTDEB("checkforsoftware"); + SDT_PROBE1(opencrypto, dev, ioctl, error, + __LINE__); goto bail; } } else @@ -561,6 +576,7 @@ cryptof_ioctl( error = crypto_newsession(&sid, (txform ? &crie : &cria), crid); if (error) { CRYPTDEB("crypto_newsession"); + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } @@ -571,6 +587,7 @@ cryptof_ioctl( if (cse == NULL) { crypto_freesession(sid); error = EINVAL; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); CRYPTDEB("csecreate"); goto bail; } @@ -603,8 +620,10 @@ bail: case CIOCFSESSION: ses = *(u_int32_t *)data; cse = csefind(fcr, ses); - if (cse == NULL) + if (cse == NULL) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); + } csedelete(fcr, cse); error = csefree(cse); break; @@ -634,8 +653,10 @@ bail: case CIOCKEY32: case CIOCKEY232: #endif - if (!crypto_userasymcrypto) + if (!crypto_userasymcrypto) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EPERM); /* XXX compat? */ + } #ifdef COMPAT_FREEBSD32 if (cmd == CIOCKEY32 || cmd == CIOCKEY232) { kop = &kopc; @@ -669,8 +690,12 @@ bail: * fallback to doing them in software. */ *(int *)data = 0; - } else + } else { error = crypto_getfeat((int *)data); + if (error) + SDT_PROBE1(opencrypto, dev, ioctl, error, + __LINE__); + } break; case CIOCFINDDEV: error = cryptodev_find((struct crypt_find_op *)data); @@ -678,12 +703,15 @@ bail: case CIOCCRYPTAEAD: caead = (struct crypt_aead *)data; cse = csefind(fcr, caead->ses); - if (cse == NULL) + if (cse == NULL) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); + } error = cryptodev_aead(cse, caead, active_cred, td); break; default: error = EINVAL; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); break; } return (error); @@ -711,8 +739,36 @@ rtems_bsd_cryptof_ioctl(rtems_libio_t *iop, ioctl_command_t request, } #endif /* __rtems__ */ -static int cryptodev_cb(void *); +static int cryptodev_cb(struct cryptop *); + +static struct cryptop_data * +cod_alloc(struct csession *cse, size_t len, struct thread *td) +{ + struct cryptop_data *cod; + struct uio *uio; + + cod = malloc(sizeof(struct cryptop_data), M_XDATA, M_WAITOK | M_ZERO); + + cod->cse = cse; + uio = &cod->uio; + uio->uio_iov = cod->iovec; + uio->uio_iovcnt = 1; + uio->uio_resid = len; + uio->uio_segflg = UIO_SYSSPACE; + uio->uio_rw = UIO_WRITE; + uio->uio_td = td; + uio->uio_iov[0].iov_len = len; + uio->uio_iov[0].iov_base = malloc(len, M_XDATA, M_WAITOK); + return (cod); +} + +static void +cod_free(struct cryptop_data *cod) +{ + free(cod->uio.uio_iov[0].iov_base, M_XDATA); + free(cod, M_XDATA); +} static int cryptodev_op( @@ -721,6 +777,7 @@ cryptodev_op( struct ucred *active_cred, struct thread *td) { + struct cryptop_data *cod = NULL; struct cryptop *crp = NULL; struct cryptodesc *crde = NULL, *crda = NULL; int error; @@ -737,20 +794,10 @@ cryptodev_op( } } - cse->uio.uio_iov = &cse->iovec; - cse->uio.uio_iovcnt = 1; - cse->uio.uio_offset = 0; - cse->uio.uio_resid = cop->len; - cse->uio.uio_segflg = UIO_SYSSPACE; - cse->uio.uio_rw = UIO_WRITE; - cse->uio.uio_td = td; - cse->uio.uio_iov[0].iov_len = cop->len; - if (cse->thash) { - cse->uio.uio_iov[0].iov_len += cse->thash->hashsize; - cse->uio.uio_resid += cse->thash->hashsize; - } - cse->uio.uio_iov[0].iov_base = malloc(cse->uio.uio_iov[0].iov_len, - M_XDATA, M_WAITOK); + if (cse->thash) + cod = cod_alloc(cse, cop->len + cse->thash->hashsize, td); + else + cod = cod_alloc(cse, cop->len, td); crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL)); if (crp == NULL) { @@ -777,7 +824,7 @@ cryptodev_op( goto bail; } - if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, + if ((error = copyin(cop->src, cod->uio.uio_iov[0].iov_base, cop->len))) { SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; @@ -809,10 +856,10 @@ cryptodev_op( crp->crp_ilen = cop->len; crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM | (cop->flags & COP_F_BATCH); - crp->crp_buf = (caddr_t)&cse->uio; - crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb; + crp->crp_uio = &cod->uio; + crp->crp_callback = cryptodev_cb; crp->crp_sid = cse->sid; - crp->crp_opaque = (void *)cse; + crp->crp_opaque = cod; if (cop->iv) { if (crde == NULL) { @@ -825,12 +872,11 @@ cryptodev_op( error = EINVAL; goto bail; } - if ((error = copyin(cop->iv, cse->tmp_iv, + if ((error = copyin(cop->iv, crde->crd_iv, cse->txform->blocksize))) { SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } - bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize); crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; crde->crd_skip = 0; } else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ @@ -856,19 +902,20 @@ again: * entry and the crypto_done callback into us. */ error = crypto_dispatch(crp); - mtx_lock(&cse->lock); - if (error == 0 && (crp->crp_flags & CRYPTO_F_DONE) == 0) - error = msleep(crp, &cse->lock, PWAIT, "crydev", 0); - mtx_unlock(&cse->lock); - if (error != 0) { SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } + mtx_lock(&cse->lock); + while (!cod->done) + mtx_sleep(cod, &cse->lock, PWAIT, "crydev", 0); + mtx_unlock(&cse->lock); + if (crp->crp_etype == EAGAIN) { crp->crp_etype = 0; crp->crp_flags &= ~CRYPTO_F_DONE; + cod->done = false; goto again; } @@ -878,21 +925,15 @@ again: goto bail; } - if (cse->error) { - SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); - error = cse->error; - goto bail; - } - if (cop->dst && - (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, + (error = copyout(cod->uio.uio_iov[0].iov_base, cop->dst, cop->len))) { SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } if (cop->mac && - (error = copyout((caddr_t)cse->uio.uio_iov[0].iov_base + cop->len, + (error = copyout((caddr_t)cod->uio.uio_iov[0].iov_base + cop->len, cop->mac, cse->thash->hashsize))) { SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; @@ -901,8 +942,8 @@ again: bail: if (crp) crypto_freereq(crp); - if (cse->uio.uio_iov[0].iov_base) - free(cse->uio.uio_iov[0].iov_base, M_XDATA); + if (cod) + cod_free(cod); return (error); } @@ -914,34 +955,29 @@ cryptodev_aead( struct ucred *active_cred, struct thread *td) { - struct uio *uio; + struct cryptop_data *cod = NULL; struct cryptop *crp = NULL; struct cryptodesc *crde = NULL, *crda = NULL; int error; - if (caead->len > 256*1024-4 || caead->aadlen > 256*1024-4) + if (caead->len > 256*1024-4 || caead->aadlen > 256*1024-4) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (E2BIG); + } if (cse->txform == NULL || cse->thash == NULL || caead->tag == NULL || - (caead->len % cse->txform->blocksize) != 0) + (caead->len % cse->txform->blocksize) != 0) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); + } - uio = &cse->uio; - uio->uio_iov = &cse->iovec; - uio->uio_iovcnt = 1; - uio->uio_offset = 0; - uio->uio_resid = caead->aadlen + caead->len + cse->thash->hashsize; - uio->uio_segflg = UIO_SYSSPACE; - uio->uio_rw = UIO_WRITE; - uio->uio_td = td; - uio->uio_iov[0].iov_len = uio->uio_resid; - - uio->uio_iov[0].iov_base = malloc(uio->uio_iov[0].iov_len, - M_XDATA, M_WAITOK); + cod = cod_alloc(cse, caead->aadlen + caead->len + cse->thash->hashsize, + td); crp = crypto_getreq(2); if (crp == NULL) { error = ENOMEM; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } @@ -953,13 +989,17 @@ cryptodev_aead( crde = crda->crd_next; } - if ((error = copyin(caead->aad, cse->uio.uio_iov[0].iov_base, - caead->aadlen))) + if ((error = copyin(caead->aad, cod->uio.uio_iov[0].iov_base, + caead->aadlen))) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; + } - if ((error = copyin(caead->src, (char *)cse->uio.uio_iov[0].iov_base + - caead->aadlen, caead->len))) + if ((error = copyin(caead->src, (char *)cod->uio.uio_iov[0].iov_base + + caead->aadlen, caead->len))) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; + } /* * For GCM, crd_len covers only the AAD. For other ciphers @@ -992,20 +1032,22 @@ cryptodev_aead( crp->crp_ilen = caead->aadlen + caead->len; crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM | (caead->flags & COP_F_BATCH); - crp->crp_buf = (caddr_t)&cse->uio.uio_iov; - crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb; + crp->crp_uio = &cod->uio; + crp->crp_callback = cryptodev_cb; crp->crp_sid = cse->sid; - crp->crp_opaque = (void *)cse; + crp->crp_opaque = cod; if (caead->iv) { - if (caead->ivlen > sizeof cse->tmp_iv) { + if (caead->ivlen > sizeof(crde->crd_iv)) { error = EINVAL; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } - if ((error = copyin(caead->iv, cse->tmp_iv, caead->ivlen))) + if ((error = copyin(caead->iv, crde->crd_iv, caead->ivlen))) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; - bcopy(cse->tmp_iv, crde->crd_iv, caead->ivlen); + } crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; } else { crde->crd_flags |= CRD_F_IV_PRESENT; @@ -1013,9 +1055,11 @@ cryptodev_aead( crde->crd_len -= cse->txform->blocksize; } - if ((error = copyin(caead->tag, (caddr_t)cse->uio.uio_iov[0].iov_base + - caead->len + caead->aadlen, cse->thash->hashsize))) + if ((error = copyin(caead->tag, (caddr_t)cod->uio.uio_iov[0].iov_base + + caead->len + caead->aadlen, cse->thash->hashsize))) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; + } again: /* * Let the dispatch run unlocked, then, interlock against the @@ -1025,56 +1069,64 @@ again: * entry and the crypto_done callback into us. */ error = crypto_dispatch(crp); + if (error != 0) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); + goto bail; + } + mtx_lock(&cse->lock); - if (error == 0 && (crp->crp_flags & CRYPTO_F_DONE) == 0) - error = msleep(crp, &cse->lock, PWAIT, "crydev", 0); + while (!cod->done) + mtx_sleep(cod, &cse->lock, PWAIT, "crydev", 0); mtx_unlock(&cse->lock); - if (error != 0) - goto bail; - if (crp->crp_etype == EAGAIN) { crp->crp_etype = 0; crp->crp_flags &= ~CRYPTO_F_DONE; + cod->done = false; goto again; } if (crp->crp_etype != 0) { error = crp->crp_etype; - goto bail; - } - - if (cse->error) { - error = cse->error; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } if (caead->dst && (error = copyout( - (caddr_t)cse->uio.uio_iov[0].iov_base + caead->aadlen, caead->dst, - caead->len))) + (caddr_t)cod->uio.uio_iov[0].iov_base + caead->aadlen, caead->dst, + caead->len))) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; + } - if ((error = copyout((caddr_t)cse->uio.uio_iov[0].iov_base + - caead->aadlen + caead->len, caead->tag, cse->thash->hashsize))) + if ((error = copyout((caddr_t)cod->uio.uio_iov[0].iov_base + + caead->aadlen + caead->len, caead->tag, cse->thash->hashsize))) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; + } bail: crypto_freereq(crp); - free(cse->uio.uio_iov[0].iov_base, M_XDATA); + if (cod) + cod_free(cod); return (error); } static int -cryptodev_cb(void *op) +cryptodev_cb(struct cryptop *crp) { - struct cryptop *crp = (struct cryptop *) op; - struct csession *cse = (struct csession *)crp->crp_opaque; + struct cryptop_data *cod = crp->crp_opaque; - mtx_lock(&cse->lock); - cse->error = crp->crp_etype; - wakeup_one(crp); - mtx_unlock(&cse->lock); + /* + * Lock to ensure the wakeup() is not missed by the loops + * waiting on cod->done in cryptodev_op() and + * cryptodev_aead(). + */ + mtx_lock(&cod->cse->lock); + cod->done = true; + mtx_unlock(&cod->cse->lock); + wakeup(cod); return (0); } @@ -1095,6 +1147,7 @@ cryptodev_key(struct crypt_kop *kop) int in, out, size, i; if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EFBIG); } @@ -1104,30 +1157,38 @@ cryptodev_key(struct crypt_kop *kop) case CRK_MOD_EXP: if (in == 3 && out == 1) break; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); case CRK_MOD_EXP_CRT: if (in == 6 && out == 1) break; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); case CRK_DSA_SIGN: if (in == 5 && out == 2) break; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); case CRK_DSA_VERIFY: if (in == 7 && out == 0) break; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); case CRK_DH_COMPUTE_KEY: if (in == 3 && out == 1) break; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); default: + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); } krp = (struct cryptkop *)malloc(sizeof *krp, M_XDATA, M_WAITOK|M_ZERO); - if (!krp) + if (!krp) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (ENOMEM); + } krp->krp_op = kop->crk_op; krp->krp_status = kop->crk_status; krp->krp_iparams = kop->crk_iparams; @@ -1137,9 +1198,11 @@ cryptodev_key(struct crypt_kop *kop) krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb; for (i = 0; i < CRK_MAXPARAM; i++) { - if (kop->crk_param[i].crp_nbits > 65536) + if (kop->crk_param[i].crp_nbits > 65536) { /* Limit is the same as in OpenBSD */ + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto fail; + } krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits; } for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) { @@ -1150,22 +1213,28 @@ cryptodev_key(struct crypt_kop *kop) if (i >= krp->krp_iparams) continue; error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size); - if (error) + if (error) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto fail; + } } error = crypto_kdispatch(krp); - if (error) + if (error) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto fail; + } error = tsleep(krp, PSOCK, "crydev", 0); if (error) { /* XXX can this happen? if so, how do we recover? */ + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto fail; } kop->crk_crid = krp->krp_crid; /* device that did the work */ if (krp->krp_status != 0) { error = krp->krp_status; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto fail; } @@ -1174,8 +1243,10 @@ cryptodev_key(struct crypt_kop *kop) if (size == 0) continue; error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size); - if (error) + if (error) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto fail; + } } fail: diff --git a/freebsd/sys/opencrypto/cryptodev.h b/freebsd/sys/opencrypto/cryptodev.h index cfbda068..f929d10a 100644 --- a/freebsd/sys/opencrypto/cryptodev.h +++ b/freebsd/sys/opencrypto/cryptodev.h @@ -425,8 +425,12 @@ struct cryptop { * if CRYPTO_F_ASYNC flags is set */ - caddr_t crp_buf; /* Data to be processed */ - caddr_t crp_opaque; /* Opaque pointer, passed along */ + union { + caddr_t crp_buf; /* Data to be processed */ + struct mbuf *crp_mbuf; + struct uio *crp_uio; + }; + void * crp_opaque; /* Opaque pointer, passed along */ struct cryptodesc *crp_desc; /* Linked list of processing descriptors */ int (*crp_callback)(struct cryptop *); /* Callback function */ @@ -538,5 +542,6 @@ extern void crypto_copydata(int flags, caddr_t buf, int off, int size, caddr_t out); extern int crypto_apply(int flags, caddr_t buf, int off, int len, int (*f)(void *, void *, u_int), void *arg); + #endif /* _KERNEL */ #endif /* _CRYPTO_CRYPTO_H_ */ diff --git a/freebsd/sys/opencrypto/cryptosoft.c b/freebsd/sys/opencrypto/cryptosoft.c index f0858b3c..b2828452 100644 --- a/freebsd/sys/opencrypto/cryptosoft.c +++ b/freebsd/sys/opencrypto/cryptosoft.c @@ -609,9 +609,7 @@ swcr_authenc(struct cryptop *crp) bzero(blk, blksz); crypto_copydata(crp->crp_flags, buf, crde->crd_skip + i, len, blk); - if (!(crde->crd_flags & CRD_F_ENCRYPT)) { - exf->decrypt(swe->sw_kschedule, blk); - } + exf->decrypt(swe->sw_kschedule, blk); crypto_copyback(crp->crp_flags, buf, crde->crd_skip + i, len, blk); } @@ -988,7 +986,6 @@ swcr_freesession_locked(device_t dev, u_int64_t tid) struct swcr_data *swd; struct enc_xform *txf; struct auth_hash *axf; - struct comp_algo *cxf; u_int32_t sid = CRYPTO_SESID2LID(tid); if (sid > swcr_sesnum || swcr_sessions == NULL || @@ -1063,7 +1060,7 @@ swcr_freesession_locked(device_t dev, u_int64_t tid) break; case CRYPTO_DEFLATE_COMP: - cxf = swd->sw_cxf; + /* Nothing to do */ break; } diff --git a/freebsd/sys/opencrypto/xform_userland.h b/freebsd/sys/opencrypto/xform_userland.h index 04266dc8..ef4845aa 100644 --- a/freebsd/sys/opencrypto/xform_userland.h +++ b/freebsd/sys/opencrypto/xform_userland.h @@ -34,7 +34,7 @@ #define KMALLOC(size, type, flags) malloc(size, type, flags) #define KFREE(ptr, type) free(ptr, type) #else /* not _KERNEL */ -#ifdef _STAND +#ifdef _STANDALONE #include <stand.h> #else /* !_STAND */ #include <stdlib.h> diff --git a/freebsd/sys/powerpc/include/machine/spr.h b/freebsd/sys/powerpc/include/machine/spr.h index 3e479415..db94753b 100644 --- a/freebsd/sys/powerpc/include/machine/spr.h +++ b/freebsd/sys/powerpc/include/machine/spr.h @@ -199,6 +199,9 @@ #define FSL_E300C3 0x8085 #define FSL_E300C4 0x8086 +#define SPR_LPCR 0x13e /* Logical Partitioning Control */ +#define LPCR_LPES 0x008 /* Bit 60 */ + #define SPR_EPCR 0x133 #define EPCR_EXTGS 0x80000000 #define EPCR_DTLBGS 0x40000000 @@ -673,19 +676,7 @@ #define PMC970N_CYCLES 0xf /* Processor cycles */ #define PMC970N_ICOMP 0x9 /* Instructions completed */ -#if defined(AIM) - -#define SPR_ESR 0x3d4 /* 4.. Exception Syndrome Register */ -#define ESR_MCI 0x80000000 /* Machine check - instruction */ -#define ESR_PIL 0x08000000 /* Program interrupt - illegal */ -#define ESR_PPR 0x04000000 /* Program interrupt - privileged */ -#define ESR_PTR 0x02000000 /* Program interrupt - trap */ -#define ESR_ST 0x01000000 /* Store operation */ -#define ESR_DST 0x00800000 /* Data storage interrupt - store fault */ -#define ESR_DIZ 0x00800000 /* Data/instruction storage interrupt - zone fault */ -#define ESR_U0F 0x00008000 /* Data storage interrupt - U0 fault */ - -#elif defined(BOOKE) +#if defined(BOOKE) #define SPR_MCARU 0x239 /* ..8 Machine Check Address register upper bits */ #define SPR_MCSR 0x23c /* ..8 Machine Check Syndrome register */ diff --git a/freebsd/sys/sys/_domainset.h b/freebsd/sys/sys/_domainset.h new file mode 100644 index 00000000..30d8501c --- /dev/null +++ b/freebsd/sys/sys/_domainset.h @@ -0,0 +1,60 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2017, Jeffrey Roberson <jeff@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS__DOMAINSET_H_ +#define _SYS__DOMAINSET_H_ + +#include <sys/_bitset.h> + +#ifdef _KERNEL +#define DOMAINSET_SETSIZE MAXMEMDOM +#endif + +#define DOMAINSET_MAXSIZE 256 + +#ifndef DOMAINSET_SETSIZE +#define DOMAINSET_SETSIZE DOMAINSET_MAXSIZE +#endif + +BITSET_DEFINE(_domainset, DOMAINSET_SETSIZE); +typedef struct _domainset domainset_t; + +/* + * This structure is intended to be embedded in objects which have policy + * attributes. Each object keeps its own iterator so round-robin is + * synchronized and accurate. + */ +struct domainset; +struct domainset_ref { + struct domainset * volatile dr_policy; + int dr_iterator; +}; + +#endif /* !_SYS__DOMAINSET_H_ */ diff --git a/freebsd/sys/sys/bus_dma.h b/freebsd/sys/sys/bus_dma.h index c5799661..2bf46ca8 100644 --- a/freebsd/sys/sys/bus_dma.h +++ b/freebsd/sys/sys/bus_dma.h @@ -1,7 +1,7 @@ /* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */ /*- - * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * SPDX-License-Identifier: (BSD-2-Clause-NetBSD AND BSD-4-Clause) * * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. * All rights reserved. @@ -176,6 +176,14 @@ int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, void *lockfuncarg, bus_dma_tag_t *dmat); +/* + * Set the memory domain to be used for allocations. + * + * Automatic for PCI devices. Must be set prior to creating maps or + * allocating memory. + */ +int bus_dma_tag_set_domain(bus_dma_tag_t dmat, int domain); + int bus_dma_tag_destroy(bus_dma_tag_t dmat); /* diff --git a/freebsd/sys/sys/capsicum.h b/freebsd/sys/sys/capsicum.h index ae466952..847b4478 100644 --- a/freebsd/sys/sys/capsicum.h +++ b/freebsd/sys/sys/capsicum.h @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2008-2010, 2015 Robert N. M. Watson * Copyright (c) 2012 FreeBSD Foundation * All rights reserved. diff --git a/freebsd/sys/sys/conf.h b/freebsd/sys/sys/conf.h index 7f240f68..3980eba2 100644 --- a/freebsd/sys/sys/conf.h +++ b/freebsd/sys/sys/conf.h @@ -367,8 +367,8 @@ struct dumperinfo { off_t mediasize; /* Space available in bytes. */ void *blockbuf; /* Buffer for padding shorter dump blocks */ off_t dumpoff; /* Offset of ongoing kernel dump. */ - struct kerneldumpcrypto *kdc; /* Kernel dump crypto. */ - struct kerneldumpgz *kdgz; /* Kernel dump compression. */ + struct kerneldumpcrypto *kdcrypto; /* Kernel dump crypto. */ + struct kerneldumpcomp *kdcomp; /* Kernel dump compression. */ }; #ifndef __rtems__ diff --git a/freebsd/sys/sys/domainset.h b/freebsd/sys/sys/domainset.h new file mode 100644 index 00000000..6580e1ed --- /dev/null +++ b/freebsd/sys/sys/domainset.h @@ -0,0 +1,102 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2017, Jeffrey Roberson <jeff@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_DOMAINSETSET_H_ +#define _SYS_DOMAINSETSET_H_ + +#include <sys/_domainset.h> + +#include <sys/bitset.h> + +#define _NDOMAINSETBITS _BITSET_BITS +#define _NDOMAINSETWORDS __bitset_words(DOMAINSET_SETSIZE) + +#define DOMAINSETSETBUFSIZ ((2 + sizeof(long) * 2) * _NDOMAINSETWORDS) + +#define DOMAINSET_CLR(n, p) BIT_CLR(DOMAINSET_SETSIZE, n, p) +#define DOMAINSET_COPY(f, t) BIT_COPY(DOMAINSET_SETSIZE, f, t) +#define DOMAINSET_ISSET(n, p) BIT_ISSET(DOMAINSET_SETSIZE, n, p) +#define DOMAINSET_SET(n, p) BIT_SET(DOMAINSET_SETSIZE, n, p) +#define DOMAINSET_ZERO(p) BIT_ZERO(DOMAINSET_SETSIZE, p) +#define DOMAINSET_FILL(p) BIT_FILL(DOMAINSET_SETSIZE, p) +#define DOMAINSET_SETOF(n, p) BIT_SETOF(DOMAINSET_SETSIZE, n, p) +#define DOMAINSET_EMPTY(p) BIT_EMPTY(DOMAINSET_SETSIZE, p) +#define DOMAINSET_ISFULLSET(p) BIT_ISFULLSET(DOMAINSET_SETSIZE, p) +#define DOMAINSET_SUBSET(p, c) BIT_SUBSET(DOMAINSET_SETSIZE, p, c) +#define DOMAINSET_OVERLAP(p, c) BIT_OVERLAP(DOMAINSET_SETSIZE, p, c) +#define DOMAINSET_CMP(p, c) BIT_CMP(DOMAINSET_SETSIZE, p, c) +#define DOMAINSET_OR(d, s) BIT_OR(DOMAINSET_SETSIZE, d, s) +#define DOMAINSET_AND(d, s) BIT_AND(DOMAINSET_SETSIZE, d, s) +#define DOMAINSET_NAND(d, s) BIT_NAND(DOMAINSET_SETSIZE, d, s) +#define DOMAINSET_CLR_ATOMIC(n, p) BIT_CLR_ATOMIC(DOMAINSET_SETSIZE, n, p) +#define DOMAINSET_SET_ATOMIC(n, p) BIT_SET_ATOMIC(DOMAINSET_SETSIZE, n, p) +#define DOMAINSET_SET_ATOMIC_ACQ(n, p) \ + BIT_SET_ATOMIC_ACQ(DOMAINSET_SETSIZE, n, p) +#define DOMAINSET_AND_ATOMIC(n, p) BIT_AND_ATOMIC(DOMAINSET_SETSIZE, n, p) +#define DOMAINSET_OR_ATOMIC(d, s) BIT_OR_ATOMIC(DOMAINSET_SETSIZE, d, s) +#define DOMAINSET_COPY_STORE_REL(f, t) \ + BIT_COPY_STORE_REL(DOMAINSET_SETSIZE, f, t) +#define DOMAINSET_FFS(p) BIT_FFS(DOMAINSET_SETSIZE, p) +#define DOMAINSET_FLS(p) BIT_FLS(DOMAINSET_SETSIZE, p) +#define DOMAINSET_COUNT(p) BIT_COUNT(DOMAINSET_SETSIZE, p) +#define DOMAINSET_FSET BITSET_FSET(_NDOMAINSETWORDS) +#define DOMAINSET_T_INITIALIZER BITSET_T_INITIALIZER + +#define DOMAINSET_POLICY_INVALID 0 +#define DOMAINSET_POLICY_ROUNDROBIN 1 +#define DOMAINSET_POLICY_FIRSTTOUCH 2 +#define DOMAINSET_POLICY_PREFER 3 +#define DOMAINSET_POLICY_MAX DOMAINSET_POLICY_PREFER + +#ifdef _KERNEL +#include <sys/queue.h> +LIST_HEAD(domainlist, domainset); + +struct domainset { + LIST_ENTRY(domainset) ds_link; + domainset_t ds_mask; /* allowed domains. */ + uint16_t ds_policy; /* Policy type. */ + int16_t ds_prefer; /* Preferred domain or -1. */ + uint16_t ds_cnt; /* popcnt from above. */ + uint16_t ds_max; /* Maximum domain in set. */ +}; + +void domainset_zero(void); + +#else +__BEGIN_DECLS +int cpuset_getdomain(cpulevel_t, cpuwhich_t, id_t, size_t, domainset_t *, + int *); +int cpuset_setdomain(cpulevel_t, cpuwhich_t, id_t, size_t, + const domainset_t *, int); + +__END_DECLS +#endif +#endif /* !_SYS_DOMAINSETSET_H_ */ diff --git a/freebsd/sys/sys/gtaskqueue.h b/freebsd/sys/sys/gtaskqueue.h index e8519637..41094603 100644 --- a/freebsd/sys/sys/gtaskqueue.h +++ b/freebsd/sys/sys/gtaskqueue.h @@ -1,6 +1,8 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2014 Jeffrey Roberson <jeff@freebsd.org> - * Copyright (c) 2016 Matthew Macy <mmacy@nextbsd.org> + * Copyright (c) 2016 Matthew Macy <mmacy@mattmacy.io> * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/freebsd/sys/sys/kernel.h b/freebsd/sys/sys/kernel.h index 1cc03275..81ceca04 100644 --- a/freebsd/sys/sys/kernel.h +++ b/freebsd/sys/sys/kernel.h @@ -54,6 +54,9 @@ /* for intrhook below */ #include <sys/queue.h> +/* for timestamping SYSINITs; other files may assume this is included here */ +#include <sys/tslog.h> + /* Global variables for the kernel. */ #ifndef __rtems__ @@ -240,6 +243,35 @@ struct sysinit { * correct warnings when -Wcast-qual is used. * */ +#ifdef TSLOG +struct sysinit_tslog { + sysinit_cfunc_t func; + const void * data; + const char * name; +}; +static inline void +sysinit_tslog_shim(const void * data) +{ + const struct sysinit_tslog * x = data; + + TSRAW(curthread, TS_ENTER, "SYSINIT", x->name); + (x->func)(x->data); + TSRAW(curthread, TS_EXIT, "SYSINIT", x->name); +} +#define C_SYSINIT(uniquifier, subsystem, order, func, ident) \ + static struct sysinit_tslog uniquifier ## _sys_init_tslog = { \ + func, \ + (ident), \ + #uniquifier \ + }; \ + static struct sysinit uniquifier ## _sys_init = { \ + subsystem, \ + order, \ + sysinit_tslog_shim, \ + &uniquifier ## _sys_init_tslog \ + }; \ + DATA_SET(sysinit_set,uniquifier ## _sys_init) +#else #ifndef __rtems__ #define C_SYSINIT(uniquifier, subsystem, order, func, ident) \ static struct sysinit uniquifier ## _sys_init = { \ @@ -274,6 +306,7 @@ struct sysinit { #define SYSINIT_DOMAIN_REFERENCE(dom) \ SYSINIT_REFERENCE(domain_add_ ## dom) #endif /* __rtems__ */ +#endif #define SYSINIT(uniquifier, subsystem, order, func, ident) \ C_SYSINIT(uniquifier, subsystem, order, \ diff --git a/freebsd/sys/sys/libkern.h b/freebsd/sys/sys/libkern.h index 4d043f5a..dc24036b 100644 --- a/freebsd/sys/sys/libkern.h +++ b/freebsd/sys/sys/libkern.h @@ -86,6 +86,13 @@ hex2ascii(int hex) return (hex2ascii_data[hex]); } +static inline bool +validbcd(int bcd) +{ + + return (bcd == 0 || (bcd > 0 && bcd <= 0x99 && bcd2bin_data[bcd] != 0)); +} + static __inline int imax(int a, int b) { return (a > b ? a : b); } static __inline int imin(int a, int b) { return (a < b ? a : b); } static __inline long lmax(long a, long b) { return (a > b ? a : b); } diff --git a/freebsd/sys/sys/malloc.h b/freebsd/sys/sys/malloc.h index c5ab6125..1920ff69 100644 --- a/freebsd/sys/sys/malloc.h +++ b/freebsd/sys/sys/malloc.h @@ -41,6 +41,7 @@ #include <sys/queue.h> #include <sys/_lock.h> #include <sys/_mutex.h> +#include <machine/_limits.h> #define MINALLOCSIZE UMA_SMALLEST_UNIT @@ -156,13 +157,6 @@ MALLOC_DECLARE(M_DEVBUF); MALLOC_DECLARE(M_TEMP); /* - * Deprecated macro versions of not-quite-malloc() and free(). - */ -#define MALLOC(space, cast, size, type, flags) \ - ((space) = (cast)malloc((u_long)(size), (type), (flags))) -#define FREE(addr, type) free((addr), (type)) - -/* * XXX this should be declared in <sys/uio.h>, but that tends to fail * because <sys/uio.h> is included in a header before the source file * has a chance to include <sys/malloc.h> to get MALLOC_DECLARE() defined. @@ -181,21 +175,45 @@ void *contigmalloc(unsigned long size, struct malloc_type *type, int flags, vm_paddr_t low, vm_paddr_t high, unsigned long alignment, vm_paddr_t boundary) __malloc_like __result_use_check __alloc_size(1) __alloc_align(6); +void *contigmalloc_domain(unsigned long size, struct malloc_type *type, + int domain, int flags, vm_paddr_t low, vm_paddr_t high, + unsigned long alignment, vm_paddr_t boundary) + __malloc_like __result_use_check __alloc_size(1) __alloc_align(6); void free(void *addr, struct malloc_type *type); -void *malloc(unsigned long size, struct malloc_type *type, int flags) - __malloc_like __result_use_check __alloc_size(1); +void free_domain(void *addr, struct malloc_type *type); +void *malloc(size_t size, struct malloc_type *type, int flags) __malloc_like + __result_use_check __alloc_size(1); +void *malloc_domain(size_t size, struct malloc_type *type, int domain, + int flags) __malloc_like __result_use_check __alloc_size(1); +void *mallocarray(size_t nmemb, size_t size, struct malloc_type *type, + int flags) __malloc_like __result_use_check + __alloc_size2(1, 2); void malloc_init(void *); int malloc_last_fail(void); void malloc_type_allocated(struct malloc_type *type, unsigned long size); void malloc_type_freed(struct malloc_type *type, unsigned long size); void malloc_type_list(malloc_type_list_func_t *, void *); void malloc_uninit(void *); -void *realloc(void *addr, unsigned long size, struct malloc_type *type, - int flags) __result_use_check __alloc_size(2); -void *reallocf(void *addr, unsigned long size, struct malloc_type *type, - int flags) __alloc_size(2); +void *realloc(void *addr, size_t size, struct malloc_type *type, int flags) + __result_use_check __alloc_size(2); +void *reallocf(void *addr, size_t size, struct malloc_type *type, int flags) + __result_use_check __alloc_size(2); struct malloc_type *malloc_desc2type(const char *desc); + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 8 / 2)) +static inline bool +WOULD_OVERFLOW(size_t nmemb, size_t size) +{ + + return ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && __SIZE_T_MAX / nmemb < size); +} +#undef MUL_NO_OVERFLOW #endif /* _KERNEL */ #endif /* !_SYS_MALLOC_H_ */ diff --git a/freebsd/sys/sys/mount.h b/freebsd/sys/sys/mount.h index 362c54e9..9d499004 100644 --- a/freebsd/sys/sys/mount.h +++ b/freebsd/sys/sys/mount.h @@ -40,6 +40,7 @@ #ifdef _KERNEL #include <sys/lock.h> #include <sys/lockmgr.h> +#include <sys/tslog.h> #include <sys/_mutex.h> #include <sys/_sx.h> #endif @@ -708,9 +709,11 @@ vfs_statfs_t __vfs_statfs; #define VFS_MOUNT(MP) ({ \ int _rc; \ \ + TSRAW(curthread, TS_ENTER, "VFS_MOUNT", (MP)->mnt_vfc->vfc_name);\ VFS_PROLOGUE(MP); \ _rc = (*(MP)->mnt_op->vfs_mount)(MP); \ VFS_EPILOGUE(MP); \ + TSRAW(curthread, TS_EXIT, "VFS_MOUNT", (MP)->mnt_vfc->vfc_name);\ _rc; }) #define VFS_UNMOUNT(MP, FORCE) ({ \ diff --git a/freebsd/sys/sys/mouse.h b/freebsd/sys/sys/mouse.h index 9fd1d6d8..a1f950cf 100644 --- a/freebsd/sys/sys/mouse.h +++ b/freebsd/sys/sys/mouse.h @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-1-Clause + * * Copyright (c) 1992, 1993 Erik Forsberg. * Copyright (c) 1996, 1997 Kazutaka YOKOTA * All rights reserved. @@ -135,6 +137,7 @@ typedef struct synapticshw { int maximumYCoord; int infoXupmm; int infoYupmm; + int forcePad; } synapticshw_t; /* iftype */ diff --git a/freebsd/sys/sys/nv.h b/freebsd/sys/sys/nv.h index fcea2b3e..bf40f8f3 100644 --- a/freebsd/sys/sys/nv.h +++ b/freebsd/sys/sys/nv.h @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2009-2013 The FreeBSD Foundation * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo@FreeBSD.org> * All rights reserved. diff --git a/freebsd/sys/sys/proc.h b/freebsd/sys/sys/proc.h index 7178c316..ab292769 100644 --- a/freebsd/sys/sys/proc.h +++ b/freebsd/sys/sys/proc.h @@ -62,11 +62,18 @@ #include <sys/time.h> /* For structs itimerval, timeval. */ #else #include <sys/pcpu.h> +#include <sys/systm.h> #endif #include <sys/ucontext.h> #include <sys/ucred.h> -#include <sys/_vm_domain.h> +#include <sys/types.h> +#include <sys/domainset.h> + #include <machine/proc.h> /* Machine-dependent proc substruct. */ +#ifdef _KERNEL +#include <machine/cpu.h> +#endif + /* * One structure allocated per session. @@ -179,11 +186,14 @@ struct procdesc; struct racct; struct sbuf; struct sleepqueue; +struct socket; struct syscall_args; struct td_sched; struct thread; struct trapframe; struct turnstile; +struct vm_map; +struct vm_map_entry; /* * XXX: Does this belong in resource.h or resourcevar.h instead? @@ -239,6 +249,7 @@ struct thread { TAILQ_ENTRY(thread) td_lockq; /* (t) Lock queue. */ LIST_ENTRY(thread) td_hash; /* (d) Hash chain. */ struct cpuset *td_cpuset; /* (t) CPU affinity mask. */ + struct domainset_ref td_domain; /* (a) NUMA policy */ #endif /* __rtems__ */ struct seltd *td_sel; /* Select queue/channel. */ struct sleepqueue *td_sleepqueue; /* (k) Associated sleep queue. */ @@ -246,7 +257,6 @@ struct thread { struct turnstile *td_turnstile; /* (k) Associated turnstile. */ struct rl_q_entry *td_rlqe; /* (k) Associated range lock entry. */ struct umtx_q *td_umtxq; /* (c?) Link for when we're blocked. */ - struct vm_domain_policy td_vm_dom_policy; /* (c) current numa domain policy */ lwpid_t td_tid; /* (b) Thread ID. */ sigqueue_t td_sigqueue; /* (c) Sigs arrived, not delivered. */ #define td_siglist td_sigqueue.sq_signals @@ -315,7 +325,6 @@ struct thread { pid_t td_dbg_forked; /* (c) Child pid for debugger. */ u_int td_vp_reserv; /* (k) Count of reserved vnodes. */ int td_no_sleeping; /* (k) Sleeping disabled count. */ - int td_dom_rr_idx; /* (k) RR Numa domain selection. */ void *td_su; /* (k) FFS SU private */ sbintime_t td_sleeptimo; /* (t) Sleep timeout. */ int td_rtcgen; /* (s) rtc_generation of abs. sleep */ @@ -698,7 +707,6 @@ struct proc { uint64_t p_prev_runtime; /* (c) Resource usage accounting. */ struct racct *p_racct; /* (b) Resource accounting. */ int p_throttled; /* (c) Flag for racct pcpu throttling */ - struct vm_domain_policy p_vm_dom_policy; /* (c) process default VM domain, or -1 */ /* * An orphan is the child that has beed re-parented to the * debugger as a result of attaching to it. Need to keep @@ -1060,6 +1068,8 @@ void fork_exit(void (*)(void *, struct trapframe *), void *, struct trapframe *); void fork_return(struct thread *, struct trapframe *); int inferior(struct proc *p); +void kern_proc_vmmap_resident(struct vm_map *map, struct vm_map_entry *entry, + int *resident_count, bool *super); #ifndef __rtems__ void kern_yield(int); void kick_proc0(void); diff --git a/freebsd/sys/sys/random.h b/freebsd/sys/sys/random.h index b022f5a3..78acaf9d 100644 --- a/freebsd/sys/sys/random.h +++ b/freebsd/sys/sys/random.h @@ -104,6 +104,7 @@ enum random_entropy_source { RANDOM_PURE_RNDTEST, RANDOM_PURE_VIRTIO, RANDOM_PURE_BROADCOM, + RANDOM_PURE_CCP, ENTROPYSOURCE }; diff --git a/freebsd/sys/sys/rman.h b/freebsd/sys/sys/rman.h index 4de6022f..9c2f4653 100644 --- a/freebsd/sys/sys/rman.h +++ b/freebsd/sys/sys/rman.h @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: MIT + * * Copyright 1998 Massachusetts Institute of Technology * * Permission to use, copy, modify, and distribute this software and diff --git a/freebsd/sys/sys/sf_buf.h b/freebsd/sys/sys/sf_buf.h index 08f1d9d7..b4ea671a 100644 --- a/freebsd/sys/sys/sf_buf.h +++ b/freebsd/sys/sys/sf_buf.h @@ -77,9 +77,6 @@ struct sfstat { /* sendfile statistics */ * that do no invalidate cache on the rest of CPUs. * SFBUF_NOMD This machine doesn't have machine/sf_buf.h * - * SFBUF_OPTIONAL_DIRECT_MAP Value of this define is used as boolean - * variable that tells whether machine is - * capable of direct map or not at runtime. * SFBUF_MAP This machine provides its own sf_buf_map() and * sf_buf_unmap(). * SFBUF_PROCESS_PAGE This machine provides sf_buf_process_page() @@ -109,9 +106,6 @@ struct sf_buf; #ifndef SFBUF_NOMD #include <machine/sf_buf.h> #endif -#ifdef SFBUF_OPTIONAL_DIRECT_MAP -#include <machine/md_var.h> -#endif #ifdef SFBUF struct sf_buf *sf_buf_alloc(struct vm_page *, int); @@ -121,10 +115,8 @@ void sf_buf_ref(struct sf_buf *); static inline vm_offset_t sf_buf_kva(struct sf_buf *sf) { -#ifdef SFBUF_OPTIONAL_DIRECT_MAP - if (SFBUF_OPTIONAL_DIRECT_MAP) - return (SFBUF_PHYS_DMAP(VM_PAGE_TO_PHYS((vm_page_t)sf))); -#endif + if (PMAP_HAS_DMAP) + return (PHYS_TO_DMAP(VM_PAGE_TO_PHYS((vm_page_t)sf))); return (sf->kva); } @@ -132,10 +124,8 @@ sf_buf_kva(struct sf_buf *sf) static inline vm_page_t sf_buf_page(struct sf_buf *sf) { -#ifdef SFBUF_OPTIONAL_DIRECT_MAP - if (SFBUF_OPTIONAL_DIRECT_MAP) + if (PMAP_HAS_DMAP) return ((vm_page_t)sf); -#endif return (sf->m); } diff --git a/freebsd/sys/sys/smp.h b/freebsd/sys/sys/smp.h index f1950fa2..aa0c3119 100644 --- a/freebsd/sys/sys/smp.h +++ b/freebsd/sys/sys/smp.h @@ -155,10 +155,13 @@ struct cpu_group *smp_topo_find(struct cpu_group *top, int cpu); extern void (*cpustop_restartfunc)(void); extern int smp_cpus; -extern volatile cpuset_t started_cpus; -extern volatile cpuset_t stopped_cpus; -extern volatile cpuset_t suspended_cpus; -extern cpuset_t hlt_cpus_mask; +/* The suspend/resume cpusets are x86 only, but minimize ifdefs. */ +extern volatile cpuset_t resuming_cpus; /* woken up cpus in suspend pen */ +extern volatile cpuset_t started_cpus; /* cpus to let out of stop pen */ +extern volatile cpuset_t stopped_cpus; /* cpus in stop pen */ +extern volatile cpuset_t suspended_cpus; /* cpus [near] sleeping in susp pen */ +extern volatile cpuset_t toresume_cpus; /* cpus to let out of suspend pen */ +extern cpuset_t hlt_cpus_mask; /* XXX 'mask' is detail in old impl */ extern cpuset_t logical_cpus_mask; #endif /* SMP */ diff --git a/freebsd/sys/sys/socketvar.h b/freebsd/sys/sys/socketvar.h index d58ac2ea..f877a0df 100644 --- a/freebsd/sys/sys/socketvar.h +++ b/freebsd/sys/sys/socketvar.h @@ -71,7 +71,7 @@ struct socket; * (a) constant after allocation, no locking required. * (b) locked by SOCK_LOCK(so). * (cr) locked by SOCKBUF_LOCK(&so->so_rcv). - * (cs) locked by SOCKBUF_LOCK(&so->so_rcv). + * (cs) locked by SOCKBUF_LOCK(&so->so_snd). * (e) locked by SOLISTEN_LOCK() of corresponding listening socket. * (f) not locked since integer reads/writes are atomic. * (g) used only as a sleep/wakeup address, no value. diff --git a/freebsd/sys/sys/sysproto.h b/freebsd/sys/sys/sysproto.h index d5cda835..9148a395 100644 --- a/freebsd/sys/sys/sysproto.h +++ b/freebsd/sys/sys/sysproto.h @@ -11,6 +11,7 @@ #include <sys/signal.h> #include <sys/acl.h> #include <sys/cpuset.h> +#include <sys/domainset.h> #include <sys/_ffcounter.h> #include <sys/_semaphore.h> #include <sys/ucontext.h> @@ -1738,16 +1739,6 @@ struct utimensat_args { char times_l_[PADL_(struct timespec *)]; struct timespec * times; char times_r_[PADR_(struct timespec *)]; char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)]; }; -struct numa_getaffinity_args { - char which_l_[PADL_(cpuwhich_t)]; cpuwhich_t which; char which_r_[PADR_(cpuwhich_t)]; - char id_l_[PADL_(id_t)]; id_t id; char id_r_[PADR_(id_t)]; - char policy_l_[PADL_(struct vm_domain_policy_entry *)]; struct vm_domain_policy_entry * policy; char policy_r_[PADR_(struct vm_domain_policy_entry *)]; -}; -struct numa_setaffinity_args { - char which_l_[PADL_(cpuwhich_t)]; cpuwhich_t which; char which_r_[PADR_(cpuwhich_t)]; - char id_l_[PADL_(id_t)]; id_t id; char id_r_[PADR_(id_t)]; - char policy_l_[PADL_(const struct vm_domain_policy_entry *)]; const struct vm_domain_policy_entry * policy; char policy_r_[PADR_(const struct vm_domain_policy_entry *)]; -}; struct fdatasync_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; }; @@ -1808,6 +1799,22 @@ struct kevent_args { char timeout_l_[PADL_(const struct timespec *)]; const struct timespec * timeout; char timeout_r_[PADR_(const struct timespec *)]; }; #ifndef __rtems__ +struct cpuset_getdomain_args { + char level_l_[PADL_(cpulevel_t)]; cpulevel_t level; char level_r_[PADR_(cpulevel_t)]; + char which_l_[PADL_(cpuwhich_t)]; cpuwhich_t which; char which_r_[PADR_(cpuwhich_t)]; + char id_l_[PADL_(id_t)]; id_t id; char id_r_[PADR_(id_t)]; + char domainsetsize_l_[PADL_(size_t)]; size_t domainsetsize; char domainsetsize_r_[PADR_(size_t)]; + char mask_l_[PADL_(domainset_t *)]; domainset_t * mask; char mask_r_[PADR_(domainset_t *)]; + char policy_l_[PADL_(int *)]; int * policy; char policy_r_[PADR_(int *)]; +}; +struct cpuset_setdomain_args { + char level_l_[PADL_(cpulevel_t)]; cpulevel_t level; char level_r_[PADR_(cpulevel_t)]; + char which_l_[PADL_(cpuwhich_t)]; cpuwhich_t which; char which_r_[PADR_(cpuwhich_t)]; + char id_l_[PADL_(id_t)]; id_t id; char id_r_[PADR_(id_t)]; + char domainsetsize_l_[PADL_(size_t)]; size_t domainsetsize; char domainsetsize_r_[PADR_(size_t)]; + char mask_l_[PADL_(domainset_t *)]; domainset_t * mask; char mask_r_[PADR_(domainset_t *)]; + char policy_l_[PADL_(int)]; int policy; char policy_r_[PADR_(int)]; +}; int nosys(struct thread *, struct nosys_args *); void sys_sys_exit(struct thread *, struct sys_exit_args *); int sys_fork(struct thread *, struct fork_args *); @@ -2175,8 +2182,6 @@ int sys_procctl(struct thread *, struct procctl_args *); int sys_ppoll(struct thread *, struct ppoll_args *); int sys_futimens(struct thread *, struct futimens_args *); int sys_utimensat(struct thread *, struct utimensat_args *); -int sys_numa_getaffinity(struct thread *, struct numa_getaffinity_args *); -int sys_numa_setaffinity(struct thread *, struct numa_setaffinity_args *); int sys_fdatasync(struct thread *, struct fdatasync_args *); int sys_fstat(struct thread *, struct fstat_args *); int sys_fstatat(struct thread *, struct fstatat_args *); @@ -2188,6 +2193,8 @@ int sys_getfsstat(struct thread *, struct getfsstat_args *); int sys_fhstatfs(struct thread *, struct fhstatfs_args *); int sys_mknodat(struct thread *, struct mknodat_args *); int sys_kevent(struct thread *, struct kevent_args *); +int sys_cpuset_getdomain(struct thread *, struct cpuset_getdomain_args *); +int sys_cpuset_setdomain(struct thread *, struct cpuset_setdomain_args *); #ifdef COMPAT_43 @@ -3067,8 +3074,6 @@ int freebsd11_mknodat(struct thread *, struct freebsd11_mknodat_args *); #define SYS_AUE_ppoll AUE_POLL #define SYS_AUE_futimens AUE_FUTIMES #define SYS_AUE_utimensat AUE_FUTIMESAT -#define SYS_AUE_numa_getaffinity AUE_NULL -#define SYS_AUE_numa_setaffinity AUE_NULL #define SYS_AUE_fdatasync AUE_FSYNC #define SYS_AUE_fstat AUE_FSTAT #define SYS_AUE_fstatat AUE_FSTATAT @@ -3080,6 +3085,8 @@ int freebsd11_mknodat(struct thread *, struct freebsd11_mknodat_args *); #define SYS_AUE_fhstatfs AUE_FHSTATFS #define SYS_AUE_mknodat AUE_MKNODAT #define SYS_AUE_kevent AUE_KEVENT +#define SYS_AUE_cpuset_getdomain AUE_NULL +#define SYS_AUE_cpuset_setdomain AUE_NULL #endif /* __rtems__ */ #undef PAD_ diff --git a/freebsd/sys/sys/systm.h b/freebsd/sys/sys/systm.h index e89719b8..2dfe959b 100644 --- a/freebsd/sys/sys/systm.h +++ b/freebsd/sys/sys/systm.h @@ -610,6 +610,22 @@ void intr_prof_stack_use(struct thread *td, struct trapframe *frame); void counted_warning(unsigned *counter, const char *msg); +/* + * APIs to manage deprecation and obsolescence. + */ +struct device; +void _gone_in(int major, const char *msg); +void _gone_in_dev(struct device *dev, int major, const char *msg); +#ifdef NO_OBSOLETE_CODE +#define __gone_ok(m, msg) \ + _Static_assert(m < P_OSREL_MAJOR(__FreeBSD_version)), \ + "Obsolete code" msg); +#else +#define __gone_ok(m, msg) +#endif +#define gone_in(major, msg) __gone_ok(major, msg) _gone_in(major, msg) +#define gone_in_dev(dev, major, msg) __gone_ok(major, msg) _gone_in_dev(dev, major, msg) + __NULLABILITY_PRAGMA_POP #endif /* !_SYS_SYSTM_H_ */ diff --git a/freebsd/sys/sys/tslog.h b/freebsd/sys/sys/tslog.h new file mode 100644 index 00000000..4b2971e4 --- /dev/null +++ b/freebsd/sys/sys/tslog.h @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2017 Colin Percival + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _TSLOG_H_ +#define _TSLOG_H_ + +#ifdef TSLOG +#include <sys/_types.h> +#include <sys/pcpu.h> +#endif + +#define TS_ENTER 0 +#define TS_EXIT 1 +#define TS_THREAD 2 +#define TS_EVENT 3 + +#define TSENTER() TSRAW(curthread, TS_ENTER, __func__, NULL) +#define TSENTER2(x) TSRAW(curthread, TS_ENTER, __func__, x) +#define TSEXIT() TSRAW(curthread, TS_EXIT, __func__, NULL) +#define TSEXIT2(x) TSRAW(curthread, TS_EXIT, __func__, x) +#define TSTHREAD(td, x) TSRAW(td, TS_THREAD, x, NULL) +#define TSEVENT(x) TSRAW(curthread, TS_EVENT, x, NULL) +#define TSEVENT2(x, y) TSRAW(curthread, TS_EVENT, x, y) +#define TSLINE() TSEVENT2(__FILE__, __XSTRING(__LINE__)) +#define TSWAIT(x) TSEVENT2("WAIT", x); +#define TSUNWAIT(x) TSEVENT2("UNWAIT", x); +#define TSHOLD(x) TSEVENT2("HOLD", x); +#define TSRELEASE(x) TSEVENT2("RELEASE", x); + +#ifdef TSLOG +#define TSRAW(a, b, c, d) tslog(a, b, c, d) +void tslog(void *, int, const char *, const char *); +#else +#define TSRAW(a, b, c, d) /* Timestamp logging disabled */ +#endif + +#endif /* _TSLOG_H_ */ diff --git a/freebsd/sys/sys/vmmeter.h b/freebsd/sys/sys/vmmeter.h index 33d96b26..901604ae 100644 --- a/freebsd/sys/sys/vmmeter.h +++ b/freebsd/sys/sys/vmmeter.h @@ -41,7 +41,6 @@ */ #define MAXSLP 20 -/* Systemwide totals computed every five seconds. */ struct vmtotal { uint64_t t_vm; /* total virtual memory */ uint64_t t_avm; /* active virtual memory */ @@ -53,12 +52,12 @@ struct vmtotal { uint64_t t_armshr; /* active shared real memory */ uint64_t t_free; /* free memory pages */ int16_t t_rq; /* length of the run queue */ - int16_t t_dw; /* jobs in ``disk wait'' (neg + int16_t t_dw; /* threads in ``disk wait'' (neg priority) */ - int16_t t_pw; /* jobs in page wait */ - int16_t t_sl; /* jobs sleeping in core */ + int16_t t_pw; /* threads in page wait */ + int16_t t_sl; /* threads sleeping in core */ int16_t t_sw; /* swapped out runnable/short - block jobs */ + block threads */ uint16_t t_pad[3]; }; diff --git a/freebsd/sys/sys/watchdog.h b/freebsd/sys/sys/watchdog.h index 1b85ce7a..191456a4 100644 --- a/freebsd/sys/sys/watchdog.h +++ b/freebsd/sys/sys/watchdog.h @@ -112,6 +112,14 @@ EVENTHANDLER_DECLARE(watchdog_list, watchdog_fn); u_int wdog_kern_last_timeout(void); int wdog_kern_pat(u_int utim); + +/* + * The following function pointer is used to attach a software watchdog + * if no hardware watchdog has been attached, and if the software module + * has initialized the function pointer. + */ + +extern void (*wdog_software_attach)(void); #endif #endif /* _SYS_WATCHDOG_H */ diff --git a/freebsd/sys/vm/uma.h b/freebsd/sys/vm/uma.h index 6fbe6588..2f80a448 100644 --- a/freebsd/sys/vm/uma.h +++ b/freebsd/sys/vm/uma.h @@ -128,7 +128,8 @@ typedef void (*uma_fini)(void *mem, int size); /* * Import new memory into a cache zone. */ -typedef int (*uma_import)(void *arg, void **store, int count, int flags); +typedef int (*uma_import)(void *arg, void **store, int count, int domain, + int flags); /* * Free memory from a cache zone. @@ -281,6 +282,10 @@ uma_zone_t uma_zcache_create(char *name, int size, uma_ctor ctor, uma_dtor dtor, * Allocates mp_maxid + 1 slabs sized to * sizeof(struct pcpu). */ +#define UMA_ZONE_NUMA 0x10000 /* + * NUMA aware Zone. Implements a best + * effort first-touch policy. + */ /* * These flags are shared between the keg and zone. In zones wishing to add @@ -326,6 +331,19 @@ void uma_zdestroy(uma_zone_t zone); void *uma_zalloc_arg(uma_zone_t zone, void *arg, int flags); /* + * Allocate an item from a specific NUMA domain. This uses a slow path in + * the allocator but is guaranteed to allocate memory from the requested + * domain if M_WAITOK is set. + * + * Arguments: + * zone The zone we are allocating from + * arg This data is passed to the ctor function + * domain The domain to allocate from. + * flags See sys/malloc.h for available flags. + */ +void *uma_zalloc_domain(uma_zone_t zone, void *arg, int domain, int flags); + +/* * Allocates an item out of a zone without supplying an argument * * This is just a wrapper for uma_zalloc_arg for convenience. @@ -354,6 +372,16 @@ uma_zalloc(uma_zone_t zone, int flags) void uma_zfree_arg(uma_zone_t zone, void *item, void *arg); /* + * Frees an item back to the specified zone's domain specific pool. + * + * Arguments: + * zone The zone the item was originally allocated out of. + * item The memory to be freed. + * arg Argument passed to the destructor + */ +void uma_zfree_domain(uma_zone_t zone, void *item, void *arg); + +/* * Frees an item back to a zone without supplying an argument * * This is just a wrapper for uma_zfree_arg for convenience. @@ -373,25 +401,21 @@ uma_zfree(uma_zone_t zone, void *item) void uma_zwait(uma_zone_t zone); /* - * XXX The rest of the prototypes in this header are h0h0 magic for the VM. - * If you think you need to use it for a normal zone you're probably incorrect. - */ - -/* * Backend page supplier routines * * Arguments: * zone The zone that is requesting pages. * size The number of bytes being requested. * pflag Flags for these memory pages, see below. + * domain The NUMA domain that we prefer for this allocation. * wait Indicates our willingness to block. * * Returns: * A pointer to the allocated memory or NULL on failure. */ -typedef void *(*uma_alloc)(uma_zone_t zone, vm_size_t size, uint8_t *pflag, - int wait); +typedef void *(*uma_alloc)(uma_zone_t zone, vm_size_t size, int domain, + uint8_t *pflag, int wait); /* * Backend page free routines @@ -406,8 +430,6 @@ typedef void *(*uma_alloc)(uma_zone_t zone, vm_size_t size, uint8_t *pflag, */ typedef void (*uma_free)(void *item, vm_size_t size, uint8_t pflag); - - /* * Sets up the uma allocator. (Called by vm_mem_init) * @@ -702,6 +724,14 @@ struct uma_percpu_stat { void uma_reclaim_wakeup(void); void uma_reclaim_worker(void *); +unsigned long uma_limit(void); + +/* Return the amount of memory managed by UMA. */ +unsigned long uma_size(void); + +/* Return the amount of memory remaining. May be negative. */ +long uma_avail(void); + #ifdef __rtems__ void rtems_uma_drain_timeout(void); #endif /* __rtems__ */ diff --git a/freebsd/sys/vm/uma_core.c b/freebsd/sys/vm/uma_core.c index 3d4abec0..a1c45c93 100644 --- a/freebsd/sys/vm/uma_core.c +++ b/freebsd/sys/vm/uma_core.c @@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$"); #include <sys/eventhandler.h> #include <sys/kernel.h> #include <sys/types.h> +#include <sys/limits.h> #include <sys/queue.h> #include <sys/malloc.h> #include <sys/ktr.h> @@ -84,6 +85,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_page.h> #include <vm/vm_pageout.h> #include <vm/vm_param.h> +#include <vm/vm_phys.h> #include <vm/vm_map.h> #include <vm/vm_kern.h> #include <vm/vm_extern.h> @@ -93,21 +95,28 @@ __FBSDID("$FreeBSD$"); #include <ddb/ddb.h> #ifdef __rtems__ - #include <rtems/bsd/bsd.h> - - #ifdef RTEMS_SMP - #include <rtems/score/smp.h> - - /* - * It is essential that we have a per-processor cache, otherwise the - * critical_enter()/critical_exit() protection would be insufficient. - */ - #undef curcpu - #define curcpu _SMP_Get_current_processor() - #undef mp_maxid - #define mp_maxid (rtems_get_processor_count() - 1) - #define SMP - #endif +#include <rtems/bsd/bsd.h> +#include <rtems/malloc.h> +#include <rtems.h> + +#undef CACHE_LINE_SIZE +#define CACHE_LINE_SIZE CPU_CACHE_LINE_BYTES + +#ifdef RTEMS_SMP +#include <rtems/score/smp.h> + +/* +* It is essential that we have a per-processor cache, otherwise the +* critical_enter()/critical_exit() protection would be insufficient. +*/ +#undef curcpu +#define curcpu _SMP_Get_current_processor() +#undef mp_maxid +#define mp_maxid (rtems_get_processor_count() - 1) +#undef mp_ncpus +#define mp_ncpus rtems_get_processor_count() +#define SMP +#endif /* RTEMS_SMP */ #endif /* __rtems__ */ #ifdef DEBUG_MEMGUARD @@ -115,17 +124,12 @@ __FBSDID("$FreeBSD$"); #endif /* - * This is the zone and keg from which all zones are spawned. The idea is that - * even the zone & keg heads are allocated from the allocator, so we use the - * bss section to bootstrap us. + * This is the zone and keg from which all zones are spawned. */ -static struct uma_keg masterkeg; -static struct uma_zone masterzone_k; -static struct uma_zone masterzone_z; -static uma_zone_t kegs = &masterzone_k; -static uma_zone_t zones = &masterzone_z; +static uma_zone_t kegs; +static uma_zone_t zones; -/* This is the zone from which all of uma_slab_t's are allocated. */ +/* This is the zone from which all offpage uma_slab_ts are allocated. */ static uma_zone_t slabzone; /* @@ -173,7 +177,7 @@ static struct mtx uma_boot_pages_mtx; static struct sx uma_drain_lock; /* kmem soft limit. */ -static unsigned long uma_kmem_limit; +static unsigned long uma_kmem_limit = LONG_MAX; static volatile unsigned long uma_kmem_total; #ifndef __rtems__ @@ -258,17 +262,19 @@ struct uma_bucket_zone bucket_zones[] = { */ enum zfreeskip { SKIP_NONE = 0, SKIP_DTOR, SKIP_FINI }; +#define UMA_ANYDOMAIN -1 /* Special value for domain search. */ + /* Prototypes.. */ #ifndef __rtems__ -static void *noobj_alloc(uma_zone_t, vm_size_t, uint8_t *, int); +static void *noobj_alloc(uma_zone_t, vm_size_t, int, uint8_t *, int); #endif /* __rtems__ */ -static void *page_alloc(uma_zone_t, vm_size_t, uint8_t *, int); +static void *page_alloc(uma_zone_t, vm_size_t, int, uint8_t *, int); #ifndef __rtems__ -static void *startup_alloc(uma_zone_t, vm_size_t, uint8_t *, int); +static void *startup_alloc(uma_zone_t, vm_size_t, int, uint8_t *, int); #endif /* __rtems__ */ static void page_free(void *, vm_size_t, uint8_t); -static uma_slab_t keg_alloc_slab(uma_keg_t, uma_zone_t, int); +static uma_slab_t keg_alloc_slab(uma_keg_t, uma_zone_t, int, int); static void cache_drain(uma_zone_t); static void bucket_drain(uma_zone_t, uma_bucket_t); static void bucket_cache_drain(uma_zone_t zone); @@ -286,25 +292,25 @@ static int hash_expand(struct uma_hash *, struct uma_hash *); static void hash_free(struct uma_hash *hash); static void uma_timeout(void *); static void uma_startup3(void); -static void *zone_alloc_item(uma_zone_t, void *, int); +static void *zone_alloc_item(uma_zone_t, void *, int, int); static void zone_free_item(uma_zone_t, void *, void *, enum zfreeskip); static void bucket_enable(void); static void bucket_init(void); static uma_bucket_t bucket_alloc(uma_zone_t zone, void *, int); static void bucket_free(uma_zone_t zone, uma_bucket_t, void *); static void bucket_zone_drain(void); -static uma_bucket_t zone_alloc_bucket(uma_zone_t zone, void *, int flags); -static uma_slab_t zone_fetch_slab(uma_zone_t zone, uma_keg_t last, int flags); +static uma_bucket_t zone_alloc_bucket(uma_zone_t, void *, int, int); +static uma_slab_t zone_fetch_slab(uma_zone_t, uma_keg_t, int, int); #ifndef __rtems__ -static uma_slab_t zone_fetch_slab_multi(uma_zone_t zone, uma_keg_t last, int flags); +static uma_slab_t zone_fetch_slab_multi(uma_zone_t, uma_keg_t, int, int); #endif /* __rtems__ */ static void *slab_alloc_item(uma_keg_t keg, uma_slab_t slab); static void slab_free_item(uma_keg_t keg, uma_slab_t slab, void *item); static uma_keg_t uma_kcreate(uma_zone_t zone, size_t size, uma_init uminit, uma_fini fini, int align, uint32_t flags); -static int zone_import(uma_zone_t zone, void **bucket, int max, int flags); -static void zone_release(uma_zone_t zone, void **bucket, int cnt); -static void uma_zero_item(void *item, uma_zone_t zone); +static int zone_import(uma_zone_t, void **, int, int, int); +static void zone_release(uma_zone_t, void **, int); +static void uma_zero_item(void *, uma_zone_t); void uma_print_zone(uma_zone_t); void uma_print_stats(void); @@ -372,7 +378,7 @@ bucket_init(void) size += sizeof(void *) * ubz->ubz_entries; ubz->ubz_zone = uma_zcreate(ubz->ubz_name, size, NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, - UMA_ZONE_MTXCLASS | UMA_ZFLAG_BUCKET); + UMA_ZONE_MTXCLASS | UMA_ZFLAG_BUCKET | UMA_ZONE_NUMA); } } @@ -612,7 +618,7 @@ hash_alloc(struct uma_hash *hash) } else { alloc = sizeof(hash->uh_slab_hash[0]) * UMA_HASH_SIZE_INIT; hash->uh_slab_hash = zone_alloc_item(hashzone, NULL, - M_WAITOK); + UMA_ANYDOMAIN, M_WAITOK); hash->uh_hashsize = UMA_HASH_SIZE_INIT; } if (hash->uh_slab_hash) { @@ -779,6 +785,7 @@ cache_drain_safe_cpu(uma_zone_t zone) { uma_cache_t cache; uma_bucket_t b1, b2; + int domain; if (zone->uz_flags & UMA_ZFLAG_INTERNAL) return; @@ -786,10 +793,14 @@ cache_drain_safe_cpu(uma_zone_t zone) b1 = b2 = NULL; ZONE_LOCK(zone); critical_enter(); + if (zone->uz_flags & UMA_ZONE_NUMA) + domain = PCPU_GET(domain); + else + domain = 0; cache = &zone->uz_cpu[curcpu]; if (cache->uc_allocbucket) { if (cache->uc_allocbucket->ub_cnt != 0) - LIST_INSERT_HEAD(&zone->uz_buckets, + LIST_INSERT_HEAD(&zone->uz_domain[domain].uzd_buckets, cache->uc_allocbucket, ub_link); else b1 = cache->uc_allocbucket; @@ -797,7 +808,7 @@ cache_drain_safe_cpu(uma_zone_t zone) } if (cache->uc_freebucket) { if (cache->uc_freebucket->ub_cnt != 0) - LIST_INSERT_HEAD(&zone->uz_buckets, + LIST_INSERT_HEAD(&zone->uz_domain[domain].uzd_buckets, cache->uc_freebucket, ub_link); else b2 = cache->uc_freebucket; @@ -853,18 +864,22 @@ cache_drain_safe(uma_zone_t zone) static void bucket_cache_drain(uma_zone_t zone) { + uma_zone_domain_t zdom; uma_bucket_t bucket; + int i; /* - * Drain the bucket queues and free the buckets, we just keep two per - * cpu (alloc/free). + * Drain the bucket queues and free the buckets. */ - while ((bucket = LIST_FIRST(&zone->uz_buckets)) != NULL) { - LIST_REMOVE(bucket, ub_link); - ZONE_UNLOCK(zone); - bucket_drain(zone, bucket); - bucket_free(zone, bucket, NULL); - ZONE_LOCK(zone); + for (i = 0; i < vm_ndomains; i++) { + zdom = &zone->uz_domain[i]; + while ((bucket = LIST_FIRST(&zdom->uzd_buckets)) != NULL) { + LIST_REMOVE(bucket, ub_link); + ZONE_UNLOCK(zone); + bucket_drain(zone, bucket); + bucket_free(zone, bucket, NULL); + ZONE_LOCK(zone); + } } /* @@ -909,7 +924,9 @@ static void keg_drain(uma_keg_t keg) { struct slabhead freeslabs = { 0 }; + uma_domain_t dom; uma_slab_t slab, tmp; + int i; /* * We don't want to take pages from statically allocated kegs at this @@ -924,22 +941,27 @@ keg_drain(uma_keg_t keg) if (keg->uk_free == 0) goto finished; - LIST_FOREACH_SAFE(slab, &keg->uk_free_slab, us_link, tmp) { + for (i = 0; i < vm_ndomains; i++) { + dom = &keg->uk_domain[i]; + LIST_FOREACH_SAFE(slab, &dom->ud_free_slab, us_link, tmp) { #ifndef __rtems__ - /* We have nowhere to free these to. */ - if (slab->us_flags & UMA_SLAB_BOOT) - continue; + /* We have nowhere to free these to. */ + if (slab->us_flags & UMA_SLAB_BOOT) + continue; #endif /* __rtems__ */ - LIST_REMOVE(slab, us_link); - keg->uk_pages -= keg->uk_ppera; - keg->uk_free -= keg->uk_ipers; + LIST_REMOVE(slab, us_link); + keg->uk_pages -= keg->uk_ppera; + keg->uk_free -= keg->uk_ipers; - if (keg->uk_flags & UMA_ZONE_HASH) - UMA_HASH_REMOVE(&keg->uk_hash, slab, slab->us_data); + if (keg->uk_flags & UMA_ZONE_HASH) + UMA_HASH_REMOVE(&keg->uk_hash, slab, + slab->us_data); - SLIST_INSERT_HEAD(&freeslabs, slab, us_hlink); + SLIST_INSERT_HEAD(&freeslabs, slab, us_hlink); + } } + finished: KEG_UNLOCK(keg); @@ -999,7 +1021,7 @@ zone_drain(uma_zone_t zone) * caller specified M_NOWAIT. */ static uma_slab_t -keg_alloc_slab(uma_keg_t keg, uma_zone_t zone, int wait) +keg_alloc_slab(uma_keg_t keg, uma_zone_t zone, int domain, int wait) { uma_alloc allocf; uma_slab_t slab; @@ -1008,6 +1030,8 @@ keg_alloc_slab(uma_keg_t keg, uma_zone_t zone, int wait) uint8_t flags; int i; + KASSERT(domain >= 0 && domain < vm_ndomains, + ("keg_alloc_slab: domain %d out of range", domain)); mtx_assert(&keg->uk_lock, MA_OWNED); slab = NULL; mem = NULL; @@ -1017,7 +1041,7 @@ keg_alloc_slab(uma_keg_t keg, uma_zone_t zone, int wait) size = keg->uk_ppera * PAGE_SIZE; if (keg->uk_flags & UMA_ZONE_OFFPAGE) { - slab = zone_alloc_item(keg->uk_slabzone, NULL, wait); + slab = zone_alloc_item(keg->uk_slabzone, NULL, domain, wait); if (slab == NULL) goto out; } @@ -1038,7 +1062,7 @@ keg_alloc_slab(uma_keg_t keg, uma_zone_t zone, int wait) wait |= M_NODUMP; /* zone is passed for legacy reasons. */ - mem = allocf(zone, size, &flags, wait); + mem = allocf(zone, size, domain, &flags, wait); if (mem == NULL) { if (keg->uk_flags & UMA_ZONE_OFFPAGE) zone_free_item(keg->uk_slabzone, slab, NULL, SKIP_NONE); @@ -1059,6 +1083,7 @@ keg_alloc_slab(uma_keg_t keg, uma_zone_t zone, int wait) slab->us_data = mem; slab->us_freecount = keg->uk_ipers; slab->us_flags = flags; + slab->us_domain = domain; BIT_FILL(SLAB_SETSIZE, &slab->us_free); #ifdef INVARIANTS BIT_ZERO(SLAB_SETSIZE, &slab->us_debugfree); @@ -1099,7 +1124,8 @@ out: * the VM is ready. */ static void * -startup_alloc(uma_zone_t zone, vm_size_t bytes, uint8_t *pflag, int wait) +startup_alloc(uma_zone_t zone, vm_size_t bytes, int domain, uint8_t *pflag, + int wait) { uma_keg_t keg; void *mem; @@ -1132,7 +1158,7 @@ startup_alloc(uma_zone_t zone, vm_size_t bytes, uint8_t *pflag, int wait) #else keg->uk_allocf = page_alloc; #endif - return keg->uk_allocf(zone, bytes, pflag, wait); + return keg->uk_allocf(zone, bytes, domain, pflag, wait); } #endif /* __rtems__ */ @@ -1148,13 +1174,14 @@ startup_alloc(uma_zone_t zone, vm_size_t bytes, uint8_t *pflag, int wait) * NULL if M_NOWAIT is set. */ static void * -page_alloc(uma_zone_t zone, vm_size_t bytes, uint8_t *pflag, int wait) +page_alloc(uma_zone_t zone, vm_size_t bytes, int domain, uint8_t *pflag, + int wait) { void *p; /* Returned page */ #ifndef __rtems__ *pflag = UMA_SLAB_KERNEL; - p = (void *) kmem_malloc(kernel_arena, bytes, wait); + p = (void *) kmem_malloc_domain(domain, bytes, wait); #else /* __rtems__ */ *pflag = 0; p = rtems_bsd_page_alloc(bytes, wait); @@ -1176,7 +1203,8 @@ page_alloc(uma_zone_t zone, vm_size_t bytes, uint8_t *pflag, int wait) * NULL if M_NOWAIT is set. */ static void * -noobj_alloc(uma_zone_t zone, vm_size_t bytes, uint8_t *flags, int wait) +noobj_alloc(uma_zone_t zone, vm_size_t bytes, int domain, uint8_t *flags, + int wait) { TAILQ_HEAD(, vm_page) alloctail; u_long npages; @@ -1189,7 +1217,7 @@ noobj_alloc(uma_zone_t zone, vm_size_t bytes, uint8_t *flags, int wait) npages = howmany(bytes, PAGE_SIZE); while (npages > 0) { - p = vm_page_alloc(NULL, 0, VM_ALLOC_INTERRUPT | + p = vm_page_alloc_domain(NULL, 0, domain, VM_ALLOC_INTERRUPT | VM_ALLOC_WIRED | VM_ALLOC_NOOBJ | ((wait & M_WAITOK) != 0 ? VM_ALLOC_WAITOK : VM_ALLOC_NOWAIT)); @@ -1469,6 +1497,7 @@ keg_ctor(void *mem, int size, void *udata, int flags) keg->uk_init = arg->uminit; keg->uk_fini = arg->fini; keg->uk_align = arg->align; + keg->uk_cursor = 0; keg->uk_free = 0; keg->uk_reserve = 0; keg->uk_pages = 0; @@ -1614,6 +1643,8 @@ zone_ctor(void *mem, int size, void *udata, int flags) zone->uz_count_min = 0; zone->uz_flags = 0; zone->uz_warning = NULL; + /* The domain structures follow the cpu structures. */ + zone->uz_domain = (struct uma_zone_domain *)&zone->uz_cpu[mp_ncpus]; timevalclear(&zone->uz_ratecheck); keg = arg->keg; @@ -1819,22 +1850,60 @@ void uma_startup(void *mem, int npages) { struct uma_zctor_args args; + uma_keg_t masterkeg; + uintptr_t m; +#ifndef __rtems__ + int zsize; + int ksize; +#else /* __rtems__ */ + size_t zsize, ksize, size; +#endif /* __rtems__ */ rw_init(&uma_rwlock, "UMA lock"); + ksize = sizeof(struct uma_keg) + + (sizeof(struct uma_domain) * vm_ndomains); + zsize = sizeof(struct uma_zone) + + (sizeof(struct uma_cache) * mp_ncpus) + + (sizeof(struct uma_zone_domain) * vm_ndomains); +#ifdef __rtems__ + size = 2 * roundup(zsize, CACHE_LINE_SIZE) + + roundup(ksize, CACHE_LINE_SIZE); +#endif /* __rtems__ */ + +#ifndef __rtems__ + /* Use bootpages memory for the zone of zones and zone of kegs. */ + m = (uintptr_t)mem; +#else /* __rtems__ */ + m = (uintptr_t)rtems_heap_allocate_aligned_with_boundary( + size, CACHE_LINE_SIZE, 0); + BSD_ASSERT(m != 0); + memset((void *)m, 0, size); +#endif /* __rtems__ */ + zones = (uma_zone_t)m; + m += roundup(zsize, CACHE_LINE_SIZE); + kegs = (uma_zone_t)m; + m += roundup(zsize, CACHE_LINE_SIZE); + masterkeg = (uma_keg_t)m; +#ifndef __rtems__ + m += roundup(ksize, CACHE_LINE_SIZE); + m = roundup(m, PAGE_SIZE); + npages -= (m - (uintptr_t)mem) / PAGE_SIZE; + mem = (void *)m; +#endif /* __rtems__ */ + /* "manually" create the initial zone */ memset(&args, 0, sizeof(args)); args.name = "UMA Kegs"; - args.size = sizeof(struct uma_keg); + args.size = ksize; args.ctor = keg_ctor; args.dtor = keg_dtor; args.uminit = zero_init; args.fini = NULL; - args.keg = &masterkeg; + args.keg = masterkeg; args.align = 32 - 1; args.flags = UMA_ZFLAG_INTERNAL; - /* The initial zone has no Per cpu queues so it's smaller */ - zone_ctor(kegs, sizeof(struct uma_zone), &args, M_WAITOK); + zone_ctor(kegs, zsize, &args, M_WAITOK); #ifndef __rtems__ mtx_init(&uma_boot_pages_mtx, "UMA boot pages", NULL, MTX_DEF); @@ -1844,7 +1913,8 @@ uma_startup(void *mem, int npages) args.name = "UMA Zones"; args.size = sizeof(struct uma_zone) + - (sizeof(struct uma_cache) * (mp_maxid + 1)); + (sizeof(struct uma_cache) * (mp_maxid + 1)) + + (sizeof(struct uma_zone_domain) * vm_ndomains); args.ctor = zone_ctor; args.dtor = zone_dtor; args.uminit = zero_init; @@ -1852,8 +1922,7 @@ uma_startup(void *mem, int npages) args.keg = NULL; args.align = 32 - 1; args.flags = UMA_ZFLAG_INTERNAL; - /* The initial zone has no Per cpu queues so it's smaller */ - zone_ctor(zones, sizeof(struct uma_zone), &args, M_WAITOK); + zone_ctor(zones, zsize, &args, M_WAITOK); /* Now make a zone for slab headers */ slabzone = uma_zcreate("UMA Slabs", @@ -1924,7 +1993,7 @@ uma_kcreate(uma_zone_t zone, size_t size, uma_init uminit, uma_fini fini, args.align = (align == UMA_ALIGN_CACHE) ? uma_align_cache : align; args.flags = flags; args.zone = zone; - return (zone_alloc_item(kegs, &args, M_WAITOK)); + return (zone_alloc_item(kegs, &args, UMA_ANYDOMAIN, M_WAITOK)); } /* See uma.h */ @@ -1987,7 +2056,7 @@ uma_zcreate(const char *name, size_t size, uma_ctor ctor, uma_dtor dtor, locked = true; } #endif /* __rtems__ */ - res = zone_alloc_item(zones, &args, M_WAITOK); + res = zone_alloc_item(zones, &args, UMA_ANYDOMAIN, M_WAITOK); #ifndef __rtems__ if (locked) #endif /* __rtems__ */ @@ -2030,7 +2099,7 @@ uma_zsecond_create(char *name, uma_ctor ctor, uma_dtor dtor, } #endif /* __rtems__ */ /* XXX Attaches only one keg of potentially many. */ - res = zone_alloc_item(zones, &args, M_WAITOK); + res = zone_alloc_item(zones, &args, UMA_ANYDOMAIN, M_WAITOK); #ifndef __rtems__ if (locked) #endif /* __rtems__ */ @@ -2059,7 +2128,7 @@ uma_zcache_create(char *name, int size, uma_ctor ctor, uma_dtor dtor, args.align = 0; args.flags = flags; - return (zone_alloc_item(zones, &args, M_WAITOK)); + return (zone_alloc_item(zones, &args, UMA_ANYDOMAIN, M_WAITOK)); } #ifndef __rtems__ @@ -2166,11 +2235,11 @@ uma_zwait(uma_zone_t zone) void * uma_zalloc_arg(uma_zone_t zone, void *udata, int flags) { - void *item; - uma_cache_t cache; + uma_zone_domain_t zdom; uma_bucket_t bucket; - int lockfail; - int cpu; + uma_cache_t cache; + void *item; + int cpu, domain, lockfail; /* Enable entropy collection for RANDOM_ENABLE_UMA kernel option */ random_harvest_fast_uma(&zone, sizeof(zone), 1, RANDOM_UMA); @@ -2269,6 +2338,11 @@ zalloc_start: if (bucket != NULL) bucket_free(zone, bucket, udata); + if (zone->uz_flags & UMA_ZONE_NUMA) + domain = PCPU_GET(domain); + else + domain = UMA_ANYDOMAIN; + /* Short-circuit for zones without buckets and low memory. */ if (zone->uz_count == 0 || bucketdisable) goto zalloc_item; @@ -2309,7 +2383,11 @@ zalloc_start: /* * Check the zone's cache of buckets. */ - if ((bucket = LIST_FIRST(&zone->uz_buckets)) != NULL) { + if (domain == UMA_ANYDOMAIN) + zdom = &zone->uz_domain[0]; + else + zdom = &zone->uz_domain[domain]; + if ((bucket = LIST_FIRST(&zdom->uzd_buckets)) != NULL) { KASSERT(bucket->ub_cnt != 0, ("uma_zalloc_arg: Returning an empty bucket.")); @@ -2334,7 +2412,7 @@ zalloc_start: * works we'll restart the allocation from the beginning and it * will use the just filled bucket. */ - bucket = zone_alloc_bucket(zone, udata, flags); + bucket = zone_alloc_bucket(zone, udata, domain, flags); CTR3(KTR_UMA, "uma_zalloc: zone %s(%p) bucket zone returned %p", zone->uz_name, zone, bucket); if (bucket != NULL) { @@ -2347,10 +2425,12 @@ zalloc_start: * initialized bucket to make this less likely or claim * the memory directly. */ - if (cache->uc_allocbucket == NULL) - cache->uc_allocbucket = bucket; + if (cache->uc_allocbucket != NULL || + (zone->uz_flags & UMA_ZONE_NUMA && + domain != PCPU_GET(domain))) + LIST_INSERT_HEAD(&zdom->uzd_buckets, bucket, ub_link); else - LIST_INSERT_HEAD(&zone->uz_buckets, bucket, ub_link); + cache->uc_allocbucket = bucket; ZONE_UNLOCK(zone); goto zalloc_start; } @@ -2359,38 +2439,103 @@ zalloc_start: * We may not be able to get a bucket so return an actual item. */ zalloc_item: - item = zone_alloc_item(zone, udata, flags); + item = zone_alloc_item(zone, udata, domain, flags); return (item); } +void * +uma_zalloc_domain(uma_zone_t zone, void *udata, int domain, int flags) +{ + + /* Enable entropy collection for RANDOM_ENABLE_UMA kernel option */ + random_harvest_fast_uma(&zone, sizeof(zone), 1, RANDOM_UMA); + + /* This is the fast path allocation */ + CTR5(KTR_UMA, + "uma_zalloc_domain thread %x zone %s(%p) domain %d flags %d", + curthread, zone->uz_name, zone, domain, flags); + + if (flags & M_WAITOK) { + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, + "uma_zalloc_domain: zone \"%s\"", zone->uz_name); + } + KASSERT(curthread->td_critnest == 0 || SCHEDULER_STOPPED(), + ("uma_zalloc_domain: called with spinlock or critical section held")); + + return (zone_alloc_item(zone, udata, domain, flags)); +} + +/* + * Find a slab with some space. Prefer slabs that are partially used over those + * that are totally full. This helps to reduce fragmentation. + * + * If 'rr' is 1, search all domains starting from 'domain'. Otherwise check + * only 'domain'. + */ +static uma_slab_t +keg_first_slab(uma_keg_t keg, int domain, int rr) +{ + uma_domain_t dom; + uma_slab_t slab; + int start; + + KASSERT(domain >= 0 && domain < vm_ndomains, + ("keg_first_slab: domain %d out of range", domain)); + + slab = NULL; + start = domain; + do { + dom = &keg->uk_domain[domain]; + if (!LIST_EMPTY(&dom->ud_part_slab)) + return (LIST_FIRST(&dom->ud_part_slab)); + if (!LIST_EMPTY(&dom->ud_free_slab)) { + slab = LIST_FIRST(&dom->ud_free_slab); + LIST_REMOVE(slab, us_link); + LIST_INSERT_HEAD(&dom->ud_part_slab, slab, us_link); + return (slab); + } + if (rr) + domain = (domain + 1) % vm_ndomains; + } while (domain != start); + + return (NULL); +} + static uma_slab_t -keg_fetch_slab(uma_keg_t keg, uma_zone_t zone, int flags) +keg_fetch_slab(uma_keg_t keg, uma_zone_t zone, int rdomain, int flags) { + uma_domain_t dom; uma_slab_t slab; - int reserve; + int allocflags, domain, reserve, rr, start; mtx_assert(&keg->uk_lock, MA_OWNED); slab = NULL; reserve = 0; + allocflags = flags; if ((flags & M_USE_RESERVE) == 0) reserve = keg->uk_reserve; - for (;;) { - /* - * Find a slab with some space. Prefer slabs that are partially - * used over those that are totally full. This helps to reduce - * fragmentation. - */ - if (keg->uk_free > reserve) { - if (!LIST_EMPTY(&keg->uk_part_slab)) { - slab = LIST_FIRST(&keg->uk_part_slab); - } else { - slab = LIST_FIRST(&keg->uk_free_slab); - LIST_REMOVE(slab, us_link); - LIST_INSERT_HEAD(&keg->uk_part_slab, slab, - us_link); - } + /* + * Round-robin for non first-touch zones when there is more than one + * domain. + */ + if (vm_ndomains == 1) + rdomain = 0; + rr = rdomain == UMA_ANYDOMAIN; + if (rr) { + keg->uk_cursor = (keg->uk_cursor + 1) % vm_ndomains; + domain = start = keg->uk_cursor; + /* Only block on the second pass. */ + if ((flags & (M_WAITOK | M_NOVM)) == M_WAITOK) + allocflags = (allocflags & ~M_WAITOK) | M_NOWAIT; + } else + domain = start = rdomain; + +again: + do { + if (keg->uk_free > reserve && + (slab = keg_first_slab(keg, domain, rr)) != NULL) { MPASS(slab->us_keg == keg); return (slab); } @@ -2413,12 +2558,12 @@ keg_fetch_slab(uma_keg_t keg, uma_zone_t zone, int flags) zone_maxaction(zone); } if (flags & M_NOWAIT) - break; + return (NULL); zone->uz_sleeps++; msleep(keg, &keg->uk_lock, PVM, "keglimit", 0); continue; } - slab = keg_alloc_slab(keg, zone, flags); + slab = keg_alloc_slab(keg, zone, domain, allocflags); /* * If we got a slab here it's safe to mark it partially used * and return. We assume that the caller is going to remove @@ -2426,21 +2571,37 @@ keg_fetch_slab(uma_keg_t keg, uma_zone_t zone, int flags) */ if (slab) { MPASS(slab->us_keg == keg); - LIST_INSERT_HEAD(&keg->uk_part_slab, slab, us_link); + dom = &keg->uk_domain[slab->us_domain]; + LIST_INSERT_HEAD(&dom->ud_part_slab, slab, us_link); return (slab); } - /* - * We might not have been able to get a slab but another cpu - * could have while we were unlocked. Check again before we - * fail. - */ - flags |= M_NOVM; + if (rr) { + keg->uk_cursor = (keg->uk_cursor + 1) % vm_ndomains; + domain = keg->uk_cursor; + } + } while (domain != start); + + /* Retry domain scan with blocking. */ + if (allocflags != flags) { + allocflags = flags; + goto again; } - return (slab); + + /* + * We might not have been able to get a slab but another cpu + * could have while we were unlocked. Check again before we + * fail. + */ + if (keg->uk_free > reserve && + (slab = keg_first_slab(keg, domain, rr)) != NULL) { + MPASS(slab->us_keg == keg); + return (slab); + } + return (NULL); } static uma_slab_t -zone_fetch_slab(uma_zone_t zone, uma_keg_t keg, int flags) +zone_fetch_slab(uma_zone_t zone, uma_keg_t keg, int domain, int flags) { uma_slab_t slab; @@ -2450,7 +2611,7 @@ zone_fetch_slab(uma_zone_t zone, uma_keg_t keg, int flags) } for (;;) { - slab = keg_fetch_slab(keg, zone, flags); + slab = keg_fetch_slab(keg, zone, domain, flags); if (slab) return (slab); if (flags & (M_NOWAIT | M_NOVM)) @@ -2468,7 +2629,7 @@ zone_fetch_slab(uma_zone_t zone, uma_keg_t keg, int flags) * The last pointer is used to seed the search. It is not required. */ static uma_slab_t -zone_fetch_slab_multi(uma_zone_t zone, uma_keg_t last, int rflags) +zone_fetch_slab_multi(uma_zone_t zone, uma_keg_t last, int domain, int rflags) { uma_klink_t klink; uma_slab_t slab; @@ -2488,7 +2649,7 @@ zone_fetch_slab_multi(uma_zone_t zone, uma_keg_t last, int rflags) * the search. */ if (last != NULL) { - slab = keg_fetch_slab(last, zone, flags); + slab = keg_fetch_slab(last, zone, domain, flags); if (slab) return (slab); KEG_UNLOCK(last); @@ -2509,7 +2670,7 @@ zone_fetch_slab_multi(uma_zone_t zone, uma_keg_t last, int rflags) keg = klink->kl_keg; KEG_LOCK(keg); if ((keg->uk_flags & UMA_ZFLAG_FULL) == 0) { - slab = keg_fetch_slab(keg, zone, flags); + slab = keg_fetch_slab(keg, zone, domain, flags); if (slab) return (slab); } @@ -2546,6 +2707,7 @@ zone_fetch_slab_multi(uma_zone_t zone, uma_keg_t last, int rflags) static void * slab_alloc_item(uma_keg_t keg, uma_slab_t slab) { + uma_domain_t dom; void *item; uint8_t freei; @@ -2561,32 +2723,48 @@ slab_alloc_item(uma_keg_t keg, uma_slab_t slab) /* Move this slab to the full list */ if (slab->us_freecount == 0) { LIST_REMOVE(slab, us_link); - LIST_INSERT_HEAD(&keg->uk_full_slab, slab, us_link); + dom = &keg->uk_domain[slab->us_domain]; + LIST_INSERT_HEAD(&dom->ud_full_slab, slab, us_link); } return (item); } static int -zone_import(uma_zone_t zone, void **bucket, int max, int flags) +zone_import(uma_zone_t zone, void **bucket, int max, int domain, int flags) { uma_slab_t slab; uma_keg_t keg; + int stripe; int i; slab = NULL; keg = NULL; /* Try to keep the buckets totally full */ for (i = 0; i < max; ) { - if ((slab = zone->uz_slab(zone, keg, flags)) == NULL) + if ((slab = zone->uz_slab(zone, keg, domain, flags)) == NULL) break; keg = slab->us_keg; + stripe = howmany(max, vm_ndomains); while (slab->us_freecount && i < max) { bucket[i++] = slab_alloc_item(keg, slab); if (keg->uk_free <= keg->uk_reserve) break; +#ifdef NUMA + /* + * If the zone is striped we pick a new slab for every + * N allocations. Eliminating this conditional will + * instead pick a new domain for each bucket rather + * than stripe within each bucket. The current option + * produces more fragmentation and requires more cpu + * time but yields better distribution. + */ + if ((zone->uz_flags & UMA_ZONE_NUMA) == 0 && + vm_ndomains > 1 && --stripe == 0) + break; +#endif } - /* Don't grab more than one slab at a time. */ + /* Don't block if we allocated any successfully. */ flags &= ~M_WAITOK; flags |= M_NOWAIT; } @@ -2597,7 +2775,7 @@ zone_import(uma_zone_t zone, void **bucket, int max, int flags) } static uma_bucket_t -zone_alloc_bucket(uma_zone_t zone, void *udata, int flags) +zone_alloc_bucket(uma_zone_t zone, void *udata, int domain, int flags) { uma_bucket_t bucket; int max; @@ -2609,7 +2787,7 @@ zone_alloc_bucket(uma_zone_t zone, void *udata, int flags) max = MIN(bucket->ub_entries, zone->uz_count); bucket->ub_cnt = zone->uz_import(zone->uz_arg, bucket->ub_bucket, - max, flags); + max, domain, flags); /* * Initialize the memory if necessary. @@ -2651,6 +2829,7 @@ zone_alloc_bucket(uma_zone_t zone, void *udata, int flags) * Arguments * zone The zone to alloc for. * udata The data to be passed to the constructor. + * domain The domain to allocate from or UMA_ANYDOMAIN. * flags M_WAITOK, M_NOWAIT, M_ZERO. * * Returns @@ -2659,13 +2838,13 @@ zone_alloc_bucket(uma_zone_t zone, void *udata, int flags) */ static void * -zone_alloc_item(uma_zone_t zone, void *udata, int flags) +zone_alloc_item(uma_zone_t zone, void *udata, int domain, int flags) { void *item; item = NULL; - if (zone->uz_import(zone->uz_arg, &item, 1, flags) != 1) + if (zone->uz_import(zone->uz_arg, &item, 1, domain, flags) != 1) goto fail; atomic_add_long(&zone->uz_allocs, 1); @@ -2711,8 +2890,8 @@ uma_zfree_arg(uma_zone_t zone, void *item, void *udata) { uma_cache_t cache; uma_bucket_t bucket; - int lockfail; - int cpu; + uma_zone_domain_t zdom; + int cpu, domain, lockfail; /* Enable entropy collection for RANDOM_ENABLE_UMA kernel option */ random_harvest_fast_uma(&zone, sizeof(zone), 1, RANDOM_UMA); @@ -2828,6 +3007,12 @@ zfree_start: /* We are no longer associated with this CPU. */ critical_exit(); + if ((zone->uz_flags & UMA_ZONE_NUMA) != 0) + domain = PCPU_GET(domain); + else + domain = 0; + zdom = &zone->uz_domain[0]; + /* Can we throw this on the zone full list? */ if (bucket != NULL) { CTR3(KTR_UMA, @@ -2836,7 +3021,7 @@ zfree_start: /* ub_cnt is pointing to the last free item */ KASSERT(bucket->ub_cnt != 0, ("uma_zfree: Attempting to insert an empty bucket onto the full list.\n")); - LIST_INSERT_HEAD(&zone->uz_buckets, bucket, ub_link); + LIST_INSERT_HEAD(&zdom->uzd_buckets, bucket, ub_link); } /* @@ -2854,7 +3039,9 @@ zfree_start: critical_enter(); cpu = curcpu; cache = &zone->uz_cpu[cpu]; - if (cache->uc_freebucket == NULL) { + if (cache->uc_freebucket == NULL && + ((zone->uz_flags & UMA_ZONE_NUMA) == 0 || + domain == PCPU_GET(domain))) { cache->uc_freebucket = bucket; goto zfree_start; } @@ -2876,21 +3063,43 @@ zfree_item: return; } +void +uma_zfree_domain(uma_zone_t zone, void *item, void *udata) +{ + + /* Enable entropy collection for RANDOM_ENABLE_UMA kernel option */ + random_harvest_fast_uma(&zone, sizeof(zone), 1, RANDOM_UMA); + + CTR2(KTR_UMA, "uma_zfree_domain thread %x zone %s", curthread, + zone->uz_name); + + KASSERT(curthread->td_critnest == 0 || SCHEDULER_STOPPED(), + ("uma_zfree_domain: called with spinlock or critical section held")); + + /* uma_zfree(..., NULL) does nothing, to match free(9). */ + if (item == NULL) + return; + zone_free_item(zone, item, udata, SKIP_NONE); +} + static void slab_free_item(uma_keg_t keg, uma_slab_t slab, void *item) { + uma_domain_t dom; uint8_t freei; mtx_assert(&keg->uk_lock, MA_OWNED); MPASS(keg == slab->us_keg); + dom = &keg->uk_domain[slab->us_domain]; + /* Do we need to remove from any lists? */ if (slab->us_freecount+1 == keg->uk_ipers) { LIST_REMOVE(slab, us_link); - LIST_INSERT_HEAD(&keg->uk_free_slab, slab, us_link); + LIST_INSERT_HEAD(&dom->ud_free_slab, slab, us_link); } else if (slab->us_freecount == 0) { LIST_REMOVE(slab, us_link); - LIST_INSERT_HEAD(&keg->uk_part_slab, slab, us_link); + LIST_INSERT_HEAD(&dom->ud_part_slab, slab, us_link); } /* Slab management. */ @@ -3223,24 +3432,28 @@ uma_zone_reserve_kva(uma_zone_t zone, int count) void uma_prealloc(uma_zone_t zone, int items) { - int slabs; + uma_domain_t dom; uma_slab_t slab; uma_keg_t keg; + int domain, slabs; keg = zone_first_keg(zone); if (keg == NULL) return; KEG_LOCK(keg); slabs = items / keg->uk_ipers; + domain = 0; if (slabs * keg->uk_ipers < items) slabs++; while (slabs > 0) { - slab = keg_alloc_slab(keg, zone, M_WAITOK); + slab = keg_alloc_slab(keg, zone, domain, M_WAITOK); if (slab == NULL) break; MPASS(slab->us_keg == keg); - LIST_INSERT_HEAD(&keg->uk_free_slab, slab, us_link); + dom = &keg->uk_domain[slab->us_domain]; + LIST_INSERT_HEAD(&dom->ud_free_slab, slab, us_link); slabs--; + domain = (domain + 1) % vm_ndomains; } KEG_UNLOCK(keg); } @@ -3295,7 +3508,7 @@ uma_reclaim_worker(void *arg __unused) for (;;) { sx_xlock(&uma_drain_lock); - while (uma_reclaim_needed == 0) + while (atomic_load_int(&uma_reclaim_needed) == 0) sx_sleep(uma_reclaim, &uma_drain_lock, PVM, "umarcl", hz); #ifndef __rtems__ @@ -3304,7 +3517,7 @@ uma_reclaim_worker(void *arg __unused) sx_xlock(&uma_drain_lock); #endif /* __rtems__ */ uma_reclaim_locked(true); - atomic_set_int(&uma_reclaim_needed, 0); + atomic_store_int(&uma_reclaim_needed, 0); sx_xunlock(&uma_drain_lock); /* Don't fire more than once per-second. */ pause("umarclslp", hz); @@ -3331,34 +3544,47 @@ uma_zone_exhausted_nolock(uma_zone_t zone) #ifndef __rtems__ void * -uma_large_malloc(vm_size_t size, int wait) +uma_large_malloc_domain(vm_size_t size, int domain, int wait) { - void *mem; + vm_offset_t addr; uma_slab_t slab; - uint8_t flags; - slab = zone_alloc_item(slabzone, NULL, wait); + slab = zone_alloc_item(slabzone, NULL, domain, wait); if (slab == NULL) return (NULL); - mem = page_alloc(NULL, size, &flags, wait); - if (mem) { - vsetslab((vm_offset_t)mem, slab); - slab->us_data = mem; - slab->us_flags = flags | UMA_SLAB_MALLOC; + if (domain == UMA_ANYDOMAIN) + addr = kmem_malloc(kernel_arena, size, wait); + else + addr = kmem_malloc_domain(domain, size, wait); + if (addr != 0) { + vsetslab(addr, slab); + slab->us_data = (void *)addr; + slab->us_flags = UMA_SLAB_KERNEL | UMA_SLAB_MALLOC; slab->us_size = size; + slab->us_domain = vm_phys_domidx(PHYS_TO_VM_PAGE( + pmap_kextract(addr))); uma_total_inc(size); } else { zone_free_item(slabzone, slab, NULL, SKIP_NONE); } - return (mem); + return ((void *)addr); +} + +void * +uma_large_malloc(vm_size_t size, int wait) +{ + + return uma_large_malloc_domain(size, UMA_ANYDOMAIN, wait); } void uma_large_free(uma_slab_t slab) { - page_free(slab->us_data, slab->us_size, slab->us_flags); + KASSERT((slab->us_flags & UMA_SLAB_KERNEL) != 0, + ("uma_large_free: Memory not allocated with uma_large_malloc.")); + kmem_free(kernel_arena, (vm_offset_t)slab->us_data, slab->us_size); uma_total_dec(slab->us_size); zone_free_item(slabzone, slab, NULL, SKIP_NONE); } @@ -3394,7 +3620,14 @@ unsigned long uma_size(void) { - return uma_kmem_total; + return (uma_kmem_total); +} + +long +uma_avail(void) +{ + + return (uma_kmem_limit - uma_kmem_total); } void @@ -3423,7 +3656,9 @@ cache_print(uma_cache_t cache) static void uma_print_keg(uma_keg_t keg) { + uma_domain_t dom; uma_slab_t slab; + int i; printf("keg: %s(%p) size %d(%d) flags %#x ipers %d ppera %d " "out %d free %d limit %d\n", @@ -3431,15 +3666,18 @@ uma_print_keg(uma_keg_t keg) keg->uk_ipers, keg->uk_ppera, (keg->uk_pages / keg->uk_ppera) * keg->uk_ipers - keg->uk_free, keg->uk_free, (keg->uk_maxpages / keg->uk_ppera) * keg->uk_ipers); - printf("Part slabs:\n"); - LIST_FOREACH(slab, &keg->uk_part_slab, us_link) - slab_print(slab); - printf("Free slabs:\n"); - LIST_FOREACH(slab, &keg->uk_free_slab, us_link) - slab_print(slab); - printf("Full slabs:\n"); - LIST_FOREACH(slab, &keg->uk_full_slab, us_link) - slab_print(slab); + for (i = 0; i < vm_ndomains; i++) { + dom = &keg->uk_domain[i]; + printf("Part slabs:\n"); + LIST_FOREACH(slab, &dom->ud_part_slab, us_link) + slab_print(slab); + printf("Free slabs:\n"); + LIST_FOREACH(slab, &dom->ud_free_slab, us_link) + slab_print(slab); + printf("Full slabs:\n"); + LIST_FOREACH(slab, &dom->ud_full_slab, us_link) + slab_print(slab); + } } void @@ -3531,6 +3769,7 @@ sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS) struct uma_type_header uth; struct uma_percpu_stat ups; uma_bucket_t bucket; + uma_zone_domain_t zdom; struct sbuf sbuf; uma_cache_t cache; uma_klink_t kl; @@ -3586,8 +3825,12 @@ sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS) (LIST_FIRST(&kz->uk_zones) != z)) uth.uth_zone_flags = UTH_ZONE_SECONDARY; - LIST_FOREACH(bucket, &z->uz_buckets, ub_link) - uth.uth_zone_free += bucket->ub_cnt; + for (i = 0; i < vm_ndomains; i++) { + zdom = &z->uz_domain[i]; + LIST_FOREACH(bucket, &zdom->uzd_buckets, + ub_link) + uth.uth_zone_free += bucket->ub_cnt; + } uth.uth_allocs = z->uz_allocs; uth.uth_frees = z->uz_frees; uth.uth_fails = z->uz_fails; @@ -3754,11 +3997,12 @@ uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item) #ifdef DDB DB_SHOW_COMMAND(uma, db_show_uma) { - uint64_t allocs, frees, sleeps; uma_bucket_t bucket; uma_keg_t kz; uma_zone_t z; - int cachefree; + uma_zone_domain_t zdom; + uint64_t allocs, frees, sleeps; + int cachefree, i; db_printf("%18s %8s %8s %8s %12s %8s %8s\n", "Zone", "Size", "Used", "Free", "Requests", "Sleeps", "Bucket"); @@ -3775,8 +4019,12 @@ DB_SHOW_COMMAND(uma, db_show_uma) if (!((z->uz_flags & UMA_ZONE_SECONDARY) && (LIST_FIRST(&kz->uk_zones) != z))) cachefree += kz->uk_free; - LIST_FOREACH(bucket, &z->uz_buckets, ub_link) - cachefree += bucket->ub_cnt; + for (i = 0; i < vm_ndomains; i++) { + zdom = &z->uz_domain[i]; + LIST_FOREACH(bucket, &zdom->uzd_buckets, + ub_link) + cachefree += bucket->ub_cnt; + } db_printf("%18s %8ju %8jd %8d %12ju %8ju %8u\n", z->uz_name, (uintmax_t)kz->uk_size, (intmax_t)(allocs - frees), cachefree, @@ -3789,17 +4037,21 @@ DB_SHOW_COMMAND(uma, db_show_uma) DB_SHOW_COMMAND(umacache, db_show_umacache) { - uint64_t allocs, frees; uma_bucket_t bucket; uma_zone_t z; - int cachefree; + uma_zone_domain_t zdom; + uint64_t allocs, frees; + int cachefree, i; db_printf("%18s %8s %8s %8s %12s %8s\n", "Zone", "Size", "Used", "Free", "Requests", "Bucket"); LIST_FOREACH(z, &uma_cachezones, uz_link) { uma_zone_sumstat(z, &cachefree, &allocs, &frees, NULL); - LIST_FOREACH(bucket, &z->uz_buckets, ub_link) - cachefree += bucket->ub_cnt; + for (i = 0; i < vm_ndomains; i++) { + zdom = &z->uz_domain[i]; + LIST_FOREACH(bucket, &zdom->uzd_buckets, ub_link) + cachefree += bucket->ub_cnt; + } db_printf("%18s %8ju %8jd %8d %12ju %8u\n", z->uz_name, (uintmax_t)z->uz_size, (intmax_t)(allocs - frees), cachefree, diff --git a/freebsd/sys/vm/uma_int.h b/freebsd/sys/vm/uma_int.h index 592e79d7..5852a1c3 100644 --- a/freebsd/sys/vm/uma_int.h +++ b/freebsd/sys/vm/uma_int.h @@ -39,7 +39,22 @@ */ /* - * Here's a quick description of the relationship between the objects: + * The brief summary; Zones describe unique allocation types. Zones are + * organized into per-CPU caches which are filled by buckets. Buckets are + * organized according to memory domains. Buckets are filled from kegs which + * are also organized according to memory domains. Kegs describe a unique + * allocation type, backend memory provider, and layout. Kegs are associated + * with one or more zones and zones reference one or more kegs. Kegs provide + * slabs which are virtually contiguous collections of pages. Each slab is + * broken down int one or more items that will satisfy an individual allocation. + * + * Allocation is satisfied in the following order: + * 1) Per-CPU cache + * 2) Per-domain cache of buckets + * 3) Slab from any of N kegs + * 4) Backend page provider + * + * More detail on individual objects is contained below: * * Kegs contain lists of slabs which are stored in either the full bin, empty * bin, or partially allocated bin, to reduce fragmentation. They also contain @@ -47,6 +62,13 @@ * and rsize is the result of that. The Keg also stores information for * managing a hash of page addresses that maps pages to uma_slab_t structures * for pages that don't have embedded uma_slab_t's. + * + * Keg slab lists are organized by memory domain to support NUMA allocation + * policies. By default allocations are spread across domains to reduce the + * potential for hotspots. Special keg creation flags may be specified to + * prefer location allocation. However there is no strict enforcement as frees + * may happen on any CPU and these are returned to the CPU-local cache + * regardless of the originating domain. * * The uma_slab_t may be embedded in a UMA_SLAB_SIZE chunk of memory or it may * be allocated off the page from a special slab zone. The free list within a @@ -182,6 +204,17 @@ struct uma_cache { typedef struct uma_cache * uma_cache_t; /* + * Per-domain memory list. Embedded in the kegs. + */ +struct uma_domain { + LIST_HEAD(,uma_slab) ud_part_slab; /* partially allocated slabs */ + LIST_HEAD(,uma_slab) ud_free_slab; /* empty slab list */ + LIST_HEAD(,uma_slab) ud_full_slab; /* full slabs */ +}; + +typedef struct uma_domain * uma_domain_t; + +/* * Keg management structure * * TODO: Optimize for cache line size @@ -192,10 +225,8 @@ struct uma_keg { struct uma_hash uk_hash; LIST_HEAD(,uma_zone) uk_zones; /* Keg's zones */ - LIST_HEAD(,uma_slab) uk_part_slab; /* partially allocated slabs */ - LIST_HEAD(,uma_slab) uk_free_slab; /* empty slab list */ - LIST_HEAD(,uma_slab) uk_full_slab; /* full slabs */ + uint32_t uk_cursor; /* Domain alloc cursor. */ uint32_t uk_align; /* Alignment mask */ uint32_t uk_pages; /* Total page count */ uint32_t uk_free; /* Count of items free in slabs */ @@ -221,6 +252,9 @@ struct uma_keg { /* Least used fields go to the last cache line. */ const char *uk_name; /* Name of creating zone. */ LIST_ENTRY(uma_keg) uk_link; /* List of all kegs */ + + /* Must be last, variable sized. */ + struct uma_domain uk_domain[]; /* Keg's slab lists. */ }; typedef struct uma_keg * uma_keg_t; @@ -250,7 +284,7 @@ struct uma_slab { #endif uint16_t us_freecount; /* How many are free? */ uint8_t us_flags; /* Page flags see uma.h */ - uint8_t us_pad; /* Pad to 32bits, unused. */ + uint8_t us_domain; /* Backing NUMA domain. */ }; #define us_link us_type._us_link @@ -258,8 +292,12 @@ struct uma_slab { #define us_size us_type._us_size #endif /* __rtems__ */ +#if MAXMEMDOM >= 255 +#error "Slab domain type insufficient" +#endif + typedef struct uma_slab * uma_slab_t; -typedef uma_slab_t (*uma_slaballoc)(uma_zone_t, uma_keg_t, int); +typedef uma_slab_t (*uma_slaballoc)(uma_zone_t, uma_keg_t, int, int); struct uma_klink { LIST_ENTRY(uma_klink) kl_link; @@ -267,6 +305,12 @@ struct uma_klink { }; typedef struct uma_klink *uma_klink_t; +struct uma_zone_domain { + LIST_HEAD(,uma_bucket) uzd_buckets; /* full buckets */ +}; + +typedef struct uma_zone_domain * uma_zone_domain_t; + /* * Zone management structure * @@ -279,7 +323,7 @@ struct uma_zone { const char *uz_name; /* Text name of the zone */ LIST_ENTRY(uma_zone) uz_link; /* List of all zones in keg */ - LIST_HEAD(,uma_bucket) uz_buckets; /* full buckets */ + struct uma_zone_domain *uz_domain; /* per-domain buckets */ LIST_HEAD(,uma_klink) uz_kegs; /* List of kegs. */ struct uma_klink uz_klink; /* klink for first keg. */ @@ -313,7 +357,9 @@ struct uma_zone { * This HAS to be the last item because we adjust the zone size * based on NCPU and then allocate the space for the zones. */ - struct uma_cache uz_cpu[1]; /* Per cpu caches */ + struct uma_cache uz_cpu[]; /* Per cpu caches */ + + /* uz_domain follows here. */ }; /* @@ -344,6 +390,7 @@ zone_first_keg(uma_zone_t zone) /* Internal prototypes */ static __inline uma_slab_t hash_sfind(struct uma_hash *hash, uint8_t *data); void *uma_large_malloc(vm_size_t size, int wait); +void *uma_large_malloc_domain(vm_size_t size, int domain, int wait); void uma_large_free(uma_slab_t slab); /* Lock Macros */ @@ -437,16 +484,12 @@ vsetslab(vm_offset_t va, uma_slab_t slab) * if they can provide more efficient allocation functions. This is useful * for using direct mapped addresses. */ -void *uma_small_alloc(uma_zone_t zone, vm_size_t bytes, uint8_t *pflag, - int wait); +void *uma_small_alloc(uma_zone_t zone, vm_size_t bytes, int domain, + uint8_t *pflag, int wait); void uma_small_free(void *mem, vm_size_t size, uint8_t flags); /* Set a global soft limit on UMA managed memory. */ void uma_set_limit(unsigned long limit); -unsigned long uma_limit(void); - -/* Return the amount of memory managed by UMA. */ -unsigned long uma_size(void); #endif /* _KERNEL */ #endif /* VM_UMA_INT_H */ diff --git a/freebsd/sys/vm/vm.h b/freebsd/sys/vm/vm.h index f674fc56..b5de53d3 100644 --- a/freebsd/sys/vm/vm.h +++ b/freebsd/sys/vm/vm.h @@ -146,6 +146,8 @@ extern void vm_ksubmap_init(struct kva_md_info *); extern int old_mlock; +#define vm_ndomains 1 + struct ucred; int swap_reserve(vm_ooffset_t incr); int swap_reserve_by_cred(vm_ooffset_t incr, struct ucred *cred); diff --git a/freebsd/sys/vm/vm_extern.h b/freebsd/sys/vm/vm_extern.h index c92933ca..e64637c1 100644 --- a/freebsd/sys/vm/vm_extern.h +++ b/freebsd/sys/vm/vm_extern.h @@ -56,14 +56,21 @@ void kmap_free_wakeup(vm_map_t, vm_offset_t, vm_size_t); /* These operate on virtual addresses backed by memory. */ vm_offset_t kmem_alloc_attr(struct vmem *, vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, vm_memattr_t memattr); +vm_offset_t kmem_alloc_attr_domain(int domain, vm_size_t size, int flags, + vm_paddr_t low, vm_paddr_t high, vm_memattr_t memattr); vm_offset_t kmem_alloc_contig(struct vmem *, vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary, vm_memattr_t memattr); +vm_offset_t kmem_alloc_contig_domain(int domain, vm_size_t size, int flags, + vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary, + vm_memattr_t memattr); vm_offset_t kmem_malloc(struct vmem *, vm_size_t size, int flags); +vm_offset_t kmem_malloc_domain(int domain, vm_size_t size, int flags); void kmem_free(struct vmem *, vm_offset_t, vm_size_t); /* This provides memory for previously allocated address space. */ int kmem_back(vm_object_t, vm_offset_t, vm_size_t, int); +int kmem_back_domain(int, vm_object_t, vm_offset_t, vm_size_t, int); void kmem_unback(vm_object_t, vm_offset_t, vm_size_t); /* Bootstrapping. */ diff --git a/freebsd/sys/x86/include/machine/bus.h b/freebsd/sys/x86/include/machine/bus.h index 041ab156..297b5edc 100644 --- a/freebsd/sys/x86/include/machine/bus.h +++ b/freebsd/sys/x86/include/machine/bus.h @@ -118,6 +118,7 @@ #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF #if defined(__amd64__) || defined(PAE) +#define BUS_SPACE_MAXADDR_48BIT 0xFFFFFFFFFFFFULL #define BUS_SPACE_MAXADDR 0xFFFFFFFFFFFFFFFFULL #else #define BUS_SPACE_MAXADDR 0xFFFFFFFF diff --git a/freebsd/sys/x86/pci/pci_bus.c b/freebsd/sys/x86/pci/pci_bus.c index 8d37bdcd..0db41c18 100644 --- a/freebsd/sys/x86/pci/pci_bus.c +++ b/freebsd/sys/x86/pci/pci_bus.c @@ -686,8 +686,7 @@ DRIVER_MODULE(pcib, legacy, legacy_pcib_driver, hostb_devclass, 0, 0); * ID is available and the PCI BIOS isn't, but for now we just * eat the PnP ID and do nothing else. * - * XXX we should silence this probe, as it will generally confuse - * people. + * we silence this probe, as it will generally confuse people. */ static struct isa_pnp_id pcibus_pnp_ids[] = { { 0x030ad041 /* PNP0A03 */, "PCI Bus" }, @@ -751,6 +750,7 @@ static devclass_t pcib_devclass; DEFINE_CLASS_1(pcib, pcibios_pcib_driver, pcibios_pcib_pci_methods, sizeof(struct pcib_softc), pcib_driver); DRIVER_MODULE(pcibios_pcib, pci, pcibios_pcib_driver, pcib_devclass, 0, 0); +ISA_PNP_INFO(pcibus_pnp_ids); static int pcibios_pcib_probe(device_t dev) |