diff options
Diffstat (limited to 'sys')
287 files changed, 5878 insertions, 1329 deletions
diff --git a/sys/amd64/amd64/apic_vector.S b/sys/amd64/amd64/apic_vector.S index a1279e6..b3ca520 100644 --- a/sys/amd64/amd64/apic_vector.S +++ b/sys/amd64/amd64/apic_vector.S @@ -174,22 +174,6 @@ IDTVEC(xen_intr_upcall) jmp doreti #endif -#ifdef HYPERV -/* - * This is the Hyper-V vmbus channel direct callback interrupt. - * Only used when it is running on Hyper-V. - */ - .text - SUPERALIGN_TEXT -IDTVEC(hv_vmbus_callback) - PUSH_FRAME - FAKE_MCOUNT(TF_RIP(%rsp)) - movq %rsp, %rdi - call hv_vector_handler - MEXITCOUNT - jmp doreti -#endif - #ifdef SMP /* * Global address space TLB shootdown. diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S index caabfd9..fd8cdac 100644 --- a/sys/amd64/amd64/exception.S +++ b/sys/amd64/amd64/exception.S @@ -659,6 +659,7 @@ MCOUNT_LABEL(eintr) .text SUPERALIGN_TEXT .type doreti,@function + .globl doreti doreti: FAKE_MCOUNT($bintr) /* init "from" bintr -> doreti */ /* diff --git a/sys/amd64/amd64/minidump_machdep.c b/sys/amd64/amd64/minidump_machdep.c index cc32cdc..df04f42 100644 --- a/sys/amd64/amd64/minidump_machdep.c +++ b/sys/amd64/amd64/minidump_machdep.c @@ -56,9 +56,6 @@ CTASSERT(sizeof(struct kerneldumpheader) == 512); */ #define SIZEOF_METADATA (64*1024) -#define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK) -#define DEV_ALIGN(x) (((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1)) - uint64_t *vm_page_dump; int vm_page_dump_size; @@ -222,6 +219,7 @@ minidumpsys(struct dumperinfo *di) int error; uint64_t bits; uint64_t *pml4, *pdp, *pd, *pt, pa; + size_t size; int i, ii, j, k, n, bit; int retry_count; struct minidumphdr mdhdr; @@ -319,12 +317,12 @@ minidumpsys(struct dumperinfo *di) dumpsize += PAGE_SIZE; /* Determine dump offset on device. */ - if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) { + if (di->mediasize < SIZEOF_METADATA + dumpsize + di->blocksize * 2) { error = E2BIG; goto fail; } dumplo = di->mediaoffset + di->mediasize - dumpsize; - dumplo -= sizeof(kdh) * 2; + dumplo -= di->blocksize * 2; progress = dumpsize; /* Initialize mdhdr */ @@ -344,10 +342,10 @@ minidumpsys(struct dumperinfo *di) ptoa((uintmax_t)physmem) / 1048576); /* Dump leader */ - error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); + error = dump_write_pad(di, &kdh, 0, dumplo, sizeof(kdh), &size); if (error) goto fail; - dumplo += sizeof(kdh); + dumplo += size; /* Dump my header */ bzero(&fakepd, sizeof(fakepd)); @@ -432,10 +430,10 @@ minidumpsys(struct dumperinfo *di) goto fail; /* Dump trailer */ - error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); + error = dump_write_pad(di, &kdh, 0, dumplo, sizeof(kdh), &size); if (error) goto fail; - dumplo += sizeof(kdh); + dumplo += size; /* Signal completion, signoff and exit stage left. */ dump_write(di, NULL, 0, 0, 0); diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index 0ed672d..272da43 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -350,8 +350,6 @@ device virtio_scsi # VirtIO SCSI device device virtio_balloon # VirtIO Memory Balloon device # HyperV drivers and enchancement support -# NOTE: HYPERV depends on hyperv. They must be added or removed together. -options HYPERV # Hyper-V kernel infrastructure device hyperv # HyperV drivers # Xen HVM Guest Optimizations diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES index 3e7876a..c87ad64 100644 --- a/sys/amd64/conf/NOTES +++ b/sys/amd64/conf/NOTES @@ -515,7 +515,6 @@ device virtio_random # VirtIO Entropy device device virtio_console # VirtIO Console device # Microsoft Hyper-V enchancement support -options HYPERV # Hyper-V kernel infrastructure device hyperv # HyperV drivers # Xen HVM Guest Optimizations diff --git a/sys/arm/allwinner/a10_common.c b/sys/arm/allwinner/a10_common.c index d20853a..82be0c0 100644 --- a/sys/arm/allwinner/a10_common.c +++ b/sys/arm/allwinner/a10_common.c @@ -42,7 +42,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG static int fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, @@ -69,4 +69,4 @@ fdt_pic_decode_t fdt_pic_table[] = { NULL }; -#endif /* ARM_INTRNG */ +#endif /* INTRNG */ diff --git a/sys/arm/altera/socfpga/socfpga_common.c b/sys/arm/altera/socfpga/socfpga_common.c index 3615c94..740d342 100644 --- a/sys/arm/altera/socfpga/socfpga_common.c +++ b/sys/arm/altera/socfpga/socfpga_common.c @@ -74,7 +74,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG static int fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) diff --git a/sys/arm/amlogic/aml8726/aml8726_machdep.c b/sys/arm/amlogic/aml8726/aml8726_machdep.c index 1ad25b4..5037180 100644 --- a/sys/arm/amlogic/aml8726/aml8726_machdep.c +++ b/sys/arm/amlogic/aml8726/aml8726_machdep.c @@ -184,7 +184,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG #ifndef DEV_GIC static int fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, @@ -213,4 +213,4 @@ fdt_pic_decode_t fdt_pic_table[] = { #endif NULL }; -#endif /* ARM_INTRNG */ +#endif /* INTRNG */ diff --git a/sys/arm/annapurna/alpine/common.c b/sys/arm/annapurna/alpine/common.c index 5d45b55..cf90556 100644 --- a/sys/arm/annapurna/alpine/common.c +++ b/sys/arm/annapurna/alpine/common.c @@ -136,7 +136,7 @@ infinite: while (1) {} } -#ifndef ARM_INTRNG +#ifndef INTRNG static int alpine_pic_decode_fdt(uint32_t iparent, uint32_t *intr, int *interrupt, int *trig, int *pol) diff --git a/sys/arm/arm/gic.c b/sys/arm/arm/gic.c index 5c0aece..85d1557 100644 --- a/sys/arm/arm/gic.c +++ b/sys/arm/arm/gic.c @@ -50,7 +50,7 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/mutex.h> #include <sys/smp.h> -#ifdef ARM_INTRNG +#ifdef INTRNG #include <sys/sched.h> #endif #include <machine/bus.h> @@ -62,7 +62,7 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> -#ifdef ARM_INTRNG +#ifdef INTRNG #include "pic_if.h" #endif @@ -116,12 +116,14 @@ __FBSDID("$FreeBSD$"); #define GIC_DEFAULT_ICFGR_INIT 0x00000000 #endif -#ifdef ARM_INTRNG +#ifdef INTRNG struct gic_irqsrc { struct intr_irqsrc gi_isrc; uint32_t gi_irq; enum intr_polarity gi_pol; enum intr_trigger gi_trig; +#define GI_FLAG_EARLY_EOI (1 << 0) + u_int gi_flags; }; static u_int gic_irq_cpu; @@ -134,9 +136,22 @@ u_int sgi_first_unused = GIC_FIRST_SGI; #endif #endif +#ifdef INTRNG +struct arm_gic_range { + uint64_t bus; + uint64_t host; + uint64_t size; +}; + +struct arm_gic_devinfo { + struct ofw_bus_devinfo obdinfo; + struct resource_list rl; +}; +#endif + struct arm_gic_softc { device_t gic_dev; -#ifdef ARM_INTRNG +#ifdef INTRNG void * gic_intrhand; struct gic_irqsrc * gic_irqs; #endif @@ -151,16 +166,24 @@ struct arm_gic_softc { #ifdef GIC_DEBUG_SPURIOUS uint32_t last_irq[MAXCPU]; #endif + +#ifdef INTRNG + /* FDT child data */ + pcell_t addr_cells; + pcell_t size_cells; + int nranges; + struct arm_gic_range * ranges; +#endif }; -#ifdef ARM_INTRNG +#ifdef INTRNG #define GIC_INTR_ISRC(sc, irq) (&sc->gic_irqs[irq].gi_isrc) #endif static struct resource_spec arm_gic_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Distributor registers */ { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* CPU Interrupt Intf. registers */ -#ifdef ARM_INTRNG +#ifdef INTRNG { SYS_RES_IRQ, 0, RF_ACTIVE | RF_OPTIONAL }, /* Parent interrupt */ #endif { -1, 0 } @@ -181,7 +204,7 @@ static struct arm_gic_softc *gic_sc = NULL; #define gic_d_write_4(_sc, _reg, _val) \ bus_space_write_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg), (_val)) -#ifndef ARM_INTRNG +#ifndef INTRNG static int gic_config_irq(int irq, enum intr_trigger trig, enum intr_polarity pol); static void gic_post_filter(void *); @@ -195,6 +218,7 @@ static struct ofw_compat_data compat_data[] = { {"arm,cortex-a7-gic", true}, {"arm,arm11mp-gic", true}, {"brcm,brahma-b15-gic", true}, + {"qcom,msm-qgic2", true}, {NULL, false} }; @@ -211,7 +235,7 @@ arm_gic_probe(device_t dev) return (BUS_PROBE_DEFAULT); } -#ifdef ARM_INTRNG +#ifdef INTRNG static inline void gic_irq_unmask(struct arm_gic_softc *sc, u_int irq) { @@ -251,7 +275,7 @@ gic_cpu_mask(struct arm_gic_softc *sc) } #ifdef SMP -#ifdef ARM_INTRNG +#ifdef INTRNG static void arm_gic_init_secondary(device_t dev) { @@ -323,10 +347,10 @@ arm_gic_init_secondary(device_t dev) gic_d_write_4(sc, GICD_ISENABLER(29 >> 5), (1UL << (29 & 0x1F))); gic_d_write_4(sc, GICD_ISENABLER(30 >> 5), (1UL << (30 & 0x1F))); } -#endif /* ARM_INTRNG */ +#endif /* INTRNG */ #endif /* SMP */ -#ifndef ARM_INTRNG +#ifndef INTRNG int gic_decode_fdt(phandle_t iparent, pcell_t *intr, int *interrupt, int *trig, int *pol) @@ -387,7 +411,7 @@ gic_decode_fdt(phandle_t iparent, pcell_t *intr, int *interrupt, } #endif -#ifdef ARM_INTRNG +#ifdef INTRNG static inline intptr_t gic_xref(device_t dev) { @@ -437,6 +461,107 @@ arm_gic_register_isrcs(struct arm_gic_softc *sc, uint32_t num) sc->nirqs = num; return (0); } + +static int +arm_gic_fill_ranges(phandle_t node, struct arm_gic_softc *sc) +{ + pcell_t host_cells; + cell_t *base_ranges; + ssize_t nbase_ranges; + int i, j, k; + + host_cells = 1; + OF_getencprop(OF_parent(node), "#address-cells", &host_cells, + sizeof(host_cells)); + sc->addr_cells = 2; + OF_getencprop(node, "#address-cells", &sc->addr_cells, + sizeof(sc->addr_cells)); + sc->size_cells = 2; + OF_getencprop(node, "#size-cells", &sc->size_cells, + sizeof(sc->size_cells)); + + nbase_ranges = OF_getproplen(node, "ranges"); + if (nbase_ranges < 0) + return (-1); + sc->nranges = nbase_ranges / sizeof(cell_t) / + (sc->addr_cells + host_cells + sc->size_cells); + if (sc->nranges == 0) + return (0); + + sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]), + M_DEVBUF, M_WAITOK); + base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK); + OF_getencprop(node, "ranges", base_ranges, nbase_ranges); + + for (i = 0, j = 0; i < sc->nranges; i++) { + sc->ranges[i].bus = 0; + for (k = 0; k < sc->addr_cells; k++) { + sc->ranges[i].bus <<= 32; + sc->ranges[i].bus |= base_ranges[j++]; + } + sc->ranges[i].host = 0; + for (k = 0; k < host_cells; k++) { + sc->ranges[i].host <<= 32; + sc->ranges[i].host |= base_ranges[j++]; + } + sc->ranges[i].size = 0; + for (k = 0; k < sc->size_cells; k++) { + sc->ranges[i].size <<= 32; + sc->ranges[i].size |= base_ranges[j++]; + } + } + + free(base_ranges, M_DEVBUF); + return (sc->nranges); +} + +static bool +arm_gic_add_children(device_t dev) +{ + struct arm_gic_softc *sc; + struct arm_gic_devinfo *dinfo; + phandle_t child, node; + device_t cdev; + + sc = device_get_softc(dev); + node = ofw_bus_get_node(dev); + + /* If we have no children don't probe for them */ + child = OF_child(node); + if (child == 0) + return (false); + + if (arm_gic_fill_ranges(node, sc) < 0) { + device_printf(dev, "Have a child, but no ranges\n"); + return (false); + } + + for (; child != 0; child = OF_peer(child)) { + dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); + + if (ofw_bus_gen_setup_devinfo(&dinfo->obdinfo, child) != 0) { + free(dinfo, M_DEVBUF); + continue; + } + + resource_list_init(&dinfo->rl); + ofw_bus_reg_to_rl(dev, child, sc->addr_cells, + sc->size_cells, &dinfo->rl); + + cdev = device_add_child(dev, NULL, -1); + if (cdev == NULL) { + device_printf(dev, "<%s>: device_add_child failed\n", + dinfo->obdinfo.obd_name); + resource_list_free(&dinfo->rl); + ofw_bus_gen_destroy_devinfo(&dinfo->obdinfo); + free(dinfo, M_DEVBUF); + continue; + } + device_set_ivars(cdev, dinfo); + } + + return (true); +} #endif static int @@ -445,7 +570,7 @@ arm_gic_attach(device_t dev) struct arm_gic_softc *sc; int i; uint32_t icciidr, mask, nirqs; -#ifdef ARM_INTRNG +#ifdef INTRNG phandle_t pxref; intptr_t xref = gic_xref(dev); #endif @@ -481,7 +606,7 @@ arm_gic_attach(device_t dev) nirqs = gic_d_read_4(sc, GICD_TYPER); nirqs = 32 * ((nirqs & 0x1f) + 1); -#ifdef ARM_INTRNG +#ifdef INTRNG if (arm_gic_register_isrcs(sc, nirqs)) { device_printf(dev, "could not register irqs\n"); goto cleanup; @@ -537,7 +662,7 @@ arm_gic_attach(device_t dev) /* Enable interrupt distribution */ gic_d_write_4(sc, GICD_CTLR, 0x01); -#ifndef ARM_INTRNG +#ifndef INTRNG return (0); #else /* @@ -578,6 +703,13 @@ arm_gic_attach(device_t dev) } OF_device_register_xref(xref, dev); + + /* If we have children probe and attach them */ + if (arm_gic_add_children(dev)) { + bus_generic_probe(dev); + return (bus_generic_attach(dev)); + } + return (0); cleanup: @@ -591,7 +723,76 @@ cleanup: #endif } -#ifdef ARM_INTRNG +#ifdef INTRNG +static struct resource * +arm_gic_alloc_resource(device_t bus, device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) +{ + struct arm_gic_softc *sc; + struct arm_gic_devinfo *di; + struct resource_list_entry *rle; + int j; + + KASSERT(type == SYS_RES_MEMORY, ("Invalid resoure type %x", type)); + + sc = device_get_softc(bus); + + /* + * Request for the default allocation with a given rid: use resource + * list stored in the local device info. + */ + if (RMAN_IS_DEFAULT_RANGE(start, end)) { + if ((di = device_get_ivars(child)) == NULL) + return (NULL); + + if (type == SYS_RES_IOPORT) + type = SYS_RES_MEMORY; + + rle = resource_list_find(&di->rl, type, *rid); + if (rle == NULL) { + if (bootverbose) + device_printf(bus, "no default resources for " + "rid = %d, type = %d\n", *rid, type); + return (NULL); + } + start = rle->start; + end = rle->end; + count = rle->count; + } + + /* Remap through ranges property */ + for (j = 0; j < sc->nranges; j++) { + if (start >= sc->ranges[j].bus && end < + sc->ranges[j].bus + sc->ranges[j].size) { + start -= sc->ranges[j].bus; + start += sc->ranges[j].host; + end -= sc->ranges[j].bus; + end += sc->ranges[j].host; + break; + } + } + if (j == sc->nranges && sc->nranges != 0) { + if (bootverbose) + device_printf(bus, "Could not map resource " + "%#jx-%#jx\n", (uintmax_t)start, (uintmax_t)end); + + return (NULL); + } + + return (bus_generic_alloc_resource(bus, child, type, rid, start, end, + count, flags)); +} + +static const struct ofw_bus_devinfo * +arm_gic_ofw_get_devinfo(device_t bus __unused, device_t child) +{ + struct arm_gic_devinfo *di; + + di = device_get_ivars(child); + + return (&di->obdinfo); +} + static int arm_gic_intr(void *arg) { @@ -654,12 +855,12 @@ dispatch_irq: #ifdef GIC_DEBUG_SPURIOUS sc->last_irq[PCPU_GET(cpuid)] = irq; #endif - if (gi->gi_trig == INTR_TRIGGER_EDGE) + if ((gi->gi_flags & GI_FLAG_EARLY_EOI) == GI_FLAG_EARLY_EOI) gic_c_write_4(sc, GICC_EOIR, irq_active_reg); if (intr_isrc_dispatch(&gi->gi_isrc, tf) != 0) { gic_irq_mask(sc, irq); - if (gi->gi_trig != INTR_TRIGGER_EDGE) + if ((gi->gi_flags & GI_FLAG_EARLY_EOI) != GI_FLAG_EARLY_EOI) gic_c_write_4(sc, GICC_EOIR, irq_active_reg); device_printf(sc->gic_dev, "Stray irq %u disabled\n", irq); } @@ -888,6 +1089,9 @@ arm_gic_setup_intr(device_t dev, struct intr_irqsrc *isrc, gi->gi_pol = pol; gi->gi_trig = trig; + /* Edge triggered interrupts need an early EOI sent */ + if (gi->gi_pol == INTR_TRIGGER_EDGE) + gi->gi_flags |= GI_FLAG_EARLY_EOI; /* * XXX - In case that per CPU interrupt is going to be enabled in time @@ -961,7 +1165,7 @@ arm_gic_post_filter(device_t dev, struct intr_irqsrc *isrc) struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc; /* EOI for edge-triggered done earlier. */ - if (gi->gi_trig == INTR_TRIGGER_EDGE) + if ((gi->gi_flags & GI_FLAG_EARLY_EOI) == GI_FLAG_EARLY_EOI) return; arm_irq_memory_barrier(0); @@ -1225,13 +1429,28 @@ pic_ipi_clear(int ipi) arm_gic_ipi_clear(gic_sc->gic_dev, ipi); } #endif -#endif /* ARM_INTRNG */ +#endif /* INTRNG */ static device_method_t arm_gic_methods[] = { /* Device interface */ DEVMETHOD(device_probe, arm_gic_probe), DEVMETHOD(device_attach, arm_gic_attach), -#ifdef ARM_INTRNG + +#ifdef INTRNG + /* Bus interface */ + DEVMETHOD(bus_add_child, bus_generic_add_child), + DEVMETHOD(bus_alloc_resource, arm_gic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource,bus_generic_activate_resource), + + /* ofw_bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, arm_gic_ofw_get_devinfo), + DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), + DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), + DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), + DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), + DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), + /* Interrupt controller interface */ DEVMETHOD(pic_disable_intr, arm_gic_disable_intr), DEVMETHOD(pic_enable_intr, arm_gic_enable_intr), @@ -1263,3 +1482,89 @@ EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); EARLY_DRIVER_MODULE(gic, ofwbus, arm_gic_driver, arm_gic_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); + +#ifdef INTRNG +/* + * GICv2m support -- the GICv2 MSI/MSI-X controller. + */ + +#define GICV2M_MSI_TYPER 0x008 +#define MSI_TYPER_SPI_BASE(x) (((x) >> 16) & 0x3ff) +#define MSI_TYPER_SPI_COUNT(x) (((x) >> 0) & 0x3ff) +#define GICv2M_MSI_SETSPI_NS 0x040 +#define GICV2M_MSI_IIDR 0xFCC + +struct arm_gicv2m_softc { + struct resource *sc_mem; + struct mtx sc_mutex; + u_int sc_spi_start; + u_int sc_spi_count; + u_int sc_spi_offset; +}; + +static struct ofw_compat_data gicv2m_compat_data[] = { + {"arm,gic-v2m-frame", true}, + {NULL, false} +}; + +static int +arm_gicv2m_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_search_compatible(dev, gicv2m_compat_data)->ocd_data) + return (ENXIO); + + device_set_desc(dev, "ARM Generic Interrupt Controller MSI/MSIX"); + return (BUS_PROBE_DEFAULT); +} + +static int +arm_gicv2m_attach(device_t dev) +{ + struct arm_gicv2m_softc *sc; + uint32_t typer; + int rid; + + sc = device_get_softc(dev); + + rid = 0; + sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (sc->sc_mem == NULL) { + device_printf(dev, "Unable to allocate resources\n"); + return (ENXIO); + } + + typer = bus_read_4(sc->sc_mem, GICV2M_MSI_TYPER); + sc->sc_spi_start = MSI_TYPER_SPI_BASE(typer); + sc->sc_spi_count = MSI_TYPER_SPI_COUNT(typer); + + mtx_init(&sc->sc_mutex, "GICv2m lock", "", MTX_DEF); + + if (bootverbose) + device_printf(dev, "using spi %u to %u\n", sc->sc_spi_start, + sc->sc_spi_start + sc->sc_spi_count - 1); + + return (0); +} + +static device_method_t arm_gicv2m_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, arm_gicv2m_probe), + DEVMETHOD(device_attach, arm_gicv2m_attach), + + /* End */ + DEVMETHOD_END +}; + +DEFINE_CLASS_0(gicv2m, arm_gicv2m_driver, arm_gicv2m_methods, + sizeof(struct arm_gicv2m_softc)); + +static devclass_t arm_gicv2m_devclass; + +EARLY_DRIVER_MODULE(gicv2m, gic, arm_gicv2m_driver, + arm_gicv2m_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); +#endif diff --git a/sys/arm/arm/machdep_intr.c b/sys/arm/arm/machdep_intr.c index 504d262..b21dfa1 100644 --- a/sys/arm/arm/machdep_intr.c +++ b/sys/arm/arm/machdep_intr.c @@ -49,7 +49,7 @@ __FBSDID("$FreeBSD$"); #include <machine/cpu.h> #include <machine/smp.h> -#ifdef ARM_INTRNG +#ifdef INTRNG #include "pic_if.h" #ifdef SMP @@ -131,7 +131,7 @@ arm_irq_memory_barrier(uintptr_t irq) cpu_l2cache_drain_writebuf(); } -#ifdef ARM_INTRNG +#ifdef INTRNG #ifdef SMP static inline struct intr_ipi * intr_ipi_lookup(u_int ipi) diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c index 699881c..db52622 100644 --- a/sys/arm/arm/mp_machdep.c +++ b/sys/arm/arm/mp_machdep.c @@ -74,7 +74,7 @@ volatile int mp_naps; /* Set to 1 once we're ready to let the APs out of the pen. */ volatile int aps_ready = 0; -#ifndef ARM_INTRNG +#ifndef INTRNG static int ipi_handler(void *arg); #endif void set_stackptrs(int cpu); @@ -152,7 +152,7 @@ init_secondary(int cpu) { struct pcpu *pc; uint32_t loop_counter; -#ifndef ARM_INTRNG +#ifndef INTRNG int start = 0, end = 0; #endif uint32_t actlr_mask, actlr_set; @@ -207,7 +207,7 @@ init_secondary(int cpu) mtx_unlock_spin(&ap_boot_mtx); -#ifndef ARM_INTRNG +#ifndef INTRNG /* Enable ipi */ #ifdef IPI_IRQ_START start = IPI_IRQ_START; @@ -243,7 +243,7 @@ init_secondary(int cpu) /* NOTREACHED */ } -#ifdef ARM_INTRNG +#ifdef INTRNG static void ipi_rendezvous(void *dummy __unused) { @@ -421,14 +421,14 @@ static void release_aps(void *dummy __unused) { uint32_t loop_counter; -#ifndef ARM_INTRNG +#ifndef INTRNG int start = 0, end = 0; #endif if (mp_ncpus == 1) return; -#ifdef ARM_INTRNG +#ifdef INTRNG intr_pic_ipi_setup(IPI_RENDEZVOUS, "rendezvous", ipi_rendezvous, NULL); intr_pic_ipi_setup(IPI_AST, "ast", ipi_ast, NULL); intr_pic_ipi_setup(IPI_STOP, "stop", ipi_stop, NULL); @@ -501,7 +501,7 @@ ipi_all_but_self(u_int ipi) other_cpus = all_cpus; CPU_CLR(PCPU_GET(cpuid), &other_cpus); CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi); -#ifdef ARM_INTRNG +#ifdef INTRNG intr_ipi_send(other_cpus, ipi); #else pic_ipi_send(other_cpus, ipi); @@ -517,7 +517,7 @@ ipi_cpu(int cpu, u_int ipi) CPU_SET(cpu, &cpus); CTR3(KTR_SMP, "%s: cpu: %d, ipi: %x", __func__, cpu, ipi); -#ifdef ARM_INTRNG +#ifdef INTRNG intr_ipi_send(cpus, ipi); #else pic_ipi_send(cpus, ipi); @@ -529,7 +529,7 @@ ipi_selected(cpuset_t cpus, u_int ipi) { CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi); -#ifdef ARM_INTRNG +#ifdef INTRNG intr_ipi_send(cpus, ipi); #else pic_ipi_send(cpus, ipi); diff --git a/sys/arm/arm/nexus.c b/sys/arm/arm/nexus.c index b718c1d..a84e0a8 100644 --- a/sys/arm/arm/nexus.c +++ b/sys/arm/arm/nexus.c @@ -86,14 +86,14 @@ static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, static int nexus_activate_resource(device_t, device_t, int, int, struct resource *); static bus_space_tag_t nexus_get_bus_tag(device_t, device_t); -#ifdef ARM_INTRNG +#ifdef INTRNG #ifdef SMP static int nexus_bind_intr(device_t, device_t, struct resource *, int); #endif #endif static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, enum intr_polarity pol); -#ifdef ARM_INTRNG +#ifdef INTRNG static int nexus_describe_intr(device_t dev, device_t child, struct resource *irq, void *cookie, const char *descr); #endif @@ -126,7 +126,7 @@ static device_method_t nexus_methods[] = { DEVMETHOD(bus_setup_intr, nexus_setup_intr), DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), DEVMETHOD(bus_get_bus_tag, nexus_get_bus_tag), -#ifdef ARM_INTRNG +#ifdef INTRNG DEVMETHOD(bus_describe_intr, nexus_describe_intr), #ifdef SMP DEVMETHOD(bus_bind_intr, nexus_bind_intr), @@ -234,7 +234,7 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, } rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) + if (rv == NULL) return (NULL); rman_set_rid(rv, *rid); @@ -280,7 +280,7 @@ nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, { int ret = ENODEV; -#ifdef ARM_INTRNG +#ifdef INTRNG device_printf(dev, "bus_config_intr is obsolete and not supported!\n"); ret = EOPNOTSUPP; #else @@ -294,14 +294,14 @@ static int nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { -#ifndef ARM_INTRNG +#ifndef INTRNG int irq; #endif if ((rman_get_flags(res) & RF_SHAREABLE) == 0) flags |= INTR_EXCL; -#ifdef ARM_INTRNG +#ifdef INTRNG return(intr_setup_irq(child, res, filt, intr, arg, flags, cookiep)); #else for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) { @@ -317,14 +317,14 @@ static int nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) { -#ifdef ARM_INTRNG +#ifdef INTRNG return (intr_teardown_irq(child, r, ih)); #else return (arm_remove_irqhandler(rman_get_start(r), ih)); #endif } -#ifdef ARM_INTRNG +#ifdef INTRNG static int nexus_describe_intr(device_t dev, device_t child, struct resource *irq, void *cookie, const char *descr) diff --git a/sys/arm/arm/pmap-v4.c b/sys/arm/arm/pmap-v4.c index 529e9f1..2d9a941 100644 --- a/sys/arm/arm/pmap-v4.c +++ b/sys/arm/arm/pmap-v4.c @@ -265,7 +265,7 @@ void (*pmap_copy_page_offs_func)(vm_paddr_t a_phys, int cnt); void (*pmap_zero_page_func)(vm_paddr_t, int, int); -struct msgbuf *msgbufp = 0; +struct msgbuf *msgbufp = NULL; /* * Crashdump maps. @@ -842,7 +842,7 @@ pmap_alloc_l2_bucket(pmap_t pm, vm_offset_t va) ptep = uma_zalloc(l2zone, M_NOWAIT); rw_wlock(&pvh_global_lock); PMAP_LOCK(pm); - if (l2b->l2b_kva != 0) { + if (l2b->l2b_kva != NULL) { /* We lost the race. */ l2->l2_occupancy--; uma_zfree(l2zone, ptep); diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index 609b291..9fb0b20 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -310,15 +310,15 @@ static pt2_entry_t *CMAP3; static caddr_t CADDR3; caddr_t _tmppt = 0; -struct msgbuf *msgbufp = 0; /* XXX move it to machdep.c */ +struct msgbuf *msgbufp = NULL; /* XXX move it to machdep.c */ /* * Crashdump maps. */ static caddr_t crashdumpmap; -static pt2_entry_t *PMAP1 = 0, *PMAP2; -static pt2_entry_t *PADDR1 = 0, *PADDR2; +static pt2_entry_t *PMAP1 = NULL, *PMAP2; +static pt2_entry_t *PADDR1 = NULL, *PADDR2; #ifdef DDB static pt2_entry_t *PMAP3; static pt2_entry_t *PADDR3; diff --git a/sys/arm/at91/at91_common.c b/sys/arm/at91/at91_common.c index bc13196..37f94d7 100644 --- a/sys/arm/at91/at91_common.c +++ b/sys/arm/at91/at91_common.c @@ -53,7 +53,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG static int fdt_aic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) diff --git a/sys/arm/at91/at91_mci.c b/sys/arm/at91/at91_mci.c index ba6040f..cf884b9 100644 --- a/sys/arm/at91/at91_mci.c +++ b/sys/arm/at91/at91_mci.c @@ -526,16 +526,16 @@ at91_mci_deactivate(device_t dev) sc = device_get_softc(dev); if (sc->intrhand) bus_teardown_intr(dev, sc->irq_res, sc->intrhand); - sc->intrhand = 0; + sc->intrhand = NULL; bus_generic_detach(sc->dev); if (sc->mem_res) bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res), sc->mem_res); - sc->mem_res = 0; + sc->mem_res = NULL; if (sc->irq_res) bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res), sc->irq_res); - sc->irq_res = 0; + sc->irq_res = NULL; return; } diff --git a/sys/arm/at91/at91_pio.c b/sys/arm/at91/at91_pio.c index 0de46c5..0d9bd46 100644 --- a/sys/arm/at91/at91_pio.c +++ b/sys/arm/at91/at91_pio.c @@ -240,16 +240,16 @@ at91_pio_deactivate(device_t dev) sc = device_get_softc(dev); if (sc->intrhand) bus_teardown_intr(dev, sc->irq_res, sc->intrhand); - sc->intrhand = 0; + sc->intrhand = NULL; bus_generic_detach(sc->dev); if (sc->mem_res) bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res), sc->mem_res); - sc->mem_res = 0; + sc->mem_res = NULL; if (sc->irq_res) bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res), sc->irq_res); - sc->irq_res = 0; + sc->irq_res = NULL; } static void diff --git a/sys/arm/at91/at91_pmc.c b/sys/arm/at91/at91_pmc.c index 16f62ec..e93e3b7 100644 --- a/sys/arm/at91/at91_pmc.c +++ b/sys/arm/at91/at91_pmc.c @@ -636,7 +636,7 @@ at91_pmc_deactivate(device_t dev) if (sc->mem_res) bus_release_resource(dev, SYS_RES_IOPORT, rman_get_rid(sc->mem_res), sc->mem_res); - sc->mem_res = 0; + sc->mem_res = NULL; } static int diff --git a/sys/arm/at91/at91_rtc.c b/sys/arm/at91/at91_rtc.c index 6ed044a..7bb80b9 100644 --- a/sys/arm/at91/at91_rtc.c +++ b/sys/arm/at91/at91_rtc.c @@ -232,18 +232,18 @@ at91_rtc_deactivate(device_t dev) WR4(sc, RTC_IDR, 0xffffffff); if (sc->intrhand) bus_teardown_intr(dev, sc->irq_res, sc->intrhand); - sc->intrhand = 0; + sc->intrhand = NULL; #endif bus_generic_detach(sc->dev); if (sc->mem_res) bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res), sc->mem_res); - sc->mem_res = 0; + sc->mem_res = NULL; #ifdef AT91_RTC_USE_INTERRUPTS if (sc->irq_res) bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res), sc->irq_res); - sc->irq_res = 0; + sc->irq_res = NULL; #endif return; } diff --git a/sys/arm/at91/at91_ssc.c b/sys/arm/at91/at91_ssc.c index 8a32f55..d79020b 100644 --- a/sys/arm/at91/at91_ssc.c +++ b/sys/arm/at91/at91_ssc.c @@ -193,16 +193,16 @@ at91_ssc_deactivate(device_t dev) sc = device_get_softc(dev); if (sc->intrhand) bus_teardown_intr(dev, sc->irq_res, sc->intrhand); - sc->intrhand = 0; + sc->intrhand = NULL; bus_generic_detach(sc->dev); if (sc->mem_res) bus_release_resource(dev, SYS_RES_IOPORT, rman_get_rid(sc->mem_res), sc->mem_res); - sc->mem_res = 0; + sc->mem_res = NULL; if (sc->irq_res) bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res), sc->irq_res); - sc->irq_res = 0; + sc->irq_res = NULL; return; } diff --git a/sys/arm/at91/at91_twi.c b/sys/arm/at91/at91_twi.c index f9a7294..28676fc 100644 --- a/sys/arm/at91/at91_twi.c +++ b/sys/arm/at91/at91_twi.c @@ -216,16 +216,16 @@ at91_twi_deactivate(device_t dev) sc = device_get_softc(dev); if (sc->intrhand) bus_teardown_intr(dev, sc->irq_res, sc->intrhand); - sc->intrhand = 0; + sc->intrhand = NULL; bus_generic_detach(sc->dev); if (sc->mem_res) bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res), sc->mem_res); - sc->mem_res = 0; + sc->mem_res = NULL; if (sc->irq_res) bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res), sc->irq_res); - sc->irq_res = 0; + sc->irq_res = NULL; return; } diff --git a/sys/arm/at91/if_ate.c b/sys/arm/at91/if_ate.c index ac200b4..082b24f 100644 --- a/sys/arm/at91/if_ate.c +++ b/sys/arm/at91/if_ate.c @@ -1184,7 +1184,7 @@ atestart_locked(struct ifnet *ifp) } IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == 0) + if (m == NULL) break; e = bus_dmamap_load_mbuf_sg(sc->mtag, sc->tx_map[sc->txhead], m, diff --git a/sys/arm/broadcom/bcm2835/bcm2835_common.c b/sys/arm/broadcom/bcm2835/bcm2835_common.c index bcb84b7..e7ce52b 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_common.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_common.c @@ -50,7 +50,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG static int fdt_intc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) @@ -78,4 +78,4 @@ fdt_pic_decode_t fdt_pic_table[] = { &fdt_intc_decode_ic, NULL }; -#endif /* ARM_INTRNG */ +#endif /* INTRNG */ diff --git a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c index d448fc5..7c67a38 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c @@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$"); #include "gpio_if.h" -#ifdef ARM_INTRNG +#ifdef INTRNG #include "pic_if.h" #endif @@ -84,7 +84,7 @@ struct bcm_gpio_sysctl { uint32_t pin; }; -#ifdef ARM_INTRNG +#ifdef INTRNG struct bcm_gpio_irqsrc { struct intr_irqsrc bgi_isrc; uint32_t bgi_irq; @@ -105,11 +105,11 @@ struct bcm_gpio_softc { int sc_ro_npins; int sc_ro_pins[BCM_GPIO_PINS]; struct gpio_pin sc_gpio_pins[BCM_GPIO_PINS]; -#ifndef ARM_INTRNG +#ifndef INTRNG struct intr_event * sc_events[BCM_GPIO_PINS]; #endif struct bcm_gpio_sysctl sc_sysctl[BCM_GPIO_PINS]; -#ifdef ARM_INTRNG +#ifdef INTRNG struct bcm_gpio_irqsrc sc_isrcs[BCM_GPIO_PINS]; #else enum intr_trigger sc_irq_trigger[BCM_GPIO_PINS]; @@ -153,7 +153,7 @@ enum bcm_gpio_pud { static struct bcm_gpio_softc *bcm_gpio_sc = NULL; -#ifdef ARM_INTRNG +#ifdef INTRNG static int bcm_gpio_intr_bank0(void *arg); static int bcm_gpio_intr_bank1(void *arg); static int bcm_gpio_pic_attach(struct bcm_gpio_softc *sc); @@ -691,7 +691,7 @@ bcm_gpio_get_reserved_pins(struct bcm_gpio_softc *sc) return (0); } -#ifndef ARM_INTRNG +#ifndef INTRNG static int bcm_gpio_intr(void *arg) { @@ -741,7 +741,7 @@ bcm_gpio_probe(device_t dev) return (BUS_PROBE_DEFAULT); } -#ifdef ARM_INTRNG +#ifdef INTRNG static int bcm_gpio_intr_attach(device_t dev) { @@ -862,7 +862,7 @@ bcm_gpio_attach(device_t dev) sc->sc_gpio_pins[i].gp_pin = j; sc->sc_gpio_pins[i].gp_caps = BCM_GPIO_DEFAULT_CAPS; sc->sc_gpio_pins[i].gp_flags = bcm_gpio_func_flag(func); -#ifndef ARM_INTRNG +#ifndef INTRNG /* The default is active-low interrupts. */ sc->sc_irq_trigger[i] = INTR_TRIGGER_LEVEL; sc->sc_irq_polarity[i] = INTR_POLARITY_LOW; @@ -892,7 +892,7 @@ bcm_gpio_detach(device_t dev) return (EBUSY); } -#ifdef ARM_INTRNG +#ifdef INTRNG static inline void bcm_gpio_isrc_eoi(struct bcm_gpio_softc *sc, struct bcm_gpio_irqsrc *bgi) { @@ -1372,7 +1372,7 @@ static device_method_t bcm_gpio_methods[] = { DEVMETHOD(gpio_pin_set, bcm_gpio_pin_set), DEVMETHOD(gpio_pin_toggle, bcm_gpio_pin_toggle), -#ifdef ARM_INTRNG +#ifdef INTRNG /* Interrupt controller interface */ DEVMETHOD(pic_disable_intr, bcm_gpio_pic_disable_intr), DEVMETHOD(pic_enable_intr, bcm_gpio_pic_enable_intr), diff --git a/sys/arm/broadcom/bcm2835/bcm2835_intr.c b/sys/arm/broadcom/bcm2835/bcm2835_intr.c index 936dc52..8124c96 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_intr.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_intr.c @@ -52,7 +52,7 @@ __FBSDID("$FreeBSD$"); #include <arm/broadcom/bcm2835/bcm2836.h> #endif -#ifdef ARM_INTRNG +#ifdef INTRNG #include "pic_if.h" #endif @@ -105,7 +105,7 @@ __FBSDID("$FreeBSD$"); #define BANK1_END (BANK1_START + 32 - 1) #define BANK2_START (BANK1_START + 32) #define BANK2_END (BANK2_START + 32 - 1) -#ifndef ARM_INTRNG +#ifndef INTRNG #define BANK3_START (BANK2_START + 32) #define BANK3_END (BANK3_START + 32 - 1) #endif @@ -113,7 +113,7 @@ __FBSDID("$FreeBSD$"); #define IS_IRQ_BASIC(n) (((n) >= 0) && ((n) < BANK1_START)) #define IS_IRQ_BANK1(n) (((n) >= BANK1_START) && ((n) <= BANK1_END)) #define IS_IRQ_BANK2(n) (((n) >= BANK2_START) && ((n) <= BANK2_END)) -#ifndef ARM_INTRNG +#ifndef INTRNG #define ID_IRQ_BCM2836(n) (((n) >= BANK3_START) && ((n) <= BANK3_END)) #endif #define IRQ_BANK1(n) ((n) - BANK1_START) @@ -125,7 +125,7 @@ __FBSDID("$FreeBSD$"); #define dprintf(fmt, args...) #endif -#ifdef ARM_INTRNG +#ifdef INTRNG #define BCM_INTC_NIRQS 72 /* 8 + 32 + 32 */ struct bcm_intc_irqsrc { @@ -142,7 +142,7 @@ struct bcm_intc_softc { struct resource * intc_res; bus_space_tag_t intc_bst; bus_space_handle_t intc_bsh; -#ifdef ARM_INTRNG +#ifdef INTRNG struct resource * intc_irq_res; void * intc_irq_hdl; struct bcm_intc_irqsrc intc_isrcs[BCM_INTC_NIRQS]; @@ -156,7 +156,7 @@ static struct bcm_intc_softc *bcm_intc_sc = NULL; #define intc_write_4(_sc, reg, val) \ bus_space_write_4((_sc)->intc_bst, (_sc)->intc_bsh, (reg), (val)) -#ifdef ARM_INTRNG +#ifdef INTRNG static inline void bcm_intc_isrc_mask(struct bcm_intc_softc *sc, struct bcm_intc_irqsrc *bii) { @@ -360,7 +360,7 @@ bcm_intc_attach(device_t dev) { struct bcm_intc_softc *sc = device_get_softc(dev); int rid = 0; -#ifdef ARM_INTRNG +#ifdef INTRNG intptr_t xref; #endif sc->sc_dev = dev; @@ -374,7 +374,7 @@ bcm_intc_attach(device_t dev) return (ENXIO); } -#ifdef ARM_INTRNG +#ifdef INTRNG xref = OF_xref_from_node(ofw_bus_get_node(dev)); if (bcm_intc_pic_register(sc, xref) != 0) { bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->intc_res); @@ -412,7 +412,7 @@ static device_method_t bcm_intc_methods[] = { DEVMETHOD(device_probe, bcm_intc_probe), DEVMETHOD(device_attach, bcm_intc_attach), -#ifdef ARM_INTRNG +#ifdef INTRNG DEVMETHOD(pic_disable_intr, bcm_intc_disable_intr), DEVMETHOD(pic_enable_intr, bcm_intc_enable_intr), DEVMETHOD(pic_map_intr, bcm_intc_map_intr), @@ -434,7 +434,7 @@ static devclass_t bcm_intc_devclass; DRIVER_MODULE(intc, simplebus, bcm_intc_driver, bcm_intc_devclass, 0, 0); -#ifndef ARM_INTRNG +#ifndef INTRNG int arm_get_next_irq(int last_irq) { diff --git a/sys/arm/broadcom/bcm2835/bcm2836.c b/sys/arm/broadcom/bcm2835/bcm2836.c index f9a2fcc..16c1e4b 100644 --- a/sys/arm/broadcom/bcm2835/bcm2836.c +++ b/sys/arm/broadcom/bcm2835/bcm2836.c @@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus_subr.h> #include <dev/ofw/ofw_bus.h> -#ifdef ARM_INTRNG +#ifdef INTRNG #include "pic_if.h" #else #include <arm/broadcom/bcm2835/bcm2836.h> @@ -72,7 +72,7 @@ __FBSDID("$FreeBSD$"); #define MAILBOX0_IRQEN (1 << 0) #endif -#ifdef ARM_INTRNG +#ifdef INTRNG #define BCM_LINTC_CONTROL_REG 0x00 #define BCM_LINTC_PRESCALER_REG 0x08 #define BCM_LINTC_GPU_ROUTING_REG 0x0c diff --git a/sys/arm/broadcom/bcm2835/bcm2836.h b/sys/arm/broadcom/bcm2835/bcm2836.h index 14abfe2..6068975 100644 --- a/sys/arm/broadcom/bcm2835/bcm2836.h +++ b/sys/arm/broadcom/bcm2835/bcm2836.h @@ -30,7 +30,7 @@ #ifndef _BCM2815_BCM2836_H #define _BCM2815_BCM2836_H -#ifndef ARM_INTRNG +#ifndef INTRNG #define BCM2836_GPU_IRQ 8 int bcm2836_get_next_irq(int); diff --git a/sys/arm/broadcom/bcm2835/bcm2836_mp.c b/sys/arm/broadcom/bcm2835/bcm2836_mp.c index a361319..bbbc514 100644 --- a/sys/arm/broadcom/bcm2835/bcm2836_mp.c +++ b/sys/arm/broadcom/bcm2835/bcm2836_mp.c @@ -139,7 +139,7 @@ platform_mp_start_ap(void) } } -#ifndef ARM_INTRNG +#ifndef INTRNG void pic_ipi_send(cpuset_t cpus, u_int ipi) { diff --git a/sys/arm/cavium/cns11xx/if_ece.c b/sys/arm/cavium/cns11xx/if_ece.c index 20bc07e..2ae3d22 100644 --- a/sys/arm/cavium/cns11xx/if_ece.c +++ b/sys/arm/cavium/cns11xx/if_ece.c @@ -1064,8 +1064,8 @@ clear_mac_entries(struct ece_softc *ec, int include_this_mac) struct mac_list * current; char mac[ETHER_ADDR_LEN]; - current = 0; - mac_list_header = 0; + current = NULL; + mac_list_header = NULL; table_end = read_mac_entry(ec, mac, 1); while (!table_end) { @@ -1608,7 +1608,7 @@ ece_encap(struct ece_softc *sc, struct mbuf *m0) struct ifnet *ifp; bus_dma_segment_t segs[MAX_FRAGMENT]; bus_dmamap_t mapp; - eth_tx_desc_t *desc = 0; + eth_tx_desc_t *desc = NULL; int csum_flags; int desc_no; int error; diff --git a/sys/arm/conf/A20 b/sys/arm/conf/A20 index 8f56523..f28080c 100644 --- a/sys/arm/conf/A20 +++ b/sys/arm/conf/A20 @@ -23,7 +23,7 @@ ident A20 include "std.armv6" include "../allwinner/a20/std.a20" -options ARM_INTRNG +options INTRNG options SOC_ALLWINNER_A20 diff --git a/sys/arm/conf/ALPINE b/sys/arm/conf/ALPINE index fa30865..55e4468d3 100644 --- a/sys/arm/conf/ALPINE +++ b/sys/arm/conf/ALPINE @@ -37,7 +37,7 @@ options DDB #Enable the kernel debugger # Interrupt controller device gic -options ARM_INTRNG +options INTRNG # Pseudo devices device loop diff --git a/sys/arm/conf/ARMADA38X b/sys/arm/conf/ARMADA38X index 13c3aa2..1903e62 100644 --- a/sys/arm/conf/ARMADA38X +++ b/sys/arm/conf/ARMADA38X @@ -62,7 +62,7 @@ device pci # Interrupt controllers device gic -options ARM_INTRNG +options INTRNG # Timers device mpcore_timer diff --git a/sys/arm/conf/BEAGLEBONE b/sys/arm/conf/BEAGLEBONE index 1885c0c..4497b0ff 100644 --- a/sys/arm/conf/BEAGLEBONE +++ b/sys/arm/conf/BEAGLEBONE @@ -28,7 +28,7 @@ include "../ti/am335x/std.am335x" makeoptions MODULES_EXTRA="dtb/am335x am335x_dmtpps" -options ARM_INTRNG +options INTRNG options HZ=100 options SCHED_4BSD # 4BSD scheduler diff --git a/sys/arm/conf/EXYNOS5.common b/sys/arm/conf/EXYNOS5.common index 770a690..c997916 100644 --- a/sys/arm/conf/EXYNOS5.common +++ b/sys/arm/conf/EXYNOS5.common @@ -87,7 +87,7 @@ device dwmmc # Interrupt controller device gic -options ARM_INTRNG +options INTRNG # ARM Generic Timer device generic_timer diff --git a/sys/arm/conf/IMX6 b/sys/arm/conf/IMX6 index 6b383e2..bc1145f 100644 --- a/sys/arm/conf/IMX6 +++ b/sys/arm/conf/IMX6 @@ -22,7 +22,7 @@ ident IMX6 include "std.armv6" include "../freescale/imx/std.imx6" -options ARM_INTRNG +options INTRNG options SOC_IMX6 diff --git a/sys/arm/conf/ODROIDC1 b/sys/arm/conf/ODROIDC1 index 550da87..16802d3 100644 --- a/sys/arm/conf/ODROIDC1 +++ b/sys/arm/conf/ODROIDC1 @@ -26,7 +26,7 @@ options SMP # Enable multiple cores # Interrupt controller device gic -options ARM_INTRNG +options INTRNG options FDT_DTB_STATIC makeoptions FDT_DTS_FILE=odroidc1.dts diff --git a/sys/arm/conf/PANDABOARD b/sys/arm/conf/PANDABOARD index 4eaa471..69a8252 100644 --- a/sys/arm/conf/PANDABOARD +++ b/sys/arm/conf/PANDABOARD @@ -60,7 +60,7 @@ options DDB # Enable the kernel debugger device fdt_pinctrl # Interrupt controller device gic -options ARM_INTRNG +options INTRNG # ARM MPCore timer device mpcore_timer diff --git a/sys/arm/conf/RK3188 b/sys/arm/conf/RK3188 index ec6ddb8..e3e5ac8 100644 --- a/sys/arm/conf/RK3188 +++ b/sys/arm/conf/RK3188 @@ -47,7 +47,7 @@ options ROOTDEVNAME=\"ufs:/dev/mmcsd0\" # Interrupt controller device gic -options ARM_INTRNG +options INTRNG # ARM MPCore timer device mpcore_timer diff --git a/sys/arm/conf/RPI-B b/sys/arm/conf/RPI-B index 9bc2636..5f6bc27 100644 --- a/sys/arm/conf/RPI-B +++ b/sys/arm/conf/RPI-B @@ -24,7 +24,7 @@ include "std.armv6" include "../broadcom/bcm2835/std.rpi" include "../broadcom/bcm2835/std.bcm2835" -options ARM_INTRNG +options INTRNG options HZ=100 options SCHED_4BSD # 4BSD scheduler diff --git a/sys/arm/conf/RPI2 b/sys/arm/conf/RPI2 index 3cee50d..e669580 100644 --- a/sys/arm/conf/RPI2 +++ b/sys/arm/conf/RPI2 @@ -24,7 +24,7 @@ include "std.armv6" include "../broadcom/bcm2835/std.rpi" include "../broadcom/bcm2835/std.bcm2836" -options ARM_INTRNG +options INTRNG options HZ=100 options SCHED_ULE # ULE scheduler diff --git a/sys/arm/conf/SOCKIT.common b/sys/arm/conf/SOCKIT.common index 3365929..3db9457 100644 --- a/sys/arm/conf/SOCKIT.common +++ b/sys/arm/conf/SOCKIT.common @@ -53,7 +53,7 @@ options INVARIANT_SUPPORT # Extra sanity checks of internal structures, require # Interrupt controller device gic -options ARM_INTRNG +options INTRNG # ARM MPCore timer device mpcore_timer diff --git a/sys/arm/conf/VIRT b/sys/arm/conf/VIRT index aabe636..374af87 100644 --- a/sys/arm/conf/VIRT +++ b/sys/arm/conf/VIRT @@ -47,7 +47,7 @@ options INVARIANT_SUPPORT # Extra sanity checks of internal structures, require # Interrupt controller device gic -options ARM_INTRNG +options INTRNG # ARM Generic Timer device generic_timer diff --git a/sys/arm/conf/VSATV102 b/sys/arm/conf/VSATV102 index 96e3ba4..c08060a 100644 --- a/sys/arm/conf/VSATV102 +++ b/sys/arm/conf/VSATV102 @@ -26,7 +26,7 @@ options SMP # Enable multiple cores # Interrupt controller device gic -options ARM_INTRNG +options INTRNG options FDT_DTB_STATIC makeoptions FDT_DTS_FILE=vsatv102-m6.dts diff --git a/sys/arm/conf/VYBRID b/sys/arm/conf/VYBRID index 471b8d5..3e15e42 100644 --- a/sys/arm/conf/VYBRID +++ b/sys/arm/conf/VYBRID @@ -62,7 +62,7 @@ options NO_SWAPPING # Interrupt controller device gic -options ARM_INTRNG +options INTRNG # ARM MPCore timer device mpcore_timer diff --git a/sys/arm/conf/ZEDBOARD b/sys/arm/conf/ZEDBOARD index 41ec23a..1c024cc 100644 --- a/sys/arm/conf/ZEDBOARD +++ b/sys/arm/conf/ZEDBOARD @@ -52,7 +52,7 @@ options ROOTDEVNAME=\"ufs:mmcsd0s2a\" # Interrupt controller device gic -options ARM_INTRNG +options INTRNG # Cache controller device pl310 # PL310 L2 cache controller diff --git a/sys/arm/freescale/imx/imx6_machdep.c b/sys/arm/freescale/imx/imx6_machdep.c index 061355d..d5417c2 100644 --- a/sys/arm/freescale/imx/imx6_machdep.c +++ b/sys/arm/freescale/imx/imx6_machdep.c @@ -58,7 +58,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { static uint32_t gpio1_node; -#ifndef ARM_INTRNG +#ifndef INTRNG /* * Work around the linux workaround for imx6 erratum 006687, in which some * ethernet interrupts don't go to the GPC and thus won't wake the system from diff --git a/sys/arm/freescale/imx/imx_common.c b/sys/arm/freescale/imx/imx_common.c index 50922e6..c423873 100644 --- a/sys/arm/freescale/imx/imx_common.c +++ b/sys/arm/freescale/imx/imx_common.c @@ -54,7 +54,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG static int fdt_intc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) @@ -71,4 +71,4 @@ fdt_pic_decode_t fdt_pic_table[] = { &fdt_intc_decode_ic, NULL }; -#endif /* ARM_INTRNG */ +#endif /* INTRNG */ diff --git a/sys/arm/freescale/imx/imx_gpio.c b/sys/arm/freescale/imx/imx_gpio.c index df0f2ad..ba82f5c 100644 --- a/sys/arm/freescale/imx/imx_gpio.c +++ b/sys/arm/freescale/imx/imx_gpio.c @@ -60,7 +60,7 @@ __FBSDID("$FreeBSD$"); #include "gpio_if.h" -#ifdef ARM_INTRNG +#ifdef INTRNG #include "pic_if.h" #endif @@ -91,7 +91,7 @@ __FBSDID("$FreeBSD$"); #define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT) #define NGPIO 32 -#ifdef ARM_INTRNG +#ifdef INTRNG struct gpio_irqsrc { struct intr_irqsrc gi_isrc; u_int gi_irq; @@ -110,7 +110,7 @@ struct imx51_gpio_softc { bus_space_handle_t sc_ioh; int gpio_npins; struct gpio_pin gpio_pins[NGPIO]; -#ifdef ARM_INTRNG +#ifdef INTRNG struct gpio_irqsrc gpio_pic_irqsrc[NGPIO]; #endif }; @@ -155,7 +155,7 @@ static int imx51_gpio_pin_set(device_t, uint32_t, unsigned int); static int imx51_gpio_pin_get(device_t, uint32_t, unsigned int *); static int imx51_gpio_pin_toggle(device_t, uint32_t pin); -#ifdef ARM_INTRNG +#ifdef INTRNG static int gpio_pic_map_fdt(device_t dev, u_int ncells, pcell_t *cells, u_int *irqp, enum intr_polarity *polp, enum intr_trigger *trigp) @@ -653,7 +653,7 @@ imx51_gpio_attach(device_t dev) */ WRITE4(sc, IMX_GPIO_IMR_REG, 0); for (irq = 0; irq < 2; irq++) { -#ifdef ARM_INTRNG +#ifdef INTRNG if ((bus_setup_intr(dev, sc->sc_res[1 + irq], INTR_TYPE_CLK, gpio_pic_filter, NULL, sc, &sc->gpio_ih[irq]))) { device_printf(dev, @@ -675,7 +675,7 @@ imx51_gpio_attach(device_t dev) "imx_gpio%d.%d", unit, i); } -#ifdef ARM_INTRNG +#ifdef INTRNG gpio_pic_register_isrcs(sc); intr_pic_register(dev, OF_xref_from_node(ofw_bus_get_node(dev))); #endif @@ -713,7 +713,7 @@ static device_method_t imx51_gpio_methods[] = { DEVMETHOD(device_attach, imx51_gpio_attach), DEVMETHOD(device_detach, imx51_gpio_detach), -#ifdef ARM_INTRNG +#ifdef INTRNG /* Interrupt controller interface */ DEVMETHOD(pic_disable_intr, gpio_pic_disable_intr), DEVMETHOD(pic_enable_intr, gpio_pic_enable_intr), diff --git a/sys/arm/freescale/vybrid/vf_common.c b/sys/arm/freescale/vybrid/vf_common.c index 913902a..494f5d6 100644 --- a/sys/arm/freescale/vybrid/vf_common.c +++ b/sys/arm/freescale/vybrid/vf_common.c @@ -66,7 +66,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG static int fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) diff --git a/sys/arm/include/intr.h b/sys/arm/include/intr.h index e81bc7d..7a91525 100644 --- a/sys/arm/include/intr.h +++ b/sys/arm/include/intr.h @@ -43,7 +43,7 @@ #include <dev/ofw/openfirm.h> #endif -#ifdef ARM_INTRNG +#ifdef INTRNG #ifndef NIRQ #define NIRQ 1024 /* XXX - It should be an option. */ @@ -63,7 +63,7 @@ void intr_ipi_setup(u_int, const char *, intr_ipi_handler_t *, void *, int intr_pic_ipi_setup(u_int, const char *, intr_ipi_handler_t *, void *); #endif -#else /* ARM_INTRNG */ +#else /* INTRNG */ /* XXX move to std.* files? */ #ifdef CPU_XSCALE_81342 @@ -111,7 +111,7 @@ int gic_decode_fdt(phandle_t, pcell_t *, int *, int *, int *); int intr_fdt_map_irq(phandle_t, pcell_t *, int); #endif -#endif /* ARM_INTRNG */ +#endif /* INTRNG */ void arm_irq_memory_barrier(uintptr_t); diff --git a/sys/arm/include/smp.h b/sys/arm/include/smp.h index e685cc3..704fffa 100644 --- a/sys/arm/include/smp.h +++ b/sys/arm/include/smp.h @@ -6,7 +6,7 @@ #include <sys/_cpuset.h> #include <machine/pcb.h> -#ifdef ARM_INTRNG +#ifdef INTRNG enum { IPI_AST, IPI_PREEMPT, @@ -37,7 +37,7 @@ void ipi_cpu(int cpu, u_int ipi); void ipi_selected(cpuset_t cpus, u_int ipi); /* PIC interface */ -#ifndef ARM_INTRNG +#ifndef INTRNG void pic_ipi_send(cpuset_t cpus, u_int ipi); void pic_ipi_clear(int ipi); int pic_ipi_read(int arg); diff --git a/sys/arm/lpc/lpc_intc.c b/sys/arm/lpc/lpc_intc.c index d4b2517..db7c300 100644 --- a/sys/arm/lpc/lpc_intc.c +++ b/sys/arm/lpc/lpc_intc.c @@ -231,7 +231,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG static int fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) diff --git a/sys/arm/mv/mpic.c b/sys/arm/mv/mpic.c index 4f246a4..4c5856a 100644 --- a/sys/arm/mv/mpic.c +++ b/sys/arm/mv/mpic.c @@ -60,7 +60,7 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus_subr.h> #include <dev/fdt/fdt_common.h> -#ifdef ARM_INTRNG +#ifdef INTRNG #include "pic_if.h" #endif @@ -98,7 +98,7 @@ __FBSDID("$FreeBSD$"); #define MPIC_PPI 32 -#ifdef ARM_INTRNG +#ifdef INTRNG struct mv_mpic_irqsrc { struct intr_irqsrc mmi_isrc; u_int mmi_irq; @@ -115,7 +115,7 @@ struct mv_mpic_softc { bus_space_tag_t drbl_bst; bus_space_handle_t drbl_bsh; struct mtx mtx; -#ifdef ARM_INTRNG +#ifdef INTRNG struct mv_mpic_irqsrc * mpic_isrcs; #endif int nirqs; @@ -151,7 +151,7 @@ static void mpic_mask_irq_err(uintptr_t nb); static void mpic_unmask_irq_err(uintptr_t nb); static int mpic_intr(void *arg); static void mpic_unmask_msi(void); -#ifndef ARM_INTRNG +#ifndef INTRNG static void arm_mask_irq_err(uintptr_t); static void arm_unmask_irq_err(uintptr_t); #endif @@ -185,7 +185,7 @@ mv_mpic_probe(device_t dev) return (0); } -#ifdef ARM_INTRNG +#ifdef INTRNG static int mv_mpic_register_isrcs(struct mv_mpic_softc *sc) { @@ -241,7 +241,7 @@ mv_mpic_attach(device_t dev) device_printf(dev, "could not allocate resources\n"); return (ENXIO); } -#ifdef ARM_INTRNG +#ifdef INTRNG if (sc->mpic_res[3] == NULL) device_printf(dev, "No interrupt to use.\n"); else @@ -268,7 +268,7 @@ mv_mpic_attach(device_t dev) val = MPIC_READ(mv_mpic_sc, MPIC_CTRL); sc->nirqs = MPIC_CTRL_NIRQS(val); -#ifdef ARM_INTRNG +#ifdef INTRNG if (mv_mpic_register_isrcs(sc) != 0) { device_printf(dev, "could not register PIC ISRCs\n"); bus_release_resources(dev, mv_mpic_spec, sc->mpic_res); @@ -286,7 +286,7 @@ mv_mpic_attach(device_t dev) return (0); } -#ifdef ARM_INTRNG +#ifdef INTRNG static int mpic_intr(void *arg) { @@ -370,7 +370,7 @@ static device_method_t mv_mpic_methods[] = { DEVMETHOD(device_probe, mv_mpic_probe), DEVMETHOD(device_attach, mv_mpic_attach), -#ifdef ARM_INTRNG +#ifdef INTRNG DEVMETHOD(pic_disable_intr, mpic_disable_intr), DEVMETHOD(pic_enable_intr, mpic_enable_intr), DEVMETHOD(pic_map_intr, mpic_map_intr), @@ -391,7 +391,7 @@ static devclass_t mv_mpic_devclass; EARLY_DRIVER_MODULE(mpic, simplebus, mv_mpic_driver, mv_mpic_devclass, 0, 0, BUS_PASS_INTERRUPT); -#ifndef ARM_INTRNG +#ifndef INTRNG int arm_get_next_irq(int last) { diff --git a/sys/arm/mv/mv_common.c b/sys/arm/mv/mv_common.c index a1d2a2d..5a19993 100644 --- a/sys/arm/mv/mv_common.c +++ b/sys/arm/mv/mv_common.c @@ -2282,7 +2282,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG static int fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) diff --git a/sys/arm/nvidia/tegra124/std.tegra124 b/sys/arm/nvidia/tegra124/std.tegra124 index 127b001..35de225 100644 --- a/sys/arm/nvidia/tegra124/std.tegra124 +++ b/sys/arm/nvidia/tegra124/std.tegra124 @@ -6,7 +6,7 @@ makeoptions CONF_CFLAGS="-march=armv7a" options KERNVIRTADDR = 0xc0200000 makeoptions KERNVIRTADDR = 0xc0200000 -options ARM_INTRNG +options INTRNG options IPI_IRQ_START=0 options IPI_IRQ_END=15 diff --git a/sys/arm/qemu/virt_common.c b/sys/arm/qemu/virt_common.c index 572fee8..03cba30 100644 --- a/sys/arm/qemu/virt_common.c +++ b/sys/arm/qemu/virt_common.c @@ -41,7 +41,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG fdt_pic_decode_t fdt_pic_table[] = { &gic_decode_fdt, NULL diff --git a/sys/arm/rockchip/rk30xx_common.c b/sys/arm/rockchip/rk30xx_common.c index 723c429..aa66b72 100644 --- a/sys/arm/rockchip/rk30xx_common.c +++ b/sys/arm/rockchip/rk30xx_common.c @@ -42,7 +42,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG static int fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) diff --git a/sys/arm/samsung/exynos/exynos5_common.c b/sys/arm/samsung/exynos/exynos5_common.c index 8818f04..b91e083 100644 --- a/sys/arm/samsung/exynos/exynos5_common.c +++ b/sys/arm/samsung/exynos/exynos5_common.c @@ -53,7 +53,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG static int fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) diff --git a/sys/arm/ti/aintc.c b/sys/arm/ti/aintc.c index 8a544d0..ebe4864 100644 --- a/sys/arm/ti/aintc.c +++ b/sys/arm/ti/aintc.c @@ -48,7 +48,7 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> -#ifdef ARM_INTRNG +#ifdef INTRNG #include "pic_if.h" #endif @@ -68,7 +68,7 @@ __FBSDID("$FreeBSD$"); #define INTC_NIRQS 128 -#ifdef ARM_INTRNG +#ifdef INTRNG struct ti_aintc_irqsrc { struct intr_irqsrc tai_isrc; u_int tai_irq; @@ -81,7 +81,7 @@ struct ti_aintc_softc { bus_space_tag_t aintc_bst; bus_space_handle_t aintc_bsh; uint8_t ver; -#ifdef ARM_INTRNG +#ifdef INTRNG struct ti_aintc_irqsrc aintc_isrcs[INTC_NIRQS]; #endif }; @@ -105,7 +105,7 @@ static struct ofw_compat_data compat_data[] = { {NULL, 0}, }; -#ifdef ARM_INTRNG +#ifdef INTRNG static inline void ti_aintc_irq_eoi(struct ti_aintc_softc *sc) { @@ -295,7 +295,7 @@ ti_aintc_attach(device_t dev) /*Set Priority Threshold */ aintc_write_4(sc, INTC_THRESHOLD, 0xFF); -#ifndef ARM_INTRNG +#ifndef INTRNG arm_post_filter = aintc_post_filter; #else if (ti_aintc_pic_attach(sc) != 0) { @@ -310,7 +310,7 @@ static device_method_t ti_aintc_methods[] = { DEVMETHOD(device_probe, ti_aintc_probe), DEVMETHOD(device_attach, ti_aintc_attach), -#ifdef ARM_INTRNG +#ifdef INTRNG DEVMETHOD(pic_disable_intr, ti_aintc_disable_intr), DEVMETHOD(pic_enable_intr, ti_aintc_enable_intr), DEVMETHOD(pic_map_intr, ti_aintc_map_intr), @@ -334,7 +334,7 @@ EARLY_DRIVER_MODULE(aintc, simplebus, ti_aintc_driver, ti_aintc_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); SIMPLEBUS_PNP_INFO(compat_data); -#ifndef ARM_INTRNG +#ifndef INTRNG int arm_get_next_irq(int last_irq) { diff --git a/sys/arm/ti/omap4/omap4_prcm_clks.c b/sys/arm/ti/omap4/omap4_prcm_clks.c index fc5fb97..e83e6ee 100644 --- a/sys/arm/ti/omap4/omap4_prcm_clks.c +++ b/sys/arm/ti/omap4/omap4_prcm_clks.c @@ -366,9 +366,9 @@ static struct omap4_clk_details g_omap4_clk_details[] = { OMAP4_GENERIC_CLOCK_DETAILS(UART2_CLK, FREQ_48MHZ, CM2_INSTANCE, (L4PER_CM2_OFFSET + 0x0148), CLKCTRL_MODULEMODE_ENABLE), OMAP4_GENERIC_CLOCK_DETAILS(UART3_CLK, FREQ_48MHZ, CM2_INSTANCE, - (L4PER_CM2_OFFSET + 0x0140), CLKCTRL_MODULEMODE_ENABLE), + (L4PER_CM2_OFFSET + 0x0150), CLKCTRL_MODULEMODE_ENABLE), OMAP4_GENERIC_CLOCK_DETAILS(UART4_CLK, FREQ_48MHZ, CM2_INSTANCE, - (L4PER_CM2_OFFSET + 0x0148), CLKCTRL_MODULEMODE_ENABLE), + (L4PER_CM2_OFFSET + 0x0158), CLKCTRL_MODULEMODE_ENABLE), /* General purpose timers */ OMAP4_GENERIC_CLOCK_DETAILS(TIMER1_CLK, -1, PRM_INSTANCE, diff --git a/sys/arm/ti/ti_common.c b/sys/arm/ti/ti_common.c index aaf9a6a..41c5a72 100644 --- a/sys/arm/ti/ti_common.c +++ b/sys/arm/ti/ti_common.c @@ -53,7 +53,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG #ifdef SOC_TI_AM335X static int fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, @@ -81,4 +81,4 @@ fdt_pic_decode_t fdt_pic_table[] = { #endif NULL }; -#endif /* !ARM_INTRNG */ +#endif /* !INTRNG */ diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c index 633fbf0..54e5042 100644 --- a/sys/arm/ti/ti_gpio.c +++ b/sys/arm/ti/ti_gpio.c @@ -66,7 +66,7 @@ __FBSDID("$FreeBSD$"); #include "gpio_if.h" #include "ti_gpio_if.h" -#ifdef ARM_INTRNG +#ifdef INTRNG #include "pic_if.h" #endif @@ -121,7 +121,7 @@ __FBSDID("$FreeBSD$"); static int ti_gpio_intr(void *arg); static int ti_gpio_detach(device_t); -#ifdef ARM_INTRNG +#ifdef INTRNG static int ti_gpio_pic_attach(struct ti_gpio_softc *sc); static int ti_gpio_pic_detach(struct ti_gpio_softc *sc); #endif @@ -546,7 +546,7 @@ ti_gpio_pin_toggle(device_t dev, uint32_t pin) return (0); } -#ifndef ARM_INTRNG +#ifndef INTRNG /** * ti_gpio_intr - ISR for all GPIO modules * @arg: the soft context pointer @@ -655,7 +655,7 @@ static int ti_gpio_attach(device_t dev) { struct ti_gpio_softc *sc; -#ifndef ARM_INTRNG +#ifndef INTRNG unsigned int i; #endif int err; @@ -696,7 +696,7 @@ ti_gpio_attach(device_t dev) return (ENXIO); } -#ifdef ARM_INTRNG +#ifdef INTRNG if (ti_gpio_pic_attach(sc) != 0) { device_printf(dev, "WARNING: unable to attach PIC\n"); ti_gpio_detach(dev); @@ -771,7 +771,7 @@ ti_gpio_detach(device_t dev) if (sc->sc_mem_res != NULL) ti_gpio_intr_clr(sc, 0xffffffff); gpiobus_detach_bus(dev); -#ifdef ARM_INTRNG +#ifdef INTRNG if (sc->sc_isrcs != NULL) ti_gpio_pic_detach(sc); #else @@ -798,7 +798,7 @@ ti_gpio_detach(device_t dev) return (0); } -#ifdef ARM_INTRNG +#ifdef INTRNG static inline void ti_gpio_rwreg_set(struct ti_gpio_softc *sc, uint32_t reg, uint32_t mask) { @@ -1300,7 +1300,7 @@ static device_method_t ti_gpio_methods[] = { DEVMETHOD(gpio_pin_set, ti_gpio_pin_set), DEVMETHOD(gpio_pin_toggle, ti_gpio_pin_toggle), -#ifdef ARM_INTRNG +#ifdef INTRNG /* Interrupt controller interface */ DEVMETHOD(pic_disable_intr, ti_gpio_pic_disable_intr), DEVMETHOD(pic_enable_intr, ti_gpio_pic_enable_intr), diff --git a/sys/arm/ti/ti_gpio.h b/sys/arm/ti/ti_gpio.h index f16728b..174dd62 100644 --- a/sys/arm/ti/ti_gpio.h +++ b/sys/arm/ti/ti_gpio.h @@ -39,7 +39,7 @@ */ #define MAX_GPIO_INTRS 8 -#ifndef ARM_INTRNG +#ifndef INTRNG struct ti_gpio_mask_arg { void *softc; int pin; @@ -61,7 +61,7 @@ struct ti_gpio_irqsrc { struct ti_gpio_softc { device_t sc_dev; device_t sc_busdev; -#ifndef ARM_INTRNG +#ifndef INTRNG /* Interrupt trigger type and level. */ enum intr_trigger *sc_irq_trigger; enum intr_polarity *sc_irq_polarity; @@ -74,7 +74,7 @@ struct ti_gpio_softc { struct resource *sc_mem_res; int sc_irq_rid; struct resource *sc_irq_res; -#ifndef ARM_INTRNG +#ifndef INTRNG /* Interrupt events. */ struct intr_event **sc_events; struct ti_gpio_mask_arg *sc_mask_args; diff --git a/sys/arm/versatile/versatile_common.c b/sys/arm/versatile/versatile_common.c index c47c298..aca54b7 100644 --- a/sys/arm/versatile/versatile_common.c +++ b/sys/arm/versatile/versatile_common.c @@ -50,7 +50,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG static int fdt_intc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) diff --git a/sys/arm/xilinx/zy7_machdep.c b/sys/arm/xilinx/zy7_machdep.c index 4b43683..dd179b7 100644 --- a/sys/arm/xilinx/zy7_machdep.c +++ b/sys/arm/xilinx/zy7_machdep.c @@ -98,7 +98,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; -#ifndef ARM_INTRNG +#ifndef INTRNG static int fdt_gic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) diff --git a/sys/arm/xscale/ixp425/ixp425_qmgr.c b/sys/arm/xscale/ixp425/ixp425_qmgr.c index cb6c8de..822623c 100644 --- a/sys/arm/xscale/ixp425/ixp425_qmgr.c +++ b/sys/arm/xscale/ixp425/ixp425_qmgr.c @@ -355,7 +355,7 @@ ixpqmgr_qconfig(int qId, int qEntries, int ne, int nf, int srcSel, if (cb == NULL) { /* Reset to dummy callback */ qi->cb = dummyCallback; - qi->cbarg = 0; + qi->cbarg = NULL; } else { qi->cb = cb; qi->cbarg = cbarg; diff --git a/sys/arm64/arm64/gic_fdt.c b/sys/arm64/arm64/gic_fdt.c index 34d8009..f92cd83 100644 --- a/sys/arm64/arm64/gic_fdt.c +++ b/sys/arm64/arm64/gic_fdt.c @@ -198,7 +198,7 @@ arm_gic_fdt_attach(device_t dev) static struct resource * arm_gic_fdt_alloc_resource(device_t bus, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct arm_gic_fdt_softc *sc = device_get_softc(bus); struct gic_devinfo *di; diff --git a/sys/arm64/arm64/gic_v3_its.c b/sys/arm64/arm64/gic_v3_its.c index aef6346..c830c99 100644 --- a/sys/arm64/arm64/gic_v3_its.c +++ b/sys/arm64/arm64/gic_v3_its.c @@ -565,7 +565,7 @@ its_init_cpu(struct gic_v3_its_softc *sc) * this function was called during GICv3 secondary initialization. */ if (sc == NULL) { - if (device_is_attached(its_sc->dev)) { + if (its_sc != NULL && device_is_attached(its_sc->dev)) { /* * XXX ARM64TODO: This is part of the workaround that * saves ITS software context for further use in diff --git a/sys/arm64/arm64/nexus.c b/sys/arm64/arm64/nexus.c index f48a7aa..ec71409 100644 --- a/sys/arm64/arm64/nexus.c +++ b/sys/arm64/arm64/nexus.c @@ -250,7 +250,7 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, } rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) + if (rv == NULL) return (NULL); rman_set_rid(rv, *rid); diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index f8a7fdd..2cf3c33 100644 --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -221,6 +221,8 @@ struct msgbuf *msgbufp = NULL; static struct rwlock_padalign pvh_global_lock; vm_paddr_t dmap_phys_base; /* The start of the dmap region */ +vm_paddr_t dmap_phys_max; /* The limit of the dmap region */ +vm_offset_t dmap_max_addr; /* The virtual address limit of the dmap */ /* This code assumes all L1 DMAP entries will be used */ CTASSERT((DMAP_MIN_ADDRESS & ~L0_OFFSET) == DMAP_MIN_ADDRESS); @@ -550,15 +552,15 @@ pmap_early_vtophys(vm_offset_t l1pt, vm_offset_t va) } static void -pmap_bootstrap_dmap(vm_offset_t kern_l1, vm_paddr_t kernstart) +pmap_bootstrap_dmap(vm_offset_t kern_l1, vm_paddr_t min_pa, vm_paddr_t max_pa) { vm_offset_t va; vm_paddr_t pa; u_int l1_slot; - pa = dmap_phys_base = kernstart & ~L1_OFFSET; + pa = dmap_phys_base = min_pa & ~L1_OFFSET; va = DMAP_MIN_ADDRESS; - for (; va < DMAP_MAX_ADDRESS; + for (; va < DMAP_MAX_ADDRESS && pa < max_pa; pa += L1_SIZE, va += L1_SIZE, l1_slot++) { l1_slot = ((va - DMAP_MIN_ADDRESS) >> L1_SHIFT); @@ -567,6 +569,10 @@ pmap_bootstrap_dmap(vm_offset_t kern_l1, vm_paddr_t kernstart) ATTR_IDX(CACHED_MEMORY) | L1_BLOCK); } + /* Set the upper limit of the DMAP region */ + dmap_phys_max = pa; + dmap_max_addr = va; + cpu_dcache_wb_range((vm_offset_t)pagetable_dmap, PAGE_SIZE * DMAP_TABLES); cpu_tlb_flushID(); @@ -651,7 +657,7 @@ pmap_bootstrap(vm_offset_t l0pt, vm_offset_t l1pt, vm_paddr_t kernstart, pt_entry_t *l2; vm_offset_t va, freemempos; vm_offset_t dpcpu, msgbufpv; - vm_paddr_t pa, min_pa; + vm_paddr_t pa, max_pa, min_pa; int i; kern_delta = KERNBASE - kernstart; @@ -671,7 +677,7 @@ pmap_bootstrap(vm_offset_t l0pt, vm_offset_t l1pt, vm_paddr_t kernstart, rw_init(&pvh_global_lock, "pmap pv global"); /* Assume the address we were loaded to is a valid physical address */ - min_pa = KERNBASE - kern_delta; + min_pa = max_pa = KERNBASE - kern_delta; /* * Find the minimum physical address. physmap is sorted, @@ -682,11 +688,12 @@ pmap_bootstrap(vm_offset_t l0pt, vm_offset_t l1pt, vm_paddr_t kernstart, continue; if (physmap[i] <= min_pa) min_pa = physmap[i]; - break; + if (physmap[i + 1] > max_pa) + max_pa = physmap[i + 1]; } /* Create a direct map region early so we can use it for pa -> va */ - pmap_bootstrap_dmap(l1pt, min_pa); + pmap_bootstrap_dmap(l1pt, min_pa, max_pa); va = KERNBASE; pa = KERNBASE - kern_delta; diff --git a/sys/arm64/include/vmparam.h b/sys/arm64/include/vmparam.h index 8dc8809..3d46ece 100644 --- a/sys/arm64/include/vmparam.h +++ b/sys/arm64/include/vmparam.h @@ -162,19 +162,19 @@ #define VM_MIN_KERNEL_ADDRESS (0xffff000000000000UL) #define VM_MAX_KERNEL_ADDRESS (0xffff008000000000UL) -/* 2TiB for the direct map region */ +/* 2 TiB maximum for the direct map region */ #define DMAP_MIN_ADDRESS (0xfffffd0000000000UL) #define DMAP_MAX_ADDRESS (0xffffff0000000000UL) #define DMAP_MIN_PHYSADDR (dmap_phys_base) -#define DMAP_MAX_PHYSADDR (dmap_phys_base + (DMAP_MAX_ADDRESS - DMAP_MIN_ADDRESS)) +#define DMAP_MAX_PHYSADDR (dmap_phys_max) /* True if pa is in the dmap range */ #define PHYS_IN_DMAP(pa) ((pa) >= DMAP_MIN_PHYSADDR && \ (pa) < DMAP_MAX_PHYSADDR) /* True if va is in the dmap range */ #define VIRT_IN_DMAP(va) ((va) >= DMAP_MIN_ADDRESS && \ - (va) < DMAP_MAX_ADDRESS) + (va) < (dmap_max_addr)) #define PHYS_TO_DMAP(pa) \ ({ \ @@ -237,6 +237,8 @@ #ifndef LOCORE extern vm_paddr_t dmap_phys_base; +extern vm_paddr_t dmap_phys_max; +extern vm_offset_t dmap_max_addr; extern u_int tsb_kernel_ldd_phys; extern vm_offset_t vm_max_kernel_address; extern vm_offset_t init_pt_va; diff --git a/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c b/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c index 1b95cde..a1096d9 100644 --- a/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c +++ b/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c @@ -101,6 +101,17 @@ elf64_exec(struct preloaded_file *fp) char buf[24]; int revision; + /* + * Report the RSDP to the kernel. While this can be found with + * a BIOS boot, the RSDP may be elsewhere when booted from UEFI. + * The old code used the 'hints' method to communite this to + * the kernel. However, while convenient, the 'hints' method + * is fragile and does not work when static hints are compiled + * into the kernel. Instead, move to setting different tunables + * that start with acpi. The old 'hints' can be removed before + * we branch for FreeBSD 12. + */ + rsdp = efi_get_table(&acpi20_guid); if (rsdp == NULL) { rsdp = efi_get_table(&acpi_guid); @@ -108,23 +119,29 @@ elf64_exec(struct preloaded_file *fp) if (rsdp != NULL) { sprintf(buf, "0x%016llx", (unsigned long long)rsdp); setenv("hint.acpi.0.rsdp", buf, 1); + setenv("acpi.rsdp", buf, 1); revision = rsdp->Revision; if (revision == 0) revision = 1; sprintf(buf, "%d", revision); setenv("hint.acpi.0.revision", buf, 1); + setenv("acpi.revision", buf, 1); strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); buf[sizeof(rsdp->OemId)] = '\0'; setenv("hint.acpi.0.oem", buf, 1); + setenv("acpi.oem", buf, 1); sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress); setenv("hint.acpi.0.rsdt", buf, 1); + setenv("acpi.rsdt", buf, 1); if (revision >= 2) { /* XXX extended checksum? */ sprintf(buf, "0x%016llx", (unsigned long long)rsdp->XsdtPhysicalAddress); setenv("hint.acpi.0.xsdt", buf, 1); + setenv("acpi.xsdt", buf, 1); sprintf(buf, "%d", rsdp->Length); setenv("hint.acpi.0.xsdt_length", buf, 1); + setenv("acpi.xsdt_length", buf, 1); } } diff --git a/sys/boot/fdt/dts/mips/fbsd-mt7620a.dtsi b/sys/boot/fdt/dts/mips/fbsd-mt7620a.dtsi new file mode 100644 index 0000000..8f4c9d5 --- /dev/null +++ b/sys/boot/fdt/dts/mips/fbsd-mt7620a.dtsi @@ -0,0 +1,52 @@ +/* $FreeBSD$ */ + +/ { + + /* + * FreeBSD's stdin and stdout, so we can have a console + */ + chosen { + stdin = &uartlite; + stdout = &uartlite; + }; + + /* + * OpenWRT doesn't define a clock controller, but we currently need one + */ + clkctrl: cltctrl { + compatible = "ralink,rt2880-clock"; + #clock-cells = <1>; + }; + + palmbus@10000000 { + /* + * Make palmbus compatible to our simplebus + */ + compatible = "simple-bus"; + + /* + * Reference uartlite@c00 as uartlite, so we can address it + * within the chosen node above + */ + uartlite: uartlite@c00 {}; + }; + + usbphy: usbphy { + clocks = <&clkctrl 22 &clkctrl 25>; + clock-names = "host", "device"; + }; + + pcie@10140000 { + /* + * Our driver is different that OpenWRT's, so we need slightly + * different values for the reg property + */ + reg = <0x10140000 0x10000>; + + /* + * Also, we need resets and clocks defined, so we can properly + * initialize the PCIe + */ + clocks = <&clkctrl 26>; + }; +}; diff --git a/sys/boot/fdt/dts/mips/fbsd-mt7620n.dtsi b/sys/boot/fdt/dts/mips/fbsd-mt7620n.dtsi new file mode 100644 index 0000000..c1d537b --- /dev/null +++ b/sys/boot/fdt/dts/mips/fbsd-mt7620n.dtsi @@ -0,0 +1,38 @@ +/* $FreeBSD$ */ + +/ { + + /* + * FreeBSD's stdin and stdout, so we can have a console + */ + chosen { + stdin = &uartlite; + stdout = &uartlite; + }; + + /* + * OpenWRT doesn't define a clock controller, but we currently need one + */ + clkctrl: cltctrl { + compatible = "ralink,rt2880-clock"; + #clock-cells = <1>; + }; + + palmbus@10000000 { + /* + * Make palmbus compatible to our simplebus + */ + compatible = "simple-bus"; + + /* + * Reference uartlite@c00 as uartlite, so we can address it + * within the chosen node above + */ + uartlite: uartlite@c00 {}; + }; + + usbphy: usbphy { + clocks = <&clkctrl 22 &clkctrl 25>; + clock-names = "host", "device"; + }; +}; diff --git a/sys/boot/fdt/dts/mips/fbsd-mt7621.dtsi b/sys/boot/fdt/dts/mips/fbsd-mt7621.dtsi new file mode 100644 index 0000000..91ae1b1 --- /dev/null +++ b/sys/boot/fdt/dts/mips/fbsd-mt7621.dtsi @@ -0,0 +1,102 @@ +/* $FreeBSD$ */ + +/ { + + /* + * FreeBSD's stdin and stdout, so we can have a console + */ + chosen { + stdin = &uartlite; + stdout = &uartlite; + }; + + /* + * OpenWRT doesn't define a clock controller, but we currently need one + */ + clkctrl: cltctrl { + compatible = "ralink,rt2880-clock"; + #clock-cells = <1>; + }; + + gic: interrupt-controller@1fbc0000 { + /* + * OpenWRT does not define the GIC interrupt, but we need it + * for now, at least until we re-work our GIC driver + */ + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + palmbus@1E000000 { + /* + * Make palmbus compatible to our simplebus + */ + compatible = "simple-bus"; + + /* + * Reference uartlite@c00 as uartlite, so we can address it + * within the chosen node above + */ + uartlite: uartlite@c00 { + /* + * Mark uartlite as compatible to mtk,ns16550a instead + * of simply ns16550a so we can autodetect the UART + * clock + */ + compatible = "mtk,ns16550a"; + }; + + gpio@600 { + /* + * Mark gpio as compatible to simple-bus and override + * its #size-cells and provide a default ranges property + * so we can attach instances of our mtk_gpio_v2 driver + * to it for now. Provide exactly the same resources to + * the instances of mtk_gpio_v2. + */ + compatible = "simple-bus"; + ranges = <0x0 0x600 0x100>; + #size-cells = <1>; + + interrupt-parent = <&gic>; + + gpio0: bank@0 { + reg = <0x0 0x100>; + interrupts = <GIC_SHARED 6 IRQ_TYPE_LEVEL_HIGH>; + }; + + gpio1: bank@1 { + reg = <0x0 0x100>; + interrupts = <GIC_SHARED 6 IRQ_TYPE_LEVEL_HIGH>; + }; + + gpio2: bank@2 { + reg = <0x0 0x100>; + interrupts = <GIC_SHARED 6 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + }; + + xhci@1E1C0000 { + /* + * A slightly different value for reg size is needed by our + * driver for the moment + */ + reg = <0x1e1c0000 0x20000>; + }; + + pcie@1e140000 { + /* + * Our driver is different that OpenWRT's, so we need slightly + * different values for the reg property + */ + reg = <0x1e140000 0x10000>; + + /* + * Also, we need resets and clocks defined, so we can properly + * initialize the PCIe + */ + resets = <&rstctrl 24>, <&rstctrl 25>, <&rstctrl 26>; + clocks = <&clkctrl 24>, <&clkctrl 25>, <&clkctrl 26>; + }; +}; diff --git a/sys/boot/fdt/dts/mips/fbsd-mt7628an.dtsi b/sys/boot/fdt/dts/mips/fbsd-mt7628an.dtsi new file mode 100644 index 0000000..42401b5 --- /dev/null +++ b/sys/boot/fdt/dts/mips/fbsd-mt7628an.dtsi @@ -0,0 +1,88 @@ +/* $FreeBSD$ */ + +/ { + + /* + * FreeBSD's stdin and stdout, so we can have a console + */ + chosen { + stdin = &uartlite; + stdout = &uartlite; + }; + + /* + * OpenWRT doesn't define a clock controller, but we currently need one + */ + clkctrl: cltctrl { + compatible = "ralink,rt2880-clock"; + #clock-cells = <1>; + }; + + palmbus@10000000 { + /* + * Make palmbus compatible to our simplebus + */ + compatible = "simple-bus"; + + /* + * Reference uart2@e00 as uartlite, so we can address it + * within the chosen node above + */ + uartlite: uart2@e00 { + /* + * Mark uartlite as compatible to mtk,ns16550a instead + * of simply ns16550a so we can autodetect the UART + * clock + */ + compatible = "mtk,ns16550a"; + }; + + gpio@600 { + /* + * Mark gpio as compatible to simple-bus and override + * its #size-cells and provide a default ranges property + * so we can attach instances of our mtk_gpio_v2 driver + * to it for now. Provide exactly the same resources to + * the instances of mtk_gpio_v2. + */ + compatible = "simple-bus"; + ranges = <0x0 0x600 0x100>; + #size-cells = <1>; + + gpio0: bank@0 { + reg = <0x0 0x100>; + interrupts = <6>; + }; + + gpio1: bank@1 { + reg = <0x0 0x100>; + interrupts = <6>; + }; + + gpio2: bank@2 { + reg = <0x0 0x100>; + interrupts = <6>; + }; + }; + }; + + usbphy: usbphy@10120000 { + clocks = <&clkctrl 22 &clkctrl 25>; + clock-names = "host", "device"; + }; + + pcie@10140000 { + /* + * Our driver is different that OpenWRT's, so we need slightly + * different values for the reg property + */ + reg = <0x10140000 0x10000>; + + /* + * Also, we need resets and clocks defined, so we can properly + * initialize the PCIe + */ + resets = <&rstctrl 26>, <&rstctrl 27>; + clocks = <&clkctrl 26>, <&clkctrl 27>; + }; +}; diff --git a/sys/boot/fdt/dts/mips/fbsd-rt2880.dtsi b/sys/boot/fdt/dts/mips/fbsd-rt2880.dtsi new file mode 100644 index 0000000..96ebafe --- /dev/null +++ b/sys/boot/fdt/dts/mips/fbsd-rt2880.dtsi @@ -0,0 +1,33 @@ +/* $FreeBSD$ */ + +/ { + + /* + * FreeBSD's stdin and stdout, so we can have a console + */ + chosen { + stdin = &uartlite; + stdout = &uartlite; + }; + + /* + * OpenWRT doesn't define a clock controller, but we currently need one + */ + clkctrl: cltctrl { + compatible = "ralink,rt2880-clock"; + #clock-cells = <1>; + }; + + palmbus@300000 { + /* + * Make palmbus compatible to our simplebus + */ + compatible = "simple-bus"; + + /* + * Reference uartlite@c00 as uartlite, so we can address it + * within the chosen node above + */ + uartlite: uartlite@c00 {}; + }; +}; diff --git a/sys/boot/fdt/dts/mips/fbsd-rt3050.dtsi b/sys/boot/fdt/dts/mips/fbsd-rt3050.dtsi new file mode 100644 index 0000000..13eb530 --- /dev/null +++ b/sys/boot/fdt/dts/mips/fbsd-rt3050.dtsi @@ -0,0 +1,41 @@ +/* $FreeBSD$ */ + +/ { + + /* + * FreeBSD's stdin and stdout, so we can have a console + */ + chosen { + stdin = &uartlite; + stdout = &uartlite; + }; + + /* + * OpenWRT doesn't define a clock controller, but we currently need one + */ + clkctrl: cltctrl { + compatible = "ralink,rt2880-clock"; + #clock-cells = <1>; + }; + + palmbus@10000000 { + /* + * Make palmbus compatible to our simplebus + */ + compatible = "simple-bus"; + + /* + * Reference uartlite@c00 as uartlite, so we can address it + * within the chosen node above + */ + uartlite: uartlite@c00 {}; + }; + + usbphy: usbphy { + compatible = "ralink,rt3050-usbphy"; + resets = <&rstctrl 22>; + reset-names = "otg"; + clocks = <&clkctrl 18>; + clock-names = "otg"; + }; +}; diff --git a/sys/boot/fdt/dts/mips/fbsd-rt3352.dtsi b/sys/boot/fdt/dts/mips/fbsd-rt3352.dtsi new file mode 100644 index 0000000..a6a6887 --- /dev/null +++ b/sys/boot/fdt/dts/mips/fbsd-rt3352.dtsi @@ -0,0 +1,38 @@ +/* $FreeBSD$ */ + +/ { + + /* + * FreeBSD's stdin and stdout, so we can have a console + */ + chosen { + stdin = &uartlite; + stdout = &uartlite; + }; + + /* + * OpenWRT doesn't define a clock controller, but we currently need one + */ + clkctrl: cltctrl { + compatible = "ralink,rt2880-clock"; + #clock-cells = <1>; + }; + + palmbus@10000000 { + /* + * Make palmbus compatible to our simplebus + */ + compatible = "simple-bus"; + + /* + * Reference uartlite@c00 as uartlite, so we can address it + * within the chosen node above + */ + uartlite: uartlite@c00 {}; + }; + + usbphy { + clocks = <&clkctrl 18 &clkctrl 20>; + clock-names = "host", "device"; + }; +}; diff --git a/sys/boot/fdt/dts/mips/fbsd-rt3883.dtsi b/sys/boot/fdt/dts/mips/fbsd-rt3883.dtsi new file mode 100644 index 0000000..de32f9b --- /dev/null +++ b/sys/boot/fdt/dts/mips/fbsd-rt3883.dtsi @@ -0,0 +1,50 @@ +/* $FreeBSD$ */ + +/ { + + /* + * FreeBSD's stdin and stdout, so we can have a console + */ + chosen { + stdin = &uartlite; + stdout = &uartlite; + }; + + /* + * OpenWRT doesn't define a clock controller, but we currently need one + */ + clkctrl: cltctrl { + compatible = "ralink,rt2880-clock"; + #clock-cells = <1>; + }; + + palmbus@10000000 { + /* + * Make palmbus compatible to our simplebus + */ + compatible = "simple-bus"; + + /* + * Reference uartlite@c00 as uartlite, so we can address it + * within the chosen node above + */ + uartlite: uartlite@c00 {}; + }; + + usbphy: usbphy { + clocks = <&clkctrl 22 &clkctrl 25>; + clock-names = "host", "device"; + }; + + pci@10140000 { + #address-cells = <3>; + #size-cells = <2>; + ranges = < + 0x02000000 0 0x00000000 0x20000000 0 0x10000000 + 0x01000000 0 0x00000000 0x10160000 0 0x00010000 + >; + + interrupt-parent = <&cpuintc>; + interrupts = <4>; + }; +}; diff --git a/sys/boot/fdt/dts/mips/fbsd-rt5350.dtsi b/sys/boot/fdt/dts/mips/fbsd-rt5350.dtsi new file mode 100644 index 0000000..5cc5383 --- /dev/null +++ b/sys/boot/fdt/dts/mips/fbsd-rt5350.dtsi @@ -0,0 +1,38 @@ +/* $FreeBSD$ */ + +/ { + + /* + * FreeBSD's stdin and stdout, so we can have a console + */ + chosen { + stdin = &uartlite; + stdout = &uartlite; + }; + + /* + * OpenWRT doesn't define a clock controller, but we currently need one + */ + clkctrl: cltctrl { + compatible = "ralink,rt2880-clock"; + #clock-cells = <1>; + }; + + palmbus@10000000 { + /* + * Make palmbus compatible to our simplebus + */ + compatible = "simple-bus"; + + /* + * Reference uartlite@c00 as uartlite, so we can address it + * within the chosen node above + */ + uartlite: uartlite@c00 {}; + }; + + usbphy { + clocks = <&clkctrl 18>; + clock-names = "host"; + }; +}; diff --git a/sys/boot/i386/libi386/biosacpi.c b/sys/boot/i386/libi386/biosacpi.c index bedc722..8167fca 100644 --- a/sys/boot/i386/libi386/biosacpi.c +++ b/sys/boot/i386/libi386/biosacpi.c @@ -60,25 +60,40 @@ biosacpi_detect(void) if ((rsdp = biosacpi_find_rsdp()) == NULL) return; - /* export values from the RSDP */ + /* + * Report the RSDP to the kernel. While this can be found with + * a BIOS boot, the RSDP may be elsewhere when booted from UEFI. + * The old code used the 'hints' method to communite this to + * the kernel. However, while convenient, the 'hints' method + * is fragile and does not work when static hints are compiled + * into the kernel. Instead, move to setting different tunables + * that start with acpi. The old 'hints' can be removed before + * we branch for FreeBSD 12. + */ sprintf(buf, "0x%08x", VTOP(rsdp)); setenv("hint.acpi.0.rsdp", buf, 1); + setenv("acpi.rsdp", buf, 1); revision = rsdp->Revision; if (revision == 0) revision = 1; sprintf(buf, "%d", revision); setenv("hint.acpi.0.revision", buf, 1); + setenv("acpi.revision", buf, 1); strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); buf[sizeof(rsdp->OemId)] = '\0'; setenv("hint.acpi.0.oem", buf, 1); + setenv("acpi.oem", buf, 1); sprintf(buf, "0x%08x", rsdp->RsdtPhysicalAddress); setenv("hint.acpi.0.rsdt", buf, 1); + setenv("acpi.rsdt", buf, 1); if (revision >= 2) { /* XXX extended checksum? */ sprintf(buf, "0x%016llx", rsdp->XsdtPhysicalAddress); setenv("hint.acpi.0.xsdt", buf, 1); + setenv("acpi.xsdt", buf, 1); sprintf(buf, "%d", rsdp->Length); setenv("hint.acpi.0.xsdt_length", buf, 1); + setenv("acpi.xsdt_length", buf, 1); } } diff --git a/sys/cam/ata/ata_all.c b/sys/cam/ata/ata_all.c index d5220e8..51231b7 100644 --- a/sys/cam/ata/ata_all.c +++ b/sys/cam/ata/ata_all.c @@ -211,29 +211,64 @@ ata_op_string(struct ata_cmd *cmd) char * ata_cmd_string(struct ata_cmd *cmd, char *cmd_string, size_t len) { + struct sbuf sb; + int error; - snprintf(cmd_string, len, "%02x %02x %02x %02x " + if (len == 0) + return (""); + + sbuf_new(&sb, cmd_string, len, SBUF_FIXEDLEN); + ata_cmd_sbuf(cmd, &sb); + + error = sbuf_finish(&sb); + if (error != 0 && error != ENOMEM) + return (""); + + return(sbuf_data(&sb)); +} + +void +ata_cmd_sbuf(struct ata_cmd *cmd, struct sbuf *sb) +{ + sbuf_printf(sb, "%02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x", cmd->command, cmd->features, cmd->lba_low, cmd->lba_mid, cmd->lba_high, cmd->device, cmd->lba_low_exp, cmd->lba_mid_exp, cmd->lba_high_exp, cmd->features_exp, cmd->sector_count, cmd->sector_count_exp); - - return(cmd_string); } char * ata_res_string(struct ata_res *res, char *res_string, size_t len) { + struct sbuf sb; + int error; + + if (len == 0) + return (""); + + sbuf_new(&sb, res_string, len, SBUF_FIXEDLEN); + ata_res_sbuf(res, &sb); + + error = sbuf_finish(&sb); + if (error != 0 && error != ENOMEM) + return (""); + + return(sbuf_data(&sb)); +} + +int +ata_res_sbuf(struct ata_res *res, struct sbuf *sb) +{ - snprintf(res_string, len, "%02x %02x %02x %02x " + sbuf_printf(sb, "%02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x", res->status, res->error, res->lba_low, res->lba_mid, res->lba_high, res->device, res->lba_low_exp, res->lba_mid_exp, res->lba_high_exp, res->sector_count, res->sector_count_exp); - return(res_string); + return (0); } /* @@ -242,11 +277,10 @@ ata_res_string(struct ata_res *res, char *res_string, size_t len) int ata_command_sbuf(struct ccb_ataio *ataio, struct sbuf *sb) { - char cmd_str[(12 * 3) + 1]; - sbuf_printf(sb, "%s. ACB: %s", - ata_op_string(&ataio->cmd), - ata_cmd_string(&ataio->cmd, cmd_str, sizeof(cmd_str))); + sbuf_printf(sb, "%s. ACB: ", + ata_op_string(&ataio->cmd)); + ata_cmd_sbuf(&ataio->cmd, sb); return(0); } @@ -284,20 +318,6 @@ ata_status_sbuf(struct ccb_ataio *ataio, struct sbuf *sb) return(0); } -/* - * ata_res_sbuf() returns 0 for success and -1 for failure. - */ -int -ata_res_sbuf(struct ccb_ataio *ataio, struct sbuf *sb) -{ - char res_str[(11 * 3) + 1]; - - sbuf_printf(sb, "RES: %s", - ata_res_string(&ataio->res, res_str, sizeof(res_str))); - - return(0); -} - void ata_print_ident(struct ata_params *ident_data) { diff --git a/sys/cam/ata/ata_all.h b/sys/cam/ata/ata_all.h index 91e941c..0eda4f4 100644 --- a/sys/cam/ata/ata_all.h +++ b/sys/cam/ata/ata_all.h @@ -46,6 +46,7 @@ struct ata_cmd { #define CAM_ATAIO_CONTROL 0x04 /* Control, not a command */ #define CAM_ATAIO_NEEDRESULT 0x08 /* Request requires result. */ #define CAM_ATAIO_DMA 0x10 /* DMA command */ +#define CAM_ATAIO_AUX_HACK 0x20 /* Kludge to make FPDMA DSM TRIM work */ u_int8_t command; u_int8_t features; @@ -103,10 +104,11 @@ int ata_version(int ver); char * ata_op_string(struct ata_cmd *cmd); char * ata_cmd_string(struct ata_cmd *cmd, char *cmd_string, size_t len); +void ata_cmd_sbuf(struct ata_cmd *cmd, struct sbuf *sb); char * ata_res_string(struct ata_res *res, char *res_string, size_t len); int ata_command_sbuf(struct ccb_ataio *ataio, struct sbuf *sb); int ata_status_sbuf(struct ccb_ataio *ataio, struct sbuf *sb); -int ata_res_sbuf(struct ccb_ataio *ataio, struct sbuf *sb); +int ata_res_sbuf(struct ata_res *res, struct sbuf *sb); void ata_print_ident(struct ata_params *ident_data); void ata_print_ident_short(struct ata_params *ident_data); diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c index 38cf46e..05134d7 100644 --- a/sys/cam/ata/ata_da.c +++ b/sys/cam/ata/ata_da.c @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); #include <cam/cam_periph.h> #include <cam/cam_xpt_periph.h> #include <cam/cam_sim.h> +#include <cam/cam_iosched.h> #include <cam/ata/ata_all.h> @@ -68,6 +69,8 @@ __FBSDID("$FreeBSD$"); #define ATA_MAX_28BIT_LBA 268435455UL +extern int iosched_debug; + typedef enum { ADA_STATE_RAHEAD, ADA_STATE_WCACHE, @@ -87,17 +90,21 @@ typedef enum { ADA_FLAG_CAN_CFA = 0x0400, ADA_FLAG_CAN_POWERMGT = 0x0800, ADA_FLAG_CAN_DMA48 = 0x1000, - ADA_FLAG_DIRTY = 0x2000 + ADA_FLAG_DIRTY = 0x2000, + ADA_FLAG_CAN_NCQ_TRIM = 0x4000, /* CAN_TRIM also set */ + ADA_FLAG_PIM_CAN_NCQ_TRIM = 0x8000 } ada_flags; typedef enum { ADA_Q_NONE = 0x00, ADA_Q_4K = 0x01, + ADA_Q_NCQ_TRIM_BROKEN = 0x02, } ada_quirks; #define ADA_Q_BIT_STRING \ "\020" \ - "\0014K" + "\0014K" \ + "\002NCQ_TRIM_BROKEN" typedef enum { ADA_CCB_RAHEAD = 0x01, @@ -112,6 +119,23 @@ typedef enum { #define ccb_state ppriv_field0 #define ccb_bp ppriv_ptr1 +typedef enum { + ADA_DELETE_NONE, + ADA_DELETE_DISABLE, + ADA_DELETE_CFA_ERASE, + ADA_DELETE_DSM_TRIM, + ADA_DELETE_NCQ_DSM_TRIM, + ADA_DELETE_MIN = ADA_DELETE_CFA_ERASE, + ADA_DELETE_MAX = ADA_DELETE_NCQ_DSM_TRIM, +} ada_delete_methods; + +static const char *ada_delete_method_names[] = + { "NONE", "DISABLE", "CFA_ERASE", "DSM_TRIM", "NCQ_DSM_TRIM" }; +#if 0 +static const char *ada_delete_method_desc[] = + { "NONE", "DISABLED", "CFA Erase", "DSM Trim", "DSM Trim via NCQ" }; +#endif + struct disk_params { u_int8_t heads; u_int8_t secs_per_track; @@ -128,18 +152,18 @@ struct trim_request { }; struct ada_softc { - struct bio_queue_head bio_queue; - struct bio_queue_head trim_queue; + struct cam_iosched_softc *cam_iosched; int outstanding_cmds; /* Number of active commands */ int refcount; /* Active xpt_action() calls */ ada_state state; ada_flags flags; ada_quirks quirks; - int sort_io_queue; + ada_delete_methods delete_method; int trim_max_ranges; - int trim_running; int read_ahead; int write_cache; + int unmappedio; + int rotating; #ifdef ADA_TEST_FAILURE int force_read_error; int force_write_error; @@ -153,6 +177,13 @@ struct ada_softc { struct sysctl_oid *sysctl_tree; struct callout sendordered_c; struct trim_request trim_req; +#ifdef CAM_IO_STATS + struct sysctl_ctx_list sysctl_stats_ctx; + struct sysctl_oid *sysctl_stats_tree; + u_int timeouts; + u_int errors; + u_int invalidations; +#endif }; struct ada_quirk_entry { @@ -330,6 +361,38 @@ static struct ada_quirk_entry ada_quirk_table[] = }, { /* + * Crucial M500 SSDs MU07 firmware + * NCQ Trim works + */ + { T_DIRECT, SIP_MEDIA_FIXED, "*", "Crucial CT*M500*", "MU07" }, + /*quirks*/0 + }, + { + /* + * Crucial M500 SSDs all other firmware + * NCQ Trim doesn't work + */ + { T_DIRECT, SIP_MEDIA_FIXED, "*", "Crucial CT*M500*", "*" }, + /*quirks*/ADA_Q_NCQ_TRIM_BROKEN + }, + { + /* + * Crucial M550 SSDs + * NCQ Trim doesn't work, but only on MU01 firmware + */ + { T_DIRECT, SIP_MEDIA_FIXED, "*", "Crucial CT*M550*", "MU01" }, + /*quirks*/ADA_Q_NCQ_TRIM_BROKEN + }, + { + /* + * Crucial MX100 SSDs + * NCQ Trim doesn't work, but only on MU01 firmware + */ + { T_DIRECT, SIP_MEDIA_FIXED, "*", "Crucial CT*MX100*", "MU01" }, + /*quirks*/ADA_Q_NCQ_TRIM_BROKEN + }, + { + /* * Crucial RealSSD C300 SSDs * 4k optimised */ @@ -338,6 +401,14 @@ static struct ada_quirk_entry ada_quirk_table[] = }, { /* + * FCCT M500 SSDs + * NCQ Trim doesn't work + */ + { T_DIRECT, SIP_MEDIA_FIXED, "*", "FCCT*M500*", "*" }, + /*quirks*/ADA_Q_NCQ_TRIM_BROKEN + }, + { + /* * Intel 320 Series SSDs * 4k optimised & trim only works in 4k requests + 4k aligned */ @@ -402,6 +473,30 @@ static struct ada_quirk_entry ada_quirk_table[] = }, { /* + * Micron M500 SSDs firmware MU07 + * NCQ Trim works? + */ + { T_DIRECT, SIP_MEDIA_FIXED, "*", "Micron M500*", "MU07" }, + /*quirks*/0 + }, + { + /* + * Micron M500 SSDs all other firmware + * NCQ Trim doesn't work + */ + { T_DIRECT, SIP_MEDIA_FIXED, "*", "Micron M500*", "*" }, + /*quirks*/ADA_Q_NCQ_TRIM_BROKEN + }, + { + /* + * Micron M5[15]0 SSDs + * NCQ Trim doesn't work, but only MU01 firmware + */ + { T_DIRECT, SIP_MEDIA_FIXED, "*", "Micron M5[15]0*", "MU01" }, + /*quirks*/ADA_Q_NCQ_TRIM_BROKEN + }, + { + /* * OCZ Agility 2 SSDs * 4k optimised & trim only works in 4k requests + 4k aligned */ @@ -451,25 +546,33 @@ static struct ada_quirk_entry ada_quirk_table[] = { /* * Samsung 830 Series SSDs - * 4k optimised + * 4k optimised, NCQ TRIM Broken (normal TRIM is fine) */ { T_DIRECT, SIP_MEDIA_FIXED, "*", "SAMSUNG SSD 830 Series*", "*" }, - /*quirks*/ADA_Q_4K + /*quirks*/ADA_Q_4K | ADA_Q_NCQ_TRIM_BROKEN }, { /* * Samsung 840 SSDs - * 4k optimised + * 4k optimised, NCQ TRIM Broken (normal TRIM is fine) */ { T_DIRECT, SIP_MEDIA_FIXED, "*", "Samsung SSD 840*", "*" }, - /*quirks*/ADA_Q_4K + /*quirks*/ADA_Q_4K | ADA_Q_NCQ_TRIM_BROKEN }, { /* * Samsung 850 SSDs - * 4k optimised + * 4k optimised, NCQ TRIM broken (normal TRIM fine) */ { T_DIRECT, SIP_MEDIA_FIXED, "*", "Samsung SSD 850*", "*" }, + /*quirks*/ADA_Q_4K | ADA_Q_NCQ_TRIM_BROKEN + }, + { + /* + * Samsung SM863 Series SSDs (MZ7KM*) + * 4k optimised, NCQ believed to be working + */ + { T_DIRECT, SIP_MEDIA_FIXED, "*", "SAMSUNG MZ7KM*", "*" }, /*quirks*/ADA_Q_4K }, { @@ -477,11 +580,11 @@ static struct ada_quirk_entry ada_quirk_table[] = * Samsung 843T Series SSDs (MZ7WD*) * Samsung PM851 Series SSDs (MZ7TE*) * Samsung PM853T Series SSDs (MZ7GE*) - * Samsung SM863 Series SSDs (MZ7KM*) - * 4k optimised + * 4k optimised, NCQ believed to be broken since these are + * appear to be built with the same controllers as the 840/850. */ { T_DIRECT, SIP_MEDIA_FIXED, "*", "SAMSUNG MZ7*", "*" }, - /*quirks*/ADA_Q_4K + /*quirks*/ADA_Q_4K | ADA_Q_NCQ_TRIM_BROKEN }, { /* @@ -566,8 +669,6 @@ static void adaresume(void *arg); softc->read_ahead : ada_read_ahead) #define ADA_WC (softc->write_cache >= 0 ? \ softc->write_cache : ada_write_cache) -#define ADA_SIO (softc->sort_io_queue >= 0 ? \ - softc->sort_io_queue : cam_sort_io_queues) /* * Most platforms map firmware geometry to actual, but some don't. If @@ -624,6 +725,8 @@ static struct periph_driver adadriver = TAILQ_HEAD_INITIALIZER(adadriver.units), /* generation */ 0 }; +static int adadeletemethodsysctl(SYSCTL_HANDLER_ARGS); + PERIPHDRIVER_DECLARE(ada, adadriver); static int @@ -719,11 +822,7 @@ adaschedule(struct cam_periph *periph) if (softc->state != ADA_STATE_NORMAL) return; - /* Check if we have more work to do. */ - if (bioq_first(&softc->bio_queue) || - (!softc->trim_running && bioq_first(&softc->trim_queue))) { - xpt_schedule(periph, CAM_PRIORITY_NORMAL); - } + cam_iosched_schedule(softc->cam_iosched, periph); } /* @@ -756,14 +855,7 @@ adastrategy(struct bio *bp) /* * Place it in the queue of disk activities for this disk */ - if (bp->bio_cmd == BIO_DELETE) { - bioq_disksort(&softc->trim_queue, bp); - } else { - if (ADA_SIO) - bioq_disksort(&softc->bio_queue, bp); - else - bioq_insert_tail(&softc->bio_queue, bp); - } + cam_iosched_queue_work(softc->cam_iosched, bp); /* * Schedule ourselves for performing the work. @@ -836,6 +928,11 @@ adadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t len if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) { xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); + /* + * Tell the drive to flush its internal cache. if we + * can't flush in 5s we have big problems. No need to + * wait the default 60s to detect problems. + */ ccb.ccb_h.ccb_state = ADA_CCB_DUMP; cam_fill_ataio(&ccb.ataio, 0, @@ -844,7 +941,7 @@ adadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t len 0, NULL, 0, - ada_default_timeout*1000); + 5*1000); if (softc->flags & ADA_FLAG_CAN_48BIT) ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE48, 0, 0, 0); @@ -918,14 +1015,16 @@ adaoninvalidate(struct cam_periph *periph) * De-register any async callbacks. */ xpt_register_async(0, adaasync, periph, periph->path); +#ifdef CAM_IO_STATS + softc->invalidations++; +#endif /* * Return all queued I/O with ENXIO. * XXX Handle any transactions queued to the card * with XPT_ABORT_CCB. */ - bioq_flush(&softc->bio_queue, NULL, ENXIO); - bioq_flush(&softc->trim_queue, NULL, ENXIO); + cam_iosched_flush(softc->cam_iosched, NULL, ENXIO); disk_gone(softc->disk); } @@ -939,12 +1038,20 @@ adacleanup(struct cam_periph *periph) cam_periph_unlock(periph); + cam_iosched_fini(softc->cam_iosched); + /* * If we can't free the sysctl tree, oh well... */ - if ((softc->flags & ADA_FLAG_SCTX_INIT) != 0 - && sysctl_ctx_free(&softc->sysctl_ctx) != 0) { - xpt_print(periph->path, "can't remove sysctl context\n"); + if ((softc->flags & ADA_FLAG_SCTX_INIT) != 0) { +#ifdef CAM_IO_STATS + if (sysctl_ctx_free(&softc->sysctl_stats_ctx) != 0) + xpt_print(periph->path, + "can't remove sysctl stats context\n"); +#endif + if (sysctl_ctx_free(&softc->sysctl_ctx) != 0) + xpt_print(periph->path, + "can't remove sysctl context\n"); } disk_destroy(softc->disk); @@ -954,6 +1061,20 @@ adacleanup(struct cam_periph *periph) } static void +adasetdeletemethod(struct ada_softc *softc) +{ + + if (softc->flags & ADA_FLAG_CAN_NCQ_TRIM) + softc->delete_method = ADA_DELETE_NCQ_DSM_TRIM; + else if (softc->flags & ADA_FLAG_CAN_TRIM) + softc->delete_method = ADA_DELETE_DSM_TRIM; + else if ((softc->flags & ADA_FLAG_CAN_CFA) && !(softc->flags & ADA_FLAG_CAN_48BIT)) + softc->delete_method = ADA_DELETE_CFA_ERASE; + else + softc->delete_method = ADA_DELETE_NONE; +} + +static void adaasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg) { @@ -1018,11 +1139,26 @@ adaasync(void *callback_arg, u_int32_t code, softc->flags |= ADA_FLAG_CAN_NCQ; else softc->flags &= ~ADA_FLAG_CAN_NCQ; + if ((cgd.ident_data.support_dsm & ATA_SUPPORT_DSM_TRIM) && - (cgd.inq_flags & SID_DMA)) + (cgd.inq_flags & SID_DMA)) { softc->flags |= ADA_FLAG_CAN_TRIM; - else - softc->flags &= ~ADA_FLAG_CAN_TRIM; + /* + * If we can do RCVSND_FPDMA_QUEUED commands, we may be able to do + * NCQ trims, if we support trims at all. We also need support from + * the sim do do things properly. Perhaps we should look at log 13 + * dword 0 bit 0 and dword 1 bit 0 are set too... + */ + if ((softc->quirks & ADA_Q_NCQ_TRIM_BROKEN) == 0 && + (softc->flags & ADA_FLAG_PIM_CAN_NCQ_TRIM) != 0 && + (cgd.ident_data.satacapabilities2 & ATA_SUPPORT_RCVSND_FPDMA_QUEUED) != 0 && + (softc->flags & ADA_FLAG_CAN_TRIM) != 0) + softc->flags |= ADA_FLAG_CAN_NCQ_TRIM; + else + softc->flags &= ~ADA_FLAG_CAN_NCQ_TRIM; + } else + softc->flags &= ~(ADA_FLAG_CAN_TRIM | ADA_FLAG_CAN_NCQ_TRIM); + adasetdeletemethod(softc); cam_periph_async(periph, code, path, arg); break; @@ -1100,6 +1236,10 @@ adasysctlinit(void *context, int pending) return; } + SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), + OID_AUTO, "delete_method", CTLTYPE_STRING | CTLFLAG_RW, + softc, 0, adadeletemethodsysctl, "A", + "BIO_DELETE execution method"); SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO, "read_ahead", CTLFLAG_RW | CTLFLAG_MPSAFE, &softc->read_ahead, 0, "Enable disk read ahead."); @@ -1107,9 +1247,11 @@ adasysctlinit(void *context, int pending) OID_AUTO, "write_cache", CTLFLAG_RW | CTLFLAG_MPSAFE, &softc->write_cache, 0, "Enable disk write cache."); SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), - OID_AUTO, "sort_io_queue", CTLFLAG_RW | CTLFLAG_MPSAFE, - &softc->sort_io_queue, 0, - "Sort IO queue to try and optimise disk access patterns"); + OID_AUTO, "unmapped_io", CTLFLAG_RD | CTLFLAG_MPSAFE, + &softc->unmappedio, 0, "Unmapped I/O leaf"); + SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), + OID_AUTO, "rotating", CTLFLAG_RD | CTLFLAG_MPSAFE, + &softc->rotating, 0, "Rotating media"); #ifdef ADA_TEST_FAILURE /* * Add a 'door bell' sysctl which allows one to set it from userland @@ -1129,6 +1271,31 @@ adasysctlinit(void *context, int pending) &softc->periodic_read_error, 0, "Force a read error every N reads (don't set too low)."); #endif + +#ifdef CAM_IO_STATS + softc->sysctl_stats_tree = SYSCTL_ADD_NODE(&softc->sysctl_stats_ctx, + SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO, "stats", + CTLFLAG_RD, 0, "Statistics"); + SYSCTL_ADD_INT(&softc->sysctl_stats_ctx, + SYSCTL_CHILDREN(softc->sysctl_stats_tree), + OID_AUTO, "timeouts", CTLFLAG_RD | CTLFLAG_MPSAFE, + &softc->timeouts, 0, + "Device timeouts reported by the SIM"); + SYSCTL_ADD_INT(&softc->sysctl_stats_ctx, + SYSCTL_CHILDREN(softc->sysctl_stats_tree), + OID_AUTO, "errors", CTLFLAG_RD | CTLFLAG_MPSAFE, + &softc->errors, 0, + "Transport errors reported by the SIM."); + SYSCTL_ADD_INT(&softc->sysctl_stats_ctx, + SYSCTL_CHILDREN(softc->sysctl_stats_tree), + OID_AUTO, "pack_invalidations", CTLFLAG_RD | CTLFLAG_MPSAFE, + &softc->invalidations, 0, + "Device pack invalidations."); +#endif + + cam_iosched_sysctl_init(softc->cam_iosched, &softc->sysctl_ctx, + softc->sysctl_tree); + cam_periph_release(periph); } @@ -1148,6 +1315,43 @@ adagetattr(struct bio *bp) return ret; } +static int +adadeletemethodsysctl(SYSCTL_HANDLER_ARGS) +{ + char buf[16]; + const char *p; + struct ada_softc *softc; + int i, error, value, methods; + + softc = (struct ada_softc *)arg1; + + value = softc->delete_method; + if (value < 0 || value > ADA_DELETE_MAX) + p = "UNKNOWN"; + else + p = ada_delete_method_names[value]; + strncpy(buf, p, sizeof(buf)); + error = sysctl_handle_string(oidp, buf, sizeof(buf), req); + if (error != 0 || req->newptr == NULL) + return (error); + methods = 1 << ADA_DELETE_DISABLE; + if ((softc->flags & ADA_FLAG_CAN_CFA) && + !(softc->flags & ADA_FLAG_CAN_48BIT)) + methods |= 1 << ADA_DELETE_CFA_ERASE; + if (softc->flags & ADA_FLAG_CAN_TRIM) + methods |= 1 << ADA_DELETE_DSM_TRIM; + if (softc->flags & ADA_FLAG_CAN_NCQ_TRIM) + methods |= 1 << ADA_DELETE_NCQ_DSM_TRIM; + for (i = 0; i <= ADA_DELETE_MAX; i++) { + if (!(methods & (1 << i)) || + strcmp(buf, ada_delete_method_names[i]) != 0) + continue; + softc->delete_method = i; + return (0); + } + return (EINVAL); +} + static cam_status adaregister(struct cam_periph *periph, void *arg) { @@ -1175,8 +1379,11 @@ adaregister(struct cam_periph *periph, void *arg) return(CAM_REQ_CMP_ERR); } - bioq_init(&softc->bio_queue); - bioq_init(&softc->trim_queue); + if (cam_iosched_init(&softc->cam_iosched, periph) != 0) { + printf("adaregister: Unable to probe new device. " + "Unable to allocate iosched memory\n"); + return(CAM_REQ_CMP_ERR); + } if ((cgd->ident_data.capabilities1 & ATA_SUPPORT_DMA) && (cgd->inq_flags & SID_DMA)) @@ -1206,6 +1413,8 @@ adaregister(struct cam_periph *periph, void *arg) if (cgd->ident_data.support.command2 & ATA_SUPPORT_CFA) softc->flags |= ADA_FLAG_CAN_CFA; + adasetdeletemethod(softc); + periph->softc = softc; /* @@ -1246,10 +1455,12 @@ adaregister(struct cam_periph *periph, void *arg) "kern.cam.ada.%d.write_cache", periph->unit_number); TUNABLE_INT_FETCH(announce_buf, &softc->write_cache); /* Disable queue sorting for non-rotational media by default. */ - if (cgd->ident_data.media_rotation_rate == ATA_RATE_NON_ROTATING) - softc->sort_io_queue = 0; - else - softc->sort_io_queue = -1; + if (cgd->ident_data.media_rotation_rate == ATA_RATE_NON_ROTATING) { + softc->rotating = 0; + } else { + softc->rotating = 1; + } + cam_iosched_set_sort_queue(softc->cam_iosched, softc->rotating ? -1 : 0); adagetparams(periph, cgd); softc->disk = disk_alloc(); softc->disk->d_rotation_rate = cgd->ident_data.media_rotation_rate; @@ -1292,8 +1503,23 @@ adaregister(struct cam_periph *periph, void *arg) softc->disk->d_delmaxsize = 256 * softc->params.secsize; } else softc->disk->d_delmaxsize = maxio; - if ((cpi.hba_misc & PIM_UNMAPPED) != 0) + if ((cpi.hba_misc & PIM_UNMAPPED) != 0) { softc->disk->d_flags |= DISKFLAG_UNMAPPED_BIO; + softc->unmappedio = 1; + } + /* + * If we can do RCVSND_FPDMA_QUEUED commands, we may be able to do + * NCQ trims, if we support trims at all. We also need support from + * the sim do do things properly. Perhaps we should look at log 13 + * dword 0 bit 0 and dword 1 bit 0 are set too... + */ + if (cpi.hba_misc & PIM_NCQ_KLUDGE) + softc->flags |= ADA_FLAG_PIM_CAN_NCQ_TRIM; + if ((softc->quirks & ADA_Q_NCQ_TRIM_BROKEN) == 0 && + (softc->flags & ADA_FLAG_PIM_CAN_NCQ_TRIM) != 0 && + (cgd->ident_data.satacapabilities2 & ATA_SUPPORT_RCVSND_FPDMA_QUEUED) != 0 && + (softc->flags & ADA_FLAG_CAN_TRIM) != 0) + softc->flags |= ADA_FLAG_CAN_NCQ_TRIM; strlcpy(softc->disk->d_descr, cgd->ident_data.model, MIN(sizeof(softc->disk->d_descr), sizeof(cgd->ident_data.model))); strlcpy(softc->disk->d_ident, cgd->ident_data.serial, @@ -1320,6 +1546,7 @@ adaregister(struct cam_periph *periph, void *arg) softc->disk->d_fwsectors = softc->params.secs_per_track; softc->disk->d_fwheads = softc->params.heads; ata_disk_firmware_geom_adjust(softc->disk); + adasetdeletemethod(softc); /* * Acquire a reference to the periph before we register with GEOM. @@ -1389,10 +1616,9 @@ adaregister(struct cam_periph *periph, void *arg) return(CAM_REQ_CMP); } -static void -ada_dsmtrim(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio) +static int +ada_dsmtrim_req_create(struct ada_softc *softc, struct bio *bp, struct trim_request *req) { - struct trim_request *req = &softc->trim_req; uint64_t lastlba = (uint64_t)-1; int c, lastcount = 0, off, ranges = 0; @@ -1402,8 +1628,6 @@ ada_dsmtrim(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio) uint64_t lba = bp->bio_pblkno; int count = bp->bio_bcount / softc->params.secsize; - bioq_remove(&softc->trim_queue, bp); - /* Try to extend the previous range. */ if (lba == lastlba) { c = min(count, ATA_DSM_RANGE_MAX - lastcount); @@ -1439,12 +1663,27 @@ ada_dsmtrim(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio) } lastlba = lba; TAILQ_INSERT_TAIL(&req->bps, bp, bio_queue); - bp = bioq_first(&softc->trim_queue); - if (bp == NULL || - bp->bio_bcount / softc->params.secsize > - (softc->trim_max_ranges - ranges) * ATA_DSM_RANGE_MAX) + + bp = cam_iosched_next_trim(softc->cam_iosched); + if (bp == NULL) + break; + if (bp->bio_bcount / softc->params.secsize > + (softc->trim_max_ranges - ranges) * ATA_DSM_RANGE_MAX) { + cam_iosched_put_back_trim(softc->cam_iosched, bp); break; + } } while (1); + + return (ranges); +} + +static void +ada_dsmtrim(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio) +{ + struct trim_request *req = &softc->trim_req; + int ranges; + + ranges = ada_dsmtrim_req_create(softc, bp, req); cam_fill_ataio(ataio, ada_retry_count, adadone, @@ -1460,6 +1699,30 @@ ada_dsmtrim(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio) } static void +ada_ncq_dsmtrim(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio) +{ + struct trim_request *req = &softc->trim_req; + int ranges; + + ranges = ada_dsmtrim_req_create(softc, bp, req); + cam_fill_ataio(ataio, + ada_retry_count, + adadone, + CAM_DIR_OUT, + 0, + req->data, + ((ranges + ATA_DSM_BLK_RANGES - 1) / + ATA_DSM_BLK_RANGES) * ATA_DSM_BLK_SIZE, + ada_default_timeout * 1000); + ata_ncq_cmd(ataio, + ATA_SEND_FPDMA_QUEUED, + 0, + (ranges + ATA_DSM_BLK_RANGES - 1) / ATA_DSM_BLK_RANGES); + ataio->cmd.sector_count_exp = ATA_SFPDMA_DSM; + ataio->cmd.flags |= CAM_ATAIO_AUX_HACK; +} + +static void ada_cfaerase(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio) { struct trim_request *req = &softc->trim_req; @@ -1468,7 +1731,6 @@ ada_cfaerase(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio) bzero(req, sizeof(*req)); TAILQ_INIT(&req->bps); - bioq_remove(&softc->trim_queue, bp); TAILQ_INSERT_TAIL(&req->bps, bp, bio_queue); cam_fill_ataio(ataio, @@ -1499,37 +1761,14 @@ adastart(struct cam_periph *periph, union ccb *start_ccb) struct bio *bp; u_int8_t tag_code; - /* Run TRIM if not running yet. */ - if (!softc->trim_running && - (bp = bioq_first(&softc->trim_queue)) != 0) { - if (softc->flags & ADA_FLAG_CAN_TRIM) { - ada_dsmtrim(softc, bp, ataio); - } else if ((softc->flags & ADA_FLAG_CAN_CFA) && - !(softc->flags & ADA_FLAG_CAN_48BIT)) { - ada_cfaerase(softc, bp, ataio); - } else { - /* This can happen if DMA was disabled. */ - bioq_remove(&softc->trim_queue, bp); - biofinish(bp, NULL, EOPNOTSUPP); - xpt_release_ccb(start_ccb); - adaschedule(periph); - return; - } - softc->trim_running = 1; - start_ccb->ccb_h.ccb_state = ADA_CCB_TRIM; - start_ccb->ccb_h.flags |= CAM_UNLOCKED; - goto out; - } - /* Run regular command. */ - bp = bioq_first(&softc->bio_queue); + bp = cam_iosched_next_bio(softc->cam_iosched); if (bp == NULL) { xpt_release_ccb(start_ccb); break; } - bioq_remove(&softc->bio_queue, bp); - if ((bp->bio_flags & BIO_ORDERED) != 0 - || (softc->flags & ADA_FLAG_NEED_OTAG) != 0) { + if ((bp->bio_flags & BIO_ORDERED) != 0 || + (bp->bio_cmd != BIO_DELETE && (softc->flags & ADA_FLAG_NEED_OTAG) != 0)) { softc->flags &= ~ADA_FLAG_NEED_OTAG; softc->flags |= ADA_FLAG_WAS_OTAG; tag_code = 0; @@ -1659,6 +1898,27 @@ adastart(struct cam_periph *periph, union ccb *start_ccb) } break; } + case BIO_DELETE: + switch (softc->delete_method) { + case ADA_DELETE_NCQ_DSM_TRIM: + ada_ncq_dsmtrim(softc, bp, ataio); + break; + case ADA_DELETE_DSM_TRIM: + ada_dsmtrim(softc, bp, ataio); + break; + case ADA_DELETE_CFA_ERASE: + ada_cfaerase(softc, bp, ataio); + break; + default: + biofinish(bp, NULL, EOPNOTSUPP); + xpt_release_ccb(start_ccb); + adaschedule(periph); + return; + } + start_ccb->ccb_h.ccb_state = ADA_CCB_TRIM; + start_ccb->ccb_h.flags |= CAM_UNLOCKED; + cam_iosched_submit_trim(softc->cam_iosched); + goto out; case BIO_FLUSH: cam_fill_ataio(ataio, 1, @@ -1742,6 +2002,7 @@ adadone(struct cam_periph *periph, union ccb *done_ccb) int error; cam_periph_lock(periph); + bp = (struct bio *)done_ccb->ccb_h.ccb_bp; if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { error = adaerror(done_ccb, 0, 0); if (error == ERESTART) { @@ -1755,12 +2016,25 @@ adadone(struct cam_periph *periph, union ccb *done_ccb) /*reduction*/0, /*timeout*/0, /*getcount_only*/0); + /* + * If we get an error on an NCQ DSM TRIM, fall back + * to a non-NCQ DSM TRIM forever. Please note that if + * CAN_NCQ_TRIM is set, CAN_TRIM is necessarily set too. + * However, for this one trim, we treat it as advisory + * and return success up the stack. + */ + if (state == ADA_CCB_TRIM && + error != 0 && + (softc->flags & ADA_FLAG_CAN_NCQ_TRIM) != 0) { + softc->flags &= ~ADA_FLAG_CAN_NCQ_TRIM; + error = 0; + adasetdeletemethod(softc); + } } else { if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) panic("REQ_CMP with QFRZN"); error = 0; } - bp = (struct bio *)done_ccb->ccb_h.ccb_bp; bp->bio_error = error; if (error != 0) { bp->bio_resid = bp->bio_bcount; @@ -1776,6 +2050,8 @@ adadone(struct cam_periph *periph, union ccb *done_ccb) softc->outstanding_cmds--; if (softc->outstanding_cmds == 0) softc->flags |= ADA_FLAG_WAS_OTAG; + + cam_iosched_bio_complete(softc->cam_iosched, bp, done_ccb); xpt_release_ccb(done_ccb); if (state == ADA_CCB_TRIM) { TAILQ_HEAD(, bio) queue; @@ -1793,7 +2069,7 @@ adadone(struct cam_periph *periph, union ccb *done_ccb) * daschedule again so that we don't stall if there are * no other I/Os pending apart from BIO_DELETEs. */ - softc->trim_running = 0; + cam_iosched_trim_done(softc->cam_iosched); adaschedule(periph); cam_periph_unlock(periph); while ((bp1 = TAILQ_FIRST(&queue)) != NULL) { @@ -1807,6 +2083,7 @@ adadone(struct cam_periph *periph, union ccb *done_ccb) biodone(bp1); } } else { + adaschedule(periph); cam_periph_unlock(periph); biodone(bp); } @@ -1898,6 +2175,29 @@ out: static int adaerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) { +#ifdef CAM_IO_STATS + struct ada_softc *softc; + struct cam_periph *periph; + + periph = xpt_path_periph(ccb->ccb_h.path); + softc = (struct ada_softc *)periph->softc; + + switch (ccb->ccb_h.status & CAM_STATUS_MASK) { + case CAM_CMD_TIMEOUT: + softc->timeouts++; + break; + case CAM_REQ_ABORTED: + case CAM_REQ_CMP_ERR: + case CAM_REQ_TERMIO: + case CAM_UNREC_HBA_ERROR: + case CAM_DATA_RUN_ERR: + case CAM_ATA_STATUS_ERROR: + softc->errors++; + break; + default: + break; + } +#endif return(cam_periph_error(ccb, cam_flags, sense_flags, NULL)); } diff --git a/sys/cam/cam.c b/sys/cam/cam.c index 1f627ef..5061dd6 100644 --- a/sys/cam/cam.c +++ b/sys/cam/cam.c @@ -412,7 +412,8 @@ cam_error_string(struct cam_device *device, union ccb *ccb, char *str, } if (proto_flags & CAM_EAF_PRINT_RESULT) { sbuf_cat(&sb, path_str); - ata_res_sbuf(&ccb->ataio, &sb); + sbuf_printf(&sb, "RES: "); + ata_res_sbuf(&ccb->ataio.res, &sb); sbuf_printf(&sb, "\n"); } diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h index 28415ed..c739aa6 100644 --- a/sys/cam/cam_ccb.h +++ b/sys/cam/cam_ccb.h @@ -581,6 +581,7 @@ typedef enum { } pi_tmflag; typedef enum { + PIM_NCQ_KLUDGE = 0x200, /* Supports the sata ncq trim kludge */ PIM_EXTLUNS = 0x100,/* 64bit extended LUNs supported */ PIM_SCANHILO = 0x80, /* Bus scans from high ID to low ID */ PIM_NOREMOVE = 0x40, /* Removeable devices not included in scan */ diff --git a/sys/cam/cam_iosched.c b/sys/cam/cam_iosched.c new file mode 100644 index 0000000..8e78663 --- /dev/null +++ b/sys/cam/cam_iosched.c @@ -0,0 +1,1603 @@ +/*- + * CAM IO Scheduler Interface + * + * Copyright (c) 2015 Netflix, Inc. + * 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, + * without modification, immediately at the beginning of the file. + * 2. 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 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$ + */ + +#include "opt_cam.h" +#include "opt_ddb.h" + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> + +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/bio.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/sysctl.h> + +#include <cam/cam.h> +#include <cam/cam_ccb.h> +#include <cam/cam_periph.h> +#include <cam/cam_xpt_periph.h> +#include <cam/cam_iosched.h> + +#include <ddb/ddb.h> + +static MALLOC_DEFINE(M_CAMSCHED, "CAM I/O Scheduler", + "CAM I/O Scheduler buffers"); + +/* + * Default I/O scheduler for FreeBSD. This implementation is just a thin-vineer + * over the bioq_* interface, with notions of separate calls for normal I/O and + * for trims. + */ + +#ifdef CAM_NETFLIX_IOSCHED + +SYSCTL_DECL(_kern_cam); +static int do_netflix_iosched = 1; +TUNABLE_INT("kern.cam.do_netflix_iosched", &do_netflix_iosched); +SYSCTL_INT(_kern_cam, OID_AUTO, do_netflix_iosched, CTLFLAG_RD, + &do_netflix_iosched, 1, + "Enable Netflix I/O scheduler optimizations."); + +static int alpha_bits = 9; +TUNABLE_INT("kern.cam.iosched_alpha_bits", &alpha_bits); +SYSCTL_INT(_kern_cam, OID_AUTO, iosched_alpha_bits, CTLFLAG_RW, + &alpha_bits, 1, + "Bits in EMA's alpha."); + + + +struct iop_stats; +struct cam_iosched_softc; + +int iosched_debug = 0; + +typedef enum { + none = 0, /* No limits */ + queue_depth, /* Limit how many ops we queue to SIM */ + iops, /* Limit # of IOPS to the drive */ + bandwidth, /* Limit bandwidth to the drive */ + limiter_max +} io_limiter; + +static const char *cam_iosched_limiter_names[] = + { "none", "queue_depth", "iops", "bandwidth" }; + +/* + * Called to initialize the bits of the iop_stats structure relevant to the + * limiter. Called just after the limiter is set. + */ +typedef int l_init_t(struct iop_stats *); + +/* + * Called every tick. + */ +typedef int l_tick_t(struct iop_stats *); + +/* + * Called to see if the limiter thinks this IOP can be allowed to + * proceed. If so, the limiter assumes that the while IOP proceeded + * and makes any accounting of it that's needed. + */ +typedef int l_iop_t(struct iop_stats *, struct bio *); + +/* + * Called when an I/O completes so the limiter can updates its + * accounting. Pending I/Os may complete in any order (even when + * sent to the hardware at the same time), so the limiter may not + * make any assumptions other than this I/O has completed. If it + * returns 1, then xpt_schedule() needs to be called again. + */ +typedef int l_iodone_t(struct iop_stats *, struct bio *); + +static l_iop_t cam_iosched_qd_iop; +static l_iop_t cam_iosched_qd_caniop; +static l_iodone_t cam_iosched_qd_iodone; + +static l_init_t cam_iosched_iops_init; +static l_tick_t cam_iosched_iops_tick; +static l_iop_t cam_iosched_iops_caniop; +static l_iop_t cam_iosched_iops_iop; + +static l_init_t cam_iosched_bw_init; +static l_tick_t cam_iosched_bw_tick; +static l_iop_t cam_iosched_bw_caniop; +static l_iop_t cam_iosched_bw_iop; + +struct limswitch +{ + l_init_t *l_init; + l_tick_t *l_tick; + l_iop_t *l_iop; + l_iop_t *l_caniop; + l_iodone_t *l_iodone; +} limsw[] = +{ + { /* none */ + .l_init = NULL, + .l_tick = NULL, + .l_iop = NULL, + .l_iodone= NULL, + }, + { /* queue_depth */ + .l_init = NULL, + .l_tick = NULL, + .l_caniop = cam_iosched_qd_caniop, + .l_iop = cam_iosched_qd_iop, + .l_iodone= cam_iosched_qd_iodone, + }, + { /* iops */ + .l_init = cam_iosched_iops_init, + .l_tick = cam_iosched_iops_tick, + .l_caniop = cam_iosched_iops_caniop, + .l_iop = cam_iosched_iops_iop, + .l_iodone= NULL, + }, + { /* bandwidth */ + .l_init = cam_iosched_bw_init, + .l_tick = cam_iosched_bw_tick, + .l_caniop = cam_iosched_bw_caniop, + .l_iop = cam_iosched_bw_iop, + .l_iodone= NULL, + }, +}; + +struct iop_stats +{ + /* + * sysctl state for this subnode. + */ + struct sysctl_ctx_list sysctl_ctx; + struct sysctl_oid *sysctl_tree; + + /* + * Information about the current rate limiters, if any + */ + io_limiter limiter; /* How are I/Os being limited */ + int min; /* Low range of limit */ + int max; /* High range of limit */ + int current; /* Current rate limiter */ + int l_value1; /* per-limiter scratch value 1. */ + int l_value2; /* per-limiter scratch value 2. */ + + + /* + * Debug information about counts of I/Os that have gone through the + * scheduler. + */ + int pending; /* I/Os pending in the hardware */ + int queued; /* number currently in the queue */ + int total; /* Total for all time -- wraps */ + int in; /* number queued all time -- wraps */ + int out; /* number completed all time -- wraps */ + + /* + * Statistics on different bits of the process. + */ + /* Exp Moving Average, alpha = 1 / (1 << alpha_bits) */ + sbintime_t ema; + sbintime_t emss; /* Exp Moving sum of the squares */ + sbintime_t sd; /* Last computed sd */ + + struct cam_iosched_softc *softc; +}; + + +typedef enum { + set_max = 0, /* current = max */ + read_latency, /* Steer read latency by throttling writes */ + cl_max /* Keep last */ +} control_type; + +static const char *cam_iosched_control_type_names[] = + { "set_max", "read_latency" }; + +struct control_loop +{ + /* + * sysctl state for this subnode. + */ + struct sysctl_ctx_list sysctl_ctx; + struct sysctl_oid *sysctl_tree; + + sbintime_t next_steer; /* Time of next steer */ + sbintime_t steer_interval; /* How often do we steer? */ + sbintime_t lolat; + sbintime_t hilat; + int alpha; + control_type type; /* What type of control? */ + int last_count; /* Last I/O count */ + + struct cam_iosched_softc *softc; +}; + +#endif + +struct cam_iosched_softc +{ + struct bio_queue_head bio_queue; + struct bio_queue_head trim_queue; + /* scheduler flags < 16, user flags >= 16 */ + uint32_t flags; + int sort_io_queue; +#ifdef CAM_NETFLIX_IOSCHED + int read_bias; /* Read bias setting */ + int current_read_bias; /* Current read bias state */ + int total_ticks; + + struct bio_queue_head write_queue; + struct iop_stats read_stats, write_stats, trim_stats; + struct sysctl_ctx_list sysctl_ctx; + struct sysctl_oid *sysctl_tree; + + int quanta; /* Number of quanta per second */ + struct callout ticker; /* Callout for our quota system */ + struct cam_periph *periph; /* cam periph associated with this device */ + uint32_t this_frac; /* Fraction of a second (1024ths) for this tick */ + sbintime_t last_time; /* Last time we ticked */ + struct control_loop cl; +#endif +}; + +#ifdef CAM_NETFLIX_IOSCHED +/* + * helper functions to call the limsw functions. + */ +static int +cam_iosched_limiter_init(struct iop_stats *ios) +{ + int lim = ios->limiter; + + /* maybe this should be a kassert */ + if (lim < none || lim >= limiter_max) + return EINVAL; + + if (limsw[lim].l_init) + return limsw[lim].l_init(ios); + + return 0; +} + +static int +cam_iosched_limiter_tick(struct iop_stats *ios) +{ + int lim = ios->limiter; + + /* maybe this should be a kassert */ + if (lim < none || lim >= limiter_max) + return EINVAL; + + if (limsw[lim].l_tick) + return limsw[lim].l_tick(ios); + + return 0; +} + +static int +cam_iosched_limiter_iop(struct iop_stats *ios, struct bio *bp) +{ + int lim = ios->limiter; + + /* maybe this should be a kassert */ + if (lim < none || lim >= limiter_max) + return EINVAL; + + if (limsw[lim].l_iop) + return limsw[lim].l_iop(ios, bp); + + return 0; +} + +static int +cam_iosched_limiter_caniop(struct iop_stats *ios, struct bio *bp) +{ + int lim = ios->limiter; + + /* maybe this should be a kassert */ + if (lim < none || lim >= limiter_max) + return EINVAL; + + if (limsw[lim].l_caniop) + return limsw[lim].l_caniop(ios, bp); + + return 0; +} + +static int +cam_iosched_limiter_iodone(struct iop_stats *ios, struct bio *bp) +{ + int lim = ios->limiter; + + /* maybe this should be a kassert */ + if (lim < none || lim >= limiter_max) + return 0; + + if (limsw[lim].l_iodone) + return limsw[lim].l_iodone(ios, bp); + + return 0; +} + +/* + * Functions to implement the different kinds of limiters + */ + +static int +cam_iosched_qd_iop(struct iop_stats *ios, struct bio *bp) +{ + + if (ios->current <= 0 || ios->pending < ios->current) + return 0; + + return EAGAIN; +} + +static int +cam_iosched_qd_caniop(struct iop_stats *ios, struct bio *bp) +{ + + if (ios->current <= 0 || ios->pending < ios->current) + return 0; + + return EAGAIN; +} + +static int +cam_iosched_qd_iodone(struct iop_stats *ios, struct bio *bp) +{ + + if (ios->current <= 0 || ios->pending != ios->current) + return 0; + + return 1; +} + +static int +cam_iosched_iops_init(struct iop_stats *ios) +{ + + ios->l_value1 = ios->current / ios->softc->quanta; + if (ios->l_value1 <= 0) + ios->l_value1 = 1; + + return 0; +} + +static int +cam_iosched_iops_tick(struct iop_stats *ios) +{ + + ios->l_value1 = (int)((ios->current * (uint64_t)ios->softc->this_frac) >> 16); + if (ios->l_value1 <= 0) + ios->l_value1 = 1; + + return 0; +} + +static int +cam_iosched_iops_caniop(struct iop_stats *ios, struct bio *bp) +{ + + /* + * So if we have any more IOPs left, allow it, + * otherwise wait. + */ + if (ios->l_value1 <= 0) + return EAGAIN; + return 0; +} + +static int +cam_iosched_iops_iop(struct iop_stats *ios, struct bio *bp) +{ + int rv; + + rv = cam_iosched_limiter_caniop(ios, bp); + if (rv == 0) + ios->l_value1--; + + return rv; +} + +static int +cam_iosched_bw_init(struct iop_stats *ios) +{ + + /* ios->current is in kB/s, so scale to bytes */ + ios->l_value1 = ios->current * 1000 / ios->softc->quanta; + + return 0; +} + +static int +cam_iosched_bw_tick(struct iop_stats *ios) +{ + int bw; + + /* + * If we're in the hole for available quota from + * the last time, then add the quantum for this. + * If we have any left over from last quantum, + * then too bad, that's lost. Also, ios->current + * is in kB/s, so scale. + * + * We also allow up to 4 quanta of credits to + * accumulate to deal with burstiness. 4 is extremely + * arbitrary. + */ + bw = (int)((ios->current * 1000ull * (uint64_t)ios->softc->this_frac) >> 16); + if (ios->l_value1 < bw * 4) + ios->l_value1 += bw; + + return 0; +} + +static int +cam_iosched_bw_caniop(struct iop_stats *ios, struct bio *bp) +{ + /* + * So if we have any more bw quota left, allow it, + * otherwise wait. Not, we'll go negative and that's + * OK. We'll just get a lettle less next quota. + * + * Note on going negative: that allows us to process + * requests in order better, since we won't allow + * shorter reads to get around the long one that we + * don't have the quota to do just yet. It also prevents + * starvation by being a little more permissive about + * what we let through this quantum (to prevent the + * starvation), at the cost of getting a little less + * next quantum. + */ + if (ios->l_value1 <= 0) + return EAGAIN; + + + return 0; +} + +static int +cam_iosched_bw_iop(struct iop_stats *ios, struct bio *bp) +{ + int rv; + + rv = cam_iosched_limiter_caniop(ios, bp); + if (rv == 0) + ios->l_value1 -= bp->bio_length; + + return rv; +} + +static void cam_iosched_cl_maybe_steer(struct control_loop *clp); + +static void +cam_iosched_ticker(void *arg) +{ + struct cam_iosched_softc *isc = arg; + sbintime_t now, delta; + + callout_reset(&isc->ticker, hz / isc->quanta - 1, cam_iosched_ticker, isc); + + now = sbinuptime(); + delta = now - isc->last_time; + isc->this_frac = (uint32_t)delta >> 16; /* Note: discards seconds -- should be 0 harmless if not */ + isc->last_time = now; + + cam_iosched_cl_maybe_steer(&isc->cl); + + cam_iosched_limiter_tick(&isc->read_stats); + cam_iosched_limiter_tick(&isc->write_stats); + cam_iosched_limiter_tick(&isc->trim_stats); + + cam_iosched_schedule(isc, isc->periph); + + isc->total_ticks++; +} + + +static void +cam_iosched_cl_init(struct control_loop *clp, struct cam_iosched_softc *isc) +{ + + clp->next_steer = sbinuptime(); + clp->softc = isc; + clp->steer_interval = SBT_1S * 5; /* Let's start out steering every 5s */ + clp->lolat = 5 * SBT_1MS; + clp->hilat = 15 * SBT_1MS; + clp->alpha = 20; /* Alpha == gain. 20 = .2 */ + clp->type = set_max; +} + +static void +cam_iosched_cl_maybe_steer(struct control_loop *clp) +{ + struct cam_iosched_softc *isc; + sbintime_t now, lat; + int old; + + isc = clp->softc; + now = isc->last_time; + if (now < clp->next_steer) + return; + + clp->next_steer = now + clp->steer_interval; + switch (clp->type) { + case set_max: + if (isc->write_stats.current != isc->write_stats.max) + printf("Steering write from %d kBps to %d kBps\n", + isc->write_stats.current, isc->write_stats.max); + isc->read_stats.current = isc->read_stats.max; + isc->write_stats.current = isc->write_stats.max; + isc->trim_stats.current = isc->trim_stats.max; + break; + case read_latency: + old = isc->write_stats.current; + lat = isc->read_stats.ema; + /* + * Simple PLL-like engine. Since we're steering to a range for + * the SP (set point) that makes things a little more + * complicated. In addition, we're not directly controlling our + * PV (process variable), the read latency, but instead are + * manipulating the write bandwidth limit for our MV + * (manipulation variable), analysis of this code gets a bit + * messy. Also, the MV is a very noisy control surface for read + * latency since it is affected by many hidden processes inside + * the device which change how responsive read latency will be + * in reaction to changes in write bandwidth. Unlike the classic + * boiler control PLL. this may result in over-steering while + * the SSD takes its time to react to the new, lower load. This + * is why we use a relatively low alpha of between .1 and .25 to + * compensate for this effect. At .1, it takes ~22 steering + * intervals to back off by a factor of 10. At .2 it only takes + * ~10. At .25 it only takes ~8. However some preliminary data + * from the SSD drives suggests a reasponse time in 10's of + * seconds before latency drops regardless of the new write + * rate. Careful observation will be reqiured to tune this + * effectively. + * + * Also, when there's no read traffic, we jack up the write + * limit too regardless of the last read latency. 10 is + * somewhat arbitrary. + */ + if (lat < clp->lolat || isc->read_stats.total - clp->last_count < 10) + isc->write_stats.current = isc->write_stats.current * + (100 + clp->alpha) / 100; /* Scale up */ + else if (lat > clp->hilat) + isc->write_stats.current = isc->write_stats.current * + (100 - clp->alpha) / 100; /* Scale down */ + clp->last_count = isc->read_stats.total; + + /* + * Even if we don't steer, per se, enforce the min/max limits as + * those may have changed. + */ + if (isc->write_stats.current < isc->write_stats.min) + isc->write_stats.current = isc->write_stats.min; + if (isc->write_stats.current > isc->write_stats.max) + isc->write_stats.current = isc->write_stats.max; + if (old != isc->write_stats.current) + printf("Steering write from %d kBps to %d kBps due to latency of %ldus\n", + old, isc->write_stats.current, + ((uint64_t)1000000 * (uint32_t)lat) >> 32); + break; + case cl_max: + break; + } +} +#endif + + /* Trim or similar currently pending completion */ +#define CAM_IOSCHED_FLAG_TRIM_ACTIVE (1ul << 0) + /* Callout active, and needs to be torn down */ +#define CAM_IOSCHED_FLAG_CALLOUT_ACTIVE (1ul << 1) + + /* Periph drivers set these flags to indicate work */ +#define CAM_IOSCHED_FLAG_WORK_FLAGS ((0xffffu) << 16) + +#ifdef CAM_NETFLIX_IOSCHED +static void +cam_iosched_io_metric_update(struct cam_iosched_softc *isc, + sbintime_t sim_latency, int cmd, size_t size); +#endif + +static inline int +cam_iosched_has_flagged_work(struct cam_iosched_softc *isc) +{ + return !!(isc->flags & CAM_IOSCHED_FLAG_WORK_FLAGS); +} + +static inline int +cam_iosched_has_io(struct cam_iosched_softc *isc) +{ +#ifdef CAM_NETFLIX_IOSCHED + if (do_netflix_iosched) { + struct bio *rbp = bioq_first(&isc->bio_queue); + struct bio *wbp = bioq_first(&isc->write_queue); + int can_write = wbp != NULL && + cam_iosched_limiter_caniop(&isc->write_stats, wbp) == 0; + int can_read = rbp != NULL && + cam_iosched_limiter_caniop(&isc->read_stats, rbp) == 0; + if (iosched_debug > 2) { + printf("can write %d: pending_writes %d max_writes %d\n", can_write, isc->write_stats.pending, isc->write_stats.max); + printf("can read %d: read_stats.pending %d max_reads %d\n", can_read, isc->read_stats.pending, isc->read_stats.max); + printf("Queued reads %d writes %d\n", isc->read_stats.queued, isc->write_stats.queued); + } + return can_read || can_write; + } +#endif + return bioq_first(&isc->bio_queue) != NULL; +} + +static inline int +cam_iosched_has_more_trim(struct cam_iosched_softc *isc) +{ + return !(isc->flags & CAM_IOSCHED_FLAG_TRIM_ACTIVE) && + bioq_first(&isc->trim_queue); +} + +#define cam_iosched_sort_queue(isc) ((isc)->sort_io_queue >= 0 ? \ + (isc)->sort_io_queue : cam_sort_io_queues) + + +static inline int +cam_iosched_has_work(struct cam_iosched_softc *isc) +{ +#ifdef CAM_NETFLIX_IOSCHED + if (iosched_debug > 2) + printf("has work: %d %d %d\n", cam_iosched_has_io(isc), + cam_iosched_has_more_trim(isc), + cam_iosched_has_flagged_work(isc)); +#endif + + return cam_iosched_has_io(isc) || + cam_iosched_has_more_trim(isc) || + cam_iosched_has_flagged_work(isc); +} + +#ifdef CAM_NETFLIX_IOSCHED +static void +cam_iosched_iop_stats_init(struct cam_iosched_softc *isc, struct iop_stats *ios) +{ + + ios->limiter = none; + cam_iosched_limiter_init(ios); + ios->in = 0; + ios->max = 300000; + ios->min = 1; + ios->out = 0; + ios->pending = 0; + ios->queued = 0; + ios->total = 0; + ios->ema = 0; + ios->emss = 0; + ios->sd = 0; + ios->softc = isc; +} + +static int +cam_iosched_limiter_sysctl(SYSCTL_HANDLER_ARGS) +{ + char buf[16]; + struct iop_stats *ios; + struct cam_iosched_softc *isc; + int value, i, error, cantick; + const char *p; + + ios = arg1; + isc = ios->softc; + value = ios->limiter; + if (value < none || value >= limiter_max) + p = "UNKNOWN"; + else + p = cam_iosched_limiter_names[value]; + + strlcpy(buf, p, sizeof(buf)); + error = sysctl_handle_string(oidp, buf, sizeof(buf), req); + if (error != 0 || req->newptr == NULL) + return error; + + cam_periph_lock(isc->periph); + + for (i = none; i < limiter_max; i++) { + if (strcmp(buf, cam_iosched_limiter_names[i]) != 0) + continue; + ios->limiter = i; + error = cam_iosched_limiter_init(ios); + if (error != 0) { + ios->limiter = value; + cam_periph_unlock(isc->periph); + return error; + } + cantick = !!limsw[isc->read_stats.limiter].l_tick + + !!limsw[isc->write_stats.limiter].l_tick + + !!limsw[isc->trim_stats.limiter].l_tick + + 1; /* Control loop requires it */ + if (isc->flags & CAM_IOSCHED_FLAG_CALLOUT_ACTIVE) { + if (cantick == 0) { + callout_stop(&isc->ticker); + isc->flags &= ~CAM_IOSCHED_FLAG_CALLOUT_ACTIVE; + } + } else { + if (cantick != 0) { + callout_reset(&isc->ticker, hz / isc->quanta - 1, cam_iosched_ticker, isc); + isc->flags |= CAM_IOSCHED_FLAG_CALLOUT_ACTIVE; + } + } + + cam_periph_unlock(isc->periph); + return 0; + } + + cam_periph_unlock(isc->periph); + return EINVAL; +} + +static int +cam_iosched_control_type_sysctl(SYSCTL_HANDLER_ARGS) +{ + char buf[16]; + struct control_loop *clp; + struct cam_iosched_softc *isc; + int value, i, error; + const char *p; + + clp = arg1; + isc = clp->softc; + value = clp->type; + if (value < none || value >= cl_max) + p = "UNKNOWN"; + else + p = cam_iosched_control_type_names[value]; + + strlcpy(buf, p, sizeof(buf)); + error = sysctl_handle_string(oidp, buf, sizeof(buf), req); + if (error != 0 || req->newptr == NULL) + return error; + + for (i = set_max; i < cl_max; i++) { + if (strcmp(buf, cam_iosched_control_type_names[i]) != 0) + continue; + cam_periph_lock(isc->periph); + clp->type = i; + cam_periph_unlock(isc->periph); + return 0; + } + + return EINVAL; +} + +static int +cam_iosched_sbintime_sysctl(SYSCTL_HANDLER_ARGS) +{ + char buf[16]; + sbintime_t value; + int error; + uint64_t us; + + value = *(sbintime_t *)arg1; + us = (uint64_t)value / SBT_1US; + snprintf(buf, sizeof(buf), "%ju", (intmax_t)us); + error = sysctl_handle_string(oidp, buf, sizeof(buf), req); + if (error != 0 || req->newptr == NULL) + return error; + us = strtoul(buf, NULL, 10); + if (us == 0) + return EINVAL; + *(sbintime_t *)arg1 = us * SBT_1US; + return 0; +} + +static void +cam_iosched_iop_stats_sysctl_init(struct cam_iosched_softc *isc, struct iop_stats *ios, char *name) +{ + struct sysctl_oid_list *n; + struct sysctl_ctx_list *ctx; + + ios->sysctl_tree = SYSCTL_ADD_NODE(&isc->sysctl_ctx, + SYSCTL_CHILDREN(isc->sysctl_tree), OID_AUTO, name, + CTLFLAG_RD, 0, name); + n = SYSCTL_CHILDREN(ios->sysctl_tree); + ctx = &ios->sysctl_ctx; + + SYSCTL_ADD_UQUAD(ctx, n, + OID_AUTO, "ema", CTLFLAG_RD, + &ios->ema, + "Fast Exponentially Weighted Moving Average"); + SYSCTL_ADD_UQUAD(ctx, n, + OID_AUTO, "emss", CTLFLAG_RD, + &ios->emss, + "Fast Exponentially Weighted Moving Sum of Squares (maybe wrong)"); + SYSCTL_ADD_UQUAD(ctx, n, + OID_AUTO, "sd", CTLFLAG_RD, + &ios->sd, + "Estimated SD for fast ema (may be wrong)"); + + SYSCTL_ADD_INT(ctx, n, + OID_AUTO, "pending", CTLFLAG_RD, + &ios->pending, 0, + "Instantaneous # of pending transactions"); + SYSCTL_ADD_INT(ctx, n, + OID_AUTO, "count", CTLFLAG_RD, + &ios->total, 0, + "# of transactions submitted to hardware"); + SYSCTL_ADD_INT(ctx, n, + OID_AUTO, "queued", CTLFLAG_RD, + &ios->queued, 0, + "# of transactions in the queue"); + SYSCTL_ADD_INT(ctx, n, + OID_AUTO, "in", CTLFLAG_RD, + &ios->in, 0, + "# of transactions queued to driver"); + SYSCTL_ADD_INT(ctx, n, + OID_AUTO, "out", CTLFLAG_RD, + &ios->out, 0, + "# of transactions completed"); + + SYSCTL_ADD_PROC(ctx, n, + OID_AUTO, "limiter", CTLTYPE_STRING | CTLFLAG_RW, + ios, 0, cam_iosched_limiter_sysctl, "A", + "Current limiting type."); + SYSCTL_ADD_INT(ctx, n, + OID_AUTO, "min", CTLFLAG_RW, + &ios->min, 0, + "min resource"); + SYSCTL_ADD_INT(ctx, n, + OID_AUTO, "max", CTLFLAG_RW, + &ios->max, 0, + "max resource"); + SYSCTL_ADD_INT(ctx, n, + OID_AUTO, "current", CTLFLAG_RW, + &ios->current, 0, + "current resource"); + +} + +static void +cam_iosched_iop_stats_fini(struct iop_stats *ios) +{ + if (ios->sysctl_tree) + if (sysctl_ctx_free(&ios->sysctl_ctx) != 0) + printf("can't remove iosched sysctl stats context\n"); +} + +static void +cam_iosched_cl_sysctl_init(struct cam_iosched_softc *isc) +{ + struct sysctl_oid_list *n; + struct sysctl_ctx_list *ctx; + struct control_loop *clp; + + clp = &isc->cl; + clp->sysctl_tree = SYSCTL_ADD_NODE(&isc->sysctl_ctx, + SYSCTL_CHILDREN(isc->sysctl_tree), OID_AUTO, "control", + CTLFLAG_RD, 0, "Control loop info"); + n = SYSCTL_CHILDREN(clp->sysctl_tree); + ctx = &clp->sysctl_ctx; + + SYSCTL_ADD_PROC(ctx, n, + OID_AUTO, "type", CTLTYPE_STRING | CTLFLAG_RW, + clp, 0, cam_iosched_control_type_sysctl, "A", + "Control loop algorithm"); + SYSCTL_ADD_PROC(ctx, n, + OID_AUTO, "steer_interval", CTLTYPE_STRING | CTLFLAG_RW, + &clp->steer_interval, 0, cam_iosched_sbintime_sysctl, "A", + "How often to steer (in us)"); + SYSCTL_ADD_PROC(ctx, n, + OID_AUTO, "lolat", CTLTYPE_STRING | CTLFLAG_RW, + &clp->lolat, 0, cam_iosched_sbintime_sysctl, "A", + "Low water mark for Latency (in us)"); + SYSCTL_ADD_PROC(ctx, n, + OID_AUTO, "hilat", CTLTYPE_STRING | CTLFLAG_RW, + &clp->hilat, 0, cam_iosched_sbintime_sysctl, "A", + "Hi water mark for Latency (in us)"); + SYSCTL_ADD_INT(ctx, n, + OID_AUTO, "alpha", CTLFLAG_RW, + &clp->alpha, 0, + "Alpha for PLL (x100) aka gain"); +} + +static void +cam_iosched_cl_sysctl_fini(struct control_loop *clp) +{ + if (clp->sysctl_tree) + if (sysctl_ctx_free(&clp->sysctl_ctx) != 0) + printf("can't remove iosched sysctl control loop context\n"); +} +#endif + +/* + * Allocate the iosched structure. This also insulates callers from knowing + * sizeof struct cam_iosched_softc. + */ +int +cam_iosched_init(struct cam_iosched_softc **iscp, struct cam_periph *periph) +{ + + *iscp = malloc(sizeof(**iscp), M_CAMSCHED, M_NOWAIT | M_ZERO); + if (*iscp == NULL) + return ENOMEM; +#ifdef CAM_NETFLIX_IOSCHED + if (iosched_debug) + printf("CAM IOSCHEDULER Allocating entry at %p\n", *iscp); +#endif + (*iscp)->sort_io_queue = -1; + bioq_init(&(*iscp)->bio_queue); + bioq_init(&(*iscp)->trim_queue); +#ifdef CAM_NETFLIX_IOSCHED + if (do_netflix_iosched) { + bioq_init(&(*iscp)->write_queue); + (*iscp)->read_bias = 100; + (*iscp)->current_read_bias = 100; + (*iscp)->quanta = 200; + cam_iosched_iop_stats_init(*iscp, &(*iscp)->read_stats); + cam_iosched_iop_stats_init(*iscp, &(*iscp)->write_stats); + cam_iosched_iop_stats_init(*iscp, &(*iscp)->trim_stats); + (*iscp)->trim_stats.max = 1; /* Trims are special: one at a time for now */ + (*iscp)->last_time = sbinuptime(); + callout_init_mtx(&(*iscp)->ticker, cam_periph_mtx(periph), 0); + (*iscp)->periph = periph; + cam_iosched_cl_init(&(*iscp)->cl, *iscp); + callout_reset(&(*iscp)->ticker, hz / (*iscp)->quanta - 1, cam_iosched_ticker, *iscp); + (*iscp)->flags |= CAM_IOSCHED_FLAG_CALLOUT_ACTIVE; + } +#endif + + return 0; +} + +/* + * Reclaim all used resources. This assumes that other folks have + * drained the requests in the hardware. Maybe an unwise assumption. + */ +void +cam_iosched_fini(struct cam_iosched_softc *isc) +{ + if (isc) { + cam_iosched_flush(isc, NULL, ENXIO); +#ifdef CAM_NETFLIX_IOSCHED + cam_iosched_iop_stats_fini(&isc->read_stats); + cam_iosched_iop_stats_fini(&isc->write_stats); + cam_iosched_iop_stats_fini(&isc->trim_stats); + cam_iosched_cl_sysctl_fini(&isc->cl); + if (isc->sysctl_tree) + if (sysctl_ctx_free(&isc->sysctl_ctx) != 0) + printf("can't remove iosched sysctl stats context\n"); + if (isc->flags & CAM_IOSCHED_FLAG_CALLOUT_ACTIVE) { + callout_drain(&isc->ticker); + isc->flags &= ~ CAM_IOSCHED_FLAG_CALLOUT_ACTIVE; + } + +#endif + free(isc, M_CAMSCHED); + } +} + +/* + * After we're sure we're attaching a device, go ahead and add + * hooks for any sysctl we may wish to honor. + */ +void cam_iosched_sysctl_init(struct cam_iosched_softc *isc, + struct sysctl_ctx_list *ctx, struct sysctl_oid *node) +{ +#ifdef CAM_NETFLIX_IOSCHED + struct sysctl_oid_list *n; +#endif + + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(node), + OID_AUTO, "sort_io_queue", CTLFLAG_RW | CTLFLAG_MPSAFE, + &isc->sort_io_queue, 0, + "Sort IO queue to try and optimise disk access patterns"); + +#ifdef CAM_NETFLIX_IOSCHED + if (!do_netflix_iosched) + return; + + isc->sysctl_tree = SYSCTL_ADD_NODE(&isc->sysctl_ctx, + SYSCTL_CHILDREN(node), OID_AUTO, "iosched", + CTLFLAG_RD, 0, "I/O scheduler statistics"); + n = SYSCTL_CHILDREN(isc->sysctl_tree); + ctx = &isc->sysctl_ctx; + + cam_iosched_iop_stats_sysctl_init(isc, &isc->read_stats, "read"); + cam_iosched_iop_stats_sysctl_init(isc, &isc->write_stats, "write"); + cam_iosched_iop_stats_sysctl_init(isc, &isc->trim_stats, "trim"); + cam_iosched_cl_sysctl_init(isc); + + SYSCTL_ADD_INT(ctx, n, + OID_AUTO, "read_bias", CTLFLAG_RW, + &isc->read_bias, 100, + "How biased towards read should we be independent of limits"); + + SYSCTL_ADD_INT(ctx, n, + OID_AUTO, "quanta", CTLFLAG_RW, + &isc->quanta, 200, + "How many quanta per second do we slice the I/O up into"); + + SYSCTL_ADD_INT(ctx, n, + OID_AUTO, "total_ticks", CTLFLAG_RD, + &isc->total_ticks, 0, + "Total number of ticks we've done"); +#endif +} + +/* + * Flush outstanding I/O. Consumers of this library don't know all the + * queues we may keep, so this allows all I/O to be flushed in one + * convenient call. + */ +void +cam_iosched_flush(struct cam_iosched_softc *isc, struct devstat *stp, int err) +{ + bioq_flush(&isc->bio_queue, stp, err); + bioq_flush(&isc->trim_queue, stp, err); +#ifdef CAM_NETFLIX_IOSCHED + if (do_netflix_iosched) + bioq_flush(&isc->write_queue, stp, err); +#endif +} + +#ifdef CAM_NETFLIX_IOSCHED +static struct bio * +cam_iosched_get_write(struct cam_iosched_softc *isc) +{ + struct bio *bp; + + /* + * We control the write rate by controlling how many requests we send + * down to the drive at any one time. Fewer requests limits the + * effects of both starvation when the requests take a while and write + * amplification when each request is causing more than one write to + * the NAND media. Limiting the queue depth like this will also limit + * the write throughput and give and reads that want to compete to + * compete unfairly. + */ + bp = bioq_first(&isc->write_queue); + if (bp == NULL) { + if (iosched_debug > 3) + printf("No writes present in write_queue\n"); + return NULL; + } + + /* + * If pending read, prefer that based on current read bias + * setting. + */ + if (bioq_first(&isc->bio_queue) && isc->current_read_bias) { + if (iosched_debug) + printf("Reads present and current_read_bias is %d queued writes %d queued reads %d\n", isc->current_read_bias, isc->write_stats.queued, isc->read_stats.queued); + isc->current_read_bias--; + return NULL; + } + + /* + * See if our current limiter allows this I/O. + */ + if (cam_iosched_limiter_iop(&isc->write_stats, bp) != 0) { + if (iosched_debug) + printf("Can't write because limiter says no.\n"); + return NULL; + } + + /* + * Let's do this: We've passed all the gates and we're a go + * to schedule the I/O in the SIM. + */ + isc->current_read_bias = isc->read_bias; + bioq_remove(&isc->write_queue, bp); + if (bp->bio_cmd == BIO_WRITE) { + isc->write_stats.queued--; + isc->write_stats.total++; + isc->write_stats.pending++; + } + if (iosched_debug > 9) + printf("HWQ : %p %#x\n", bp, bp->bio_cmd); + return bp; +} +#endif + +/* + * Put back a trim that you weren't able to actually schedule this time. + */ +void +cam_iosched_put_back_trim(struct cam_iosched_softc *isc, struct bio *bp) +{ + bioq_insert_head(&isc->trim_queue, bp); +#ifdef CAM_NETFLIX_IOSCHED + isc->trim_stats.queued++; + isc->trim_stats.total--; /* since we put it back, don't double count */ + isc->trim_stats.pending--; +#endif +} + +/* + * gets the next trim from the trim queue. + * + * Assumes we're called with the periph lock held. It removes this + * trim from the queue and the device must explicitly reinstert it + * should the need arise. + */ +struct bio * +cam_iosched_next_trim(struct cam_iosched_softc *isc) +{ + struct bio *bp; + + bp = bioq_first(&isc->trim_queue); + if (bp == NULL) + return NULL; + bioq_remove(&isc->trim_queue, bp); +#ifdef CAM_NETFLIX_IOSCHED + isc->trim_stats.queued--; + isc->trim_stats.total++; + isc->trim_stats.pending++; +#endif + return bp; +} + +/* + * gets the an available trim from the trim queue, if there's no trim + * already pending. It removes this trim from the queue and the device + * must explicitly reinstert it should the need arise. + * + * Assumes we're called with the periph lock held. + */ +struct bio * +cam_iosched_get_trim(struct cam_iosched_softc *isc) +{ + + if (!cam_iosched_has_more_trim(isc)) + return NULL; + + return cam_iosched_next_trim(isc); +} + +/* + * Determine what the next bit of work to do is for the periph. The + * default implementation looks to see if we have trims to do, but no + * trims outstanding. If so, we do that. Otherwise we see if we have + * other work. If we do, then we do that. Otherwise why were we called? + */ +struct bio * +cam_iosched_next_bio(struct cam_iosched_softc *isc) +{ + struct bio *bp; + + /* + * See if we have a trim that can be scheduled. We can only send one + * at a time down, so this takes that into account. + * + * XXX newer TRIM commands are queueable. Revisit this when we + * implement them. + */ + if ((bp = cam_iosched_get_trim(isc)) != NULL) + return bp; + +#ifdef CAM_NETFLIX_IOSCHED + /* + * See if we have any pending writes, and room in the queue for them, + * and if so, those are next. + */ + if (do_netflix_iosched) { + if ((bp = cam_iosched_get_write(isc)) != NULL) + return bp; + } +#endif + + /* + * next, see if there's other, normal I/O waiting. If so return that. + */ + if ((bp = bioq_first(&isc->bio_queue)) == NULL) + return NULL; + +#ifdef CAM_NETFLIX_IOSCHED + /* + * For the netflix scheduler, bio_queue is only for reads, so enforce + * the limits here. Enforce only for reads. + */ + if (do_netflix_iosched) { + if (bp->bio_cmd == BIO_READ && + cam_iosched_limiter_iop(&isc->read_stats, bp) != 0) + return NULL; + } +#endif + bioq_remove(&isc->bio_queue, bp); +#ifdef CAM_NETFLIX_IOSCHED + if (do_netflix_iosched) { + if (bp->bio_cmd == BIO_READ) { + isc->read_stats.queued--; + isc->read_stats.total++; + isc->read_stats.pending++; + } else + printf("Found bio_cmd = %#x\n", bp->bio_cmd); + } + if (iosched_debug > 9) + printf("HWQ : %p %#x\n", bp, bp->bio_cmd); +#endif + return bp; +} + +/* + * Driver has been given some work to do by the block layer. Tell the + * scheduler about it and have it queue the work up. The scheduler module + * will then return the currently most useful bit of work later, possibly + * deferring work for various reasons. + */ +void +cam_iosched_queue_work(struct cam_iosched_softc *isc, struct bio *bp) +{ + + /* + * Put all trims on the trim queue sorted, since we know + * that the collapsing code requires this. Otherwise put + * the work on the bio queue. + */ + if (bp->bio_cmd == BIO_DELETE) { + bioq_disksort(&isc->trim_queue, bp); +#ifdef CAM_NETFLIX_IOSCHED + isc->trim_stats.in++; + isc->trim_stats.queued++; +#endif + } +#ifdef CAM_NETFLIX_IOSCHED + else if (do_netflix_iosched && + (bp->bio_cmd == BIO_WRITE || bp->bio_cmd == BIO_FLUSH)) { + if (cam_iosched_sort_queue(isc)) + bioq_disksort(&isc->write_queue, bp); + else + bioq_insert_tail(&isc->write_queue, bp); + if (iosched_debug > 9) + printf("Qw : %p %#x\n", bp, bp->bio_cmd); + if (bp->bio_cmd == BIO_WRITE) { + isc->write_stats.in++; + isc->write_stats.queued++; + } + } +#endif + else { + if (cam_iosched_sort_queue(isc)) + bioq_disksort(&isc->bio_queue, bp); + else + bioq_insert_tail(&isc->bio_queue, bp); +#ifdef CAM_NETFLIX_IOSCHED + if (iosched_debug > 9) + printf("Qr : %p %#x\n", bp, bp->bio_cmd); + if (bp->bio_cmd == BIO_READ) { + isc->read_stats.in++; + isc->read_stats.queued++; + } else if (bp->bio_cmd == BIO_WRITE) { + isc->write_stats.in++; + isc->write_stats.queued++; + } +#endif + } +} + +/* + * If we have work, get it scheduled. Called with the periph lock held. + */ +void +cam_iosched_schedule(struct cam_iosched_softc *isc, struct cam_periph *periph) +{ + + if (cam_iosched_has_work(isc)) + xpt_schedule(periph, CAM_PRIORITY_NORMAL); +} + +/* + * Complete a trim request + */ +void +cam_iosched_trim_done(struct cam_iosched_softc *isc) +{ + + isc->flags &= ~CAM_IOSCHED_FLAG_TRIM_ACTIVE; +} + +/* + * Complete a bio. Called before we release the ccb with xpt_release_ccb so we + * might use notes in the ccb for statistics. + */ +int +cam_iosched_bio_complete(struct cam_iosched_softc *isc, struct bio *bp, + union ccb *done_ccb) +{ + int retval = 0; +#ifdef CAM_NETFLIX_IOSCHED + if (!do_netflix_iosched) + return retval; + + if (iosched_debug > 10) + printf("done: %p %#x\n", bp, bp->bio_cmd); + if (bp->bio_cmd == BIO_WRITE) { + retval = cam_iosched_limiter_iodone(&isc->write_stats, bp); + isc->write_stats.out++; + isc->write_stats.pending--; + } else if (bp->bio_cmd == BIO_READ) { + retval = cam_iosched_limiter_iodone(&isc->read_stats, bp); + isc->read_stats.out++; + isc->read_stats.pending--; + } else if (bp->bio_cmd == BIO_DELETE) { + isc->trim_stats.out++; + isc->trim_stats.pending--; + } else if (bp->bio_cmd != BIO_FLUSH) { + if (iosched_debug) + printf("Completing command with bio_cmd == %#x\n", bp->bio_cmd); + } + + if (!(bp->bio_flags & BIO_ERROR)) + cam_iosched_io_metric_update(isc, done_ccb->ccb_h.qos.sim_data, + bp->bio_cmd, bp->bio_bcount); +#endif + return retval; +} + +/* + * Tell the io scheduler that you've pushed a trim down into the sim. + * xxx better place for this? + */ +void +cam_iosched_submit_trim(struct cam_iosched_softc *isc) +{ + + isc->flags |= CAM_IOSCHED_FLAG_TRIM_ACTIVE; +} + +/* + * Change the sorting policy hint for I/O transactions for this device. + */ +void +cam_iosched_set_sort_queue(struct cam_iosched_softc *isc, int val) +{ + + isc->sort_io_queue = val; +} + +int +cam_iosched_has_work_flags(struct cam_iosched_softc *isc, uint32_t flags) +{ + return isc->flags & flags; +} + +void +cam_iosched_set_work_flags(struct cam_iosched_softc *isc, uint32_t flags) +{ + isc->flags |= flags; +} + +void +cam_iosched_clr_work_flags(struct cam_iosched_softc *isc, uint32_t flags) +{ + isc->flags &= ~flags; +} + +#ifdef CAM_NETFLIX_IOSCHED +/* + * After the method presented in Jack Crenshaw's 1998 article "Integer + * Suqare Roots," reprinted at + * http://www.embedded.com/electronics-blogs/programmer-s-toolbox/4219659/Integer-Square-Roots + * and well worth the read. Briefly, we find the power of 4 that's the + * largest smaller than val. We then check each smaller power of 4 to + * see if val is still bigger. The right shifts at each step divide + * the result by 2 which after successive application winds up + * accumulating the right answer. It could also have been accumulated + * using a separate root counter, but this code is smaller and faster + * than that method. This method is also integer size invariant. + * It returns floor(sqrt((float)val)), or the larget integer less than + * or equal to the square root. + */ +static uint64_t +isqrt64(uint64_t val) +{ + uint64_t res = 0; + uint64_t bit = 1ULL << (sizeof(uint64_t) * NBBY - 2); + + /* + * Find the largest power of 4 smaller than val. + */ + while (bit > val) + bit >>= 2; + + /* + * Accumulate the answer, one bit at a time (we keep moving + * them over since 2 is the square root of 4 and we test + * powers of 4). We accumulate where we find the bit, but + * the successive shifts land the bit in the right place + * by the end. + */ + while (bit != 0) { + if (val >= res + bit) { + val -= res + bit; + res = (res >> 1) + bit; + } else + res >>= 1; + bit >>= 2; + } + + return res; +} + +/* + * a and b are 32.32 fixed point stored in a 64-bit word. + * Let al and bl be the .32 part of a and b. + * Let ah and bh be the 32 part of a and b. + * R is the radix and is 1 << 32 + * + * a * b + * (ah + al / R) * (bh + bl / R) + * ah * bh + (al * bh + ah * bl) / R + al * bl / R^2 + * + * After multiplicaiton, we have to renormalize by multiply by + * R, so we wind up with + * ah * bh * R + al * bh + ah * bl + al * bl / R + * which turns out to be a very nice way to compute this value + * so long as ah and bh are < 65536 there's no loss of high bits + * and the low order bits are below the threshold of caring for + * this application. + */ +static uint64_t +mul(uint64_t a, uint64_t b) +{ + uint64_t al, ah, bl, bh; + al = a & 0xffffffff; + ah = a >> 32; + bl = b & 0xffffffff; + bh = b >> 32; + return ((ah * bh) << 32) + al * bh + ah * bl + ((al * bl) >> 32); +} + +static void +cam_iosched_update(struct iop_stats *iop, sbintime_t sim_latency) +{ + sbintime_t y, yy; + uint64_t var; + + /* + * Classic expoentially decaying average with a tiny alpha + * (2 ^ -alpha_bits). For more info see the NIST statistical + * handbook. + * + * ema_t = y_t * alpha + ema_t-1 * (1 - alpha) + * alpha = 1 / (1 << alpha_bits) + * + * Since alpha is a power of two, we can compute this w/o any mult or + * division. + */ + y = sim_latency; + iop->ema = (y + (iop->ema << alpha_bits) - iop->ema) >> alpha_bits; + + yy = mul(y, y); + iop->emss = (yy + (iop->emss << alpha_bits) - iop->emss) >> alpha_bits; + + /* + * s_1 = sum of data + * s_2 = sum of data * data + * ema ~ mean (or s_1 / N) + * emss ~ s_2 / N + * + * sd = sqrt((N * s_2 - s_1 ^ 2) / (N * (N - 1))) + * sd = sqrt((N * s_2 / N * (N - 1)) - (s_1 ^ 2 / (N * (N - 1)))) + * + * N ~ 2 / alpha - 1 + * alpha < 1 / 16 (typically much less) + * N > 31 --> N large so N * (N - 1) is approx N * N + * + * substituting and rearranging: + * sd ~ sqrt(s_2 / N - (s_1 / N) ^ 2) + * ~ sqrt(emss - ema ^ 2); + * which is the formula used here to get a decent estimate of sd which + * we use to detect outliers. Note that when first starting up, it + * takes a while for emss sum of squares estimator to converge on a + * good value. during this time, it can be less than ema^2. We + * compute a sd of 0 in that case, and ignore outliers. + */ + var = iop->emss - mul(iop->ema, iop->ema); + iop->sd = (int64_t)var < 0 ? 0 : isqrt64(var); +} + +#ifdef CAM_NETFLIX_IOSCHED +static void +cam_iosched_io_metric_update(struct cam_iosched_softc *isc, + sbintime_t sim_latency, int cmd, size_t size) +{ + /* xxx Do we need to scale based on the size of the I/O ? */ + switch (cmd) { + case BIO_READ: + cam_iosched_update(&isc->read_stats, sim_latency); + break; + case BIO_WRITE: + cam_iosched_update(&isc->write_stats, sim_latency); + break; + case BIO_DELETE: + cam_iosched_update(&isc->trim_stats, sim_latency); + break; + default: + break; + } +} +#endif + +#ifdef DDB +static int biolen(struct bio_queue_head *bq) +{ + int i = 0; + struct bio *bp; + + TAILQ_FOREACH(bp, &bq->queue, bio_queue) { + i++; + } + return i; +} + +/* + * Show the internal state of the I/O scheduler. + */ +DB_SHOW_COMMAND(iosched, cam_iosched_db_show) +{ + struct cam_iosched_softc *isc; + + if (!have_addr) { + db_printf("Need addr\n"); + return; + } + isc = (struct cam_iosched_softc *)addr; + db_printf("pending_reads: %d\n", isc->read_stats.pending); + db_printf("min_reads: %d\n", isc->read_stats.min); + db_printf("max_reads: %d\n", isc->read_stats.max); + db_printf("reads: %d\n", isc->read_stats.total); + db_printf("in_reads: %d\n", isc->read_stats.in); + db_printf("out_reads: %d\n", isc->read_stats.out); + db_printf("queued_reads: %d\n", isc->read_stats.queued); + db_printf("Current Q len %d\n", biolen(&isc->bio_queue)); + db_printf("pending_writes: %d\n", isc->write_stats.pending); + db_printf("min_writes: %d\n", isc->write_stats.min); + db_printf("max_writes: %d\n", isc->write_stats.max); + db_printf("writes: %d\n", isc->write_stats.total); + db_printf("in_writes: %d\n", isc->write_stats.in); + db_printf("out_writes: %d\n", isc->write_stats.out); + db_printf("queued_writes: %d\n", isc->write_stats.queued); + db_printf("Current Q len %d\n", biolen(&isc->write_queue)); + db_printf("pending_trims: %d\n", isc->trim_stats.pending); + db_printf("min_trims: %d\n", isc->trim_stats.min); + db_printf("max_trims: %d\n", isc->trim_stats.max); + db_printf("trims: %d\n", isc->trim_stats.total); + db_printf("in_trims: %d\n", isc->trim_stats.in); + db_printf("out_trims: %d\n", isc->trim_stats.out); + db_printf("queued_trims: %d\n", isc->trim_stats.queued); + db_printf("Current Q len %d\n", biolen(&isc->trim_queue)); + db_printf("read_bias: %d\n", isc->read_bias); + db_printf("current_read_bias: %d\n", isc->current_read_bias); + db_printf("Trim active? %s\n", + (isc->flags & CAM_IOSCHED_FLAG_TRIM_ACTIVE) ? "yes" : "no"); +} +#endif +#endif diff --git a/sys/cam/cam_iosched.h b/sys/cam/cam_iosched.h new file mode 100644 index 0000000..34c926d --- /dev/null +++ b/sys/cam/cam_iosched.h @@ -0,0 +1,64 @@ +/*- + * CAM IO Scheduler Interface + * + * Copyright (c) 2015 Netflix, Inc. + * 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, + * without modification, immediately at the beginning of the file. + * 2. 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 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 _CAM_CAM_IOSCHED_H +#define _CAM_CAM_IOSCHED_H + +/* No user-servicable parts in here. */ +#ifdef _KERNEL + +/* Forward declare all structs to keep interface thin */ +struct cam_iosched_softc; +struct sysctl_ctx_list; +struct sysctl_oid; +union ccb; +struct bio; + +int cam_iosched_init(struct cam_iosched_softc **, struct cam_periph *periph); +void cam_iosched_fini(struct cam_iosched_softc *); +void cam_iosched_sysctl_init(struct cam_iosched_softc *, struct sysctl_ctx_list *, struct sysctl_oid *); +struct bio *cam_iosched_next_trim(struct cam_iosched_softc *isc); +struct bio *cam_iosched_get_trim(struct cam_iosched_softc *isc); +struct bio *cam_iosched_next_bio(struct cam_iosched_softc *isc); +void cam_iosched_queue_work(struct cam_iosched_softc *isc, struct bio *bp); +void cam_iosched_flush(struct cam_iosched_softc *isc, struct devstat *stp, int err); +void cam_iosched_schedule(struct cam_iosched_softc *isc, struct cam_periph *periph); +void cam_iosched_finish_trim(struct cam_iosched_softc *isc); +void cam_iosched_submit_trim(struct cam_iosched_softc *isc); +void cam_iosched_put_back_trim(struct cam_iosched_softc *isc, struct bio *bp); +void cam_iosched_set_sort_queue(struct cam_iosched_softc *isc, int val); +int cam_iosched_has_work_flags(struct cam_iosched_softc *isc, uint32_t flags); +void cam_iosched_set_work_flags(struct cam_iosched_softc *isc, uint32_t flags); +void cam_iosched_clr_work_flags(struct cam_iosched_softc *isc, uint32_t flags); +void cam_iosched_trim_done(struct cam_iosched_softc *isc); +int cam_iosched_bio_complete(struct cam_iosched_softc *isc, struct bio *bp, union ccb *done_ccb); + +#endif +#endif diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index 91cb45d..299b4ec 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -86,6 +86,7 @@ static int camperiphscsisenseerror(union ccb *ccb, u_int32_t *timeout, u_int32_t *action, const char **action_string); +static void cam_periph_devctl_notify(union ccb *ccb); static int nperiph_drivers; static int initialized = 0; @@ -1615,7 +1616,7 @@ cam_periph_error(union ccb *ccb, cam_flags camflags, struct cam_periph *periph; const char *action_string; cam_status status; - int frozen, error, openings; + int frozen, error, openings, devctl_err; u_int32_t action, relsim_flags, timeout; action = SSQ_PRINT_SENSE; @@ -1624,9 +1625,26 @@ cam_periph_error(union ccb *ccb, cam_flags camflags, status = ccb->ccb_h.status; frozen = (status & CAM_DEV_QFRZN) != 0; status &= CAM_STATUS_MASK; - openings = relsim_flags = timeout = 0; + devctl_err = openings = relsim_flags = timeout = 0; orig_ccb = ccb; + /* Filter the errors that should be reported via devctl */ + switch (ccb->ccb_h.status & CAM_STATUS_MASK) { + case CAM_CMD_TIMEOUT: + case CAM_REQ_ABORTED: + case CAM_REQ_CMP_ERR: + case CAM_REQ_TERMIO: + case CAM_UNREC_HBA_ERROR: + case CAM_DATA_RUN_ERR: + case CAM_SCSI_STATUS_ERROR: + case CAM_ATA_STATUS_ERROR: + case CAM_SMP_STATUS_ERROR: + devctl_err++; + break; + default: + break; + } + switch (status) { case CAM_REQ_CMP: error = 0; @@ -1754,6 +1772,9 @@ cam_periph_error(union ccb *ccb, cam_flags camflags, xpt_print(ccb->ccb_h.path, "Retrying command\n"); } + if (devctl_err) + cam_periph_devctl_notify(orig_ccb); + if ((action & SSQ_LOST) != 0) { lun_id_t lun_id; @@ -1824,3 +1845,80 @@ cam_periph_error(union ccb *ccb, cam_flags camflags, return (error); } + +#define CAM_PERIPH_DEVD_MSG_SIZE 256 + +static void +cam_periph_devctl_notify(union ccb *ccb) +{ + struct cam_periph *periph; + struct ccb_getdev *cgd; + struct sbuf sb; + int serr, sk, asc, ascq; + char *sbmsg, *type; + + sbmsg = malloc(CAM_PERIPH_DEVD_MSG_SIZE, M_CAMPERIPH, M_NOWAIT); + if (sbmsg == NULL) + return; + + sbuf_new(&sb, sbmsg, CAM_PERIPH_DEVD_MSG_SIZE, SBUF_FIXEDLEN); + + periph = xpt_path_periph(ccb->ccb_h.path); + sbuf_printf(&sb, "device=%s%d ", periph->periph_name, + periph->unit_number); + + sbuf_printf(&sb, "serial=\""); + if ((cgd = (struct ccb_getdev *)xpt_alloc_ccb_nowait()) != NULL) { + xpt_setup_ccb(&cgd->ccb_h, ccb->ccb_h.path, + CAM_PRIORITY_NORMAL); + cgd->ccb_h.func_code = XPT_GDEV_TYPE; + xpt_action((union ccb *)cgd); + + if (cgd->ccb_h.status == CAM_REQ_CMP) + sbuf_bcat(&sb, cgd->serial_num, cgd->serial_num_len); + } + sbuf_printf(&sb, "\" "); + sbuf_printf(&sb, "cam_status=\"0x%x\" ", ccb->ccb_h.status); + + switch (ccb->ccb_h.status & CAM_STATUS_MASK) { + case CAM_CMD_TIMEOUT: + sbuf_printf(&sb, "timeout=%d ", ccb->ccb_h.timeout); + type = "timeout"; + break; + case CAM_SCSI_STATUS_ERROR: + sbuf_printf(&sb, "scsi_status=%d ", ccb->csio.scsi_status); + if (scsi_extract_sense_ccb(ccb, &serr, &sk, &asc, &ascq)) + sbuf_printf(&sb, "scsi_sense=\"%02x %02x %02x %02x\" ", + serr, sk, asc, ascq); + type = "error"; + break; + case CAM_ATA_STATUS_ERROR: + sbuf_printf(&sb, "RES=\""); + ata_res_sbuf(&ccb->ataio.res, &sb); + sbuf_printf(&sb, "\" "); + type = "error"; + break; + default: + type = "error"; + break; + } + + if (ccb->ccb_h.func_code == XPT_SCSI_IO) { + sbuf_printf(&sb, "CDB=\""); + if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) + scsi_cdb_sbuf(ccb->csio.cdb_io.cdb_ptr, &sb); + else + scsi_cdb_sbuf(ccb->csio.cdb_io.cdb_bytes, &sb); + sbuf_printf(&sb, "\" "); + } else if (ccb->ccb_h.func_code == XPT_ATA_IO) { + sbuf_printf(&sb, "ACB=\""); + ata_cmd_sbuf(&ccb->ataio.cmd, &sb); + sbuf_printf(&sb, "\" "); + } + + if (sbuf_finish(&sb) == 0) + devctl_notify("CAM", "periph", type, sbuf_data(&sb)); + sbuf_delete(&sb); + free(sbmsg, M_CAMPERIPH); +} + diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index e811fe6..b426857 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -3311,6 +3311,7 @@ xpt_run_devq(struct cam_devq *devq) lock = (mtx_owned(sim->mtx) == 0); if (lock) CAM_SIM_LOCK(sim); + work_ccb->ccb_h.qos.sim_data = sbinuptime(); // xxx uintprt_t too small 32bit platforms (*(sim->sim_action))(sim, work_ccb); if (lock) CAM_SIM_UNLOCK(sim); @@ -4439,6 +4440,8 @@ xpt_done(union ccb *done_ccb) if ((done_ccb->ccb_h.func_code & XPT_FC_QUEUED) == 0) return; + /* Store the time the ccb was in the sim */ + done_ccb->ccb_h.qos.sim_data = sbinuptime() - done_ccb->ccb_h.qos.sim_data; hash = (done_ccb->ccb_h.path_id + done_ccb->ccb_h.target_id + done_ccb->ccb_h.target_lun) % cam_num_doneqs; queue = &cam_doneqs[hash]; @@ -4459,6 +4462,8 @@ xpt_done_direct(union ccb *done_ccb) if ((done_ccb->ccb_h.func_code & XPT_FC_QUEUED) == 0) return; + /* Store the time the ccb was in the sim */ + done_ccb->ccb_h.qos.sim_data = sbinuptime() - done_ccb->ccb_h.qos.sim_data; xpt_done_process(&done_ccb->ccb_h); } diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c index 07a6435..d97e99d 100644 --- a/sys/cam/scsi/scsi_da.c +++ b/sys/cam/scsi/scsi_da.c @@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$"); #include <cam/cam_periph.h> #include <cam/cam_xpt_periph.h> #include <cam/cam_sim.h> +#include <cam/cam_iosched.h> #include <cam/scsi/scsi_message.h> @@ -199,21 +200,19 @@ struct disk_params { #define ATA_TRIM_MAX_RANGES ((UNMAP_BUF_SIZE / \ (ATA_DSM_RANGE_SIZE * ATA_DSM_BLK_SIZE)) * ATA_DSM_BLK_SIZE) +#define DA_WORK_TUR (1 << 16) + struct da_softc { - struct bio_queue_head bio_queue; - struct bio_queue_head delete_queue; + struct cam_iosched_softc *cam_iosched; struct bio_queue_head delete_run_queue; LIST_HEAD(, ccb_hdr) pending_ccbs; - int tur; /* TEST UNIT READY should be sent */ int refcount; /* Active xpt_action() calls */ da_state state; da_flags flags; da_quirks quirks; - int sort_io_queue; int minimum_cmd_size; int error_inject; int trim_max_ranges; - int delete_running; int delete_available; /* Delete methods possibly available */ u_int maxio; uint32_t unmap_max_ranges; @@ -222,6 +221,8 @@ struct da_softc { da_delete_methods delete_method_pref; da_delete_methods delete_method; da_delete_func_t *delete_func; + int unmappedio; + int rotating; struct disk_params params; struct disk *disk; union ccb saved_ccb; @@ -233,6 +234,13 @@ struct da_softc { uint8_t unmap_buf[UNMAP_BUF_SIZE]; struct scsi_read_capacity_data_long rcaplong; struct callout mediapoll_c; +#ifdef CAM_IO_STATS + struct sysctl_ctx_list sysctl_stats_ctx; + struct sysctl_oid *sysctl_stats_tree; + u_int errors; + u_int timeouts; + u_int invalidations; +#endif }; #define dadeleteflag(softc, delete_method, enable) \ @@ -1193,6 +1201,7 @@ static periph_init_t dainit; static void daasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg); static void dasysctlinit(void *context, int pending); +static int dasysctlsofttimeout(SYSCTL_HANDLER_ARGS); static int dacmdsizesysctl(SYSCTL_HANDLER_ARGS); static int dadeletemethodsysctl(SYSCTL_HANDLER_ARGS); static int dadeletemaxsysctl(SYSCTL_HANDLER_ARGS); @@ -1230,6 +1239,10 @@ static timeout_t damediapoll; #define DA_DEFAULT_TIMEOUT 60 /* Timeout in seconds */ #endif +#ifndef DA_DEFAULT_SOFTTIMEOUT +#define DA_DEFAULT_SOFTTIMEOUT 0 +#endif + #ifndef DA_DEFAULT_RETRY #define DA_DEFAULT_RETRY 4 #endif @@ -1238,12 +1251,10 @@ static timeout_t damediapoll; #define DA_DEFAULT_SEND_ORDERED 1 #endif -#define DA_SIO (softc->sort_io_queue >= 0 ? \ - softc->sort_io_queue : cam_sort_io_queues) - static int da_poll_period = DA_DEFAULT_POLL_PERIOD; static int da_retry_count = DA_DEFAULT_RETRY; static int da_default_timeout = DA_DEFAULT_TIMEOUT; +static sbintime_t da_default_softtimeout = DA_DEFAULT_SOFTTIMEOUT; static int da_send_ordered = DA_DEFAULT_SEND_ORDERED; static SYSCTL_NODE(_kern_cam, OID_AUTO, da, CTLFLAG_RD, 0, @@ -1257,6 +1268,11 @@ SYSCTL_INT(_kern_cam_da, OID_AUTO, default_timeout, CTLFLAG_RWTUN, SYSCTL_INT(_kern_cam_da, OID_AUTO, send_ordered, CTLFLAG_RWTUN, &da_send_ordered, 0, "Send Ordered Tags"); +SYSCTL_PROC(_kern_cam_da, OID_AUTO, default_softtimeout, + CTLTYPE_UINT | CTLFLAG_RW, NULL, 0, dasysctlsofttimeout, "I", + "Soft I/O timeout (ms)"); +TUNABLE_INT64("kern.cam.da.default_softtimeout", &da_default_softtimeout); + /* * DA_ORDEREDTAG_INTERVAL determines how often, relative * to the default timeout, we check to see whether an ordered @@ -1400,12 +1416,7 @@ daschedule(struct cam_periph *periph) if (softc->state != DA_STATE_NORMAL) return; - /* Check if we have more work to do. */ - if (bioq_first(&softc->bio_queue) || - (!softc->delete_running && bioq_first(&softc->delete_queue)) || - softc->tur) { - xpt_schedule(periph, CAM_PRIORITY_NORMAL); - } + cam_iosched_schedule(softc->cam_iosched, periph); } /* @@ -1438,13 +1449,7 @@ dastrategy(struct bio *bp) /* * Place it in the queue of disk activities for this disk */ - if (bp->bio_cmd == BIO_DELETE) { - bioq_disksort(&softc->delete_queue, bp); - } else if (DA_SIO) { - bioq_disksort(&softc->bio_queue, bp); - } else { - bioq_insert_tail(&softc->bio_queue, bp); - } + cam_iosched_queue_work(softc->cam_iosched, bp); /* * Schedule ourselves for performing the work. @@ -1519,7 +1524,7 @@ dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t leng /*begin_lba*/0,/* Cover the whole disk */ /*lb_count*/0, SSD_FULL_SIZE, - 5 * 60 * 1000); + 5 * 1000); xpt_polled_action((union ccb *)&csio); error = cam_periph_error((union ccb *)&csio, @@ -1599,14 +1604,16 @@ daoninvalidate(struct cam_periph *periph) xpt_register_async(0, daasync, periph, periph->path); softc->flags |= DA_FLAG_PACK_INVALID; +#ifdef CAM_IO_STATS + softc->invalidations++; +#endif /* * Return all queued I/O with ENXIO. * XXX Handle any transactions queued to the card * with XPT_ABORT_CCB. */ - bioq_flush(&softc->bio_queue, NULL, ENXIO); - bioq_flush(&softc->delete_queue, NULL, ENXIO); + cam_iosched_flush(softc->cam_iosched, NULL, ENXIO); /* * Tell GEOM that we've gone away, we'll get a callback when it is @@ -1624,12 +1631,20 @@ dacleanup(struct cam_periph *periph) cam_periph_unlock(periph); + cam_iosched_fini(softc->cam_iosched); + /* * If we can't free the sysctl tree, oh well... */ - if ((softc->flags & DA_FLAG_SCTX_INIT) != 0 - && sysctl_ctx_free(&softc->sysctl_ctx) != 0) { - xpt_print(periph->path, "can't remove sysctl context\n"); + if ((softc->flags & DA_FLAG_SCTX_INIT) != 0) { +#ifdef CAM_IO_STATS + if (sysctl_ctx_free(&softc->sysctl_stats_ctx) != 0) + xpt_print(periph->path, + "can't remove sysctl stats context\n"); +#endif + if (sysctl_ctx_free(&softc->sysctl_ctx) != 0) + xpt_print(periph->path, + "can't remove sysctl context\n"); } callout_drain(&softc->mediapoll_c); @@ -1732,9 +1747,9 @@ daasync(void *callback_arg, u_int32_t code, } case AC_SCSI_AEN: softc = (struct da_softc *)periph->softc; - if (!softc->tur) { + if (!cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR)) { if (cam_periph_acquire(periph) == CAM_REQ_CMP) { - softc->tur = 1; + cam_iosched_set_work_flags(softc->cam_iosched, DA_WORK_TUR); daschedule(periph); } } @@ -1808,9 +1823,6 @@ dasysctlinit(void *context, int pending) OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW, &softc->minimum_cmd_size, 0, dacmdsizesysctl, "I", "Minimum CDB size"); - SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), - OID_AUTO, "sort_io_queue", CTLFLAG_RW, &softc->sort_io_queue, 0, - "Sort IO queue to try and optimise disk access patterns"); SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree), @@ -1821,6 +1833,23 @@ dasysctlinit(void *context, int pending) 0, "error_inject leaf"); + SYSCTL_ADD_INT(&softc->sysctl_ctx, + SYSCTL_CHILDREN(softc->sysctl_tree), + OID_AUTO, + "unmapped_io", + CTLFLAG_RD, + &softc->unmappedio, + 0, + "Unmapped I/O leaf"); + + SYSCTL_ADD_INT(&softc->sysctl_ctx, + SYSCTL_CHILDREN(softc->sysctl_tree), + OID_AUTO, + "rotating", + CTLFLAG_RD, + &softc->rotating, + 0, + "Rotating media"); /* * Add some addressing info. @@ -1846,6 +1875,44 @@ dasysctlinit(void *context, int pending) &softc->wwpn, "World Wide Port Name"); } } + +#ifdef CAM_IO_STATS + /* + * Now add some useful stats. + * XXX These should live in cam_periph and be common to all periphs + */ + softc->sysctl_stats_tree = SYSCTL_ADD_NODE(&softc->sysctl_stats_ctx, + SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO, "stats", + CTLFLAG_RD, 0, "Statistics"); + SYSCTL_ADD_INT(&softc->sysctl_stats_ctx, + SYSCTL_CHILDREN(softc->sysctl_stats_tree), + OID_AUTO, + "errors", + CTLFLAG_RD, + &softc->errors, + 0, + "Transport errors reported by the SIM"); + SYSCTL_ADD_INT(&softc->sysctl_stats_ctx, + SYSCTL_CHILDREN(softc->sysctl_stats_tree), + OID_AUTO, + "timeouts", + CTLFLAG_RD, + &softc->timeouts, + 0, + "Device timeouts reported by the SIM"); + SYSCTL_ADD_INT(&softc->sysctl_stats_ctx, + SYSCTL_CHILDREN(softc->sysctl_stats_tree), + OID_AUTO, + "pack_invalidations", + CTLFLAG_RD, + &softc->invalidations, + 0, + "Device pack invalidations"); +#endif + + cam_iosched_sysctl_init(softc->cam_iosched, &softc->sysctl_ctx, + softc->sysctl_tree); + cam_periph_release(periph); } @@ -1904,6 +1971,26 @@ dacmdsizesysctl(SYSCTL_HANDLER_ARGS) return (0); } +static int +dasysctlsofttimeout(SYSCTL_HANDLER_ARGS) +{ + sbintime_t value; + int error; + + value = da_default_softtimeout / SBT_1MS; + + error = sysctl_handle_int(oidp, (int *)&value, 0, req); + if ((error != 0) || (req->newptr == NULL)) + return (error); + + /* XXX Should clip this to a reasonable level */ + if (value > da_default_timeout * 1000) + return (EINVAL); + + da_default_softtimeout = value * SBT_1MS; + return (0); +} + static void dadeletemethodset(struct da_softc *softc, da_delete_methods delete_method) { @@ -2075,14 +2162,18 @@ daregister(struct cam_periph *periph, void *arg) if (softc == NULL) { printf("daregister: Unable to probe new device. " - "Unable to allocate softc\n"); + "Unable to allocate softc\n"); return(CAM_REQ_CMP_ERR); } + if (cam_iosched_init(&softc->cam_iosched, periph) != 0) { + printf("daregister: Unable to probe new device. " + "Unable to allocate iosched memory\n"); + return(CAM_REQ_CMP_ERR); + } + LIST_INIT(&softc->pending_ccbs); softc->state = DA_STATE_PROBE_RC; - bioq_init(&softc->bio_queue); - bioq_init(&softc->delete_queue); bioq_init(&softc->delete_run_queue); if (SID_IS_REMOVABLE(&cgd->inq_data)) softc->flags |= DA_FLAG_PACK_REMOVABLE; @@ -2090,7 +2181,7 @@ daregister(struct cam_periph *periph, void *arg) softc->unmap_max_lba = UNMAP_RANGE_MAX; softc->ws_max_blks = WS16_MAX_BLKS; softc->trim_max_ranges = ATA_TRIM_MAX_RANGES; - softc->sort_io_queue = -1; + softc->rotating = 1; periph->softc = softc; @@ -2199,8 +2290,11 @@ daregister(struct cam_periph *periph, void *arg) softc->disk->d_flags = DISKFLAG_DIRECT_COMPLETION; if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE; - if ((cpi.hba_misc & PIM_UNMAPPED) != 0) + if ((cpi.hba_misc & PIM_UNMAPPED) != 0) { + softc->unmappedio = 1; softc->disk->d_flags |= DISKFLAG_UNMAPPED_BIO; + xpt_print(periph->path, "UNMAPPED\n"); + } cam_strvis(softc->disk->d_descr, cgd->inq_data.vendor, sizeof(cgd->inq_data.vendor), sizeof(softc->disk->d_descr)); strlcat(softc->disk->d_descr, " ", sizeof(softc->disk->d_descr)); @@ -2277,23 +2371,11 @@ skipstate: struct bio *bp; uint8_t tag_code; - /* Run BIO_DELETE if not running yet. */ - if (!softc->delete_running && - (bp = bioq_first(&softc->delete_queue)) != NULL) { - if (softc->delete_func != NULL) { - softc->delete_func(periph, start_ccb, bp); - goto out; - } else { - bioq_flush(&softc->delete_queue, NULL, 0); - /* FALLTHROUGH */ - } - } - - /* Run regular command. */ - bp = bioq_takefirst(&softc->bio_queue); +more: + bp = cam_iosched_next_bio(softc->cam_iosched); if (bp == NULL) { - if (softc->tur) { - softc->tur = 0; + if (cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR)) { + cam_iosched_clr_work_flags(softc->cam_iosched, DA_WORK_TUR); scsi_test_unit_ready(&start_ccb->csio, /*retries*/ da_retry_count, dadone, @@ -2307,9 +2389,21 @@ skipstate: xpt_release_ccb(start_ccb); break; } - if (softc->tur) { - softc->tur = 0; - cam_periph_release_locked(periph); + + if (bp->bio_cmd == BIO_DELETE) { + if (softc->delete_func != NULL) { + softc->delete_func(periph, start_ccb, bp); + goto out; + } else { + /* Not sure this is possible, but failsafe by lying and saying "sure, done." */ + biofinish(bp, NULL, 0); + goto more; + } + } + + if (cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR)) { + cam_iosched_clr_work_flags(softc->cam_iosched, DA_WORK_TUR); + cam_periph_release_locked(periph); /* XXX is this still valid? I think so but unverified */ } if ((bp->bio_flags & BIO_ORDERED) != 0 || @@ -2377,6 +2471,7 @@ skipstate: } start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO; start_ccb->ccb_h.flags |= CAM_UNLOCKED; + start_ccb->ccb_h.softtimeout = sbttotv(da_default_softtimeout); out: LIST_INSERT_HEAD(&softc->pending_ccbs, @@ -2625,11 +2720,19 @@ da_delete_unmap(struct cam_periph *periph, union ccb *ccb, struct bio *bp) * fewer LBA's than requested. */ - softc->delete_running = 1; bzero(softc->unmap_buf, sizeof(softc->unmap_buf)); bp1 = bp; do { - bioq_remove(&softc->delete_queue, bp1); + /* + * Note: ada and da are different in how they store the + * pending bp's in a trim. ada stores all of them in the + * trim_req.bps. da stores all but the first one in the + * delete_run_queue. ada then completes all the bps in + * its adadone() loop. da completes all the bps in the + * delete_run_queue in dadone, and relies on the biodone + * after to complete. This should be reconciled since there's + * no real reason to do it differently. XXX + */ if (bp1 != bp) bioq_insert_tail(&softc->delete_run_queue, bp1); lba = bp1->bio_pblkno; @@ -2669,11 +2772,15 @@ da_delete_unmap(struct cam_periph *periph, union ccb *ccb, struct bio *bp) lastcount = c; } lastlba = lba; - bp1 = bioq_first(&softc->delete_queue); - if (bp1 == NULL || ranges >= softc->unmap_max_ranges || + bp1 = cam_iosched_next_trim(softc->cam_iosched); + if (bp1 == NULL) + break; + if (ranges >= softc->unmap_max_ranges || totalcount + bp1->bio_bcount / - softc->params.secsize > softc->unmap_max_lba) + softc->params.secsize > softc->unmap_max_lba) { + cam_iosched_put_back_trim(softc->cam_iosched, bp1); break; + } } while (1); scsi_ulto2b(ranges * 16 + 6, &buf[0]); scsi_ulto2b(ranges * 16, &buf[2]); @@ -2689,6 +2796,7 @@ da_delete_unmap(struct cam_periph *periph, union ccb *ccb, struct bio *bp) da_default_timeout * 1000); ccb->ccb_h.ccb_state = DA_CCB_DELETE; ccb->ccb_h.flags |= CAM_UNLOCKED; + cam_iosched_submit_trim(softc->cam_iosched); } static void @@ -2703,12 +2811,10 @@ da_delete_trim(struct cam_periph *periph, union ccb *ccb, struct bio *bp) uint32_t lastcount = 0, c, requestcount; int ranges = 0, off, block_count; - softc->delete_running = 1; bzero(softc->unmap_buf, sizeof(softc->unmap_buf)); bp1 = bp; do { - bioq_remove(&softc->delete_queue, bp1); - if (bp1 != bp) + if (bp1 != bp)//XXX imp XXX bioq_insert_tail(&softc->delete_run_queue, bp1); lba = bp1->bio_pblkno; count = bp1->bio_bcount / softc->params.secsize; @@ -2752,10 +2858,14 @@ da_delete_trim(struct cam_periph *periph, union ccb *ccb, struct bio *bp) } } lastlba = lba; - bp1 = bioq_first(&softc->delete_queue); - if (bp1 == NULL || bp1->bio_bcount / softc->params.secsize > - (softc->trim_max_ranges - ranges) * ATA_DSM_RANGE_MAX) + bp1 = cam_iosched_next_trim(softc->cam_iosched); + if (bp1 == NULL) + break; + if (bp1->bio_bcount / softc->params.secsize > + (softc->trim_max_ranges - ranges) * ATA_DSM_RANGE_MAX) { + cam_iosched_put_back_trim(softc->cam_iosched, bp1); break; + } } while (1); block_count = (ranges + ATA_DSM_BLK_RANGES - 1) / ATA_DSM_BLK_RANGES; @@ -2770,6 +2880,7 @@ da_delete_trim(struct cam_periph *periph, union ccb *ccb, struct bio *bp) da_default_timeout * 1000); ccb->ccb_h.ccb_state = DA_CCB_DELETE; ccb->ccb_h.flags |= CAM_UNLOCKED; + cam_iosched_submit_trim(softc->cam_iosched); } /* @@ -2788,13 +2899,11 @@ da_delete_ws(struct cam_periph *periph, union ccb *ccb, struct bio *bp) softc = (struct da_softc *)periph->softc; ws_max_blks = softc->disk->d_delmaxsize / softc->params.secsize; - softc->delete_running = 1; lba = bp->bio_pblkno; count = 0; bp1 = bp; do { - bioq_remove(&softc->delete_queue, bp1); - if (bp1 != bp) + if (bp1 != bp)//XXX imp XXX bioq_insert_tail(&softc->delete_run_queue, bp1); count += bp1->bio_bcount / softc->params.secsize; if (count > ws_max_blks) { @@ -2805,11 +2914,15 @@ da_delete_ws(struct cam_periph *periph, union ccb *ccb, struct bio *bp) count = omin(count, ws_max_blks); break; } - bp1 = bioq_first(&softc->delete_queue); - if (bp1 == NULL || lba + count != bp1->bio_pblkno || + bp1 = cam_iosched_next_trim(softc->cam_iosched); + if (bp1 == NULL) + break; + if (lba + count != bp1->bio_pblkno || count + bp1->bio_bcount / - softc->params.secsize > ws_max_blks) + softc->params.secsize > ws_max_blks) { + cam_iosched_put_back_trim(softc->cam_iosched, bp1); break; + } } while (1); scsi_write_same(&ccb->csio, @@ -2827,6 +2940,7 @@ da_delete_ws(struct cam_periph *periph, union ccb *ccb, struct bio *bp) da_default_timeout * 1000); ccb->ccb_h.ccb_state = DA_CCB_DELETE; ccb->ccb_h.flags |= CAM_UNLOCKED; + cam_iosched_submit_trim(softc->cam_iosched); } static int @@ -2870,8 +2984,8 @@ cmd6workaround(union ccb *ccb) da_delete_method_desc[softc->delete_method]); while ((bp = bioq_takefirst(&softc->delete_run_queue)) != NULL) - bioq_disksort(&softc->delete_queue, bp); - bioq_disksort(&softc->delete_queue, + cam_iosched_queue_work(softc->cam_iosched, bp); + cam_iosched_queue_work(softc->cam_iosched, (struct bio *)ccb->ccb_h.ccb_bp); ccb->ccb_h.ccb_bp = NULL; return (0); @@ -2998,9 +3112,12 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) xpt_print(periph->path, "Invalidating pack\n"); softc->flags |= DA_FLAG_PACK_INVALID; +#ifdef CAM_IO_STATS + softc->invalidations++; +#endif queued_error = ENXIO; } - bioq_flush(&softc->bio_queue, NULL, + cam_iosched_flush(softc->cam_iosched, NULL, queued_error); if (bp != NULL) { bp->bio_error = error; @@ -3043,6 +3160,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) if (LIST_EMPTY(&softc->pending_ccbs)) softc->flags |= DA_FLAG_WAS_OTAG; + cam_iosched_bio_complete(softc->cam_iosched, bp, done_ccb); xpt_release_ccb(done_ccb); if (state == DA_CCB_DELETE) { TAILQ_HEAD(, bio) queue; @@ -3060,7 +3178,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) * and call daschedule again so that we don't stall if * there are no other I/Os pending apart from BIO_DELETEs. */ - softc->delete_running = 0; + cam_iosched_trim_done(softc->cam_iosched); daschedule(periph); cam_periph_unlock(periph); while ((bp1 = TAILQ_FIRST(&queue)) != NULL) { @@ -3073,8 +3191,10 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) bp1->bio_resid = 0; biodone(bp1); } - } else + } else { + daschedule(periph); cam_periph_unlock(periph); + } if (bp != NULL) biodone(bp); return; @@ -3459,7 +3579,8 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) scsi_2btoul(bdc->medium_rotation_rate); if (softc->disk->d_rotation_rate == SVPD_BDC_RATE_NON_ROTATING) { - softc->sort_io_queue = 0; + cam_iosched_set_sort_queue(softc->cam_iosched, 0); + softc->rotating = 0; } if (softc->disk->d_rotation_rate != old_rate) { disk_attr_changed(softc->disk, @@ -3521,9 +3642,9 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) ata_params->media_rotation_rate; if (softc->disk->d_rotation_rate == ATA_RATE_NON_ROTATING) { - softc->sort_io_queue = 0; + cam_iosched_set_sort_queue(softc->cam_iosched, 0); + softc->rotating = 0; } - if (softc->disk->d_rotation_rate != old_rate) { disk_attr_changed(softc->disk, "GEOM::rotation_rate", M_NOWAIT); @@ -3652,6 +3773,23 @@ daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) if (error == ERESTART) return (ERESTART); +#ifdef CAM_IO_STATS + switch (ccb->ccb_h.status & CAM_STATUS_MASK) { + case CAM_CMD_TIMEOUT: + softc->timeouts++; + break; + case CAM_REQ_ABORTED: + case CAM_REQ_CMP_ERR: + case CAM_REQ_TERMIO: + case CAM_UNREC_HBA_ERROR: + case CAM_DATA_RUN_ERR: + softc->errors++; + break; + default: + break; + } +#endif + /* * XXX * Until we have a better way of doing pack validation, @@ -3671,9 +3809,10 @@ damediapoll(void *arg) struct cam_periph *periph = arg; struct da_softc *softc = periph->softc; - if (!softc->tur && LIST_EMPTY(&softc->pending_ccbs)) { + if (!cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR) && + LIST_EMPTY(&softc->pending_ccbs)) { if (cam_periph_acquire(periph) == CAM_REQ_CMP) { - softc->tur = 1; + cam_iosched_set_work_flags(softc->cam_iosched, DA_WORK_TUR); daschedule(periph); } } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c index 1777fba..a92a54b 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c @@ -163,6 +163,7 @@ vdev_geom_attach(struct g_provider *pp, vdev_t *vd) { struct g_geom *gp; struct g_consumer *cp; + int error; g_topology_assert(); @@ -180,11 +181,17 @@ vdev_geom_attach(struct g_provider *pp, vdev_t *vd) gp->orphan = vdev_geom_orphan; gp->attrchanged = vdev_geom_attrchanged; cp = g_new_consumer(gp); - if (g_attach(cp, pp) != 0) { + error = g_attach(cp, pp); + if (error != 0) { + ZFS_LOG(1, "%s(%d): g_attach failed: %d\n", __func__, + __LINE__, error); g_wither_geom(gp, ENXIO); return (NULL); } - if (g_access(cp, 1, 0, 1) != 0) { + error = g_access(cp, 1, 0, 1); + if (error != 0) { + ZFS_LOG(1, "%s(%d): g_access failed: %d\n", __func__, + __LINE__, error); g_wither_geom(gp, ENXIO); return (NULL); } @@ -199,19 +206,29 @@ vdev_geom_attach(struct g_provider *pp, vdev_t *vd) } if (cp == NULL) { cp = g_new_consumer(gp); - if (g_attach(cp, pp) != 0) { + error = g_attach(cp, pp); + if (error != 0) { + ZFS_LOG(1, "%s(%d): g_attach failed: %d\n", + __func__, __LINE__, error); g_destroy_consumer(cp); return (NULL); } - if (g_access(cp, 1, 0, 1) != 0) { + error = g_access(cp, 1, 0, 1); + if (error != 0) { + ZFS_LOG(1, "%s(%d): g_access failed: %d\n", + __func__, __LINE__, error); g_detach(cp); g_destroy_consumer(cp); return (NULL); } ZFS_LOG(1, "Created consumer for %s.", pp->name); } else { - if (g_access(cp, 1, 0, 1) != 0) + error = g_access(cp, 1, 0, 1); + if (error != 0) { + ZFS_LOG(1, "%s(%d): g_access failed: %d\n", + __func__, __LINE__, error); return (NULL); + } ZFS_LOG(1, "Used existing consumer for %s.", pp->name); } } @@ -229,9 +246,6 @@ vdev_geom_attach(struct g_provider *pp, vdev_t *vd) cp->private = vd; vd->vdev_tsd = cp; - /* Fetch initial physical path information for this device. */ - vdev_geom_attrchanged(cp, "GEOM::physpath"); - cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE; return (cp); } @@ -625,7 +639,8 @@ vdev_geom_open_by_guids(vdev_t *vd) g_topology_assert(); - ZFS_LOG(1, "Searching by guid [%ju].", (uintmax_t)vd->vdev_guid); + ZFS_LOG(1, "Searching by guids [%ju:%ju].", + (uintmax_t)spa_guid(vd->vdev_spa), (uintmax_t)vd->vdev_guid); cp = vdev_geom_attach_by_guids(vd); if (cp != NULL) { len = strlen(cp->provider->name) + strlen("/dev/") + 1; @@ -787,6 +802,10 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, } } + /* Fetch initial physical path information for this device. */ + if (cp != NULL) + vdev_geom_attrchanged(cp, "GEOM::physpath"); + g_topology_unlock(); PICKUP_GIANT(); if (cp == NULL) { diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c index 572060e..bb5a475 100644 --- a/sys/compat/linux/linux_ioctl.c +++ b/sys/compat/linux/linux_ioctl.c @@ -2902,7 +2902,7 @@ linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw) vw->clips = NULL; ppvc = &(vw->clips); while (clipcount-- > 0) { - if (plvc == 0) { + if (plvc == NULL) { error = EFAULT; break; } else { diff --git a/sys/conf/NOTES b/sys/conf/NOTES index ec5618c..406373f 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -719,7 +719,7 @@ options ALTQ_CBQ # Class Based Queueing options ALTQ_RED # Random Early Detection options ALTQ_RIO # RED In/Out options ALTQ_HFSC # Hierarchical Packet Scheduler -options ALTQ_FAIRQ # Fair Packet Scheduler +options ALTQ_FAIRQ # Fair Packet Scheduler options ALTQ_CDNR # Traffic conditioner options ALTQ_PRIQ # Priority Queueing options ALTQ_NOPCC # Required if the TSC is unusable diff --git a/sys/conf/files b/sys/conf/files index 46e9768..6e57021 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -68,6 +68,7 @@ usbdevs_data.h optional usb \ clean "usbdevs_data.h" cam/cam.c optional scbus cam/cam_compat.c optional scbus +cam/cam_iosched.c optional scbus cam/cam_periph.c optional scbus cam/cam_queue.c optional scbus cam/cam_sim.c optional scbus @@ -1442,7 +1443,7 @@ dev/fdt/fdt_pinctrl.c optional fdt fdt_pinctrl dev/fdt/fdt_pinctrl_if.m optional fdt fdt_pinctrl dev/fdt/fdt_slicer.c optional fdt cfi | fdt nand | fdt mx25l dev/fdt/fdt_static_dtb.S optional fdt fdt_dtb_static \ - dependency "$S/boot/fdt/dts/${MACHINE}/${FDT_DTS_FILE}" + dependency "fdt_dtb_file" dev/fdt/simplebus.c optional fdt dev/fe/if_fe.c optional fe dev/fe/if_fe_pccard.c optional fe pccard @@ -3748,6 +3749,7 @@ netpfil/ipfw/ip_dn_io.c optional inet dummynet netpfil/ipfw/ip_dn_glue.c optional inet dummynet netpfil/ipfw/ip_fw2.c optional inet ipfirewall netpfil/ipfw/ip_fw_dynamic.c optional inet ipfirewall +netpfil/ipfw/ip_fw_eaction.c optional inet ipfirewall netpfil/ipfw/ip_fw_log.c optional inet ipfirewall netpfil/ipfw/ip_fw_pfil.c optional inet ipfirewall netpfil/ipfw/ip_fw_sockopt.c optional inet ipfirewall diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 85366fa..ca31558 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -277,6 +277,7 @@ dev/hyperv/vmbus/hv_hv.c optional hyperv dev/hyperv/vmbus/hv_et.c optional hyperv dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv +dev/hyperv/vmbus/amd64/hv_vector.S optional hyperv dev/nfe/if_nfe.c optional nfe pci dev/ntb/if_ntb/if_ntb.c optional if_ntb dev/ntb/ntb_hw/ntb_hw.c optional if_ntb | ntb_hw diff --git a/sys/conf/files.arm b/sys/conf/files.arm index a9da11c..b77d1fc 100644 --- a/sys/conf/files.arm +++ b/sys/conf/files.arm @@ -45,8 +45,8 @@ arm/arm/hdmi_if.m optional hdmi arm/arm/identcpu.c standard arm/arm/in_cksum.c optional inet | inet6 arm/arm/in_cksum_arm.S optional inet | inet6 -arm/arm/intr.c optional !arm_intrng -kern/subr_intr.c optional arm_intrng +arm/arm/intr.c optional !intrng +kern/subr_intr.c optional intrng arm/arm/locore.S standard no-obj arm/arm/machdep.c standard arm/arm/machdep_intr.c standard @@ -57,7 +57,6 @@ arm/arm/mpcore_timer.c optional mpcore_timer arm/arm/nexus.c standard arm/arm/ofw_machdep.c optional fdt arm/arm/physmem.c standard -kern/pic_if.m optional arm_intrng arm/arm/pl190.c optional pl190 arm/arm/pl310.c optional pl310 arm/arm/platform.c optional platform @@ -116,6 +115,7 @@ font.h optional sc \ compile-with "uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x16.fnt && file2c 'u_char dflt_font_16[16*256] = {' '};' < ${SC_DFLT_FONT}-8x16 > font.h && uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x14.fnt && file2c 'u_char dflt_font_14[14*256] = {' '};' < ${SC_DFLT_FONT}-8x14 >> font.h && uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x8.fnt && file2c 'u_char dflt_font_8[8*256] = {' '};' < ${SC_DFLT_FONT}-8x8 >> font.h" \ no-obj no-implicit-rule before-depend \ clean "font.h ${SC_DFLT_FONT}-8x14 ${SC_DFLT_FONT}-8x16 ${SC_DFLT_FONT}-8x8" +kern/pic_if.m optional intrng kern/subr_busdma_bufalloc.c standard kern/subr_sfbuf.c standard libkern/arm/aeabi_unwind.c standard diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 4b6f158..eb8585f 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -252,6 +252,7 @@ dev/hyperv/vmbus/hv_hv.c optional hyperv dev/hyperv/vmbus/hv_et.c optional hyperv dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv +dev/hyperv/vmbus/i386/hv_vector.S optional hyperv dev/ichwd/ichwd.c optional ichwd dev/if_ndis/if_ndis.c optional ndis dev/if_ndis/if_ndis_pccard.c optional ndis pccard diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk index d28e87b..3286c66 100644 --- a/sys/conf/kern.post.mk +++ b/sys/conf/kern.post.mk @@ -215,7 +215,7 @@ DEPEND_CFLAGS+= -MT${.TARGET} .if defined(.PARSEDIR) # Only add in DEPEND_CFLAGS for CFLAGS on files we expect from DEPENDOBJS # as those are the only ones we will include. -DEPEND_CFLAGS_CONDITION= !empty(DEPENDOBJS:M${.TARGET}) +DEPEND_CFLAGS_CONDITION= "${DEPENDOBJS:M${.TARGET}}" != "" CFLAGS+= ${${DEPEND_CFLAGS_CONDITION}:?${DEPEND_CFLAGS}:} .else CFLAGS+= ${DEPEND_CFLAGS} diff --git a/sys/conf/options b/sys/conf/options index 2283705..11e778f 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -329,6 +329,7 @@ CAM_DEBUG_TARGET opt_cam.h CAM_DEBUG_LUN opt_cam.h CAM_DEBUG_FLAGS opt_cam.h CAM_BOOT_DELAY opt_cam.h +CAM_NETFLIX_IOSCHED opt_cam.h SCSI_DELAY opt_scsi.h SCSI_NO_SENSE_STRINGS opt_scsi.h SCSI_NO_OP_STRINGS opt_scsi.h diff --git a/sys/conf/options.amd64 b/sys/conf/options.amd64 index 0e59187..f1d4b4a 100644 --- a/sys/conf/options.amd64 +++ b/sys/conf/options.amd64 @@ -63,7 +63,5 @@ BPF_JITTER opt_bpf.h XENHVM opt_global.h -HYPERV opt_global.h - # options for the Intel C600 SAS driver (isci) ISCI_LOGGING opt_isci.h diff --git a/sys/conf/options.arm b/sys/conf/options.arm index d6d7a37..4737b80 100644 --- a/sys/conf/options.arm +++ b/sys/conf/options.arm @@ -1,7 +1,6 @@ #$FreeBSD$ ARMV6 opt_global.h ARM_CACHE_LOCK_ENABLE opt_global.h -ARM_INTRNG opt_global.h ARM_KERN_DIRECTMAP opt_vm.h ARM_L2_PIPT opt_global.h ARM_MANY_BOARD opt_global.h @@ -24,6 +23,7 @@ DEV_PMU opt_global.h EFI opt_platform.h FLASHADDR opt_global.h GIC_DEFAULT_ICFGR_INIT opt_global.h +INTRNG opt_global.h IPI_IRQ_START opt_smp.h IPI_IRQ_END opt_smp.h FREEBSD_BOOT_LOADER opt_global.h diff --git a/sys/conf/options.i386 b/sys/conf/options.i386 index 69eb7e3..e51f82c 100644 --- a/sys/conf/options.i386 +++ b/sys/conf/options.i386 @@ -123,7 +123,5 @@ BPF_JITTER opt_bpf.h XENHVM opt_global.h -HYPERV opt_global.h - # options for the Intel C600 SAS driver (isci) ISCI_LOGGING opt_isci.h diff --git a/sys/conf/options.mips b/sys/conf/options.mips index 69708cc..daae01f 100644 --- a/sys/conf/options.mips +++ b/sys/conf/options.mips @@ -144,4 +144,5 @@ PV_STATS opt_pmap.h # # Options to use INTRNG code # -MIPS_INTRNG opt_global.h +INTRNG opt_global.h +MIPS_NIRQ opt_global.h diff --git a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c index 3b74f8c..2796055 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c +++ b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c @@ -738,7 +738,7 @@ ipf_fastroute(m0, mpp, fin, fdp) */ if (M_WRITABLE(m) == 0) { m0 = m_dup(m, M_NOWAIT); - if (m0 != 0) { + if (m0 != NULL) { FREE_MB_T(m); m = m0; *mpp = m; @@ -885,7 +885,7 @@ ipf_fastroute(m0, mpp, fin, fdp) #else MGET(m, M_NOWAIT, MT_HEADER); #endif - if (m == 0) { + if (m == NULL) { m = m0; error = ENOBUFS; goto bad; diff --git a/sys/contrib/rdma/krping/krping.c b/sys/contrib/rdma/krping/krping.c index 931f760..8e91e2a 100644 --- a/sys/contrib/rdma/krping/krping.c +++ b/sys/contrib/rdma/krping/krping.c @@ -54,8 +54,8 @@ __FBSDID("$FreeBSD$"); #include "getopt.h" extern int krping_debug; -#define DEBUG_LOG(cb, x...) if (krping_debug) krping_printf((cb)->cookie, x) -#define PRINTF(cb, x...) krping_printf((cb)->cookie, x) +#define DEBUG_LOG(cb, x...) if (krping_debug) log(LOG_INFO, x) +#define PRINTF(cb, x...) log(LOG_INFO, x) #define BIND_INFO 1 MODULE_AUTHOR("Steve Wise"); @@ -376,8 +376,8 @@ static void krping_cq_event_handler(struct ib_cq *cq, void *ctx) continue; } else { PRINTF(cb, "cq completion failed with " - "wr_id %Lx status %d opcode %d vender_err %x\n", - wc.wr_id, wc.status, wc.opcode, wc.vendor_err); + "wr_id %jx status %d opcode %d vender_err %x\n", + (uintmax_t)wc.wr_id, wc.status, wc.opcode, wc.vendor_err); goto error; } } @@ -570,8 +570,8 @@ static int krping_setup_buffers(struct krping_cb *cb) if (!cb->local_dma_lkey) { buf.addr = cb->recv_dma_addr; buf.size = sizeof cb->recv_buf; - DEBUG_LOG(cb, "recv buf dma_addr %llx size %d\n", buf.addr, - (int)buf.size); + DEBUG_LOG(cb, "recv buf dma_addr %jx size %d\n", + (uintmax_t)buf.addr, (int)buf.size); iovbase = cb->recv_dma_addr; cb->recv_mr = ib_reg_phys_mr(cb->pd, &buf, 1, IB_ACCESS_LOCAL_WRITE, @@ -585,8 +585,8 @@ static int krping_setup_buffers(struct krping_cb *cb) buf.addr = cb->send_dma_addr; buf.size = sizeof cb->send_buf; - DEBUG_LOG(cb, "send buf dma_addr %llx size %d\n", buf.addr, - (int)buf.size); + DEBUG_LOG(cb, "send buf dma_addr %jx size %d\n", + (uintmax_t)buf.addr, (int)buf.size); iovbase = cb->send_dma_addr; cb->send_mr = ib_reg_phys_mr(cb->pd, &buf, 1, 0, &iovbase); @@ -657,8 +657,8 @@ static int krping_setup_buffers(struct krping_cb *cb) ret = PTR_ERR(cb->rdma_mr); goto bail; } - DEBUG_LOG(cb, "rdma buf dma_addr %llx size %d mr rkey 0x%x\n", - buf.addr, (int)buf.size, cb->rdma_mr->rkey); + DEBUG_LOG(cb, "rdma buf dma_addr %jx size %d mr rkey 0x%x\n", + (uintmax_t)buf.addr, (int)buf.size, cb->rdma_mr->rkey); break; default: ret = -EINVAL; @@ -691,8 +691,8 @@ static int krping_setup_buffers(struct krping_cb *cb) buf.addr = cb->start_dma_addr; buf.size = cb->size; - DEBUG_LOG(cb, "start buf dma_addr %llx size %d\n", - buf.addr, (int)buf.size); + DEBUG_LOG(cb, "start buf dma_addr %jx size %d\n", + (uintmax_t)buf.addr, (int)buf.size); iovbase = cb->start_dma_addr; cb->start_mr = ib_reg_phys_mr(cb->pd, &buf, 1, flags, @@ -882,16 +882,16 @@ static u32 krping_rdma_rkey(struct krping_cb *cb, u64 buf, int post_inv) for (i=0; i < cb->fastreg_wr.wr.fast_reg.page_list_len; i++, p += PAGE_SIZE) { cb->page_list->page_list[i] = p; - DEBUG_LOG(cb, "page_list[%d] 0x%llx\n", i, p); + DEBUG_LOG(cb, "page_list[%d] 0x%jx\n", i, (uintmax_t)p); } DEBUG_LOG(cb, "post_inv = %d, fastreg new rkey 0x%x shift %u len %u" - " iova_start %llx page_list_len %u\n", + " iova_start %jx page_list_len %u\n", post_inv, cb->fastreg_wr.wr.fast_reg.rkey, cb->fastreg_wr.wr.fast_reg.page_shift, cb->fastreg_wr.wr.fast_reg.length, - cb->fastreg_wr.wr.fast_reg.iova_start, + (uintmax_t)cb->fastreg_wr.wr.fast_reg.iova_start, cb->fastreg_wr.wr.fast_reg.page_list_len); if (post_inv) @@ -930,9 +930,9 @@ static u32 krping_rdma_rkey(struct krping_cb *cb, u64 buf, int post_inv) #else cb->bind_attr.addr = buf; #endif - DEBUG_LOG(cb, "binding mw rkey 0x%x to buf %llx mr rkey 0x%x\n", + DEBUG_LOG(cb, "binding mw rkey 0x%x to buf %jx mr rkey 0x%x\n", #ifdef BIND_INFO - cb->mw->rkey, buf, cb->bind_attr.bind_info.mr->rkey); + cb->mw->rkey, (uintmax_t)buf, cb->bind_attr.bind_info.mr->rkey); #else cb->mw->rkey, buf, cb->bind_attr.mr->rkey); #endif @@ -1199,8 +1199,8 @@ static void rlat_test(struct krping_cb *cb) } PRINTF(cb, "delta sec %lu delta usec %lu iter %d size %d\n", - stop_tv.tv_sec - start_tv.tv_sec, - stop_tv.tv_usec - start_tv.tv_usec, + (unsigned long)(stop_tv.tv_sec - start_tv.tv_sec), + (unsigned long)(stop_tv.tv_usec - start_tv.tv_usec), scnt, cb->size); } @@ -1333,12 +1333,12 @@ static void wlat_test(struct krping_cb *cb) sum_poll += poll_cycles_stop[i] - poll_cycles_start[i]; sum_last_poll += poll_cycles_stop[i]-last_poll_cycles_start[i]; } - PRINTF(cb, + PRINTF(cb, "delta sec %lu delta usec %lu iter %d size %d cycle_iters %d" " sum_post %llu sum_poll %llu sum_last_poll %llu\n", - stop_tv.tv_sec - start_tv.tv_sec, - stop_tv.tv_usec - start_tv.tv_usec, - scnt, cb->size, cycle_iters, + (unsigned long)(stop_tv.tv_sec - start_tv.tv_sec), + (unsigned long)(stop_tv.tv_usec - start_tv.tv_usec), + scnt, cb->size, cycle_iters, (unsigned long long)sum_post, (unsigned long long)sum_poll, (unsigned long long)sum_last_poll); kfree(post_cycles_start); @@ -1459,11 +1459,11 @@ static void bw_test(struct krping_cb *cb) sum_poll += poll_cycles_stop[i] - poll_cycles_start[i]; sum_last_poll += poll_cycles_stop[i]-last_poll_cycles_start[i]; } - PRINTF(cb, + PRINTF(cb, "delta sec %lu delta usec %lu iter %d size %d cycle_iters %d" " sum_post %llu sum_poll %llu sum_last_poll %llu\n", - stop_tv.tv_sec - start_tv.tv_sec, - stop_tv.tv_usec - start_tv.tv_usec, + (unsigned long)(stop_tv.tv_sec - start_tv.tv_sec), + (unsigned long)(stop_tv.tv_usec - start_tv.tv_usec), scnt, cb->size, cycle_iters, (unsigned long long)sum_post, (unsigned long long)sum_poll, (unsigned long long)sum_last_poll); @@ -1588,12 +1588,12 @@ static int fastreg_supported(struct krping_cb *cb, int server) return 0; } if (!(attr.device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS)) { - PRINTF(cb, "Fastreg not supported - device_cap_flags 0x%x\n", - attr.device_cap_flags); + PRINTF(cb, "Fastreg not supported - device_cap_flags 0x%llx\n", + (unsigned long long)attr.device_cap_flags); return 0; } - DEBUG_LOG(cb, "Fastreg supported - device_cap_flags 0x%x\n", - attr.device_cap_flags); + DEBUG_LOG(cb, "Fastreg supported - device_cap_flags 0x%jx\n", + (uintmax_t)attr.device_cap_flags); return 1; } @@ -1664,19 +1664,19 @@ static void krping_fr_test5(struct krping_cb *cb) } pl = kzalloc(sizeof *pl * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s pl %p size %lu\n", __func__, pl, sizeof *pl * depth); + DEBUG_LOG(cb, "%s pl %p size %zu\n", __func__, pl, sizeof *pl * depth); mr = kzalloc(sizeof *mr * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s mr %p size %lu\n", __func__, mr, sizeof *mr * depth); + DEBUG_LOG(cb, "%s mr %p size %zu\n", __func__, mr, sizeof *mr * depth); fr = kzalloc(sizeof *fr * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s fr %p size %lu\n", __func__, fr, sizeof *fr * depth); + DEBUG_LOG(cb, "%s fr %p size %zu\n", __func__, fr, sizeof *fr * depth); sgl = kzalloc(sizeof *sgl * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s sgl %p size %lu\n", __func__, sgl, sizeof *sgl * depth); + DEBUG_LOG(cb, "%s sgl %p size %zu\n", __func__, sgl, sizeof *sgl * depth); read = kzalloc(sizeof *read * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s read %p size %lu\n", __func__, read, sizeof *read * depth); + DEBUG_LOG(cb, "%s read %p size %zu\n", __func__, read, sizeof *read * depth); buf = kzalloc(sizeof *buf * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s buf %p size %lu\n", __func__, buf, sizeof *buf * depth); + DEBUG_LOG(cb, "%s buf %p size %zu\n", __func__, buf, sizeof *buf * depth); dma_addr = kzalloc(sizeof *dma_addr * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s dma_addr %p size %lu\n", __func__, dma_addr, sizeof *dma_addr * depth); + DEBUG_LOG(cb, "%s dma_addr %p size %zu\n", __func__, dma_addr, sizeof *dma_addr * depth); if (!pl || !mr || !fr || !read || !sgl || !buf || !dma_addr) { PRINTF(cb, "kzalloc failed\n"); goto err1; @@ -1719,16 +1719,16 @@ static void krping_fr_test5(struct krping_cb *cb) DEBUG_LOG(cb, "%s dma_addr[%u] %p\n", __func__, scnt, (void *)dma_addr[scnt]); for (i=0; i<plen; i++) { pl[scnt]->page_list[i] = ((unsigned long)dma_addr[scnt] & PAGE_MASK) + (i * PAGE_SIZE); - DEBUG_LOG(cb, "%s pl[%u]->page_list[%u] 0x%llx\n", - __func__, scnt, i, pl[scnt]->page_list[i]); + DEBUG_LOG(cb, "%s pl[%u]->page_list[%u] 0x%jx\n", + __func__, scnt, i, (uintmax_t)pl[scnt]->page_list[i]); } sgl[scnt].lkey = mr[scnt]->rkey; sgl[scnt].length = cb->size; sgl[scnt].addr = (u64)buf[scnt]; - DEBUG_LOG(cb, "%s sgl[%u].lkey 0x%x length %u addr 0x%llx\n", + DEBUG_LOG(cb, "%s sgl[%u].lkey 0x%x length %u addr 0x%jx\n", __func__, scnt, sgl[scnt].lkey, sgl[scnt].length, - sgl[scnt].addr); + (uintmax_t)sgl[scnt].addr); fr[scnt].opcode = IB_WR_FAST_REG_MR; fr[scnt].wr_id = scnt; @@ -1778,9 +1778,9 @@ static void krping_fr_test5(struct krping_cb *cb) if (ret == 1) { if (wc.status) { PRINTF(cb, - "completion error %u wr_id %lld " + "completion error %u wr_id %ju " "opcode %d\n", wc.status, - wc.wr_id, wc.opcode); + (uintmax_t)wc.wr_id, wc.opcode); goto err2; } count++; @@ -1877,8 +1877,8 @@ static void krping_fr_test5_server(struct krping_cb *cb) while (cb->state < RDMA_READ_ADV) { krping_cq_event_handler(cb->cq, cb); } - DEBUG_LOG(cb, "%s client STAG %x TO 0x%llx\n", __func__, - cb->remote_rkey, cb->remote_addr); + DEBUG_LOG(cb, "%s client STAG %x TO 0x%jx\n", __func__, + cb->remote_rkey, (uintmax_t)cb->remote_addr); /* Send STAG/TO/Len to client */ krping_format_send(cb, cb->start_dma_addr); @@ -1940,7 +1940,8 @@ static void krping_fr_test5_client(struct krping_cb *cb) while (cb->state < RDMA_WRITE_ADV) { krping_cq_event_handler(cb->cq, cb); } - DEBUG_LOG(cb, "%s server STAG %x TO 0x%llx\n", __func__, cb->remote_rkey, cb->remote_addr); + DEBUG_LOG(cb, "%s server STAG %x TO 0x%jx\n", __func__, cb->remote_rkey, + (uintmax_t)cb->remote_addr); return krping_fr_test5(cb); } @@ -1978,28 +1979,28 @@ static void krping_fr_test6(struct krping_cb *cb) } pl = kzalloc(sizeof *pl * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s pl %p size %lu\n", __func__, pl, sizeof *pl * depth); + DEBUG_LOG(cb, "%s pl %p size %zu\n", __func__, pl, sizeof *pl * depth); mr = kzalloc(sizeof *mr * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s mr %p size %lu\n", __func__, mr, sizeof *mr * depth); + DEBUG_LOG(cb, "%s mr %p size %zu\n", __func__, mr, sizeof *mr * depth); fr = kzalloc(sizeof *fr * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s fr %p size %lu\n", __func__, fr, sizeof *fr * depth); + DEBUG_LOG(cb, "%s fr %p size %zu\n", __func__, fr, sizeof *fr * depth); sgl = kzalloc(sizeof *sgl * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s sgl %p size %lu\n", __func__, sgl, sizeof *sgl * depth); + DEBUG_LOG(cb, "%s sgl %p size %zu\n", __func__, sgl, sizeof *sgl * depth); write = kzalloc(sizeof *write * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s read %p size %lu\n", __func__, write, sizeof *write * depth); + DEBUG_LOG(cb, "%s read %p size %zu\n", __func__, write, sizeof *write * depth); inv = kzalloc(sizeof *inv * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s inv %p size %lu\n", __func__, inv, sizeof *inv * depth); + DEBUG_LOG(cb, "%s inv %p size %zu\n", __func__, inv, sizeof *inv * depth); buf = kzalloc(sizeof *buf * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s buf %p size %lu\n", __func__, buf, sizeof *buf * depth); + DEBUG_LOG(cb, "%s buf %p size %zu\n", __func__, buf, sizeof *buf * depth); dma_addr = kzalloc(sizeof *dma_addr * depth, GFP_KERNEL); - DEBUG_LOG(cb, "%s dma_addr %p size %lu\n", __func__, dma_addr, sizeof *dma_addr * depth); + DEBUG_LOG(cb, "%s dma_addr %p size %zu\n", __func__, dma_addr, sizeof *dma_addr * depth); if (!pl || !mr || !fr || !write || !sgl || !buf || !dma_addr) { PRINTF(cb, "kzalloc failed\n"); @@ -2043,8 +2044,8 @@ static void krping_fr_test6(struct krping_cb *cb) DEBUG_LOG(cb, "%s dma_addr[%u] %p\n", __func__, scnt, (void *)dma_addr[scnt]); for (i=0; i<plen; i++) { pl[scnt]->page_list[i] = ((unsigned long)dma_addr[scnt] & PAGE_MASK) + (i * PAGE_SIZE); - DEBUG_LOG(cb, "%s pl[%u]->page_list[%u] 0x%llx\n", - __func__, scnt, i, pl[scnt]->page_list[i]); + DEBUG_LOG(cb, "%s pl[%u]->page_list[%u] 0x%jx\n", + __func__, scnt, i, (uintmax_t)pl[scnt]->page_list[i]); } write[scnt].opcode = IB_WR_RDMA_WRITE; @@ -2101,9 +2102,9 @@ static void krping_fr_test6(struct krping_cb *cb) if (ret == 1) { if (wc.status) { PRINTF(cb, - "completion error %u wr_id %lld " + "completion error %u wr_id %ju " "opcode %d\n", wc.status, - wc.wr_id, wc.opcode); + (uintmax_t)wc.wr_id, wc.opcode); goto err2; } count++; @@ -2200,8 +2201,8 @@ static void krping_fr_test6_server(struct krping_cb *cb) while (cb->state < RDMA_READ_ADV) { krping_cq_event_handler(cb->cq, cb); } - DEBUG_LOG(cb, "%s client STAG %x TO 0x%llx\n", __func__, - cb->remote_rkey, cb->remote_addr); + DEBUG_LOG(cb, "%s client STAG %x TO 0x%jx\n", __func__, + cb->remote_rkey, (uintmax_t)cb->remote_addr); /* Send STAG/TO/Len to client */ krping_format_send(cb, cb->start_dma_addr); @@ -2263,7 +2264,8 @@ static void krping_fr_test6_client(struct krping_cb *cb) while (cb->state < RDMA_WRITE_ADV) { krping_cq_event_handler(cb->cq, cb); } - DEBUG_LOG(cb, "%s server STAG %x TO 0x%llx\n", __func__, cb->remote_rkey, cb->remote_addr); + DEBUG_LOG(cb, "%s server STAG %x TO 0x%jx\n", __func__, cb->remote_rkey, + (uintmax_t)cb->remote_addr); return krping_fr_test6(cb); } diff --git a/sys/contrib/rdma/krping/krping.h b/sys/contrib/rdma/krping/krping.h index 04be531..f201d10 100644 --- a/sys/contrib/rdma/krping/krping.h +++ b/sys/contrib/rdma/krping/krping.h @@ -17,5 +17,4 @@ struct krping_stats { int krping_doit(char *, void *); void krping_walk_cb_list(void (*)(struct krping_stats *, void *), void *); void krping_init(void); -void krping_printf(void *, const char *, ...); int krping_sigpending(void); diff --git a/sys/contrib/rdma/krping/krping_dev.c b/sys/contrib/rdma/krping/krping_dev.c index 2244d72..7902ebf 100644 --- a/sys/contrib/rdma/krping/krping_dev.c +++ b/sys/contrib/rdma/krping/krping_dev.c @@ -209,16 +209,6 @@ krping_write(struct cdev *dev, struct uio *uio, int ioflag) return(err); } -void -krping_printf(void *cookie, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vtprintf(cookie, -1, fmt, ap); - va_end(ap); -} - int krping_sigpending(void) { diff --git a/sys/ddb/db_command.c b/sys/ddb/db_command.c index 0d4f28f..4f66498 100644 --- a/sys/ddb/db_command.c +++ b/sys/ddb/db_command.c @@ -144,7 +144,7 @@ static struct command db_cmds[] = { }; struct command_table db_cmd_table = LIST_HEAD_INITIALIZER(db_cmd_table); -static struct command *db_last_command = 0; +static struct command *db_last_command = NULL; /* * if 'ed' style: 'dot' is set at start of last item printed, @@ -429,7 +429,7 @@ db_command(struct command **last_cmdp, struct command_table *cmd_table, } } *last_cmdp = cmd; - if (cmd != 0) { + if (cmd != NULL) { /* * Execute the command. */ diff --git a/sys/ddb/db_ps.c b/sys/ddb/db_ps.c index 76ab2c5..e20b363 100644 --- a/sys/ddb/db_ps.c +++ b/sys/ddb/db_ps.c @@ -184,7 +184,8 @@ db_ps(db_expr_t addr, bool hasaddr, db_expr_t count, char *modif) strlcat(state, "V", sizeof(state)); if (p->p_flag & P_SYSTEM || p->p_lock > 0) strlcat(state, "L", sizeof(state)); - if (p->p_session != NULL && SESS_LEADER(p)) + if (p->p_pgrp != NULL && p->p_session != NULL && + SESS_LEADER(p)) strlcat(state, "s", sizeof(state)); /* Cheated here and didn't compare pgid's. */ if (p->p_flag & P_CONTROLT) diff --git a/sys/ddb/db_sym.c b/sys/ddb/db_sym.c index ffcba79..25ae4bc 100644 --- a/sys/ddb/db_sym.c +++ b/sys/ddb/db_sym.c @@ -395,7 +395,7 @@ db_symbol_values(c_db_sym_t sym, const char **namep, db_expr_t *valuep) db_expr_t value; if (sym == DB_SYM_NULL) { - *namep = 0; + *namep = NULL; return; } @@ -438,13 +438,13 @@ db_printsym(db_expr_t off, db_strategy_t strategy) cursym = db_search_symbol(off, strategy, &d); db_symbol_values(cursym, &name, &value); - if (name == 0) + if (name == NULL) value = off; if (value >= DB_SMALL_VALUE_MIN && value <= DB_SMALL_VALUE_MAX) { db_printf("%+#lr", (long)off); return; } - if (name == 0 || d >= (unsigned long)db_maxoff) { + if (name == NULL || d >= (unsigned long)db_maxoff) { db_printf("%#lr", (unsigned long)off); return; } diff --git a/sys/dev/acpica/acpi_pci.c b/sys/dev/acpica/acpi_pci.c index 1dee131..44b5804 100644 --- a/sys/dev/acpica/acpi_pci.c +++ b/sys/dev/acpica/acpi_pci.c @@ -70,7 +70,7 @@ CTASSERT(ACPI_STATE_D1 == PCI_POWERSTATE_D1); CTASSERT(ACPI_STATE_D2 == PCI_POWERSTATE_D2); CTASSERT(ACPI_STATE_D3 == PCI_POWERSTATE_D3); -static int acpi_pci_attach(device_t dev); +static struct pci_devinfo *acpi_pci_alloc_devinfo(device_t dev); static void acpi_pci_child_deleted(device_t dev, device_t child); static int acpi_pci_child_location_str_method(device_t cbdev, device_t child, char *buf, size_t buflen); @@ -86,15 +86,9 @@ static int acpi_pci_set_powerstate_method(device_t dev, device_t child, static void acpi_pci_update_device(ACPI_HANDLE handle, device_t pci_child); static bus_dma_tag_t acpi_pci_get_dma_tag(device_t bus, device_t child); -#ifdef PCI_IOV -static device_t acpi_pci_create_iov_child(device_t bus, device_t pf, - uint16_t rid, uint16_t vid, uint16_t did); -#endif - static device_method_t acpi_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, acpi_pci_probe), - DEVMETHOD(device_attach, acpi_pci_attach), /* Bus interface */ DEVMETHOD(bus_read_ivar, acpi_pci_read_ivar), @@ -105,11 +99,9 @@ static device_method_t acpi_pci_methods[] = { DEVMETHOD(bus_get_domain, acpi_get_domain), /* PCI interface */ + DEVMETHOD(pci_alloc_devinfo, acpi_pci_alloc_devinfo), DEVMETHOD(pci_child_added, acpi_pci_child_added), DEVMETHOD(pci_set_powerstate, acpi_pci_set_powerstate_method), -#ifdef PCI_IOV - DEVMETHOD(pci_create_iov_child, acpi_pci_create_iov_child), -#endif DEVMETHOD_END }; @@ -123,6 +115,15 @@ MODULE_DEPEND(acpi_pci, acpi, 1, 1, 1); MODULE_DEPEND(acpi_pci, pci, 1, 1, 1); MODULE_VERSION(acpi_pci, 1); +static struct pci_devinfo * +acpi_pci_alloc_devinfo(device_t dev) +{ + struct acpi_pci_devinfo *dinfo; + + dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); + return (&dinfo->ap_dinfo); +} + static int acpi_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) { @@ -298,38 +299,6 @@ void acpi_pci_child_added(device_t dev, device_t child) { - AcpiWalkNamespace(ACPI_TYPE_DEVICE, acpi_get_handle(dev), 1, - acpi_pci_save_handle, NULL, child, NULL); -} - -static int -acpi_pci_probe(device_t dev) -{ - - if (acpi_get_handle(dev) == NULL) - return (ENXIO); - device_set_desc(dev, "ACPI PCI bus"); - return (BUS_PROBE_DEFAULT); -} - -static int -acpi_pci_attach(device_t dev) -{ - int busno, domain, error; - - error = pci_attach_common(dev); - if (error) - return (error); - - /* - * Since there can be multiple independantly numbered PCI - * busses on systems with multiple PCI domains, we can't use - * the unit number to decide which bus we are probing. We ask - * the parent pcib what our domain and bus numbers are. - */ - domain = pcib_get_domain(dev); - busno = pcib_get_bus(dev); - /* * PCI devices are added via the bus scan in the normal PCI * bus driver. As each device is added, the @@ -342,9 +311,18 @@ acpi_pci_attach(device_t dev) * pci_add_children() doesn't find. We currently just ignore * these devices. */ - pci_add_children(dev, domain, busno, sizeof(struct acpi_pci_devinfo)); + AcpiWalkNamespace(ACPI_TYPE_DEVICE, acpi_get_handle(dev), 1, + acpi_pci_save_handle, NULL, child, NULL); +} + +static int +acpi_pci_probe(device_t dev) +{ - return (bus_generic_attach(dev)); + if (acpi_get_handle(dev) == NULL) + return (ENXIO); + device_set_desc(dev, "ACPI PCI bus"); + return (BUS_PROBE_DEFAULT); } #ifdef ACPI_DMAR @@ -372,14 +350,3 @@ acpi_pci_get_dma_tag(device_t bus, device_t child) } #endif -#ifdef PCI_IOV -static device_t -acpi_pci_create_iov_child(device_t bus, device_t pf, uint16_t rid, uint16_t vid, - uint16_t did) -{ - - return (pci_add_iov_child(bus, pf, sizeof(struct acpi_pci_devinfo), rid, - vid, did)); -} -#endif - diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c index 8341f66..b27e30d 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -2417,6 +2417,9 @@ ahci_setup_fis(struct ahci_channel *ch, struct ahci_cmd_tab *ctp, union ccb *ccb fis[13] = ccb->ataio.cmd.sector_count_exp; } fis[15] = ATA_A_4BIT; + /* Gross and vile hack -- makes ncq trim work w/o changing ataio size */ + if (ccb->ataio.cmd.flags & CAM_ATAIO_AUX_HACK) + fis[16] = 1; } else { fis[15] = ccb->ataio.cmd.control; } @@ -2674,7 +2677,7 @@ ahciaction(struct cam_sim *sim, union ccb *ccb) if (ch->caps & AHCI_CAP_SPM) cpi->hba_inquiry |= PI_SATAPM; cpi->target_sprt = 0; - cpi->hba_misc = PIM_SEQSCAN | PIM_UNMAPPED; + cpi->hba_misc = PIM_SEQSCAN | PIM_UNMAPPED | PIM_NCQ_KLUDGE; cpi->hba_eng_cnt = 0; if (ch->caps & AHCI_CAP_SPM) cpi->max_target = 15; diff --git a/sys/dev/cardbus/cardbus.c b/sys/dev/cardbus/cardbus.c index e785b0f..a6037e1 100644 --- a/sys/dev/cardbus/cardbus.c +++ b/sys/dev/cardbus/cardbus.c @@ -169,6 +169,15 @@ cardbus_device_setup_regs(pcicfgregs *cfg) pci_write_config(dev, PCIR_MAXLAT, 0x14, 1); } +static struct pci_devinfo * +cardbus_alloc_devinfo(device_t dev) +{ + struct cardbus_devinfo *dinfo; + + dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); + return (&dinfo->pci); +} + static int cardbus_attach_card(device_t cbdev) { @@ -191,8 +200,7 @@ cardbus_attach_card(device_t cbdev) struct cardbus_devinfo *dinfo; dinfo = (struct cardbus_devinfo *) - pci_read_device(brdev, domain, bus, slot, func, - sizeof(struct cardbus_devinfo)); + pci_read_device(brdev, cbdev, domain, bus, slot, func); if (dinfo == NULL) continue; if (dinfo->pci.cfg.mfdev) @@ -343,6 +351,9 @@ static device_method_t cardbus_methods[] = { DEVMETHOD(card_attach_card, cardbus_attach_card), DEVMETHOD(card_detach_card, cardbus_detach_card), + /* PCI interface */ + DEVMETHOD(pci_alloc_devinfo, cardbus_alloc_devinfo), + {0,0} }; diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h index 17af344..94f84ff 100644 --- a/sys/dev/fdt/fdt_common.h +++ b/sys/dev/fdt/fdt_common.h @@ -45,7 +45,7 @@ struct fdt_sense_level { enum intr_polarity pol; }; -#if defined(__arm__) && !defined(ARM_INTRNG) +#if defined(__arm__) && !defined(INTRNG) typedef int (*fdt_pic_decode_t)(phandle_t, pcell_t *, int *, int *, int *); extern fdt_pic_decode_t fdt_pic_table[]; #endif diff --git a/sys/dev/fdt/fdt_powerpc.c b/sys/dev/fdt/fdt_powerpc.c index f408d0a..80cfa4b 100644 --- a/sys/dev/fdt/fdt_powerpc.c +++ b/sys/dev/fdt/fdt_powerpc.c @@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$"); #include "fdt_common.h" static void -fdt_fixup_busfreq(phandle_t root) +fdt_fixup_busfreq(phandle_t root, uint32_t div) { phandle_t sb, cpus, child; pcell_t freq; @@ -72,12 +72,71 @@ fdt_fixup_busfreq(phandle_t root) sizeof(freq)) <= 0) return; + if (div == 0) + return; + + freq /= div; + OF_setprop(sb, "bus-frequency", (void *)&freq, sizeof(freq)); } +static void +fdt_fixup_busfreq_mpc85xx(phandle_t root) +{ + + fdt_fixup_busfreq(root, 1); +} + +static void +fdt_fixup_busfreq_dpaa(phandle_t root) +{ + + fdt_fixup_busfreq(root, 2); +} + +static void +fdt_fixup_fman(phandle_t root) +{ + phandle_t node; + pcell_t freq; + + if ((node = fdt_find_compatible(root, "simple-bus", 1)) == 0) + return; + + if (OF_getprop(node, "bus-frequency", (void *)&freq, + sizeof(freq)) <= 0) + return; + + /* + * Set clock-frequency for FMan nodes (only on QorIQ DPAA targets). + * That frequency is equal to /soc node bus-frequency. + */ + for (node = OF_child(node); node != 0; node = OF_peer(node)) { + if (fdt_is_compatible(node, "fsl,fman") == 0) + continue; + + if (OF_setprop(node, "clock-frequency", (void *)&freq, + sizeof(freq)) == -1) { + /* + * XXX Shall we take some actions if no clock-frequency + * property was found? + */ + } + } +} + struct fdt_fixup_entry fdt_fixup_table[] = { - { "fsl,MPC8572DS", &fdt_fixup_busfreq }, - { "MPC8555CDS", &fdt_fixup_busfreq }, + { "fsl,MPC8572DS", &fdt_fixup_busfreq_mpc85xx }, + { "MPC8555CDS", &fdt_fixup_busfreq_mpc85xx }, + { "fsl,P2020", &fdt_fixup_busfreq_mpc85xx }, + { "fsl,P2041RDB", &fdt_fixup_busfreq_dpaa }, + { "fsl,P2041RDB", &fdt_fixup_fman }, + { "fsl,P3041DS", &fdt_fixup_busfreq_dpaa }, + { "fsl,P3041DS", &fdt_fixup_fman }, + { "fsl,P5020DS", &fdt_fixup_busfreq_dpaa }, + { "fsl,P5020DS", &fdt_fixup_fman }, + { "varisys,CYRUS", &fdt_fixup_busfreq_dpaa }, + { "varisys,CYRUS", &fdt_fixup_fman }, { NULL, NULL } }; diff --git a/sys/dev/flash/mx25l.c b/sys/dev/flash/mx25l.c index 6b71340..96fb4a4 100644 --- a/sys/dev/flash/mx25l.c +++ b/sys/dev/flash/mx25l.c @@ -432,6 +432,12 @@ mx25l_set_4b_mode(device_t dev, uint8_t command) return (err); } +static struct ofw_compat_data compat_data[] = { + { "st,m25p", 1 }, + { "jedec,spi-nor", 1 }, + { NULL, 0 }, +}; + static int mx25l_probe(device_t dev) { @@ -439,7 +445,7 @@ mx25l_probe(device_t dev) #ifdef FDT if (!ofw_bus_status_okay(dev)) return (ENXIO); - if (!ofw_bus_is_compatible(dev, "st,m25p")) + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) return (ENXIO); #endif device_set_desc(dev, "M25Pxx Flash Family"); diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 933f454..153f9c3 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -419,7 +419,6 @@ netvsc_attach(device_t dev) sc = device_get_softc(dev); - bzero(sc, sizeof(hn_softc_t)); sc->hn_unit = unit; sc->hn_dev = dev; @@ -2809,8 +2808,10 @@ hn_channel_attach(struct hn_softc *sc, struct hv_vmbus_channel *chan) rxr->hn_rx_flags |= HN_RX_FLAG_ATTACHED; chan->hv_chan_rxr = rxr; - if_printf(sc->hn_ifp, "link RX ring %d to channel%u\n", - idx, chan->offer_msg.child_rel_id); + if (bootverbose) { + if_printf(sc->hn_ifp, "link RX ring %d to channel%u\n", + idx, chan->offer_msg.child_rel_id); + } if (idx < sc->hn_tx_ring_inuse) { struct hn_tx_ring *txr = &sc->hn_tx_ring[idx]; @@ -2821,8 +2822,10 @@ hn_channel_attach(struct hn_softc *sc, struct hv_vmbus_channel *chan) chan->hv_chan_txr = txr; txr->hn_chan = chan; - if_printf(sc->hn_ifp, "link TX ring %d to channel%u\n", - idx, chan->offer_msg.child_rel_id); + if (bootverbose) { + if_printf(sc->hn_ifp, "link TX ring %d to channel%u\n", + idx, chan->offer_msg.child_rel_id); + } } /* Bind channel to a proper CPU */ diff --git a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c index 38f2f28..10d513c 100644 --- a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c +++ b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c @@ -981,8 +981,6 @@ storvsc_attach(device_t dev) goto cleanup; } - bzero(sc, sizeof(struct storvsc_softc)); - /* fill in driver specific properties */ sc->hs_drv_props = &g_drv_props_table[stor_type]; @@ -1259,6 +1257,7 @@ storvsc_timeout_test(struct hv_storvsc_request *reqp, } #endif /* HVS_TIMEOUT_TEST */ +#ifdef notyet /** * @brief timeout handler for requests * @@ -1306,6 +1305,7 @@ storvsc_timeout(void *arg) storvsc_timeout_test(reqp, MODE_SELECT_10, 1); #endif } +#endif /** * @brief StorVSC device poll function @@ -1458,6 +1458,7 @@ storvsc_action(struct cam_sim *sim, union ccb *ccb) return; } +#ifdef notyet if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { callout_init(&reqp->callout, 1); callout_reset_sbt(&reqp->callout, @@ -1477,6 +1478,7 @@ storvsc_action(struct cam_sim *sim, union ccb *ccb) } #endif /* HVS_TIMEOUT_TEST */ } +#endif if ((res = hv_storvsc_io_request(sc->hs_dev, reqp)) != 0) { xpt_print(ccb->ccb_h.path, @@ -2024,6 +2026,7 @@ storvsc_io_done(struct hv_storvsc_request *reqp) mtx_unlock(&sc->hs_lock); } +#ifdef notyet /* * callout_drain() will wait for the timer handler to finish * if it is running. So we don't need any lock to synchronize @@ -2034,6 +2037,7 @@ storvsc_io_done(struct hv_storvsc_request *reqp) if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { callout_drain(&reqp->callout); } +#endif ccb->ccb_h.status &= ~CAM_SIM_QUEUED; ccb->ccb_h.status &= ~CAM_STATUS_MASK; @@ -2087,8 +2091,9 @@ storvsc_io_done(struct hv_storvsc_request *reqp) reqp->softc->hs_frozen = 0; } storvsc_free_request(sc, reqp); - xpt_done(ccb); mtx_unlock(&sc->hs_lock); + + xpt_done_direct(ccb); } /** diff --git a/sys/dev/hyperv/vmbus/amd64/hv_vector.S b/sys/dev/hyperv/vmbus/amd64/hv_vector.S new file mode 100644 index 0000000..2594483 --- /dev/null +++ b/sys/dev/hyperv/vmbus/amd64/hv_vector.S @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2016 Microsoft Corp. + * 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$ + */ + +#include <machine/asmacros.h> +#include <machine/specialreg.h> + +#include "assym.s" + +/* + * This is the Hyper-V vmbus channel direct callback interrupt. + * Only used when it is running on Hyper-V. + */ + .text + SUPERALIGN_TEXT +IDTVEC(hv_vmbus_callback) + PUSH_FRAME + FAKE_MCOUNT(TF_RIP(%rsp)) + movq %rsp, %rdi + call hv_vector_handler + MEXITCOUNT + jmp doreti diff --git a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c index 42d3750..0094187 100644 --- a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c +++ b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c @@ -219,10 +219,14 @@ vmbus_channel_process_offer(hv_vmbus_channel *new_channel) sc_list_entry); mtx_unlock(&channel->sc_lock); + if (bootverbose) { + printf("VMBUS get multi-channel offer, " + "rel=%u, sub=%u\n", + new_channel->offer_msg.child_rel_id, + new_channel->offer_msg.offer.sub_channel_index); + } + /* Insert new channel into channel_anchor. */ - printf("VMBUS get multi-channel offer, rel=%u,sub=%u\n", - new_channel->offer_msg.child_rel_id, - new_channel->offer_msg.offer.sub_channel_index); mtx_lock(&hv_vmbus_g_connection.channel_lock); TAILQ_INSERT_TAIL(&hv_vmbus_g_connection.channel_anchor, new_channel, list_entry); diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c index 44e19d2..ec4b26f 100644 --- a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c +++ b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c @@ -370,9 +370,7 @@ vmbus_probe(device_t dev) { return (BUS_PROBE_DEFAULT); } -#ifdef HYPERV extern inthand_t IDTVEC(hv_vmbus_callback); -#endif /** * @brief Main vmbus driver initialization routine. @@ -406,14 +404,10 @@ vmbus_bus_init(void) return (ret); } -#ifdef HYPERV /* * Find a free IDT slot for vmbus callback. */ hv_vmbus_g_context.hv_cb_vector = lapic_ipi_alloc(IDTVEC(hv_vmbus_callback)); -#else - hv_vmbus_g_context.hv_cb_vector = -1; -#endif if (hv_vmbus_g_context.hv_cb_vector < 0) { if(bootverbose) printf("Error VMBUS: Cannot find free IDT slot for " diff --git a/sys/dev/hyperv/vmbus/i386/hv_vector.S b/sys/dev/hyperv/vmbus/i386/hv_vector.S new file mode 100644 index 0000000..55a2613 --- /dev/null +++ b/sys/dev/hyperv/vmbus/i386/hv_vector.S @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2016 Microsoft Corp. + * 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$ + */ + +#include <machine/asmacros.h> +#include <machine/specialreg.h> + +#include "assym.s" + +/* + * This is the Hyper-V vmbus channel direct callback interrupt. + * Only used when it is running on Hyper-V. + */ + .text + SUPERALIGN_TEXT +IDTVEC(hv_vmbus_callback) + PUSH_FRAME + SET_KERNEL_SREGS + cld + FAKE_MCOUNT(TF_EIP(%esp)) + pushl %esp + call hv_vector_handler + add $4, %esp + MEXITCOUNT + jmp doreti diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index dd8112f..01d7cbb 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -3011,7 +3011,6 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay) return (0); isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan); - fcp->isp_loopstate = LOOP_TESTING_LINK; /* * Wait up to N microseconds for F/W to go to a ready state. @@ -3022,7 +3021,7 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay) if (fcp->isp_fwstate == FW_READY) { break; } - if (fcp->isp_loopstate < LOOP_TESTING_LINK) + if (fcp->isp_loopstate < LOOP_HAVE_LINK) goto abort; GET_NANOTIME(&hrb); if ((NANOTIME_SUB(&hrb, &hra) / 1000 + 1000 >= usdelay)) @@ -3077,6 +3076,11 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay) fcp->isp_loopid = i; } +#if 0 + fcp->isp_loopstate = LOOP_HAVE_ADDR; +#endif + fcp->isp_loopstate = LOOP_TESTING_LINK; + if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) { nphdl = IS_24XX(isp) ? NPH_FL_ID : FL_ID; r = isp_getpdb(isp, chan, nphdl, &pdb); @@ -6138,7 +6142,7 @@ isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *opt { isp_ridacq_t rid; int chan, c; - uint32_t hdl; + uint32_t hdl, portid; void *ptr; switch (type) { @@ -6150,6 +6154,8 @@ isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *opt return (1); case RQSTYPE_RPT_ID_ACQ: isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid); + portid = (uint32_t)rid.ridacq_vp_port_hi << 16 | + rid.ridacq_vp_port_lo; if (rid.ridacq_format == 0) { for (chan = 0; chan < isp->isp_nchan; chan++) { fcparam *fcp = FCPARAM(isp, chan); @@ -6171,7 +6177,9 @@ isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *opt fcparam *fcp = FCPARAM(isp, rid.ridacq_vp_index); if (rid.ridacq_vp_status == RIDACQ_STS_COMPLETE || rid.ridacq_vp_status == RIDACQ_STS_CHANGED) { - fcp->isp_loopstate = LOOP_HAVE_LINK; + fcp->isp_topo = (rid.ridacq_map[0] >> 9) & 0x7; + fcp->isp_portid = portid; + fcp->isp_loopstate = LOOP_HAVE_ADDR; isp_async(isp, ISPASYNC_CHANGE_NOTIFY, rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER); } else { diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c index c7bce2d..48e0535 100644 --- a/sys/dev/isp/isp_library.c +++ b/sys/dev/isp/isp_library.c @@ -532,6 +532,7 @@ isp_fc_loop_statename(int state) switch (state) { case LOOP_NIL: return "NIL"; case LOOP_HAVE_LINK: return "Have Link"; + case LOOP_HAVE_ADDR: return "Have Address"; case LOOP_TESTING_LINK: return "Testing Link"; case LOOP_LTEST_DONE: return "Link Test Done"; case LOOP_SCANNING_LOOP: return "Scanning Loop"; @@ -548,7 +549,7 @@ const char * isp_fc_toponame(fcparam *fcp) { - if (fcp->isp_loopstate < LOOP_LTEST_DONE) { + if (fcp->isp_loopstate < LOOP_HAVE_ADDR) { return "Unavailable"; } switch (fcp->isp_topo) { @@ -2329,7 +2330,7 @@ isp_find_chan_by_did(ispsoftc_t *isp, uint32_t did, uint16_t *cp) for (chan = 0; chan < isp->isp_nchan; chan++) { fcparam *fcp = FCPARAM(isp, chan); if ((fcp->role & ISP_ROLE_TARGET) == 0 || - fcp->isp_loopstate < LOOP_LTEST_DONE) { + fcp->isp_loopstate < LOOP_HAVE_ADDR) { continue; } if (fcp->isp_portid == did) { diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index 104782b..a97a04f 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -490,14 +490,15 @@ typedef struct { #define LOOP_NIL 0 #define LOOP_HAVE_LINK 1 -#define LOOP_TESTING_LINK 2 -#define LOOP_LTEST_DONE 3 -#define LOOP_SCANNING_LOOP 4 -#define LOOP_LSCAN_DONE 5 -#define LOOP_SCANNING_FABRIC 6 -#define LOOP_FSCAN_DONE 7 -#define LOOP_SYNCING_PDB 8 -#define LOOP_READY 9 +#define LOOP_HAVE_ADDR 2 +#define LOOP_TESTING_LINK 3 +#define LOOP_LTEST_DONE 4 +#define LOOP_SCANNING_LOOP 5 +#define LOOP_LSCAN_DONE 6 +#define LOOP_SCANNING_FABRIC 7 +#define LOOP_FSCAN_DONE 8 +#define LOOP_SYNCING_PDB 9 +#define LOOP_READY 10 #define TOPO_NL_PORT 0 #define TOPO_FL_PORT 1 diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index fbe9abd..273ab4b 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -126,8 +126,8 @@ static int pci_remap_intr_method(device_t bus, device_t dev, static uint16_t pci_get_rid_method(device_t dev, device_t child); -static struct pci_devinfo * pci_fill_devinfo(device_t pcib, int d, int b, int s, - int f, uint16_t vid, uint16_t did, size_t size); +static struct pci_devinfo * pci_fill_devinfo(device_t pcib, device_t bus, int d, + int b, int s, int f, uint16_t vid, uint16_t did); static device_method_t pci_methods[] = { /* Device interface */ @@ -196,6 +196,7 @@ static device_method_t pci_methods[] = { DEVMETHOD(pci_msix_pba_bar, pci_msix_pba_bar_method), DEVMETHOD(pci_msix_table_bar, pci_msix_table_bar_method), DEVMETHOD(pci_get_rid, pci_get_rid_method), + DEVMETHOD(pci_alloc_devinfo, pci_alloc_devinfo_method), DEVMETHOD(pci_child_added, pci_child_added_method), #ifdef PCI_IOV DEVMETHOD(pci_iov_attach, pci_iov_attach_method), @@ -619,7 +620,7 @@ pci_hdrtypedata(device_t pcib, int b, int s, int f, pcicfgregs *cfg) /* read configuration header into pcicfgregs structure */ struct pci_devinfo * -pci_read_device(device_t pcib, int d, int b, int s, int f, size_t size) +pci_read_device(device_t pcib, device_t bus, int d, int b, int s, int f) { #define REG(n, w) PCIB_READ_CONFIG(pcib, b, s, f, n, w) uint16_t vid, did; @@ -627,19 +628,27 @@ pci_read_device(device_t pcib, int d, int b, int s, int f, size_t size) vid = REG(PCIR_VENDOR, 2); did = REG(PCIR_DEVICE, 2); if (vid != 0xffff) - return (pci_fill_devinfo(pcib, d, b, s, f, vid, did, size)); + return (pci_fill_devinfo(pcib, bus, d, b, s, f, vid, did)); return (NULL); } +struct pci_devinfo * +pci_alloc_devinfo_method(device_t dev) +{ + + return (malloc(sizeof(struct pci_devinfo), M_DEVBUF, + M_WAITOK | M_ZERO)); +} + static struct pci_devinfo * -pci_fill_devinfo(device_t pcib, int d, int b, int s, int f, uint16_t vid, - uint16_t did, size_t size) +pci_fill_devinfo(device_t pcib, device_t bus, int d, int b, int s, int f, + uint16_t vid, uint16_t did) { struct pci_devinfo *devlist_entry; pcicfgregs *cfg; - devlist_entry = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); + devlist_entry = PCI_ALLOC_DEVINFO(bus); cfg = &devlist_entry->cfg; @@ -665,7 +674,6 @@ pci_fill_devinfo(device_t pcib, int d, int b, int s, int f, uint16_t vid, cfg->hdrtype &= ~PCIM_MFDEV; STAILQ_INIT(&cfg->maps); - cfg->devinfo_size = size; cfg->iov = NULL; pci_fixancient(cfg); @@ -3854,11 +3862,11 @@ pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask) static struct pci_devinfo * pci_identify_function(device_t pcib, device_t dev, int domain, int busno, - int slot, int func, size_t dinfo_size) + int slot, int func) { struct pci_devinfo *dinfo; - dinfo = pci_read_device(pcib, domain, busno, slot, func, dinfo_size); + dinfo = pci_read_device(pcib, dev, domain, busno, slot, func); if (dinfo != NULL) pci_add_child(dev, dinfo); @@ -3866,7 +3874,7 @@ pci_identify_function(device_t pcib, device_t dev, int domain, int busno, } void -pci_add_children(device_t dev, int domain, int busno, size_t dinfo_size) +pci_add_children(device_t dev, int domain, int busno) { #define REG(n, w) PCIB_READ_CONFIG(pcib, busno, s, f, n, w) device_t pcib = device_get_parent(dev); @@ -3882,8 +3890,7 @@ pci_add_children(device_t dev, int domain, int busno, size_t dinfo_size) * functions on this bus as ARI changes the set of slots and functions * that are legal on this bus. */ - dinfo = pci_identify_function(pcib, dev, domain, busno, 0, 0, - dinfo_size); + dinfo = pci_identify_function(pcib, dev, domain, busno, 0, 0); if (dinfo != NULL && pci_enable_ari) PCIB_TRY_ENABLE_ARI(pcib, dinfo->cfg.dev); @@ -3893,8 +3900,6 @@ pci_add_children(device_t dev, int domain, int busno, size_t dinfo_size) */ first_func = 1; - KASSERT(dinfo_size >= sizeof(struct pci_devinfo), - ("dinfo_size too small")); maxslots = PCIB_MAXSLOTS(pcib); for (s = 0; s <= maxslots; s++, first_func = 0) { pcifunchigh = 0; @@ -3906,16 +3911,15 @@ pci_add_children(device_t dev, int domain, int busno, size_t dinfo_size) if (hdrtype & PCIM_MFDEV) pcifunchigh = PCIB_MAXFUNCS(pcib); for (f = first_func; f <= pcifunchigh; f++) - pci_identify_function(pcib, dev, domain, busno, s, f, - dinfo_size); + pci_identify_function(pcib, dev, domain, busno, s, f); } #undef REG } #ifdef PCI_IOV device_t -pci_add_iov_child(device_t bus, device_t pf, size_t size, uint16_t rid, - uint16_t vid, uint16_t did) +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; device_t pcib; @@ -3923,23 +3927,12 @@ pci_add_iov_child(device_t bus, device_t pf, size_t size, uint16_t rid, pf_dinfo = device_get_ivars(pf); - /* - * Do a sanity check that we have been passed the correct size. If this - * test fails then likely the pci subclass hasn't implemented the - * pci_create_iov_child method like it's supposed it. - */ - if (size != pf_dinfo->cfg.devinfo_size) { - device_printf(pf, - "PCI subclass does not properly implement PCI_IOV\n"); - return (NULL); - } - pcib = device_get_parent(bus); PCIB_DECODE_RID(pcib, rid, &busno, &slot, &func); - vf_dinfo = pci_fill_devinfo(pcib, pci_get_domain(pcib), busno, slot, func, - vid, did, size); + vf_dinfo = pci_fill_devinfo(pcib, bus, pci_get_domain(pcib), busno, + slot, func, vid, did); vf_dinfo->cfg.flags |= PCICFG_VF; pci_add_child(bus, vf_dinfo); @@ -3952,8 +3945,7 @@ pci_create_iov_child_method(device_t bus, device_t pf, uint16_t rid, uint16_t vid, uint16_t did) { - return (pci_add_iov_child(bus, pf, sizeof(struct pci_devinfo), rid, vid, - did)); + return (pci_add_iov_child(bus, pf, rid, vid, did)); } #endif @@ -4050,7 +4042,7 @@ pci_attach(device_t dev) */ domain = pcib_get_domain(dev); busno = pcib_get_bus(dev); - pci_add_children(dev, domain, busno, sizeof(struct pci_devinfo)); + pci_add_children(dev, domain, busno); return (bus_generic_attach(dev)); } diff --git a/sys/dev/pci/pci_if.m b/sys/dev/pci/pci_if.m index 7049b9f..da80305 100644 --- a/sys/dev/pci/pci_if.m +++ b/sys/dev/pci/pci_if.m @@ -213,6 +213,10 @@ METHOD uint16_t get_rid { device_t child; }; +METHOD struct pci_devinfo * alloc_devinfo { + device_t dev; +}; + METHOD void child_added { device_t dev; device_t child; diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c index d216557..287f5a2 100644 --- a/sys/dev/pci/pci_iov.c +++ b/sys/dev/pci/pci_iov.c @@ -600,14 +600,12 @@ pci_iov_enumerate_vfs(struct pci_devinfo *dinfo, const nvlist_t *config, device_t bus, dev, vf; struct pcicfg_iov *iov; struct pci_devinfo *vfinfo; - size_t size; int i, error; uint16_t vid, did, next_rid; iov = dinfo->cfg.iov; dev = dinfo->cfg.dev; bus = device_get_parent(dev); - size = dinfo->cfg.devinfo_size; next_rid = first_rid; vid = pci_get_vendor(dev); did = IOV_READ(dinfo, PCIR_SRIOV_VF_DID, 2); diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h index e11dcfa..222ffb8 100644 --- a/sys/dev/pci/pci_private.h +++ b/sys/dev/pci/pci_private.h @@ -48,14 +48,14 @@ struct pci_softc { extern int pci_do_power_resume; extern int pci_do_power_suspend; -void pci_add_children(device_t dev, int domain, int busno, - size_t dinfo_size); +void pci_add_children(device_t dev, int domain, int busno); void pci_add_child(device_t bus, struct pci_devinfo *dinfo); -device_t pci_add_iov_child(device_t bus, device_t pf, size_t dinfo_size, - uint16_t rid, uint16_t vid, uint16_t did); +device_t pci_add_iov_child(device_t bus, device_t pf, uint16_t rid, + uint16_t vid, uint16_t did); void pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask); void pci_add_resources_ea(device_t bus, device_t dev, int alloc_iov); +struct pci_devinfo *pci_alloc_devinfo_method(device_t dev); int pci_attach_common(device_t dev); void pci_driver_added(device_t dev, driver_t *driver); int pci_ea_is_enabled(device_t dev, int rid); @@ -117,8 +117,8 @@ int pci_deactivate_resource(device_t dev, device_t child, int type, void pci_delete_resource(device_t dev, device_t child, int type, int rid); struct resource_list *pci_get_resource_list (device_t dev, device_t child); -struct pci_devinfo *pci_read_device(device_t pcib, int d, int b, int s, int f, - size_t size); +struct pci_devinfo *pci_read_device(device_t pcib, device_t bus, int d, int b, + int s, int f); void pci_print_verbose(struct pci_devinfo *dinfo); int pci_freecfg(struct pci_devinfo *dinfo); void pci_child_deleted(device_t dev, device_t child); diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index c829292..8d9ea7e 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -209,7 +209,6 @@ typedef struct pcicfg { uint8_t func; /* config space function number */ uint32_t flags; /* flags defined above */ - size_t devinfo_size; /* Size of devinfo for this bus type. */ struct pcicfg_bridge bridge; /* Bridges */ struct pcicfg_pp pp; /* Power management */ diff --git a/sys/dev/rt/if_rt.c b/sys/dev/rt/if_rt.c index fd042fe..5b4dc85 100644 --- a/sys/dev/rt/if_rt.c +++ b/sys/dev/rt/if_rt.c @@ -99,13 +99,14 @@ __FBSDID("$FreeBSD$"); #ifdef FDT /* more specific and new models should go first */ static const struct ofw_compat_data rt_compat_data[] = { - { "ralink,rt3050-eth", RT_CHIPID_RT3050 }, - { "ralink,rt3352-eth", RT_CHIPID_RT3050 }, - { "ralink,rt3883-eth", RT_CHIPID_RT3050 }, - { "ralink,rt5350-eth", RT_CHIPID_RT5350 }, - { "ralink,mt7620a-eth", RT_CHIPID_MT7620 }, - { "ralink,mt7621-eth", RT_CHIPID_MT7621 }, - { NULL, 0 } + { "ralink,rt3050-eth", RT_CHIPID_RT3050 }, + { "ralink,rt3352-eth", RT_CHIPID_RT3050 }, + { "ralink,rt3883-eth", RT_CHIPID_RT3050 }, + { "ralink,rt5350-eth", RT_CHIPID_RT5350 }, + { "ralink,mt7620a-eth", RT_CHIPID_MT7620 }, + { "ralink,mt7621-eth", RT_CHIPID_MT7621 }, + { "mediatek,mt7621-eth", RT_CHIPID_MT7621 }, + { NULL, 0 } }; #endif diff --git a/sys/dev/wbwd/wbwd.c b/sys/dev/wbwd/wbwd.c index 53e9084..75fbea4 100644 --- a/sys/dev/wbwd/wbwd.c +++ b/sys/dev/wbwd/wbwd.c @@ -505,19 +505,10 @@ wb_set_watchdog(struct wb_softc *sc, unsigned int timeout) /* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog) */ write_reg(sc, WB_LDN_REG, WB_LDN_REG_LDN8); - /* Disable and validate or arm/reset watchdog. */ if (timeout == 0) { /* Disable watchdog. */ - write_reg(sc, sc->time_reg, 0x00); - sc->reg_timeout = read_reg(sc, sc->time_reg); - (*sc->ext_cfg_exit_f)(sc, 0); - - /* Re-check. */ - if (sc->reg_timeout != 0x00) { - device_printf(sc->dev, "Failed to disable watchdog: " - "0x%02x.\n", sc->reg_timeout); - return (EIO); - } + sc->reg_timeout = 0; + write_reg(sc, sc->time_reg, sc->reg_timeout); } else { /* Read current scaling factor. */ @@ -547,12 +538,12 @@ wb_set_watchdog(struct wb_softc *sc, unsigned int timeout) /* Set timer and arm/reset the watchdog. */ write_reg(sc, sc->time_reg, sc->reg_timeout); - (*sc->ext_cfg_exit_f)(sc, 0); } + (*sc->ext_cfg_exit_f)(sc, 0); + if (sc->debug_verbose) wb_print_state(sc, "After watchdog counter (re)load"); - return (0); } diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c index bf18094..649b01a 100644 --- a/sys/fs/cd9660/cd9660_vfsops.c +++ b/sys/fs/cd9660/cd9660_vfsops.c @@ -709,7 +709,7 @@ cd9660_vget_internal(mp, ino, flags, vpp, relocated, isodir) if (error || *vpp != NULL) return (error); - if (isodir == 0) { + if (isodir == NULL) { int lbn, off; lbn = lblkno(imp, ino); @@ -759,7 +759,7 @@ cd9660_vget_internal(mp, ino, flags, vpp, relocated, isodir) } #endif } else - bp = 0; + bp = NULL; ip->i_mnt = imp; diff --git a/sys/fs/msdosfs/msdosfs_conv.c b/sys/fs/msdosfs/msdosfs_conv.c index fc9b4d4..efed30c 100644 --- a/sys/fs/msdosfs/msdosfs_conv.c +++ b/sys/fs/msdosfs/msdosfs_conv.c @@ -353,7 +353,7 @@ unix2dosfn(const u_char *un, u_char dn[12], size_t unlen, u_int gen, * ignores all dots before extension, and use all * chars as filename except for dots. */ - dp = dp1 = 0; + dp = dp1 = NULL; for (cp = un + 1, i = unlen - 1; --i >= 0;) { switch (*cp++) { case '.': @@ -365,7 +365,7 @@ unix2dosfn(const u_char *un, u_char dn[12], size_t unlen, u_int gen, default: if (dp1) dp = dp1; - dp1 = 0; + dp1 = NULL; break; } } diff --git a/sys/fs/msdosfs/msdosfs_fat.c b/sys/fs/msdosfs/msdosfs_fat.c index cf03e00..5df053c 100644 --- a/sys/fs/msdosfs/msdosfs_fat.c +++ b/sys/fs/msdosfs/msdosfs_fat.c @@ -256,14 +256,14 @@ fc_lookup(struct denode *dep, u_long findcn, u_long *frcnp, u_long *fsrcnp) { int i; u_long cn; - struct fatcache *closest = 0; + struct fatcache *closest = NULL; ASSERT_VOP_LOCKED(DETOV(dep), "fc_lookup"); for (i = 0; i < FC_SIZE; i++) { cn = dep->de_fc[i].fc_frcn; if (cn != FCE_EMPTY && cn <= findcn) { - if (closest == 0 || cn > closest->fc_frcn) + if (closest == NULL || cn > closest->fc_frcn) closest = &dep->de_fc[i]; } } diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c index 0d03831..f7955f2 100644 --- a/sys/fs/msdosfs/msdosfs_lookup.c +++ b/sys/fs/msdosfs/msdosfs_lookup.c @@ -454,7 +454,7 @@ found: * in a deadlock. */ brelse(bp); - bp = 0; + bp = NULL; foundroot: /* diff --git a/sys/geom/gate/g_gate.c b/sys/geom/gate/g_gate.c index 3453eef..8cfe9d4 100644 --- a/sys/geom/gate/g_gate.c +++ b/sys/geom/gate/g_gate.c @@ -945,7 +945,7 @@ g_gate_modevent(module_t mod, int type, void *data) } mtx_unlock(&g_gate_units_lock); mtx_destroy(&g_gate_units_lock); - if (status_dev != 0) + if (status_dev != NULL) destroy_dev(status_dev); free(g_gate_units, M_GATE); break; diff --git a/sys/geom/geom_io.c b/sys/geom/geom_io.c index 61f70c1..8270274 100644 --- a/sys/geom/geom_io.c +++ b/sys/geom/geom_io.c @@ -504,11 +504,11 @@ g_io_request(struct bio *bp, struct g_consumer *cp) cmd = bp->bio_cmd; if (cmd == BIO_READ || cmd == BIO_WRITE || cmd == BIO_GETATTR) { KASSERT(bp->bio_data != NULL, - ("NULL bp->data in g_io_request(cmd=%hhu)", bp->bio_cmd)); + ("NULL bp->data in g_io_request(cmd=%hu)", bp->bio_cmd)); } if (cmd == BIO_DELETE || cmd == BIO_FLUSH) { KASSERT(bp->bio_data == NULL, - ("non-NULL bp->data in g_io_request(cmd=%hhu)", + ("non-NULL bp->data in g_io_request(cmd=%hu)", bp->bio_cmd)); } if (cmd == BIO_READ || cmd == BIO_WRITE || cmd == BIO_DELETE) { diff --git a/sys/geom/geom_subr.c b/sys/geom/geom_subr.c index bf14a86..54a99bf 100644 --- a/sys/geom/geom_subr.c +++ b/sys/geom/geom_subr.c @@ -1508,8 +1508,8 @@ DB_SHOW_COMMAND(bio, db_show_bio) db_printf("BIO %p\n", bp); db_print_bio_cmd(bp); db_print_bio_flags(bp); - db_printf(" cflags: 0x%hhx\n", bp->bio_cflags); - db_printf(" pflags: 0x%hhx\n", bp->bio_pflags); + db_printf(" cflags: 0x%hx\n", bp->bio_cflags); + db_printf(" pflags: 0x%hx\n", bp->bio_pflags); db_printf(" offset: %jd\n", (intmax_t)bp->bio_offset); db_printf(" length: %jd\n", (intmax_t)bp->bio_length); db_printf(" bcount: %ld\n", bp->bio_bcount); diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index 70f5eb1..59da980 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -1905,7 +1905,7 @@ g_mirror_worker(void *arg) g_mirror_sync_request(bp); /* WRITE */ else { KASSERT(0, - ("Invalid request cflags=0x%hhx to=%s.", + ("Invalid request cflags=0x%hx to=%s.", bp->bio_cflags, bp->bio_to->name)); } } else { diff --git a/sys/geom/raid3/g_raid3.c b/sys/geom/raid3/g_raid3.c index 584076f..617f72e 100644 --- a/sys/geom/raid3/g_raid3.c +++ b/sys/geom/raid3/g_raid3.c @@ -2127,7 +2127,7 @@ process: g_raid3_sync_request(bp); /* WRITE */ else { KASSERT(0, - ("Invalid request cflags=0x%hhx to=%s.", + ("Invalid request cflags=0x%hx to=%s.", bp->bio_cflags, bp->bio_to->name)); } } else if (g_raid3_register_request(bp) != 0) { diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index e23906d..ee2df93 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -367,8 +367,6 @@ device virtio_scsi # VirtIO SCSI device device virtio_balloon # VirtIO Memory Balloon device # HyperV drivers and enchancement support -# NOTE: HYPERV depends on hyperv. They must be added or removed together. -options HYPERV # Hyper-V kernel infrastructure device hyperv # HyperV drivers # Xen HVM Guest Optimizations diff --git a/sys/i386/i386/apic_vector.s b/sys/i386/i386/apic_vector.s index 18b3c5d..9d56b93 100644 --- a/sys/i386/i386/apic_vector.s +++ b/sys/i386/i386/apic_vector.s @@ -181,25 +181,6 @@ IDTVEC(xen_intr_upcall) jmp doreti #endif -#ifdef HYPERV -/* - * This is the Hyper-V vmbus channel direct callback interrupt. - * Only used when it is running on Hyper-V. - */ - .text - SUPERALIGN_TEXT -IDTVEC(hv_vmbus_callback) - PUSH_FRAME - SET_KERNEL_SREGS - cld - FAKE_MCOUNT(TF_EIP(%esp)) - pushl %esp - call hv_vector_handler - add $4, %esp - MEXITCOUNT - jmp doreti -#endif - #ifdef SMP /* * Global address space TLB shootdown. diff --git a/sys/i386/i386/db_disasm.c b/sys/i386/i386/db_disasm.c index 4f771dc..2b398da 100644 --- a/sys/i386/i386/db_disasm.c +++ b/sys/i386/i386/db_disasm.c @@ -953,17 +953,17 @@ db_read_address(loc, short_addr, regmodrm, addrp) return (loc); } addrp->is_reg = FALSE; - addrp->index = 0; + addrp->index = NULL; if (short_addr) { - addrp->index = 0; + addrp->index = NULL; addrp->ss = 0; switch (mod) { case 0: if (rm == 6) { get_value_inc(disp, loc, 2, FALSE); addrp->disp = disp; - addrp->base = 0; + addrp->base = NULL; } else { addrp->disp = 0; @@ -997,7 +997,7 @@ db_read_address(loc, short_addr, regmodrm, addrp) case 0: if (rm == 5) { get_value_inc(addrp->disp, loc, 4, FALSE); - addrp->base = 0; + addrp->base = NULL; } else { addrp->disp = 0; @@ -1037,7 +1037,7 @@ db_print_address(seg, size, addrp) } db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY); - if (addrp->base != 0 || addrp->index != 0) { + if (addrp->base != NULL || addrp->index != NULL) { db_printf("("); if (addrp->base) db_printf("%s", addrp->base); @@ -1171,7 +1171,7 @@ db_disasm(db_addr_t loc, bool altfmt) get_value_inc(inst, loc, 1, FALSE); short_addr = FALSE; size = LONG; - seg = 0; + seg = NULL; /* * Get prefixes @@ -1239,7 +1239,7 @@ db_disasm(db_addr_t loc, bool altfmt) if (inst == 0x0f) { get_value_inc(inst, loc, 1, FALSE); ip = db_inst_0f[inst>>4]; - if (ip == 0) { + if (ip == NULL) { ip = &db_bad_inst; } else { diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s index f91f516..c03cbce 100644 --- a/sys/i386/i386/exception.s +++ b/sys/i386/i386/exception.s @@ -343,6 +343,7 @@ MCOUNT_LABEL(eintr) .text SUPERALIGN_TEXT .type doreti,@function + .globl doreti doreti: FAKE_MCOUNT($bintr) /* init "from" bintr -> doreti */ doreti_next: diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index 5bdc988..575e42f 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -269,15 +269,15 @@ pt_entry_t *CMAP3; static pd_entry_t *KPTD; caddr_t ptvmmap = 0; caddr_t CADDR3; -struct msgbuf *msgbufp = 0; +struct msgbuf *msgbufp = NULL; /* * Crashdump maps. */ static caddr_t crashdumpmap; -static pt_entry_t *PMAP1 = 0, *PMAP2; -static pt_entry_t *PADDR1 = 0, *PADDR2; +static pt_entry_t *PMAP1 = NULL, *PMAP2; +static pt_entry_t *PADDR1 = NULL, *PADDR2; #ifdef SMP static int PMAP1cpu; static int PMAP1changedcpu; diff --git a/sys/i386/ibcs2/imgact_coff.c b/sys/i386/ibcs2/imgact_coff.c index a7543d7..3a5611d 100644 --- a/sys/i386/ibcs2/imgact_coff.c +++ b/sys/i386/ibcs2/imgact_coff.c @@ -69,7 +69,7 @@ load_coff_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, vm_offset_t map_offset; vm_offset_t map_addr; int error; - unsigned char *data_buf = 0; + unsigned char *data_buf = NULL; size_t copy_len; map_offset = trunc_page(offset); @@ -163,7 +163,7 @@ coff_load_file(struct thread *td, char *name) struct filehdr *fhdr; struct aouthdr *ahdr; struct scnhdr *scns; - char *ptr = 0; + char *ptr = NULL; int nscns; unsigned long text_offset = 0, text_address = 0, text_size = 0; unsigned long data_offset = 0, data_address = 0, data_size = 0; @@ -363,7 +363,7 @@ exec_coff_imgact(imgp) /* .bss section */ bss_size = scns[i].s_size; } else if (scns[i].s_flags & STYP_LIB) { - char *buf = 0; + char *buf = NULL; int foff = trunc_page(scns[i].s_scnptr); int off = scns[i].s_scnptr - foff; int len = round_page(scns[i].s_size + PAGE_SIZE); diff --git a/sys/isa/pnp.c b/sys/isa/pnp.c index f2e5dfc..599af84 100644 --- a/sys/isa/pnp.c +++ b/sys/isa/pnp.c @@ -416,14 +416,14 @@ static int pnp_create_devices(device_t parent, pnp_id *p, int csn, u_char *resources, int len) { - u_char tag, *resp, *resinfo, *startres = 0; + u_char tag, *resp, *resinfo, *startres = NULL; int large_len, scanning = len, retval = FALSE; uint32_t logical_id; device_t dev = 0; int ldn = 0; struct pnp_set_config_arg *csnldn; char buf[100]; - char *desc = 0; + char *desc = NULL; resp = resources; while (scanning > 0) { @@ -492,7 +492,7 @@ pnp_create_devices(device_t parent, pnp_id *p, int csn, pnp_parse_resources(dev, startres, resinfo - startres - 1, ldn); dev = 0; - startres = 0; + startres = NULL; } /* @@ -537,7 +537,7 @@ pnp_create_devices(device_t parent, pnp_id *p, int csn, pnp_parse_resources(dev, startres, resinfo - startres - 1, ldn); dev = 0; - startres = 0; + startres = NULL; scanning = 0; break; @@ -674,7 +674,7 @@ pnp_isolation_protocol(device_t parent) int csn; pnp_id id; int found = 0, len; - u_char *resources = 0; + u_char *resources = NULL; int space = 0; int error; #ifdef PC98 diff --git a/sys/kern/kern_dump.c b/sys/kern/kern_dump.c index 1fd2fdd..e3d338f 100644 --- a/sys/kern/kern_dump.c +++ b/sys/kern/kern_dump.c @@ -55,13 +55,11 @@ CTASSERT(sizeof(struct kerneldumpheader) == 512); */ #define SIZEOF_METADATA (64*1024) -#define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK) -#define DEV_ALIGN(x) (((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1)) +#define MD_ALIGN(x) roundup2((off_t)(x), PAGE_SIZE) off_t dumplo; /* Handle buffered writes. */ -static char buffer[DEV_BSIZE]; static size_t fragsz; struct dump_pa dump_map[DUMPSYS_MD_PA_NPAIRS]; @@ -125,19 +123,19 @@ dumpsys_buf_write(struct dumperinfo *di, char *ptr, size_t sz) int error; while (sz) { - len = DEV_BSIZE - fragsz; + len = di->blocksize - fragsz; if (len > sz) len = sz; - bcopy(ptr, buffer + fragsz, len); + memcpy((char *)di->blockbuf + fragsz, ptr, len); fragsz += len; ptr += len; sz -= len; - if (fragsz == DEV_BSIZE) { - error = dump_write(di, buffer, 0, dumplo, - DEV_BSIZE); + if (fragsz == di->blocksize) { + error = dump_write(di, di->blockbuf, 0, dumplo, + di->blocksize); if (error) return (error); - dumplo += DEV_BSIZE; + dumplo += di->blocksize; fragsz = 0; } } @@ -152,8 +150,8 @@ dumpsys_buf_flush(struct dumperinfo *di) if (fragsz == 0) return (0); - error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE); - dumplo += DEV_BSIZE; + error = dump_write(di, di->blockbuf, 0, dumplo, di->blocksize); + dumplo += di->blocksize; fragsz = 0; return (error); } @@ -174,7 +172,7 @@ dumpsys_cb_dumpdata(struct dump_pa *mdp, int seqnr, void *arg) error = 0; /* catch case in which chunk size is 0 */ counter = 0; /* Update twiddle every 16MB */ - va = 0; + va = NULL; pgs = mdp->pa_size / PAGE_SIZE; pa = mdp->pa_start; maxdumppgs = min(di->maxiosize / PAGE_SIZE, MAXDUMPPGS); @@ -286,7 +284,7 @@ dumpsys_generic(struct dumperinfo *di) Elf_Ehdr ehdr; uint64_t dumpsize; off_t hdrgap; - size_t hdrsz; + size_t hdrsz, size; int error; #ifndef __powerpc__ @@ -324,15 +322,15 @@ dumpsys_generic(struct dumperinfo *di) hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize; fileofs = MD_ALIGN(hdrsz); dumpsize += fileofs; - hdrgap = fileofs - DEV_ALIGN(hdrsz); + hdrgap = fileofs - roundup2((off_t)hdrsz, di->blocksize); /* Determine dump offset on device. */ - if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) { + if (di->mediasize < SIZEOF_METADATA + dumpsize + di->blocksize * 2) { error = ENOSPC; goto fail; } dumplo = di->mediaoffset + di->mediasize - dumpsize; - dumplo -= sizeof(kdh) * 2; + dumplo -= di->blocksize * 2; mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARCH_VERSION, dumpsize, di->blocksize); @@ -341,10 +339,10 @@ dumpsys_generic(struct dumperinfo *di) ehdr.e_phnum - DUMPSYS_NUM_AUX_HDRS); /* Dump leader */ - error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); + error = dump_write_pad(di, &kdh, 0, dumplo, sizeof(kdh), &size); if (error) goto fail; - dumplo += sizeof(kdh); + dumplo += size; /* Dump ELF header */ error = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr)); @@ -375,7 +373,7 @@ dumpsys_generic(struct dumperinfo *di) goto fail; /* Dump trailer */ - error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); + error = dump_write_pad(di, &kdh, 0, dumplo, sizeof(kdh), &size); if (error) goto fail; diff --git a/sys/kern/kern_environment.c b/sys/kern/kern_environment.c index 511ab69..c05c063 100644 --- a/sys/kern/kern_environment.c +++ b/sys/kern/kern_environment.c @@ -545,6 +545,36 @@ getenv_uint(const char *name, unsigned int *data) } /* + * Return an int64_t value from an environment variable. + */ +int +getenv_int64(const char *name, int64_t *data) +{ + quad_t tmp; + int64_t rval; + + rval = getenv_quad(name, &tmp); + if (rval) + *data = (int64_t) tmp; + return (rval); +} + +/* + * Return an uint64_t value from an environment variable. + */ +int +getenv_uint64(const char *name, uint64_t *data) +{ + quad_t tmp; + uint64_t rval; + + rval = getenv_quad(name, &tmp); + if (rval) + *data = (uint64_t) tmp; + return (rval); +} + +/* * Return a long value from an environment variable. */ int @@ -650,6 +680,22 @@ tunable_ulong_init(void *data) } void +tunable_int64_init(void *data) +{ + struct tunable_int64 *d = (struct tunable_int64 *)data; + + TUNABLE_INT64_FETCH(d->path, d->var); +} + +void +tunable_uint64_init(void *data) +{ + struct tunable_uint64 *d = (struct tunable_uint64 *)data; + + TUNABLE_UINT64_FETCH(d->path, d->var); +} + +void tunable_quad_init(void *data) { struct tunable_quad *d = (struct tunable_quad *)data; diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c index 134e9a2..7c0d6b5 100644 --- a/sys/kern/kern_kthread.c +++ b/sys/kern/kern_kthread.c @@ -445,7 +445,7 @@ kproc_kthread_add(void (*func)(void *), void *arg, char buf[100]; struct thread *td; - if (*procptr == 0) { + if (*procptr == NULL) { error = kproc_create(func, arg, procptr, flags, pages, "%s", procname); if (error) diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index e980176..9a41165 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1444,7 +1444,7 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS) p = LIST_FIRST(&allproc); else p = LIST_FIRST(&zombproc); - for (; p != 0; p = LIST_NEXT(p, p_list)) { + for (; p != NULL; p = LIST_NEXT(p, p_list)) { /* * Skip embryonic processes. */ diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c index 438a249..d6f7510 100644 --- a/sys/kern/kern_racct.c +++ b/sys/kern/kern_racct.c @@ -472,8 +472,8 @@ racct_create(struct racct **racctp) static void racct_destroy_locked(struct racct **racctp) { - int i; struct racct *racct; + int i; ASSERT_RACCT_ENABLED(); @@ -668,8 +668,7 @@ racct_add_buf(struct proc *p, const struct buf *bp, int is_write) static int racct_set_locked(struct proc *p, int resource, uint64_t amount, int force) { - int64_t old_amount, decayed_amount; - int64_t diff_proc, diff_cred; + int64_t old_amount, decayed_amount, diff_proc, diff_cred; #ifdef RCTL int error; #endif @@ -964,10 +963,9 @@ racct_proc_fork_done(struct proc *child) void racct_proc_exit(struct proc *p) { - int i; - uint64_t runtime; struct timeval wallclock; - uint64_t pct_estimate, pct; + uint64_t pct_estimate, pct, runtime; + int i; if (!racct_enable) return; @@ -1206,8 +1204,7 @@ racctd(void) struct thread *td; struct proc *p; struct timeval wallclock; - uint64_t runtime; - uint64_t pct, pct_estimate; + uint64_t pct, pct_estimate, runtime; ASSERT_RACCT_ENABLED(); @@ -1317,7 +1314,7 @@ racct_init(void) return; racct_zone = uma_zcreate("racct", sizeof(struct racct), - NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); + NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); /* * XXX: Move this somewhere. */ diff --git a/sys/kern/kern_rctl.c b/sys/kern/kern_rctl.c index 98b5055..9647090 100644 --- a/sys/kern/kern_rctl.c +++ b/sys/kern/kern_rctl.c @@ -210,8 +210,8 @@ static struct dict actionnames[] = { static void rctl_init(void); SYSINIT(rctl, SI_SUB_RACCT, SI_ORDER_FIRST, rctl_init, NULL); -static uma_zone_t rctl_rule_link_zone; static uma_zone_t rctl_rule_zone; +static uma_zone_t rctl_rule_link_zone; static struct rwlock rctl_lock; RW_SYSINIT(rctl_lock, &rctl_lock, "RCTL lock"); @@ -229,8 +229,7 @@ static MALLOC_DEFINE(M_RCTL, "rctl", "Resource Limits"); static int rctl_throttle_min_sysctl(SYSCTL_HANDLER_ARGS) { - int val = rctl_throttle_min; - int error; + int error, val = rctl_throttle_min; error = sysctl_handle_int(oidp, &val, 0, req); if (error || !req->newptr) @@ -247,8 +246,7 @@ static int rctl_throttle_min_sysctl(SYSCTL_HANDLER_ARGS) static int rctl_throttle_max_sysctl(SYSCTL_HANDLER_ARGS) { - int val = rctl_throttle_max; - int error; + int error, val = rctl_throttle_max; error = sysctl_handle_int(oidp, &val, 0, req); if (error || !req->newptr) @@ -265,8 +263,7 @@ static int rctl_throttle_max_sysctl(SYSCTL_HANDLER_ARGS) static int rctl_throttle_pct_sysctl(SYSCTL_HANDLER_ARGS) { - int val = rctl_throttle_pct; - int error; + int error, val = rctl_throttle_pct; error = sysctl_handle_int(oidp, &val, 0, req); if (error || !req->newptr) @@ -283,8 +280,7 @@ static int rctl_throttle_pct_sysctl(SYSCTL_HANDLER_ARGS) static int rctl_throttle_pct2_sysctl(SYSCTL_HANDLER_ARGS) { - int val = rctl_throttle_pct2; - int error; + int error, val = rctl_throttle_pct2; error = sysctl_handle_int(oidp, &val, 0, req); if (error || !req->newptr) @@ -367,8 +363,8 @@ rctl_proc_rule_to_racct(const struct proc *p, const struct rctl_rule *rule) static int64_t rctl_available_resource(const struct proc *p, const struct rctl_rule *rule) { - int64_t available; const struct racct *racct; + int64_t available; ASSERT_RACCT_ENABLED(); RCTL_LOCK_ASSERT(); @@ -515,10 +511,10 @@ rctl_enforce(struct proc *p, int resource, uint64_t amount) struct rctl_rule *rule; struct rctl_rule_link *link; struct sbuf sb; + char *buf; int64_t available; uint64_t sleep_ms, sleep_ratio; int should_deny = 0; - char *buf; ASSERT_RACCT_ENABLED(); @@ -945,8 +941,8 @@ static int rctl_racct_remove_rules(struct racct *racct, const struct rctl_rule *filter) { - int removed = 0; struct rctl_rule_link *link, *linktmp; + int removed = 0; ASSERT_RACCT_ENABLED(); RCTL_WLOCK_ASSERT(); @@ -1160,11 +1156,11 @@ rctl_rule_fully_specified(const struct rctl_rule *rule) static int rctl_string_to_rule(char *rulestr, struct rctl_rule **rulep) { - int error = 0; + struct rctl_rule *rule; char *subjectstr, *subject_idstr, *resourcestr, *actionstr, *amountstr, *perstr; - struct rctl_rule *rule; id_t id; + int error = 0; ASSERT_RACCT_ENABLED(); @@ -1450,8 +1446,8 @@ rctl_rule_remove_callback(struct racct *racct, void *arg2, void *arg3) int rctl_rule_remove(struct rctl_rule *filter) { - int found = 0; struct proc *p; + int found = 0; ASSERT_RACCT_ENABLED(); @@ -1554,8 +1550,8 @@ rctl_rule_to_sbuf(struct sbuf *sb, const struct rctl_rule *rule) static int rctl_read_inbuf(char **inputstr, const char *inbufp, size_t inbuflen) { - int error; char *str; + int error; ASSERT_RACCT_ENABLED(); @@ -1603,9 +1599,9 @@ rctl_write_outbuf(struct sbuf *outputsbuf, char *outbufp, size_t outbuflen) static struct sbuf * rctl_racct_to_sbuf(struct racct *racct, int sloppy) { - int i; - int64_t amount; struct sbuf *sb; + int64_t amount; + int i; ASSERT_RACCT_ENABLED(); @@ -1625,14 +1621,14 @@ rctl_racct_to_sbuf(struct racct *racct, int sloppy) int sys_rctl_get_racct(struct thread *td, struct rctl_get_racct_args *uap) { - int error; - char *inputstr; struct rctl_rule *filter; struct sbuf *outputsbuf = NULL; struct proc *p; struct uidinfo *uip; struct loginclass *lc; struct prison_racct *prr; + char *inputstr; + int error; if (!racct_enable) return (ENOSYS); @@ -1721,13 +1717,13 @@ rctl_get_rules_callback(struct racct *racct, void *arg2, void *arg3) int sys_rctl_get_rules(struct thread *td, struct rctl_get_rules_args *uap) { - int error; - size_t bufsize; - char *inputstr, *buf; struct sbuf *sb; struct rctl_rule *filter; struct rctl_rule_link *link; struct proc *p; + char *inputstr, *buf; + size_t bufsize; + int error; if (!racct_enable) return (ENOSYS); @@ -1807,12 +1803,12 @@ out: int sys_rctl_get_limits(struct thread *td, struct rctl_get_limits_args *uap) { - int error; - size_t bufsize; - char *inputstr, *buf; struct sbuf *sb; struct rctl_rule *filter; struct rctl_rule_link *link; + char *inputstr, *buf; + size_t bufsize; + int error; if (!racct_enable) return (ENOSYS); @@ -1889,9 +1885,9 @@ out: int sys_rctl_add_rule(struct thread *td, struct rctl_add_rule_args *uap) { - int error; struct rctl_rule *rule; char *inputstr; + int error; if (!racct_enable) return (ENOSYS); @@ -1934,9 +1930,9 @@ out: int sys_rctl_remove_rule(struct thread *td, struct rctl_remove_rule_args *uap) { - int error; struct rctl_rule *filter; char *inputstr; + int error; if (!racct_enable) return (ENOSYS); @@ -1970,12 +1966,12 @@ sys_rctl_remove_rule(struct thread *td, struct rctl_remove_rule_args *uap) void rctl_proc_ucred_changed(struct proc *p, struct ucred *newcred) { - int rulecnt, i; + LIST_HEAD(, rctl_rule_link) newrules; struct rctl_rule_link *link, *newlink; struct uidinfo *newuip; struct loginclass *newlc; struct prison_racct *newprr; - LIST_HEAD(, rctl_rule_link) newrules; + int rulecnt, i; ASSERT_RACCT_ENABLED(); @@ -2118,9 +2114,9 @@ goaround: int rctl_proc_fork(struct proc *parent, struct proc *child) { - int error; - struct rctl_rule_link *link; struct rctl_rule *rule; + struct rctl_rule_link *link; + int error; LIST_INIT(&child->p_racct->r_rule_links); @@ -2197,11 +2193,11 @@ rctl_init(void) if (!racct_enable) return; + rctl_rule_zone = uma_zcreate("rctl_rule", sizeof(struct rctl_rule), + NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); rctl_rule_link_zone = uma_zcreate("rctl_rule_link", sizeof(struct rctl_rule_link), NULL, NULL, NULL, NULL, - UMA_ALIGN_PTR, UMA_ZONE_NOFREE); - rctl_rule_zone = uma_zcreate("rctl_rule", sizeof(struct rctl_rule), - NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); + UMA_ALIGN_PTR, 0); /* * Set default values, making sure not to overwrite the ones diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c index 87e7d63..7588d4c 100644 --- a/sys/kern/kern_shutdown.c +++ b/sys/kern/kern_shutdown.c @@ -88,6 +88,8 @@ __FBSDID("$FreeBSD$"); #include <sys/signalvar.h> +static MALLOC_DEFINE(M_DUMPER, "dumper", "dumper block buffer"); + #ifndef PANIC_REBOOT_WAIT_TIME #define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */ #endif @@ -848,7 +850,9 @@ set_dumper(struct dumperinfo *di, const char *devname, struct thread *td) return (error); if (di == NULL) { - bzero(&dumper, sizeof dumper); + if (dumper.blockbuf != NULL) + free(dumper.blockbuf, M_DUMPER); + bzero(&dumper, sizeof(dumper)); dumpdevname[0] = '\0'; return (0); } @@ -860,6 +864,7 @@ set_dumper(struct dumperinfo *di, const char *devname, struct thread *td) printf("set_dumper: device name truncated from '%s' -> '%s'\n", devname, dumpdevname); } + dumper.blockbuf = malloc(di->blocksize, M_DUMPER, M_WAITOK | M_ZERO); return (0); } @@ -880,6 +885,31 @@ dump_write(struct dumperinfo *di, void *virtual, vm_offset_t physical, return (di->dumper(di->priv, virtual, physical, offset, length)); } +/* Call dumper with bounds checking. */ +int +dump_write_pad(struct dumperinfo *di, void *virtual, vm_offset_t physical, + off_t offset, size_t length, size_t *size) +{ + char *temp; + int ret; + + if (length > di->blocksize) + return (ENOMEM); + + *size = di->blocksize; + if (length == di->blocksize) + temp = virtual; + else { + temp = di->blockbuf; + memset(temp + length, 0, di->blocksize - length); + memcpy(temp, virtual, length); + } + ret = dump_write(di, temp, physical, offset, *size); + + return (ret); +} + + void mkdumpheader(struct kerneldumpheader *kdh, char *magic, uint32_t archver, uint64_t dumplen, uint32_t blksz) diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index f57cd58..aae705e 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -912,7 +912,7 @@ sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) name++; continue; } - lsp2 = 0; + lsp2 = NULL; SLIST_FOREACH(oid, lsp, oid_link) { if (oid->oid_number != *name) continue; @@ -1083,7 +1083,7 @@ sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS) { char *p; int error, oid[CTL_MAXNAME], len = 0; - struct sysctl_oid *op = 0; + struct sysctl_oid *op = NULL; struct rm_priotracker tracker; if (!req->newlen) diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index 1579c28..349a95e 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -1382,7 +1382,7 @@ link_elf_search_symbol(linker_file_t lf, caddr_t value, u_long diff = off; u_long st_value; const Elf_Sym* es; - const Elf_Sym* best = 0; + const Elf_Sym* best = NULL; int i; for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) { @@ -1400,7 +1400,7 @@ link_elf_search_symbol(linker_file_t lf, caddr_t value, } } } - if (best == 0) + if (best == NULL) *diffp = off; else *diffp = diff; diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c index 575a706..544bd253 100644 --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -1180,7 +1180,7 @@ link_elf_search_symbol(linker_file_t lf, caddr_t value, u_long diff = off; u_long st_value; const Elf_Sym *es; - const Elf_Sym *best = 0; + const Elf_Sym *best = NULL; int i; for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) { @@ -1198,7 +1198,7 @@ link_elf_search_symbol(linker_file_t lf, caddr_t value, } } } - if (best == 0) + if (best == NULL) *diffp = off; else *diffp = diff; diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c index 22616b9..0063916 100644 --- a/sys/kern/sysv_sem.c +++ b/sys/kern/sysv_sem.c @@ -980,8 +980,8 @@ sys_semop(struct thread *td, struct semop_args *uap) size_t nsops = uap->nsops; struct sembuf *sops; struct semid_kernel *semakptr; - struct sembuf *sopptr = 0; - struct sem *semptr = 0; + struct sembuf *sopptr = NULL; + struct sem *semptr = NULL; struct sem_undo *suptr; struct mtx *sema_mtxp; size_t i, j, k; diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index 62dfda6..84354f3 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -459,7 +459,7 @@ m_copym(struct mbuf *m, int off0, int len, int wait) m = m->m_next; } np = ⊤ - top = 0; + top = NULL; while (len > 0) { if (m == NULL) { KASSERT(len == M_COPYALL, diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c index 0589f4a..e329ef2 100644 --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/systm.h> #include <sys/limits.h> +#include <sys/malloc.h> #include <sys/buf.h> #include <sys/capsicum.h> #include <sys/dirent.h> @@ -60,8 +61,8 @@ __FBSDID("$FreeBSD$"); #include <sys/fcntl.h> #include <sys/file.h> #include <sys/filedesc.h> +#include <sys/jail.h> #include <sys/lock.h> -#include <sys/malloc.h> #include <sys/module.h> #include <sys/mount.h> #include <sys/mqueue.h> @@ -132,6 +133,7 @@ struct mqfs_node { LIST_HEAD(,mqfs_node) mn_children; LIST_ENTRY(mqfs_node) mn_sibling; LIST_HEAD(,mqfs_vdata) mn_vnodes; + const void *mn_pr_root; int mn_refcount; mqfs_type_t mn_type; int mn_deleted; @@ -152,6 +154,11 @@ struct mqfs_node { #define FPTOMQ(fp) ((struct mqueue *)(((struct mqfs_node *) \ (fp)->f_data)->mn_data)) +struct mqfs_osd { + struct task mo_task; + const void *mo_pr_root; +}; + TAILQ_HEAD(msgq, mqueue_msg); struct mqueue; @@ -219,6 +226,7 @@ static uma_zone_t mvdata_zone; static uma_zone_t mqnoti_zone; static struct vop_vector mqfs_vnodeops; static struct fileops mqueueops; +static unsigned mqfs_osd_jail_slot; /* * Directory structure construction and manipulation @@ -236,6 +244,9 @@ static int mqfs_destroy(struct mqfs_node *mn); static void mqfs_fileno_alloc(struct mqfs_info *mi, struct mqfs_node *mn); static void mqfs_fileno_free(struct mqfs_info *mi, struct mqfs_node *mn); static int mqfs_allocv(struct mount *mp, struct vnode **vpp, struct mqfs_node *pn); +static int mqfs_prison_create(void *obj, void *data); +static void mqfs_prison_destructor(void *data); +static void mqfs_prison_remove_task(void *context, int pending); /* * Message queue construction and maniplation @@ -436,6 +447,7 @@ mqfs_create_node(const char *name, int namelen, struct ucred *cred, int mode, node = mqnode_alloc(); strncpy(node->mn_name, name, namelen); + node->mn_pr_root = cred->cr_prison->pr_root; node->mn_type = nodetype; node->mn_refcount = 1; vfs_timestamp(&node->mn_birth); @@ -644,6 +656,10 @@ mqfs_init(struct vfsconf *vfc) { struct mqfs_node *root; struct mqfs_info *mi; + struct prison *pr; + osd_method_t methods[PR_MAXMETHOD] = { + [PR_METHOD_CREATE] = mqfs_prison_create, + }; mqnode_zone = uma_zcreate("mqnode", sizeof(struct mqfs_node), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); @@ -670,6 +686,13 @@ mqfs_init(struct vfsconf *vfc) EVENTHANDLER_PRI_ANY); mq_fdclose = mqueue_fdclose; p31b_setcfg(CTL_P1003_1B_MESSAGE_PASSING, _POSIX_MESSAGE_PASSING); + + /* Note current jails. */ + mqfs_osd_jail_slot = osd_jail_register(mqfs_prison_destructor, methods); + sx_slock(&allprison_lock); + TAILQ_FOREACH(pr, &allprison, pr_list) + (void)mqfs_prison_create(pr, NULL); + sx_sunlock(&allprison_lock); return (0); } @@ -679,10 +702,14 @@ mqfs_init(struct vfsconf *vfc) static int mqfs_uninit(struct vfsconf *vfc) { + unsigned slot; struct mqfs_info *mi; if (!unloadable) return (EOPNOTSUPP); + slot = mqfs_osd_jail_slot; + mqfs_osd_jail_slot = 0; + osd_jail_deregister(slot); EVENTHANDLER_DEREGISTER(process_exit, exit_tag); mi = &mqfs_data; mqfs_destroy(mi->mi_root); @@ -800,13 +827,17 @@ found: * Search a directory entry */ static struct mqfs_node * -mqfs_search(struct mqfs_node *pd, const char *name, int len) +mqfs_search(struct mqfs_node *pd, const char *name, int len, struct ucred *cred) { struct mqfs_node *pn; + const void *pr_root; sx_assert(&pd->mn_info->mi_lock, SX_LOCKED); + pr_root = cred->cr_prison->pr_root; LIST_FOREACH(pn, &pd->mn_children, mn_sibling) { - if (strncmp(pn->mn_name, name, len) == 0 && + /* Only match names within the same prison root directory */ + if ((pn->mn_pr_root == NULL || pn->mn_pr_root == pr_root) && + strncmp(pn->mn_name, name, len) == 0 && pn->mn_name[len] == '\0') return (pn); } @@ -878,7 +909,7 @@ mqfs_lookupx(struct vop_cachedlookup_args *ap) /* named node */ sx_xlock(&mqfs->mi_lock); - pn = mqfs_search(pd, pname, namelen); + pn = mqfs_search(pd, pname, namelen, cnp->cn_cred); if (pn != NULL) mqnode_addref(pn); sx_xunlock(&mqfs->mi_lock); @@ -1363,6 +1394,7 @@ mqfs_readdir(struct vop_readdir_args *ap) struct mqfs_node *pn; struct dirent entry; struct uio *uio; + const void *pr_root; int *tmp_ncookies = NULL; off_t offset; int error, i; @@ -1387,10 +1419,18 @@ mqfs_readdir(struct vop_readdir_args *ap) error = 0; offset = 0; + pr_root = ap->a_cred->cr_prison->pr_root; sx_xlock(&mi->mi_lock); LIST_FOREACH(pn, &pd->mn_children, mn_sibling) { entry.d_reclen = sizeof(entry); + + /* + * Only show names within the same prison root directory + * (or not associated with a prison, e.g. "." and ".."). + */ + if (pn->mn_pr_root != NULL && pn->mn_pr_root != pr_root) + continue; if (!pn->mn_fileno) mqfs_fileno_alloc(mi, pn); entry.d_fileno = pn->mn_fileno; @@ -1523,6 +1563,81 @@ mqfs_rmdir(struct vop_rmdir_args *ap) #endif /* notyet */ + +/* + * Set a destructor task with the prison's root + */ +static int +mqfs_prison_create(void *obj, void *data __unused) +{ + struct prison *pr = obj; + struct mqfs_osd *mo; + void *rsv; + + if (pr->pr_root == pr->pr_parent->pr_root) + return(0); + + mo = malloc(sizeof(struct mqfs_osd), M_PRISON, M_WAITOK); + rsv = osd_reserve(mqfs_osd_jail_slot); + TASK_INIT(&mo->mo_task, 0, mqfs_prison_remove_task, mo); + mtx_lock(&pr->pr_mtx); + mo->mo_pr_root = pr->pr_root; + (void)osd_jail_set_reserved(pr, mqfs_osd_jail_slot, rsv, mo); + mtx_unlock(&pr->pr_mtx); + return (0); +} + +/* + * Queue the task for after jail/OSD locks are released + */ +static void +mqfs_prison_destructor(void *data) +{ + struct mqfs_osd *mo = data; + + if (mqfs_osd_jail_slot != 0) + taskqueue_enqueue(taskqueue_thread, &mo->mo_task); + else + free(mo, M_PRISON); +} + +/* + * See if this prison root is obsolete, and clean up associated queues if it is + */ +static void +mqfs_prison_remove_task(void *context, int pending) +{ + struct mqfs_osd *mo = context; + struct mqfs_node *pn, *tpn; + const struct prison *pr; + const void *pr_root; + int found; + + pr_root = mo->mo_pr_root; + found = 0; + sx_slock(&allprison_lock); + TAILQ_FOREACH(pr, &allprison, pr_list) { + if (pr->pr_root == pr_root) + found = 1; + } + sx_sunlock(&allprison_lock); + if (!found) { + /* + * No jails are rooted in this directory anymore, + * so no queues should be either. + */ + sx_xlock(&mqfs_data.mi_lock); + LIST_FOREACH_SAFE(pn, &mqfs_data.mi_root->mn_children, + mn_sibling, tpn) { + if (pn->mn_pr_root == pr_root) + (void)do_unlink(pn, curthread->td_ucred); + } + sx_xunlock(&mqfs_data.mi_lock); + } + free(mo, M_PRISON); +} + + /* * Allocate a message queue */ @@ -1983,7 +2098,7 @@ kern_kmq_open(struct thread *td, const char *upath, int flags, mode_t mode, return (error); sx_xlock(&mqfs_data.mi_lock); - pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1); + pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1, td->td_ucred); if (pn == NULL) { if (!(flags & O_CREAT)) { error = ENOENT; @@ -2078,7 +2193,7 @@ sys_kmq_unlink(struct thread *td, struct kmq_unlink_args *uap) return (EINVAL); sx_xlock(&mqfs_data.mi_lock); - pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1); + pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1, td->td_ucred); if (pn != NULL) error = do_unlink(pn, td->td_ucred); else diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c index 1b2c761..0ecff7c 100644 --- a/sys/kern/uipc_sem.c +++ b/sys/kern/uipc_sem.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include <sys/file.h> #include <sys/filedesc.h> #include <sys/fnv_hash.h> +#include <sys/jail.h> #include <sys/kernel.h> #include <sys/ksem.h> #include <sys/lock.h> @@ -258,7 +259,9 @@ ksem_closef(struct file *fp, struct thread *td) static int ksem_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) { + const char *path, *pr_path; struct ksem *ks; + size_t pr_pathlen; kif->kf_type = KF_TYPE_SEM; ks = fp->f_data; @@ -268,8 +271,18 @@ ksem_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) mtx_unlock(&sem_lock); if (ks->ks_path != NULL) { sx_slock(&ksem_dict_lock); - if (ks->ks_path != NULL) - strlcpy(kif->kf_path, ks->ks_path, sizeof(kif->kf_path)); + if (ks->ks_path != NULL) { + path = ks->ks_path; + pr_path = curthread->td_ucred->cr_prison->pr_path; + if (strcmp(pr_path, "/") != 0) { + /* Return the jail-rooted pathname. */ + pr_pathlen = strlen(pr_path); + if (strncmp(path, pr_path, pr_pathlen) == 0 && + path[pr_pathlen] == '/') + path += pr_pathlen; + } + strlcpy(kif->kf_path, path, sizeof(kif->kf_path)); + } sx_sunlock(&ksem_dict_lock); } return (0); @@ -449,6 +462,8 @@ ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode, struct ksem *ks; struct file *fp; char *path; + const char *pr_path; + size_t pr_pathlen; Fnv32_t fnv; int error, fd; @@ -485,10 +500,16 @@ ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode, ks->ks_flags |= KS_ANONYMOUS; } else { path = malloc(MAXPATHLEN, M_KSEM, M_WAITOK); - error = copyinstr(name, path, MAXPATHLEN, NULL); + pr_path = td->td_ucred->cr_prison->pr_path; + + /* Construct a full pathname for jailed callers. */ + pr_pathlen = strcmp(pr_path, "/") == 0 ? 0 + : strlcpy(path, pr_path, MAXPATHLEN); + error = copyinstr(name, path + pr_pathlen, + MAXPATHLEN - pr_pathlen, NULL); /* Require paths to start with a '/' character. */ - if (error == 0 && path[0] != '/') + if (error == 0 && path[pr_pathlen] != '/') error = EINVAL; if (error) { fdclose(td, fp, fd); @@ -624,11 +645,17 @@ int sys_ksem_unlink(struct thread *td, struct ksem_unlink_args *uap) { char *path; + const char *pr_path; + size_t pr_pathlen; Fnv32_t fnv; int error; path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); - error = copyinstr(uap->name, path, MAXPATHLEN, NULL); + pr_path = td->td_ucred->cr_prison->pr_path; + pr_pathlen = strcmp(pr_path, "/") == 0 ? 0 + : strlcpy(path, pr_path, MAXPATHLEN); + error = copyinstr(uap->name, path + pr_pathlen, MAXPATHLEN - pr_pathlen, + NULL); if (error) { free(path, M_TEMP); return (error); diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index a2146b9..0657787 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/uio.h> #include <sys/signal.h> +#include <sys/jail.h> #include <sys/ktrace.h> #include <sys/lock.h> #include <sys/malloc.h> @@ -687,6 +688,8 @@ kern_shm_open(struct thread *td, const char *userpath, int flags, mode_t mode, struct shmfd *shmfd; struct file *fp; char *path; + const char *pr_path; + size_t pr_pathlen; Fnv32_t fnv; mode_t cmode; int fd, error; @@ -723,13 +726,19 @@ kern_shm_open(struct thread *td, const char *userpath, int flags, mode_t mode, shmfd = shm_alloc(td->td_ucred, cmode); } else { path = malloc(MAXPATHLEN, M_SHMFD, M_WAITOK); - error = copyinstr(userpath, path, MAXPATHLEN, NULL); + pr_path = td->td_ucred->cr_prison->pr_path; + + /* Construct a full pathname for jailed callers. */ + pr_pathlen = strcmp(pr_path, "/") == 0 ? 0 + : strlcpy(path, pr_path, MAXPATHLEN); + error = copyinstr(userpath, path + pr_pathlen, + MAXPATHLEN - pr_pathlen, NULL); #ifdef KTRACE if (error == 0 && KTRPOINT(curthread, KTR_NAMEI)) ktrnamei(path); #endif /* Require paths to start with a '/' character. */ - if (error == 0 && path[0] != '/') + if (error == 0 && path[pr_pathlen] != '/') error = EINVAL; if (error) { fdclose(td, fp, fd); @@ -823,11 +832,17 @@ int sys_shm_unlink(struct thread *td, struct shm_unlink_args *uap) { char *path; + const char *pr_path; + size_t pr_pathlen; Fnv32_t fnv; int error; path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); - error = copyinstr(uap->path, path, MAXPATHLEN, NULL); + pr_path = td->td_ucred->cr_prison->pr_path; + pr_pathlen = strcmp(pr_path, "/") == 0 ? 0 + : strlcpy(path, pr_path, MAXPATHLEN); + error = copyinstr(uap->path, path + pr_pathlen, MAXPATHLEN - pr_pathlen, + NULL); if (error) { free(path, M_TEMP); return (error); @@ -1060,7 +1075,9 @@ shm_unmap(struct file *fp, void *mem, size_t size) static int shm_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) { + const char *path, *pr_path; struct shmfd *shmfd; + size_t pr_pathlen; kif->kf_type = KF_TYPE_SHM; shmfd = fp->f_data; @@ -1071,9 +1088,18 @@ shm_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) kif->kf_un.kf_file.kf_file_size = shmfd->shm_size; if (shmfd->shm_path != NULL) { sx_slock(&shm_dict_lock); - if (shmfd->shm_path != NULL) - strlcpy(kif->kf_path, shmfd->shm_path, - sizeof(kif->kf_path)); + if (shmfd->shm_path != NULL) { + path = shmfd->shm_path; + pr_path = curthread->td_ucred->cr_prison->pr_path; + if (strcmp(pr_path, "/") != 0) { + /* Return the jail-rooted pathname. */ + pr_pathlen = strlen(pr_path); + if (strncmp(path, pr_path, pr_pathlen) == 0 && + path[pr_pathlen] == '/') + path += pr_pathlen; + } + strlcpy(kif->kf_path, path, sizeof(kif->kf_path)); + } sx_sunlock(&shm_dict_lock); } return (0); diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index 0cdd43b..cf9f4b1 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -593,7 +593,7 @@ sbappend_locked(struct sockbuf *sb, struct mbuf *m, int flags) SOCKBUF_LOCK_ASSERT(sb); - if (m == 0) + if (m == NULL) return; sbm_clrprotoflags(m, flags); SBLASTRECORDCHK(sb); @@ -746,7 +746,7 @@ sbappendrecord_locked(struct sockbuf *sb, struct mbuf *m0) SOCKBUF_LOCK_ASSERT(sb); - if (m0 == 0) + if (m0 == NULL) return; m_clrprotoflags(m0); /* @@ -885,7 +885,7 @@ sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0, SOCKBUF_LOCK_ASSERT(sb); - if (control == 0) + if (control == NULL) panic("sbappendcontrol_locked"); space = m_length(control, &n) + m_length(m0, NULL); diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 79444e0..05703ef 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -430,7 +430,7 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name, (void) fo_ioctl(nfp, FIONBIO, &tmp, td->td_ucred, td); tmp = fflag & FASYNC; (void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td); - sa = 0; + sa = NULL; error = soaccept(so, &sa); if (error != 0) goto noconnection; diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c index 40dc0c0..ea902d7 100644 --- a/sys/kern/vfs_cluster.c +++ b/sys/kern/vfs_cluster.c @@ -368,7 +368,7 @@ cluster_rbuild(struct vnode *vp, u_quad_t filesize, daddr_t lbn, return tbp; bp = trypbuf(&cluster_pbuf_freecnt); - if (bp == 0) + if (bp == NULL) return tbp; /* diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index 9eb523c..e7a709d 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -102,7 +102,7 @@ vfs_hang_addrlist(struct mount *mp, struct netexport *nep, register struct radix_node_head *rnh; register int i; struct radix_node *rn; - struct sockaddr *saddr, *smask = 0; + struct sockaddr *saddr, *smask = NULL; #if defined(INET6) || defined(INET) int off; #endif diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index f4b0596..a1116e0 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -486,7 +486,7 @@ int lookup(struct nameidata *ndp) { char *cp; /* pointer into pathname argument */ - struct vnode *dp = 0; /* the directory we are searching */ + struct vnode *dp = NULL; /* the directory we are searching */ struct vnode *tdp; /* saved dp */ struct mount *mp; /* mount table entry */ struct prison *pr; @@ -949,7 +949,7 @@ bad: int relookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp) { - struct vnode *dp = 0; /* the directory we are searching */ + struct vnode *dp = NULL; /* the directory we are searching */ int wantparent; /* 1 => wantparent or lockparent flag */ int rdonly; /* lookup read-only flag bit */ int error = 0; diff --git a/sys/libkern/strtol.c b/sys/libkern/strtol.c index 4d64025..ea7dd55 100644 --- a/sys/libkern/strtol.c +++ b/sys/libkern/strtol.c @@ -123,7 +123,7 @@ strtol(nptr, endptr, base) acc = neg ? LONG_MIN : LONG_MAX; } else if (neg) acc = -acc; - if (endptr != 0) + if (endptr != NULL) *endptr = __DECONST(char *, any ? s - 1 : nptr); return (acc); } diff --git a/sys/libkern/strtoq.c b/sys/libkern/strtoq.c index d855056..e83adb1 100644 --- a/sys/libkern/strtoq.c +++ b/sys/libkern/strtoq.c @@ -124,7 +124,7 @@ strtoq(const char *nptr, char **endptr, int base) acc = neg ? QUAD_MIN : QUAD_MAX; } else if (neg) acc = -acc; - if (endptr != 0) + if (endptr != NULL) *endptr = __DECONST(char *, any ? s - 1 : nptr); return (acc); } diff --git a/sys/libkern/strtoul.c b/sys/libkern/strtoul.c index f7399dc..44adf5a 100644 --- a/sys/libkern/strtoul.c +++ b/sys/libkern/strtoul.c @@ -102,7 +102,7 @@ strtoul(nptr, endptr, base) acc = ULONG_MAX; } else if (neg) acc = -acc; - if (endptr != 0) + if (endptr != NULL) *endptr = __DECONST(char *, any ? s - 1 : nptr); return (acc); } diff --git a/sys/libkern/strtouq.c b/sys/libkern/strtouq.c index f8303a0..49c3750 100644 --- a/sys/libkern/strtouq.c +++ b/sys/libkern/strtouq.c @@ -101,7 +101,7 @@ strtouq(const char *nptr, char **endptr, int base) acc = UQUAD_MAX; } else if (neg) acc = -acc; - if (endptr != 0) + if (endptr != NULL) *endptr = __DECONST(char *, any ? s - 1 : nptr); return (acc); } diff --git a/sys/mips/adm5120/obio.c b/sys/mips/adm5120/obio.c index 8b62629..0e09886 100644 --- a/sys/mips/adm5120/obio.c +++ b/sys/mips/adm5120/obio.c @@ -270,7 +270,7 @@ obio_alloc_resource(device_t bus, device_t child, int type, int *rid, } rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) { + if (rv == NULL) { printf("%s: could not reserve resource\n", __func__); return (0); } diff --git a/sys/mips/alchemy/obio.c b/sys/mips/alchemy/obio.c index 96b1f1d..b85ca48 100644 --- a/sys/mips/alchemy/obio.c +++ b/sys/mips/alchemy/obio.c @@ -271,7 +271,7 @@ obio_alloc_resource(device_t bus, device_t child, int type, int *rid, } rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) { + if (rv == NULL) { printf("%s: could not reserve resource\n", __func__); return (0); } diff --git a/sys/mips/atheros/apb.c b/sys/mips/atheros/apb.c index abae9c2..6a38c7d 100644 --- a/sys/mips/atheros/apb.c +++ b/sys/mips/atheros/apb.c @@ -223,7 +223,7 @@ apb_alloc_resource(device_t bus, device_t child, int type, int *rid, } rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) { + if (rv == NULL) { printf("%s: could not reserve resource\n", __func__); return (0); } diff --git a/sys/mips/conf/MEDIATEK b/sys/mips/conf/MEDIATEK new file mode 100644 index 0000000..4cf8225 --- /dev/null +++ b/sys/mips/conf/MEDIATEK @@ -0,0 +1,81 @@ +# +# MEDIATEK -- Kernel configuration file for FreeBSD/MIPS Mediatek/Ralink SoCs +# +# This includes all the configurable parts of the kernel. Please read through +# the sections below and customize the options to fit your board if needed. +# +# $FreeBSD$ +# + +#NO_UNIVERSE + +# Don't build any modules by default +makeoptions MODULES_OVERRIDE="" + +# +# Default rootfs device configuration, should be changed to suit target board +# +options ROOTDEVNAME=\"ufs:md0.uzip\" + +# +# Optional drivers section +# +# What follows is optional support drivers for the Mediatek SoCs. +# The kernel can be compiled without them if size is a concern. +# All optional drivers are built by default. +# + +# Support geom_uzip(4) compressed disk images +device geom_uzip +options GEOM_UZIP + +# Support md(4) and md-based rootfs +device md +options MD_ROOT + +# SPI and SPI flash support +device spibus +device mx25l + +# GPIO and gpioled support +device gpio +device gpioled + +# PCI support +device pci + +# +# USB (ehci, ohci, xhci, otg) support. Unneeded drivers can be commented in +# order to lower kernel size. See below for driver SoC support. +# +# For all SoCs that require USB support +device usb +# For RT3050, RT3052 and RT3350 SoCs +device dwcotg +# For RT3352, RT3662, RT3883, RT5350, MT7620, MT7628 and MT7688 +device ohci +device ehci +# For MT7621, or cases where the target board has a XHCI controller on PCI +# (for example Asus RT-N65U) +device xhci + +# USB umass(4) storage and da(4) support +device umass +device da + +# ahci(4) and ada(4) support, depends on PCI +device ahci +device ada + +# CAM support, required if either umass(4) or ahci(4) is enabled above +device pass +device scbus + +# Ethernet, BPS and bridge support +device rt +device bpf +device if_bridge + +# Extres +device ext_resources +device clk diff --git a/sys/mips/conf/MEDIATEK_BASE b/sys/mips/conf/MEDIATEK_BASE new file mode 100644 index 0000000..5e6c0ad --- /dev/null +++ b/sys/mips/conf/MEDIATEK_BASE @@ -0,0 +1,89 @@ +# +# MEDIATEK_BASE -- Base kernel configuration file for FreeBSD/MIPS +# Mediatek/Ralink SoCs. +# +# This includes all the required drivers for the SoCs. +# Ususally, users should not build this kernel configuration. It is provided +# only as a minimum base, from which customizations can be made. Please look +# at MEDIATEK kernel configuration for customization details. +# +# $FreeBSD$ +# + +#NO_UNIVERSE + +# Include the standard file list for Mediatek SoCs. +files "../mediatek/files.mtk" + +# Building a mips/mipsel kernel +machine mips mipsel + +# Little-endian machine +makeoptions MIPS_LITTLE_ENDIAN=defined + +# Default kernel load address +makeoptions KERNLOADADDR=0x80001000 + +# Mediatek/Ralink SoC support depends on FDT (with static DTB for the moment) +options FDT +options FDT_DTB_STATIC + +# We rely on MIPS_INTRNG code +options MIPS_INTRNG +options MIPS_NIRQ=256 + +# We rely on NEW_PCIB code +options NEW_PCIB + +# Build kernel with gdb(1) debug symbols +makeoptions DEBUG=-g + +# Support for DDB and KDB +options DDB +options KDB + +# Debugging for use in -current +options INVARIANTS +options INVARIANT_SUPPORT +options WITNESS +options WITNESS_SKIPSPIN +options DEBUG_REDZONE +options DEBUG_MEMGUARD + +# For small memory footprints +options VM_KMEM_SIZE_SCALE=1 + +# General options, including scheduler, etc. +options SCHED_ULE # ULE scheduler +options INET # InterNETworking +#options INET6 # IPv6 +options PSEUDOFS # Pseude-filesystem framework +options FFS # Berkeley Fast Filesystem +#options SOFTUPDATES # Enable FFS soft updates support +#options UFS_ACL # Support for access control lists +#options UFS_DIRHASH # Improve big directory performance +#options MSDOSFS # Enable support for MSDOS filesystems +options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time ext. + +# +# Standard drivers section +# +# The drivers in the following section are required in order to successfully +# compile the kernel. +# + +# FDT clock and pinctrl framework +device fdt_clock +device fdt_pinctrl + +# UART support +device uart + +# random support +device random + +# loop device support +device loop + +# ether device support +device ether diff --git a/sys/mips/conf/MT7620A_FDT b/sys/mips/conf/MT7620A_FDT new file mode 100644 index 0000000..8468304 --- /dev/null +++ b/sys/mips/conf/MT7620A_FDT @@ -0,0 +1,30 @@ +# +# MT7620A_FDT -- Kernel configuration file for FreeBSD/MIPS MT7620A SoC +# +# This includes all the configurable parts of the kernel. Please read through +# MEDIATEK kernel config and customize the options to fit your board if needed. +# +# $FreeBSD$ +# + +#NO_UNIVERSE + +# +# FDT_DTS_FILE should be modified to suit the target board type. +# +#makeoptions FDT_DTS_FILE=MT7620a.dts + +# +# The user should never have to edit what's below this line. +# If customizations are needed, they should be done to the MEDIATEK kernel +# configuration. +# + +# Start with a base configuration +include MEDIATEK_BASE + +ident MT7620A +cpu CPU_MIPS24K + +# Include optional configuration (to be edited by the user if needed) +include MEDIATEK diff --git a/sys/mips/conf/MT7620N_FDT b/sys/mips/conf/MT7620N_FDT new file mode 100644 index 0000000..64222df --- /dev/null +++ b/sys/mips/conf/MT7620N_FDT @@ -0,0 +1,30 @@ +# +# MT7620N_FDT -- Kernel configuration file for FreeBSD/MIPS MT7620N SoC +# +# This includes all the configurable parts of the kernel. Please read through +# MEDIATEK kernel config and customize the options to fit your board if needed. +# +# $FreeBSD$ +# + +#NO_UNIVERSE + +# +# FDT_DTS_FILE should be modified to suit the target board type. +# +#makeoptions FDT_DTS_FILE=WRTNODE.dts + +# +# The user should never have to edit what's below this line. +# If customizations are needed, they should be done to the MEDIATEK kernel +# configuration. +# + +# Start with a base configuration +include MEDIATEK_BASE + +ident MT7620N +cpu CPU_MIPS24K + +# Include optional configuration (to be edited by the user if needed) +include MEDIATEK diff --git a/sys/mips/conf/MT7621_FDT b/sys/mips/conf/MT7621_FDT new file mode 100644 index 0000000..a80c953 --- /dev/null +++ b/sys/mips/conf/MT7621_FDT @@ -0,0 +1,30 @@ +# +# MT7621_FDT -- Kernel configuration file for FreeBSD/MIPS MT7621 SoC +# +# This includes all the configurable parts of the kernel. Please read through +# MEDIATEK kernel config and customize the options to fit your board if needed. +# +# $FreeBSD$ +# + +#NO_UNIVERSE + +# +# FDT_DTS_FILE should be modified to suit the target board type. +# +#makeoptions FDT_DTS_FILE=ZBT-WG2626.dts + +# +# The user should never have to edit what's below this line. +# If customizations are needed, they should be done to the MEDIATEK kernel +# configuration. +# + +# Start with a base configuration +include MEDIATEK_BASE + +ident MT7621 +cpu CPU_MIPS1004K + +# Include optional configuration (to be edited by the user if needed) +include MEDIATEK diff --git a/sys/mips/conf/MT7628_FDT b/sys/mips/conf/MT7628_FDT new file mode 100644 index 0000000..bbffa65 --- /dev/null +++ b/sys/mips/conf/MT7628_FDT @@ -0,0 +1,30 @@ +# +# MT7628_FDT -- Kernel configuration file for FreeBSD/MIPS MT7628/MT7688 SoCs +# +# This includes all the configurable parts of the kernel. Please read through +# MEDIATEK kernel config and customize the options to fit your board if needed. +# +# $FreeBSD$ +# + +#NO_UNIVERSE + +# +# FDT_DTS_FILE should be modified to suit the target board type. +# +#makeoptions FDT_DTS_FILE=MT7628.dts + +# +# The user should never have to edit what's below this line. +# If customizations are needed, they should be done to the MEDIATEK kernel +# configuration. +# + +# Start with a base configuration +include MEDIATEK_BASE + +ident MT7628 +cpu CPU_MIPS24K + +# Include optional configuration (to be edited by the user if needed) +include MEDIATEK diff --git a/sys/mips/conf/RT3050_FDT b/sys/mips/conf/RT3050_FDT new file mode 100644 index 0000000..435020f --- /dev/null +++ b/sys/mips/conf/RT3050_FDT @@ -0,0 +1,31 @@ +# +# RT3050_FDT -- Kernel configuration file for FreeBSD/MIPS RT3050/RT3052/RT3350 +# SoCs +# +# This includes all the configurable parts of the kernel. Please read through +# MEDIATEK kernel config and customize the options to fit your board if needed. +# +# $FreeBSD$ +# + +#NO_UNIVERSE + +# +# FDT_DTS_FILE should be modified to suit the target board type. +# +#makeoptions FDT_DTS_FILE=DIR-600-B1.dts + +# +# The user should never have to edit what's below this line. +# If customizations are needed, they should be done to the MEDIATEK kernel +# configuration. +# + +# Start with a base configuration +include MEDIATEK_BASE + +ident RT3050 +cpu CPU_MIPS24K + +# Include optional configuration (to be edited by the user if needed) +include MEDIATEK diff --git a/sys/mips/conf/RT3352_FDT b/sys/mips/conf/RT3352_FDT new file mode 100644 index 0000000..ec33b9c --- /dev/null +++ b/sys/mips/conf/RT3352_FDT @@ -0,0 +1,30 @@ +# +# RT3352_FDT -- Kernel configuration file for FreeBSD/MIPS RT3352 SoC +# +# This includes all the configurable parts of the kernel. Please read through +# MEDIATEK kernel config and customize the options to fit your board if needed. +# +# $FreeBSD$ +# + +#NO_UNIVERSE + +# +# FDT_DTS_FILE should be modified to suit the target board type. +# +#makeoptions FDT_DTS_FILE=DIR-615-H1.dts + +# +# The user should never have to edit what's below this line. +# If customizations are needed, they should be done to the MEDIATEK kernel +# configuration. +# + +# Start with a base configuration +include MEDIATEK_BASE + +ident RT3352 +cpu CPU_MIPS24K + +# Include optional configuration (to be edited by the user if needed) +include MEDIATEK diff --git a/sys/mips/conf/RT3883_FDT b/sys/mips/conf/RT3883_FDT new file mode 100644 index 0000000..6229e2c --- /dev/null +++ b/sys/mips/conf/RT3883_FDT @@ -0,0 +1,30 @@ +# +# RT3883_FDT -- Kernel configuration file for FreeBSD/MIPS RT3662/RT3883 SoCs +# +# This includes all the configurable parts of the kernel. Please read through +# MEDIATEK kernel config and customize the options to fit your board if needed. +# +# $FreeBSD$ +# + +#NO_UNIVERSE + +# +# FDT_DTS_FILE should be modified to suit the target board type. +# +#makeoptions FDT_DTS_FILE=DIR-645.dts + +# +# The user should never have to edit what's below this line. +# If customizations are needed, they should be done to the MEDIATEK kernel +# configuration. +# + +# Start with a base configuration +include MEDIATEK_BASE + +ident RT3883 +cpu CPU_MIPS74K + +# Include optional configuration (to be edited by the user if needed) +include MEDIATEK diff --git a/sys/mips/conf/RT5350_FDT b/sys/mips/conf/RT5350_FDT new file mode 100644 index 0000000..827bdd3 --- /dev/null +++ b/sys/mips/conf/RT5350_FDT @@ -0,0 +1,30 @@ +# +# RT5350_FDT -- Kernel configuration file for FreeBSD/MIPS RT5350 SoC +# +# This includes all the configurable parts of the kernel. Please read through +# MEDIATEK kernel config and customize the options to fit your board if needed. +# +# $FreeBSD$ +# + +#NO_UNIVERSE + +# +# FDT_DTS_FILE should be modified to suit the target board type. +# +#makeoptions FDT_DTS_FILE=DIR-300-B7.dts + +# +# The user should never have to edit what's below this line. +# If customizations are needed, they should be done to the MEDIATEK kernel +# configuration. +# + +# Start with a base configuration +include MEDIATEK_BASE + +ident RT5350 +cpu CPU_MIPS24K + +# Include optional configuration (to be edited by the user if needed) +include MEDIATEK diff --git a/sys/mips/idt/obio.c b/sys/mips/idt/obio.c index b95b11a..f151a79 100644 --- a/sys/mips/idt/obio.c +++ b/sys/mips/idt/obio.c @@ -204,7 +204,7 @@ obio_alloc_resource(device_t bus, device_t child, int type, int *rid, } rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) { + if (rv == NULL) { printf("%s: could not reserve resource\n", __func__); return (0); } diff --git a/sys/mips/include/intr.h b/sys/mips/include/intr.h index 28f798f..6e00643 100644 --- a/sys/mips/include/intr.h +++ b/sys/mips/include/intr.h @@ -39,7 +39,7 @@ #ifndef _MACHINE_INTR_H_ #define _MACHINE_INTR_H_ -#ifdef MIPS_INTRNG +#ifdef INTRNG #ifdef FDT #include <dev/ofw/openfirm.h> @@ -47,8 +47,12 @@ #include <sys/intr.h> -#ifndef NIRQ -#define NIRQ 128 +#ifndef MIPS_NIRQ +#define MIPS_NIRQ 128 +#endif + +#ifndef NIRQ +#define NIRQ MIPS_NIRQ #endif #define INTR_IRQ_NSPC_SWI 4 @@ -62,6 +66,6 @@ void cpu_establish_softintr(const char *, driver_filter_t *, void (*)(void*), /* MIPS interrupt C entry point */ void cpu_intr(struct trapframe *); -#endif /* MIPS_INTRNG */ +#endif /* INTRNG */ #endif /* _MACHINE_INTR_H */ diff --git a/sys/mips/include/smp.h b/sys/mips/include/smp.h index fa4cb5c..d7a33de 100644 --- a/sys/mips/include/smp.h +++ b/sys/mips/include/smp.h @@ -21,7 +21,7 @@ #include <machine/pcb.h> -#ifdef MIPS_INTRNG +#ifdef INTRNG # define MIPS_IPI_COUNT 1 # define INTR_IPI_COUNT MIPS_IPI_COUNT #endif diff --git a/sys/mips/mediatek/mtk_ehci.c b/sys/mips/mediatek/mtk_ehci.c index 109a32a..acc30eb 100644 --- a/sys/mips/mediatek/mtk_ehci.c +++ b/sys/mips/mediatek/mtk_ehci.c @@ -78,7 +78,7 @@ ehci_fdt_probe(device_t self) if (!ofw_bus_status_okay(self)) return (ENXIO); - if (!ofw_bus_is_compatible(self, "ralink,rt3xxx-ehci")) + if (!ofw_bus_is_compatible(self, "generic-ehci")) return (ENXIO); device_set_desc(self, EHCI_HC_DEVSTR); diff --git a/sys/mips/mediatek/mtk_gpio_v1.c b/sys/mips/mediatek/mtk_gpio_v1.c index 29b2258..ad3a0fc 100644 --- a/sys/mips/mediatek/mtk_gpio_v1.c +++ b/sys/mips/mediatek/mtk_gpio_v1.c @@ -281,8 +281,8 @@ mtk_gpio_attach(device_t dev) sc->do_remap = 0; } - if (OF_hasprop(node, "mtk,num-pins") && (OF_getencprop(node, - "mtk,num-pins", &num_pins, sizeof(num_pins)) >= 0)) + if (OF_hasprop(node, "ralink,num-gpios") && (OF_getencprop(node, + "ralink,num-gpios", &num_pins, sizeof(num_pins)) >= 0)) sc->num_pins = num_pins; else sc->num_pins = MTK_GPIO_PINS; diff --git a/sys/mips/mediatek/mtk_gpio_v2.c b/sys/mips/mediatek/mtk_gpio_v2.c index 282b112..c7c0326 100644 --- a/sys/mips/mediatek/mtk_gpio_v2.c +++ b/sys/mips/mediatek/mtk_gpio_v2.c @@ -121,8 +121,8 @@ static int mtk_gpio_intr(void *arg); #define GPIO_PIORESET(_sc) GPIO_REG((_sc), 0x0040) static struct ofw_compat_data compat_data[] = { - { "mtk,mt7621-gpio", 1 }, - { "mtk,mt7628-gpio", 1 }, + { "mtk,mt7621-gpio-bank", 1 }, + { "mtk,mt7628-gpio-bank", 1 }, { NULL, 0 } }; @@ -281,7 +281,7 @@ mtk_gpio_attach(device_t dev) else sc->num_pins = MTK_GPIO_PINS; - for (i = 0; i < num_pins; i++) { + for (i = 0; i < sc->num_pins; i++) { sc->pins[i].pin_caps |= GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_INVIN | GPIO_PIN_INVOUT; sc->pins[i].intr_polarity = INTR_POLARITY_HIGH; diff --git a/sys/mips/mediatek/mtk_intr_gic.c b/sys/mips/mediatek/mtk_intr_gic.c index 3eb6ffc..ab96cac 100644 --- a/sys/mips/mediatek/mtk_intr_gic.c +++ b/sys/mips/mediatek/mtk_intr_gic.c @@ -281,10 +281,10 @@ mtk_gic_map_intr(device_t dev, struct intr_map_data *data, sc = device_get_softc(dev); if (data == NULL || data->type != INTR_MAP_DATA_FDT || - data->fdt.ncells != 1 || data->fdt.cells[0] >= sc->nirqs) + data->fdt.ncells != 3 || data->fdt.cells[1] >= sc->nirqs) return (EINVAL); - *isrcp = GIC_INTR_ISRC(sc, data->fdt.cells[0]); + *isrcp = GIC_INTR_ISRC(sc, data->fdt.cells[1]); return (0); #else return (EINVAL); diff --git a/sys/mips/mediatek/mtk_ohci.c b/sys/mips/mediatek/mtk_ohci.c index 91c98ce..0b554e7 100644 --- a/sys/mips/mediatek/mtk_ohci.c +++ b/sys/mips/mediatek/mtk_ohci.c @@ -78,7 +78,7 @@ ohci_fdt_probe(device_t self) if (!ofw_bus_status_okay(self)) return (ENXIO); - if (!ofw_bus_is_compatible(self, "ralink,rt3xxx-ohci")) + if (!ofw_bus_is_compatible(self, "generic-ohci")) return (ENXIO); device_set_desc(self, OHCI_HC_DEVSTR); diff --git a/sys/mips/mediatek/mtk_pcie.c b/sys/mips/mediatek/mtk_pcie.c index e88b9ab..66d8add 100644 --- a/sys/mips/mediatek/mtk_pcie.c +++ b/sys/mips/mediatek/mtk_pcie.c @@ -99,7 +99,7 @@ struct mtk_pci_range { u_long len; }; -#define FDT_RANGES_CELLS (3 * 2) +#define FDT_RANGES_CELLS ((1 + 2 + 3) * 2) static void mtk_pci_range_dump(struct mtk_pci_range *range) @@ -117,30 +117,33 @@ mtk_pci_ranges_decode(phandle_t node, struct mtk_pci_range *io_space, { struct mtk_pci_range *pci_space; pcell_t ranges[FDT_RANGES_CELLS]; + pcell_t addr_cells, size_cells, par_addr_cells; pcell_t *rangesptr; pcell_t cell0, cell1, cell2; - int tuples, i, rv, len; + int tuple_size, tuples, i, rv, len; /* * Retrieve 'ranges' property. */ - if (!OF_hasprop(node, "ranges")) { - printf("%s: %d\n", __FUNCTION__, 1); + if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0) return (EINVAL); - } + if (addr_cells != 3 || size_cells != 2) + return (ERANGE); + + par_addr_cells = fdt_parent_addr_cells(node); + if (par_addr_cells != 1) + return (ERANGE); len = OF_getproplen(node, "ranges"); - if (len > sizeof(ranges)) { - printf("%s: %d\n", __FUNCTION__, 2); + if (len > sizeof(ranges)) return (ENOMEM); - } - if (OF_getprop(node, "ranges", ranges, sizeof(ranges)) <= 0) { - printf("%s: %d\n", __FUNCTION__, 3); + if (OF_getprop(node, "ranges", ranges, sizeof(ranges)) <= 0) return (EINVAL); - } - tuples = len / (sizeof(pcell_t) * 3); + tuple_size = sizeof(pcell_t) * (addr_cells + par_addr_cells + + size_cells); + tuples = len / tuple_size; /* * Initialize the ranges so that we don't have to worry about @@ -159,18 +162,21 @@ mtk_pci_ranges_decode(phandle_t node, struct mtk_pci_range *io_space, cell2 = fdt_data_get((void *)rangesptr, 1); rangesptr++; - if (cell0 == 2) { + if (cell0 & 0x02000000) { pci_space = mem_space; - } else if (cell0 == 1) { + } else if (cell0 & 0x01000000) { pci_space = io_space; } else { rv = ERANGE; - printf("%s: %d\n", __FUNCTION__, 4); goto out; } - pci_space->base = cell1; - pci_space->len = cell2; + pci_space->base = fdt_data_get((void *)rangesptr, + par_addr_cells); + rangesptr += par_addr_cells; + + pci_space->len = fdt_data_get((void *)rangesptr, size_cells); + rangesptr += size_cells; } rv = 0; @@ -199,6 +205,7 @@ static struct ofw_compat_data compat_data[] = { { "ralink,rt3883-pcie", MTK_SOC_RT3883 }, { "ralink,mt7620a-pcie", MTK_SOC_MT7620A }, { "ralink,mt7621-pcie", MTK_SOC_MT7621 }, + { "mediatek,mt7621-pci", MTK_SOC_MT7621 }, { "ralink,mt7628-pcie", MTK_SOC_MT7628 }, { "ralink,mt7688-pcie", MTK_SOC_MT7628 }, { NULL, MTK_SOC_UNKNOWN } diff --git a/sys/mips/mediatek/mtk_soc.c b/sys/mips/mediatek/mtk_soc.c index b331467..5784fec 100644 --- a/sys/mips/mediatek/mtk_soc.c +++ b/sys/mips/mediatek/mtk_soc.c @@ -63,6 +63,7 @@ static const struct ofw_compat_data compat_data[] = { { "ralink,mtk7620a-soc", MTK_SOC_MT7620A }, { "ralink,mtk7620n-soc", MTK_SOC_MT7620N }, { "mediatek,mtk7621-soc", MTK_SOC_MT7621 }, + { "mediatek,mt7621-soc", MTK_SOC_MT7621 }, { "ralink,mtk7621-soc", MTK_SOC_MT7621 }, { "ralink,mtk7628an-soc", MTK_SOC_MT7628 }, { "mediatek,mt7628an-soc", MTK_SOC_MT7628 }, diff --git a/sys/mips/mediatek/mtk_usb_phy.c b/sys/mips/mediatek/mtk_usb_phy.c index d400720..59b1ffd 100644 --- a/sys/mips/mediatek/mtk_usb_phy.c +++ b/sys/mips/mediatek/mtk_usb_phy.c @@ -84,9 +84,10 @@ static void mtk_usb_phy_mt7621_init(device_t); static void mtk_usb_phy_mt7628_init(device_t); static struct ofw_compat_data compat_data[] = { - { "ralink,mt7620a-usbphy", MTK_SOC_MT7620A }, + { "ralink,mt7620-usbphy", MTK_SOC_MT7620A }, { "ralink,mt7628an-usbphy", MTK_SOC_MT7628 }, - { "ralink,rt3xxx-usbphy", MTK_SOC_RT3352 }, + { "ralink,rt3352-usbphy", MTK_SOC_RT3352 }, + { "ralink,rt3050-usbphy", MTK_SOC_RT3050 }, { NULL, MTK_SOC_UNKNOWN } }; diff --git a/sys/mips/mediatek/mtk_xhci.c b/sys/mips/mediatek/mtk_xhci.c index 0899307..138a4d4 100644 --- a/sys/mips/mediatek/mtk_xhci.c +++ b/sys/mips/mediatek/mtk_xhci.c @@ -80,7 +80,7 @@ mtk_xhci_fdt_probe(device_t self) if (!ofw_bus_status_okay(self)) return (ENXIO); - if (!ofw_bus_is_compatible(self, "mtk,usb-xhci")) + if (!ofw_bus_is_compatible(self, "mediatek,mt8173-xhci")) return (ENXIO); device_set_desc(self, XHCI_HC_DEVSTR); @@ -99,7 +99,6 @@ mtk_xhci_fdt_attach(device_t self) sc->sc_bus.parent = self; sc->sc_bus.devices = sc->sc_devices; sc->sc_bus.devices_max = XHCI_MAX_DEVICES; - sc->sc_bus.dma_bits = 32; rid = 0; sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, diff --git a/sys/mips/mips/exception.S b/sys/mips/mips/exception.S index ebfd84d..ed02e5a 100644 --- a/sys/mips/mips/exception.S +++ b/sys/mips/mips/exception.S @@ -646,7 +646,7 @@ NESTED_NOPROFILE(MipsKernIntr, KERN_EXC_FRAME_SIZE, ra) * Call the interrupt handler. a0 points at the saved frame. */ PTR_LA gp, _C_LABEL(_gp) -#ifdef MIPS_INTRNG +#ifdef INTRNG PTR_LA k0, _C_LABEL(intr_irq_handler) #else PTR_LA k0, _C_LABEL(cpu_intr) @@ -762,7 +762,7 @@ NESTED_NOPROFILE(MipsUserIntr, CALLFRAME_SIZ, ra) /* * Call the interrupt handler. */ -#ifdef MIPS_INTRNG +#ifdef INTRNG PTR_LA k0, _C_LABEL(intr_irq_handler) #else PTR_LA k0, _C_LABEL(cpu_intr) @@ -1198,7 +1198,7 @@ FPReturn: PTR_ADDU sp, sp, CALLFRAME_SIZ END(MipsFPTrap) -#ifndef MIPS_INTRNG +#ifndef INTRNG /* * Interrupt counters for vmstat. */ @@ -1225,7 +1225,7 @@ sintrcnt: #else .int INTRCNT_COUNT * (_MIPS_SZLONG / 8) * 2 #endif -#endif /* MIPS_INTRNG */ +#endif /* INTRNG */ /* diff --git a/sys/mips/mips/machdep.c b/sys/mips/mips/machdep.c index 5d25d88..3d44cda 100644 --- a/sys/mips/mips/machdep.c +++ b/sys/mips/mips/machdep.c @@ -316,7 +316,7 @@ cpu_initclocks(void) cpu_initclocks_bsp(); } -struct msgbuf *msgbufp=0; +struct msgbuf *msgbufp = NULL; /* * Initialize the hardware exception vectors, and the jump table used to diff --git a/sys/mips/mips/nexus.c b/sys/mips/mips/nexus.c index a2a8e527..45e47ef 100644 --- a/sys/mips/mips/nexus.c +++ b/sys/mips/mips/nexus.c @@ -57,7 +57,7 @@ __FBSDID("$FreeBSD$"); #include <machine/resource.h> #include <machine/vmparam.h> -#ifdef MIPS_INTRNG +#ifdef INTRNG #include <machine/intr.h> #else #include <machine/intr_machdep.h> @@ -115,7 +115,7 @@ static int nexus_setup_intr(device_t dev, device_t child, driver_intr_t *intr, void *arg, void **cookiep); static int nexus_teardown_intr(device_t, device_t, struct resource *, void *); -#ifdef MIPS_INTRNG +#ifdef INTRNG #ifdef SMP static int nexus_bind_intr(device_t, device_t, struct resource *, int); #endif @@ -148,7 +148,7 @@ static device_method_t nexus_methods[] = { DEVMETHOD(bus_activate_resource,nexus_activate_resource), DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), DEVMETHOD(bus_hinted_child, nexus_hinted_child), -#ifdef MIPS_INTRNG +#ifdef INTRNG DEVMETHOD(bus_config_intr, nexus_config_intr), DEVMETHOD(bus_describe_intr, nexus_describe_intr), #ifdef SMP @@ -315,7 +315,7 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, } rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) { + if (rv == NULL) { printf("%s: could not reserve resource for %s\n", __func__, device_get_nameunit(child)); return (0); @@ -458,7 +458,7 @@ nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { -#ifdef MIPS_INTRNG +#ifdef INTRNG return (intr_setup_irq(child, res, filt, intr, arg, flags, cookiep)); #else int irq; @@ -483,7 +483,7 @@ static int nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) { -#ifdef MIPS_INTRNG +#ifdef INTRNG return (intr_teardown_irq(child, r, ih)); #else printf("Unimplemented %s at %s:%d\n", __func__, __FILE__, __LINE__); @@ -491,7 +491,7 @@ nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) #endif } -#ifdef MIPS_INTRNG +#ifdef INTRNG static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, enum intr_polarity pol) @@ -527,7 +527,7 @@ nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, return (intr_fdt_map_irq(iparent, intr, icells)); } #endif -#endif /* MIPS_INTRNG */ +#endif /* INTRNG */ static void nexus_hinted_child(device_t bus, const char *dname, int dunit) diff --git a/sys/mips/mips/tick.c b/sys/mips/mips/tick.c index b146ad7..8bcc534 100644 --- a/sys/mips/mips/tick.c +++ b/sys/mips/mips/tick.c @@ -51,7 +51,7 @@ __FBSDID("$FreeBSD$"); #include <machine/locore.h> #include <machine/md_var.h> -#ifdef MIPS_INTRNG +#ifdef INTRNG #include <machine/intr.h> #endif @@ -328,7 +328,7 @@ static int clock_attach(device_t dev) { struct clock_softc *sc; -#ifndef MIPS_INTRNG +#ifndef INTRNG int error; #endif @@ -336,7 +336,7 @@ clock_attach(device_t dev) panic("can't attach more clocks"); softc = sc = device_get_softc(dev); -#ifdef MIPS_INTRNG +#ifdef INTRNG cpu_establish_hardintr("clock", clock_intr, NULL, sc, 5, INTR_TYPE_CLK, NULL); #else diff --git a/sys/mips/nlm/xlp_pci.c b/sys/mips/nlm/xlp_pci.c index 863c6aa..9e91146 100644 --- a/sys/mips/nlm/xlp_pci.c +++ b/sys/mips/nlm/xlp_pci.c @@ -125,8 +125,8 @@ xlp_pci_attach(device_t dev) XLP_PCI_DEVSCRATCH_REG0 << 2, (1 << 8) | irq, 4); } - dinfo = pci_read_device(pcib, pcib_get_domain(dev), - busno, s, f, sizeof(*dinfo)); + dinfo = pci_read_device(pcib, dev, pcib_get_domain(dev), + busno, s, f); pci_add_child(dev, dinfo); } } diff --git a/sys/mips/nlm/xlp_simplebus.c b/sys/mips/nlm/xlp_simplebus.c index 413775b..eb42a86 100644 --- a/sys/mips/nlm/xlp_simplebus.c +++ b/sys/mips/nlm/xlp_simplebus.c @@ -244,7 +244,7 @@ xlp_simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid, } rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) { + if (rv == NULL) { device_printf(bus, "%s: could not reserve resource for %s\n", __func__, device_get_nameunit(child)); return (NULL); diff --git a/sys/mips/rmi/xlr_pci.c b/sys/mips/rmi/xlr_pci.c index 53581a6..3d98503 100644 --- a/sys/mips/rmi/xlr_pci.c +++ b/sys/mips/rmi/xlr_pci.c @@ -537,7 +537,7 @@ xlr_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, } rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) + if (rv == NULL) return (0); rman_set_rid(rv, *rid); diff --git a/sys/mips/rt305x/obio.c b/sys/mips/rt305x/obio.c index ac27230..fc8a4ac 100644 --- a/sys/mips/rt305x/obio.c +++ b/sys/mips/rt305x/obio.c @@ -326,7 +326,7 @@ obio_alloc_resource(device_t bus, device_t child, int type, int *rid, } rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) { + if (rv == NULL) { printf("%s: could not reserve resource\n", __func__); return (0); } diff --git a/sys/mips/rt305x/rt305x_gpio.c b/sys/mips/rt305x/rt305x_gpio.c index e4f645f..56b734a 100644 --- a/sys/mips/rt305x/rt305x_gpio.c +++ b/sys/mips/rt305x/rt305x_gpio.c @@ -562,7 +562,7 @@ rt305x_gpio_alloc_resource(device_t bus, device_t child, int type, int *rid, } rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) { + if (rv == NULL) { printf("%s: could not reserve resource\n", __func__); return (0); } diff --git a/sys/modules/cam/Makefile b/sys/modules/cam/Makefile index 19bd9ec..603f055 100644 --- a/sys/modules/cam/Makefile +++ b/sys/modules/cam/Makefile @@ -21,7 +21,7 @@ SRCS+= cam_compat.c .if exists($S/${MACHINE}/${MACHINE}/cam_machdep.c) SRCS+= cam_machdep.c .endif -SRCS+= cam_periph.c cam_queue.c cam_sim.c cam_xpt.c +SRCS+= cam_iosched.c cam_periph.c cam_queue.c cam_sim.c cam_xpt.c SRCS+= scsi_all.c scsi_cd.c scsi_ch.c SRCS+= scsi_da.c SRCS+= scsi_pass.c diff --git a/sys/modules/hyperv/vmbus/Makefile b/sys/modules/hyperv/vmbus/Makefile index 637157b..8187146 100644 --- a/sys/modules/hyperv/vmbus/Makefile +++ b/sys/modules/hyperv/vmbus/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ .PATH: ${.CURDIR}/../../../dev/hyperv/vmbus \ - ${.CURDIR}/../../../dev/hyperv/utilities + ${.CURDIR}/../../../dev/hyperv/vmbus/${MACHINE_CPUARCH} KMOD= hv_vmbus SRCS= hv_channel.c \ @@ -14,8 +14,17 @@ SRCS= hv_channel.c \ hv_vmbus_priv.h SRCS+= acpi_if.h bus_if.h device_if.h opt_acpi.h +# XXX: for assym.s +SRCS+= opt_kstack_pages.h opt_nfs.h opt_apic.h opt_hwpmc_hooks.h opt_compat.h + +SRCS+= assym.s \ + hv_vector.S + +hv_vector.o: + ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \ + ${.IMPSRC} -o ${.TARGET} + CFLAGS+= -I${.CURDIR}/../../../dev/hyperv/include \ - -I${.CURDIR}/../../../dev/hyperv/vmbus \ - -I${.CURDIR}/../../../dev/hyperv/utilities + -I${.CURDIR}/../../../dev/hyperv/vmbus .include <bsd.kmod.mk> diff --git a/sys/modules/ipfw/Makefile b/sys/modules/ipfw/Makefile index a0045f3..f25762d 100644 --- a/sys/modules/ipfw/Makefile +++ b/sys/modules/ipfw/Makefile @@ -4,7 +4,7 @@ KMOD= ipfw SRCS= ip_fw2.c ip_fw_pfil.c -SRCS+= ip_fw_dynamic.c ip_fw_log.c +SRCS+= ip_fw_dynamic.c ip_fw_log.c ip_fw_eaction.c SRCS+= ip_fw_sockopt.c ip_fw_table.c ip_fw_table_algo.c ip_fw_iface.c SRCS+= ip_fw_table_value.c SRCS+= opt_inet.h opt_inet6.h opt_ipdivert.h opt_ipfw.h opt_ipsec.h diff --git a/sys/net/bpf_filter.c b/sys/net/bpf_filter.c index 40498a9..ab3198a 100644 --- a/sys/net/bpf_filter.c +++ b/sys/net/bpf_filter.c @@ -99,7 +99,7 @@ m_xword(struct mbuf *m, bpf_u_int32 k, int *err) while (k >= len) { k -= len; m = m->m_next; - if (m == 0) + if (m == NULL) goto bad; len = m->m_len; } @@ -109,7 +109,7 @@ m_xword(struct mbuf *m, bpf_u_int32 k, int *err) return (EXTRACT_LONG(cp)); } m0 = m->m_next; - if (m0 == 0 || m0->m_len + len - k < 4) + if (m0 == NULL || m0->m_len + len - k < 4) goto bad; *err = 0; np = mtod(m0, u_char *); @@ -148,7 +148,7 @@ m_xhalf(struct mbuf *m, bpf_u_int32 k, int *err) while (k >= len) { k -= len; m = m->m_next; - if (m == 0) + if (m == NULL) goto bad; len = m->m_len; } @@ -158,7 +158,7 @@ m_xhalf(struct mbuf *m, bpf_u_int32 k, int *err) return (EXTRACT_SHORT(cp)); } m0 = m->m_next; - if (m0 == 0) + if (m0 == NULL) goto bad; *err = 0; return ((cp[0] << 8) | mtod(m0, u_char *)[0]); diff --git a/sys/net/if.c b/sys/net/if.c index 2c44c87..1a11093 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1948,8 +1948,8 @@ link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) struct sockaddr *dst; struct ifnet *ifp; - if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || - ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) + if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == NULL) || + ((ifp = ifa->ifa_ifp) == NULL) || ((dst = rt_key(rt)) == NULL)) return; ifa = ifaof_ifpforaddr(dst, ifp); if (ifa) { @@ -2139,7 +2139,7 @@ if_qflush(struct ifnet *ifp) ALTQ_PURGE(ifq); #endif n = ifq->ifq_head; - while ((m = n) != 0) { + while ((m = n) != NULL) { n = m->m_nextpkt; m_freem(m); } diff --git a/sys/net/if_arcsubr.c b/sys/net/if_arcsubr.c index 16adba4..14026b4 100644 --- a/sys/net/if_arcsubr.c +++ b/sys/net/if_arcsubr.c @@ -210,7 +210,7 @@ arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, isphds = arc_isphds(atype); M_PREPEND(m, isphds ? ARC_HDRNEWLEN : ARC_HDRLEN, M_NOWAIT); - if (m == 0) + if (m == NULL) senderr(ENOBUFS); ah = mtod(m, struct arc_header *); ah->arc_type = atype; @@ -261,12 +261,12 @@ arc_frag_next(struct ifnet *ifp) struct arc_header *ah; ac = (struct arccom *)ifp->if_l2com; - if ((m = ac->curr_frag) == 0) { + if ((m = ac->curr_frag) == NULL) { int tfrags; /* dequeue new packet */ IF_DEQUEUE(&ifp->if_snd, m); - if (m == 0) + if (m == NULL) return 0; ah = mtod(m, struct arc_header *); @@ -296,7 +296,7 @@ arc_frag_next(struct ifnet *ifp) } M_PREPEND(m, ARC_HDRNEWLEN, M_NOWAIT); - if (m == 0) { + if (m == NULL) { m_freem(ac->curr_frag); ac->curr_frag = 0; return 0; @@ -315,7 +315,7 @@ arc_frag_next(struct ifnet *ifp) ac->curr_frag = 0; M_PREPEND(m, ARC_HDRNEWLEN_EXC, M_NOWAIT); - if (m == 0) + if (m == NULL) return 0; ah = mtod(m, struct arc_header *); @@ -328,7 +328,7 @@ arc_frag_next(struct ifnet *ifp) ac->curr_frag = 0; M_PREPEND(m, ARC_HDRNEWLEN, M_NOWAIT); - if (m == 0) + if (m == NULL) return 0; ah = mtod(m, struct arc_header *); @@ -740,7 +740,7 @@ arc_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, sdl = (struct sockaddr_dl *)sa; if (*LLADDR(sdl) != arcbroadcastaddr) return EADDRNOTAVAIL; - *llsa = 0; + *llsa = NULL; return 0; #ifdef INET case AF_INET: @@ -763,7 +763,7 @@ arc_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, * (This is used for multicast routers.) */ ifp->if_flags |= IFF_ALLMULTI; - *llsa = 0; + *llsa = NULL; return 0; } if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) diff --git a/sys/net/if_atmsubr.c b/sys/net/if_atmsubr.c index e1c4a67..2d38b8a 100644 --- a/sys/net/if_atmsubr.c +++ b/sys/net/if_atmsubr.c @@ -192,7 +192,7 @@ atm_output(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst, if (atm_flags & ATM_PH_LLCSNAP) sz += 8; /* sizeof snap == 8 */ M_PREPEND(m, sz, M_NOWAIT); - if (m == 0) + if (m == NULL) senderr(ENOBUFS); ad = mtod(m, struct atm_pseudohdr *); *ad = atmdst; @@ -295,7 +295,7 @@ atm_input(struct ifnet *ifp, struct atm_pseudohdr *ah, struct mbuf *m, struct atmllc *alc; if (m->m_len < sizeof(*alc) && - (m = m_pullup(m, sizeof(*alc))) == 0) + (m = m_pullup(m, sizeof(*alc))) == NULL) return; /* failed */ alc = mtod(m, struct atmllc *); if (bcmp(alc, ATMLLC_HDR, 6)) { diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index c6bcfdf..6b03711 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -3248,7 +3248,7 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir) if (hlen < sizeof(struct ip)) goto bad; if (hlen > (*mp)->m_len) { - if ((*mp = m_pullup(*mp, hlen)) == 0) + if ((*mp = m_pullup(*mp, hlen)) == NULL) goto bad; ip = mtod(*mp, struct ip *); if (ip == NULL) @@ -3366,7 +3366,7 @@ bridge_ip_checkbasic(struct mbuf **mp) goto bad; } if (hlen > m->m_len) { - if ((m = m_pullup(m, hlen)) == 0) { + if ((m = m_pullup(m, hlen)) == NULL) { KMOD_IPSTAT_INC(ips_badhlen); goto bad; } diff --git a/sys/net/if_disc.c b/sys/net/if_disc.c index b6e1d20..d7ea59e 100644 --- a/sys/net/if_disc.c +++ b/sys/net/if_disc.c @@ -216,7 +216,7 @@ discioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCADDMULTI: case SIOCDELMULTI: - if (ifr == 0) { + if (ifr == NULL) { error = EAFNOSUPPORT; /* XXX */ break; } diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 2d652ad..8698647 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -1075,7 +1075,7 @@ ether_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, e_addr = LLADDR(sdl); if (!ETHER_IS_MULTICAST(e_addr)) return EADDRNOTAVAIL; - *llsa = 0; + *llsa = NULL; return 0; #ifdef INET @@ -1100,7 +1100,7 @@ ether_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, * (This is used for multicast routers.) */ ifp->if_flags |= IFF_ALLMULTI; - *llsa = 0; + *llsa = NULL; return 0; } if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c index 84ee669..1ebd4da 100644 --- a/sys/net/if_fddisubr.c +++ b/sys/net/if_fddisubr.c @@ -235,7 +235,7 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, if (type != 0) { struct llc *l; M_PREPEND(m, LLC_SNAPFRAMELEN, M_NOWAIT); - if (m == 0) + if (m == NULL) senderr(ENOBUFS); l = mtod(m, struct llc *); l->llc_control = LLC_UI; @@ -251,7 +251,7 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, * allocate another. */ M_PREPEND(m, FDDI_HDR_LEN, M_NOWAIT); - if (m == 0) + if (m == NULL) senderr(ENOBUFS); fh = mtod(m, struct fddi_header *); fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4; @@ -607,7 +607,7 @@ fddi_resolvemulti(ifp, llsa, sa) e_addr = LLADDR(sdl); if ((e_addr[0] & 1) != 1) return (EADDRNOTAVAIL); - *llsa = 0; + *llsa = NULL; return (0); #ifdef INET @@ -634,7 +634,7 @@ fddi_resolvemulti(ifp, llsa, sa) * (This is used for multicast routers.) */ ifp->if_flags |= IFF_ALLMULTI; - *llsa = 0; + *llsa = NULL; return (0); } if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) diff --git a/sys/net/if_fwsubr.c b/sys/net/if_fwsubr.c index a070f61..c2253d4 100644 --- a/sys/net/if_fwsubr.c +++ b/sys/net/if_fwsubr.c @@ -132,7 +132,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, } destfw = (struct fw_hwaddr *)(mtag + 1); } else { - destfw = 0; + destfw = NULL; } switch (dst->sa_family) { @@ -269,7 +269,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, mtail = m_split(m, fsize, M_NOWAIT); m_tag_copy_chain(mtail, m, M_NOWAIT); } else { - mtail = 0; + mtail = NULL; } /* @@ -701,7 +701,7 @@ firewire_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, /* * No mapping needed. */ - *llsa = 0; + *llsa = NULL; return 0; #ifdef INET @@ -709,7 +709,7 @@ firewire_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, sin = (struct sockaddr_in *)sa; if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) return EADDRNOTAVAIL; - *llsa = 0; + *llsa = NULL; return 0; #endif #ifdef INET6 @@ -722,12 +722,12 @@ firewire_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, * (This is used for multicast routers.) */ ifp->if_flags |= IFF_ALLMULTI; - *llsa = 0; + *llsa = NULL; return 0; } if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) return EADDRNOTAVAIL; - *llsa = 0; + *llsa = NULL; return 0; #endif diff --git a/sys/net/if_iso88025subr.c b/sys/net/if_iso88025subr.c index 466784f..a96e2b9 100644 --- a/sys/net/if_iso88025subr.c +++ b/sys/net/if_iso88025subr.c @@ -328,7 +328,7 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, if (snap_type != 0) { struct llc *l; M_PREPEND(m, LLC_SNAPFRAMELEN, M_NOWAIT); - if (m == 0) + if (m == NULL) senderr(ENOBUFS); l = mtod(m, struct llc *); l->llc_control = LLC_UI; @@ -344,7 +344,7 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, * allocate another. */ M_PREPEND(m, ISO88025_HDR_LEN + rif_len, M_NOWAIT); - if (m == 0) + if (m == NULL) senderr(ENOBUFS); th = mtod(m, struct iso88025_header *); bcopy((caddr_t)edst, (caddr_t)&gen_th.iso88025_dhost, ISO88025_ADDR_LEN); @@ -638,7 +638,7 @@ iso88025_resolvemulti (ifp, llsa, sa) if ((e_addr[0] & 1) != 1) { return (EADDRNOTAVAIL); } - *llsa = 0; + *llsa = NULL; return (0); #ifdef INET @@ -664,7 +664,7 @@ iso88025_resolvemulti (ifp, llsa, sa) * (This is used for multicast routers.) */ ifp->if_flags |= IFF_ALLMULTI; - *llsa = 0; + *llsa = NULL; return (0); } if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c index 1291f7b..1623732 100644 --- a/sys/net/if_loop.c +++ b/sys/net/if_loop.c @@ -380,7 +380,7 @@ loioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCADDMULTI: case SIOCDELMULTI: - if (ifr == 0) { + if (ifr == NULL) { error = EAFNOSUPPORT; /* XXX */ break; } diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c index 841a0f2..092106e 100644 --- a/sys/net/if_spppsubr.c +++ b/sys/net/if_spppsubr.c @@ -4835,7 +4835,7 @@ sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) * Pick the first AF_INET address from the list, * aliases don't make any sense on a p2p link anyway. */ - si = 0; + si = NULL; if_addr_rlock(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) if (ifa->ifa_addr->sa_family == AF_INET) { @@ -4877,7 +4877,7 @@ sppp_set_ip_addr(struct sppp *sp, u_long src) * Pick the first AF_INET address from the list, * aliases don't make any sense on a p2p link anyway. */ - si = 0; + si = NULL; if_addr_rlock(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family == AF_INET) { @@ -5055,7 +5055,7 @@ sppp_params(struct sppp *sp, u_long cmd, void *data) struct spppreq *spr; int rv = 0; - if ((spr = malloc(sizeof(struct spppreq), M_TEMP, M_NOWAIT)) == 0) + if ((spr = malloc(sizeof(struct spppreq), M_TEMP, M_NOWAIT)) == NULL) return (EAGAIN); /* * ifr->ifr_data is supposed to point to a struct spppreq. diff --git a/sys/net/radix.c b/sys/net/radix.c index 2b4b954..b17858e 100644 --- a/sys/net/radix.c +++ b/sys/net/radix.c @@ -519,11 +519,11 @@ rn_addmask(void *n_arg, struct radix_mask_head *maskhead, int search, int skip) *addmask_key = mlen; x = rn_search(addmask_key, maskhead->head.rnh_treetop); if (bcmp(addmask_key, x->rn_key, mlen) != 0) - x = 0; + x = NULL; if (x || search) return (x); R_Zalloc(x, struct radix_node *, RADIX_MAX_KEY_LEN + 2 * sizeof (*x)); - if ((saved_x = x) == 0) + if ((saved_x = x) == NULL) return (0); netmask = cp = (unsigned char *)(x + 2); bcopy(addmask_key, cp, mlen); @@ -599,7 +599,7 @@ rn_addroute(void *v_arg, void *n_arg, struct radix_head *head, struct radix_node treenodes[2]) { caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg; - struct radix_node *t, *x = 0, *tt; + struct radix_node *t, *x = NULL, *tt; struct radix_node *saved_tt, *top = head->rnh_treetop; short b = 0, b_leaf = 0; int keyduplicated; @@ -722,7 +722,7 @@ rn_addroute(void *v_arg, void *n_arg, struct radix_head *head, for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) if (m->rm_bit >= b_leaf) break; - t->rn_mklist = m; *mp = 0; + t->rn_mklist = m; *mp = NULL; } on2: /* Add new route to highest possible ancestor's list */ @@ -785,7 +785,7 @@ rn_delete(void *v_arg, void *netmask_arg, struct radix_head *head) vlen = LEN(v); saved_tt = tt; top = x; - if (tt == 0 || + if (tt == NULL || bcmp(v + head_off, tt->rn_key + head_off, vlen - head_off)) return (0); /* @@ -797,10 +797,10 @@ rn_delete(void *v_arg, void *netmask_arg, struct radix_head *head) return (0); netmask = x->rn_key; while (tt->rn_mask != netmask) - if ((tt = tt->rn_dupedkey) == 0) + if ((tt = tt->rn_dupedkey) == NULL) return (0); } - if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == 0) + if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == NULL) goto on1; if (tt->rn_flags & RNF_NORMAL) { if (m->rm_leaf != tt || m->rm_refs > 0) { @@ -829,7 +829,7 @@ rn_delete(void *v_arg, void *netmask_arg, struct radix_head *head) R_Free(m); break; } - if (m == 0) { + if (m == NULL) { log(LOG_ERR, "rn_delete: couldn't find our annotation\n"); if (tt->rn_flags & RNF_NORMAL) return (0); /* Dangling ref to us */ @@ -1044,7 +1044,7 @@ rn_walktree_from(struct radix_head *h, void *a, void *m, rn = rn->rn_left; next = rn; /* Process leaves */ - while ((rn = base) != 0) { + while ((rn = base) != NULL) { base = rn->rn_dupedkey; /* printf("leaf %p\n", rn); */ if (!(rn->rn_flags & RNF_ROOT) diff --git a/sys/net/raw_usrreq.c b/sys/net/raw_usrreq.c index 87bcd89..9e22528 100644 --- a/sys/net/raw_usrreq.c +++ b/sys/net/raw_usrreq.c @@ -83,7 +83,7 @@ raw_input_ext(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src, struct mbuf *m = m0; struct socket *last; - last = 0; + last = NULL; mtx_lock(&rawcb_mtx); LIST_FOREACH(rp, &V_rawcb_list, list) { if (rp->rcb_proto.sp_family != proto->sp_family) diff --git a/sys/netgraph/atm/ccatm/ng_ccatm.c b/sys/netgraph/atm/ccatm/ng_ccatm.c index cdbc86f..cc3f751 100644 --- a/sys/netgraph/atm/ccatm/ng_ccatm.c +++ b/sys/netgraph/atm/ccatm/ng_ccatm.c @@ -441,7 +441,7 @@ send_dump(struct ccdata *data, void *uarg, const char *buf) m->m_pkthdr.len = 0; } else { m = m_getcl(M_NOWAIT, MT_DATA, 0); - if (m == 0) { + if (m == NULL) { m_freem(priv->dump_first); return (ENOBUFS); } diff --git a/sys/netgraph/ng_socket.c b/sys/netgraph/ng_socket.c index 38da313..76d6383 100644 --- a/sys/netgraph/ng_socket.c +++ b/sys/netgraph/ng_socket.c @@ -360,7 +360,7 @@ ngc_bind(struct socket *so, struct sockaddr *nam, struct thread *td) { struct ngpcb *const pcbp = sotongpcb(so); - if (pcbp == 0) + if (pcbp == NULL) return (EINVAL); return (ng_bind(nam, pcbp)); } @@ -474,7 +474,7 @@ ngd_connect(struct socket *so, struct sockaddr *nam, struct thread *td) { struct ngpcb *const pcbp = sotongpcb(so); - if (pcbp == 0) + if (pcbp == NULL) return (EINVAL); return (ng_connect_data(nam, pcbp)); } diff --git a/sys/netgraph/ng_source.c b/sys/netgraph/ng_source.c index 1883ec0..8332d20 100644 --- a/sys/netgraph/ng_source.c +++ b/sys/netgraph/ng_source.c @@ -294,7 +294,7 @@ ng_source_newhook(node_p node, hook_p hook, const char *name) sc->input = hook; } else if (strcmp(name, NG_SOURCE_HOOK_OUTPUT) == 0) { sc->output = hook; - sc->output_ifp = 0; + sc->output_ifp = NULL; bzero(&sc->stats, sizeof(sc->stats)); } else return (EINVAL); diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 7a06bea..eac3c1d 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -578,7 +578,7 @@ int arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m, const struct sockaddr *dst, u_char *desten, uint32_t *pflags) { - struct llentry *la = 0; + struct llentry *la = NULL; if (pflags != NULL) *pflags = 0; diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c index 2154149..dcadec5 100644 --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -1469,7 +1469,7 @@ igmp_input(struct mbuf **mp, int *offp, int proto) else minlen += IGMP_MINLEN; if ((!M_WRITABLE(m) || m->m_len < minlen) && - (m = m_pullup(m, minlen)) == 0) { + (m = m_pullup(m, minlen)) == NULL) { IGMPSTAT_INC(igps_rcv_tooshort); return (IPPROTO_DONE); } diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c index f2a985b..4037dbf 100644 --- a/sys/netinet/in_mcast.c +++ b/sys/netinet/in_mcast.c @@ -1810,7 +1810,7 @@ inp_getmoptions(struct inpcb *inp, struct sockopt *sopt) break; case IP_MULTICAST_TTL: - if (imo == 0) + if (imo == NULL) optval = coptval = IP_DEFAULT_MULTICAST_TTL; else optval = coptval = imo->imo_multicast_ttl; @@ -1822,7 +1822,7 @@ inp_getmoptions(struct inpcb *inp, struct sockopt *sopt) break; case IP_MULTICAST_LOOP: - if (imo == 0) + if (imo == NULL) optval = coptval = IP_DEFAULT_MULTICAST_LOOP; else optval = coptval = imo->imo_multicast_loop; diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index f23a3a8..233d1af 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -205,7 +205,7 @@ divert_packet(struct mbuf *m, int incoming) } /* Assure header */ if (m->m_len < sizeof(struct ip) && - (m = m_pullup(m, sizeof(struct ip))) == 0) + (m = m_pullup(m, sizeof(struct ip))) == NULL) return; ip = mtod(m, struct ip *); @@ -600,7 +600,7 @@ div_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, /* Packet must have a header (but that's about it) */ if (m->m_len < sizeof (struct ip) && - (m = m_pullup(m, sizeof (struct ip))) == 0) { + (m = m_pullup(m, sizeof (struct ip))) == NULL) { KMOD_IPSTAT_INC(ips_toosmall); m_freem(m); return EINVAL; @@ -666,7 +666,7 @@ div_pcblist(SYSCTL_HANDLER_ARGS) return error; inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK); - if (inp_list == 0) + if (inp_list == NULL) return ENOMEM; INP_INFO_RLOCK(&V_divcbinfo); diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index e52ff1a..7250527 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -256,10 +256,12 @@ enum ipfw_opcodes { /* arguments (4 byte each) */ O_SETDSCP, /* arg1=DSCP value */ O_IP_FLOW_LOOKUP, /* arg1=table number, u32=value */ + O_EXTERNAL_ACTION, /* arg1=id of external action handler */ + O_EXTERNAL_INSTANCE, /* arg1=id of eaction handler instance */ + O_LAST_OPCODE /* not an opcode! */ }; - /* * The extension header are filtered only for presence using a bit * vector with a flag for each header. @@ -780,6 +782,10 @@ typedef struct _ipfw_obj_tlv { #define IPFW_TLV_RULE_ENT 7 #define IPFW_TLV_TBLENT_LIST 8 #define IPFW_TLV_RANGE 9 +#define IPFW_TLV_EACTION 10 + +#define IPFW_TLV_EACTION_BASE 1000 +#define IPFW_TLV_EACTION_NAME(arg) (IPFW_TLV_EACTION_BASE + (arg)) /* Object name TLV */ typedef struct _ipfw_obj_ntlv { diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 6e6202a..fee980f 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -475,6 +475,23 @@ icmp_input(struct mbuf **mp, int *offp, int proto) * XXX if the packet contains [IPv4 AH TCP], we can't make a * notification to TCP layer. */ + i = sizeof(struct ip) + min(icmplen, ICMP_ADVLENPREF(icp)); + ip_stripoptions(m); + if (m->m_len < i && (m = m_pullup(m, i)) == NULL) { + /* This should actually not happen */ + ICMPSTAT_INC(icps_tooshort); + return (IPPROTO_DONE); + } + ip = mtod(m, struct ip *); + icp = (struct icmp *)(ip + 1); + /* + * The upper layer handler can rely on: + * - The outer IP header has no options. + * - The outer IP header, the ICMP header, the inner IP header, + * and the first n bytes of the inner payload are contiguous. + * n is at least 8, but might be larger based on + * ICMP_ADVLENPREF. See its definition in ip_icmp.h. + */ ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput; if (ctlfunc) (*ctlfunc)(code, (struct sockaddr *)&icmpsrc, @@ -657,7 +674,7 @@ icmp_reflect(struct mbuf *m) struct in_ifaddr *ia; struct in_addr t; struct nhop4_extended nh_ext; - struct mbuf *opts = 0; + struct mbuf *opts = NULL; int optlen = (ip->ip_hl << 2) - sizeof(struct ip); if (IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || @@ -773,7 +790,7 @@ match: * add on any record-route or timestamp options. */ cp = (u_char *) (ip + 1); - if ((opts = ip_srcroute(m)) == 0 && + if ((opts = ip_srcroute(m)) == NULL && (opts = m_gethdr(M_NOWAIT, MT_DATA))) { opts->m_len = sizeof(struct in_addr); mtod(opts, struct in_addr *)->s_addr = 0; diff --git a/sys/netinet/ip_icmp.h b/sys/netinet/ip_icmp.h index 38d44d7..a046432 100644 --- a/sys/netinet/ip_icmp.h +++ b/sys/netinet/ip_icmp.h @@ -136,6 +136,13 @@ struct icmp { #define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ #define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) /* N.B.: must separately check that ip_hl >= 5 */ + /* This is the minimum length required by RFC 792. */ +/* + * ICMP_ADVLENPREF is the preferred number of bytes which should be contiguous. + * SCTP needs additional 12 bytes to be able to access the initiate tag + * in packets containing an INIT chunk. + */ +#define ICMP_ADVLENPREF(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8 + 12) /* * Definition of type and code field values. diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 6f25e08..773d7ae 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -571,8 +571,7 @@ tooshort: goto ours; } if (m->m_flags & M_IP_NEXTHOP) { - dchg = (m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL); - if (dchg != 0) { + if (m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL) { /* * Directly ship the packet on. This allows * forwarding packets originally destined to us diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c index 69e12c3..ba21edc 100644 --- a/sys/netinet/ip_mroute.c +++ b/sys/netinet/ip_mroute.c @@ -2601,7 +2601,7 @@ pim_input(struct mbuf **mp, int *offp, int proto) * Get the IP and PIM headers in contiguous memory, and * possibly the PIM REGISTER header. */ - if (m->m_len < minlen && (m = m_pullup(m, minlen)) == 0) { + if (m->m_len < minlen && (m = m_pullup(m, minlen)) == NULL) { CTR1(KTR_IPMF, "%s: m_pullup() failed", __func__); return (IPPROTO_DONE); } diff --git a/sys/netinet/ip_options.c b/sys/netinet/ip_options.c index 5daf653..b050423 100644 --- a/sys/netinet/ip_options.c +++ b/sys/netinet/ip_options.c @@ -608,7 +608,7 @@ ip_pcbopts(struct inpcb *inp, int optname, struct mbuf *m) /* turn off any old options */ if (*pcbopt) (void)m_free(*pcbopt); - *pcbopt = 0; + *pcbopt = NULL; if (m == NULL || m->m_len == 0) { /* * Only turning off any previous options. diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index afdf1a7..3a8be27 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1348,7 +1348,7 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt) caddr_t req = NULL; size_t len = 0; - if (m != 0) { + if (m != NULL) { req = mtod(m, caddr_t); len = m->m_len; } diff --git a/sys/netinet/libalias/alias_db.c b/sys/netinet/libalias/alias_db.c index cceccd5..4f8159b 100644 --- a/sys/netinet/libalias/alias_db.c +++ b/sys/netinet/libalias/alias_db.c @@ -784,9 +784,9 @@ FindNewPortGroup(struct libalias *la, struct alias_link *search_result; for (j = 0; j < port_count; j++) - if (0 != (search_result = FindLinkIn(la, dst_addr, alias_addr, - dst_port, htons(port_sys + j), - link_type, 0))) + if ((search_result = FindLinkIn(la, dst_addr, + alias_addr, dst_port, htons(port_sys + j), + link_type, 0)) != NULL) break; /* Found a good range, return base */ diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 9f29444..8de3108 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -1046,7 +1046,7 @@ rip_pcblist(SYSCTL_HANDLER_ARGS) return (error); inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK); - if (inp_list == 0) + if (inp_list == NULL) return (ENOMEM); INP_INFO_RLOCK(&V_ripcbinfo); diff --git a/sys/netinet/sctp_syscalls.c b/sys/netinet/sctp_syscalls.c index 71e2f72..5c16e8d 100644 --- a/sys/netinet/sctp_syscalls.c +++ b/sys/netinet/sctp_syscalls.c @@ -562,7 +562,7 @@ sys_sctp_generic_recvmsg(td, uap) if (fromlen && uap->from) { len = fromlen; - if (len <= 0 || fromsa == 0) + if (len <= 0 || fromsa == NULL) len = 0; else { len = MIN(len, fromsa->sa_len); diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 5f43234..81d2478 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -254,48 +254,49 @@ sctp_notify(struct sctp_inpcb *inp, void sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip) { - struct ip *ip = vip; + struct ip *outer_ip, *inner_ip; struct sctphdr *sh; - struct icmp *icmph; - uint32_t vrf_id; + struct icmp *icmp; + struct sctp_inpcb *inp; + struct sctp_tcb *stcb; + struct sctp_nets *net; + struct sctp_init_chunk *ch; + struct sockaddr_in to, from; - /* FIX, for non-bsd is this right? */ - vrf_id = SCTP_DEFAULT_VRFID; if (sa->sa_family != AF_INET || ((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) { return; } if (PRC_IS_REDIRECT(cmd)) { - ip = 0; + vip = NULL; } else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) { return; } - if (ip) { - struct sctp_inpcb *inp = NULL; - struct sctp_tcb *stcb = NULL; - struct sctp_nets *net = NULL; - struct sockaddr_in to, from; - - icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) - - sizeof(struct ip))); - - sh = (struct sctphdr *)((caddr_t)ip + (ip->ip_hl << 2)); + if (vip != NULL) { + inner_ip = (struct ip *)vip; + icmp = (struct icmp *)((caddr_t)inner_ip - + (sizeof(struct icmp) - sizeof(struct ip))); + outer_ip = (struct ip *)((caddr_t)icmp - sizeof(struct ip)); + sh = (struct sctphdr *)((caddr_t)inner_ip + (inner_ip->ip_hl << 2)); bzero(&to, sizeof(to)); bzero(&from, sizeof(from)); from.sin_family = to.sin_family = AF_INET; from.sin_len = to.sin_len = sizeof(to); from.sin_port = sh->src_port; - from.sin_addr = ip->ip_src; + from.sin_addr = inner_ip->ip_src; to.sin_port = sh->dest_port; - to.sin_addr = ip->ip_dst; + to.sin_addr = inner_ip->ip_dst; /* * 'to' holds the dest of the packet that failed to be sent. * 'from' holds our local endpoint address. Thus we reverse * the to and the from in the lookup. */ + inp = NULL; + net = NULL; stcb = sctp_findassociation_addr_sa((struct sockaddr *)&to, (struct sockaddr *)&from, - &inp, &net, 1, vrf_id); + &inp, &net, 1, + SCTP_DEFAULT_VRFID); if ((stcb != NULL) && (net != NULL) && (inp != NULL) && @@ -313,19 +314,30 @@ sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip) return; } } else { - /* - * In this case we could check if we got an - * INIT chunk and if the initiate tag - * matches. But this is not there yet... - */ - SCTP_TCB_UNLOCK(stcb); - return; + if (ntohs(outer_ip->ip_len) >= + sizeof(struct ip) + + 8 + (inner_ip->ip_hl << 2) + 20) { + /* + * In this case we can check if we + * got an INIT chunk and if the + * initiate tag matches. + */ + ch = (struct sctp_init_chunk *)(sh + 1); + if ((ch->ch.chunk_type != SCTP_INITIATION) || + (ntohl(ch->init.initiate_tag) != stcb->asoc.my_vtag)) { + SCTP_TCB_UNLOCK(stcb); + return; + } + } else { + SCTP_TCB_UNLOCK(stcb); + return; + } } sctp_notify(inp, stcb, net, - icmph->icmp_type, - icmph->icmp_code, - ntohs(ip->ip_len), - ntohs(icmph->icmp_nextmtu)); + icmp->icmp_type, + icmp->icmp_code, + ntohs(inner_ip->ip_len), + ntohs(icmp->icmp_nextmtu)); } else { if ((stcb == NULL) && (inp != NULL)) { /* reduce ref-count */ @@ -457,7 +469,7 @@ sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUS uint32_t vrf_id = SCTP_DEFAULT_VRFID; inp = (struct sctp_inpcb *)so->so_pcb; - if (inp != 0) { + if (inp != NULL) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); return (EINVAL); } diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 56aa56f..fdc2e76 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -308,7 +308,7 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off, { struct sockaddr *append_sa; struct socket *so; - struct mbuf *opts = 0; + struct mbuf *opts = NULL; #ifdef INET6 struct sockaddr_in6 udp_in6; #endif @@ -856,7 +856,7 @@ udp_pcblist(SYSCTL_HANDLER_ARGS) return (error); inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK); - if (inp_list == 0) + if (inp_list == NULL) return (ENOMEM); INP_INFO_RLOCK(&V_udbinfo); diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 797093a..48f05e7 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1823,7 +1823,7 @@ in6_ifawithifp(struct ifnet *ifp, struct in6_addr *dst) { int dst_scope = in6_addrscope(dst), blen = -1, tlen; struct ifaddr *ifa; - struct in6_ifaddr *besta = 0; + struct in6_ifaddr *besta = NULL; struct in6_ifaddr *dep[2]; /* last-resort: deprecated */ dep[0] = dep[1] = NULL; diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index 7895139..f64d305 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -256,7 +256,7 @@ ip6_fragment(struct ifnet *ifp, struct mbuf *m0, int hlen, u_char nextproto, ip6f->ip6f_offlg |= IP6F_MORE_FRAG; mhip6->ip6_plen = htons((u_short)(mtu + hlen + sizeof(*ip6f) - sizeof(struct ip6_hdr))); - if ((m_frgpart = m_copy(m0, off, mtu)) == 0) { + if ((m_frgpart = m_copy(m0, off, mtu)) == NULL) { IP6STAT_INC(ip6s_odropped); return (ENOBUFS); } @@ -503,7 +503,7 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, /* * Route packet. */ - if (ro == 0) { + if (ro == NULL) { ro = &ip6route; bzero((caddr_t)ro, sizeof(*ro)); } @@ -1116,7 +1116,7 @@ ip6_insert_jumboopt(struct ip6_exthdrs *exthdrs, u_int32_t plen) * jumbo payload option, allocate a cluster to store the whole options. * Otherwise, use it to store the options. */ - if (exthdrs->ip6e_hbh == 0) { + if (exthdrs->ip6e_hbh == NULL) { mopt = m_get(M_NOWAIT, MT_DATA); if (mopt == NULL) return (ENOBUFS); @@ -1198,7 +1198,7 @@ ip6_insertfraghdr(struct mbuf *m0, struct mbuf *m, int hlen, if (hlen > sizeof(struct ip6_hdr)) { n = m_copym(m0, sizeof(struct ip6_hdr), hlen - sizeof(struct ip6_hdr), M_NOWAIT); - if (n == 0) + if (n == NULL) return (ENOBUFS); m->m_next = n; } else @@ -2515,7 +2515,7 @@ int ip6_setpktopts(struct mbuf *control, struct ip6_pktopts *opt, struct ip6_pktopts *stickyopt, struct ucred *cred, int uproto) { - struct cmsghdr *cm = 0; + struct cmsghdr *cm = NULL; if (control == NULL || opt == NULL) return (EINVAL); diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index 6fee830..aa7baad 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -1510,7 +1510,7 @@ pfxlist_onlink_check() find_pfxlist_reachable_router(pr) == NULL) pr->ndpr_stateflags |= NDPRF_DETACHED; if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 && - find_pfxlist_reachable_router(pr) != 0) + find_pfxlist_reachable_router(pr) != NULL) pr->ndpr_stateflags &= ~NDPRF_DETACHED; } } else { diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 972eb9f..2b95e48 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -163,7 +163,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto) struct mbuf *m = *mp; register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); register struct inpcb *in6p; - struct inpcb *last = 0; + struct inpcb *last = NULL; struct mbuf *opts = NULL; struct sockaddr_in6 fromsa; diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index ebcf6d6..03479fd 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -1212,9 +1212,9 @@ udp6_send(struct socket *so, int flags, struct mbuf *m, #ifdef INET if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { int hasv4addr; - struct sockaddr_in6 *sin6 = 0; + struct sockaddr_in6 *sin6 = NULL; - if (addr == 0) + if (addr == NULL) hasv4addr = (inp->inp_vflag & INP_IPV4); else { sin6 = (struct sockaddr_in6 *)addr; diff --git a/sys/netipsec/ipsec_mbuf.c b/sys/netipsec/ipsec_mbuf.c index b3df0e0..7111210 100644 --- a/sys/netipsec/ipsec_mbuf.c +++ b/sys/netipsec/ipsec_mbuf.c @@ -202,7 +202,7 @@ m_pad(struct mbuf *m, int n) if (pad > M_TRAILINGSPACE(m0)) { /* Add an mbuf to the chain. */ MGET(m1, M_NOWAIT, MT_DATA); - if (m1 == 0) { + if (m1 == NULL) { m_freem(m0); DPRINTF(("%s: unable to get extra mbuf\n", __func__)); return NULL; diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c index 865a630..7070c1d 100644 --- a/sys/netipsec/key.c +++ b/sys/netipsec/key.c @@ -4923,8 +4923,8 @@ key_update(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) dport = (struct sadb_x_nat_t_port *) mhp->ext[SADB_X_EXT_NAT_T_DPORT]; } else { - type = 0; - sport = dport = 0; + type = NULL; + sport = dport = NULL; } if (mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL && mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL) { @@ -4949,7 +4949,7 @@ key_update(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) frag = (struct sadb_x_nat_t_frag *) mhp->ext[SADB_X_EXT_NAT_T_FRAG]; } else { - frag = 0; + frag = NULL; } #endif @@ -5215,7 +5215,7 @@ key_add(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) KEY_PORTTOSADDR(&saidx.dst, dport->sadb_x_nat_t_port_port); } else { - type = 0; + type = NULL; } if (mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL && mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL) { @@ -5240,7 +5240,7 @@ key_add(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) frag = (struct sadb_x_nat_t_frag *) mhp->ext[SADB_X_EXT_NAT_T_FRAG]; } else { - frag = 0; + frag = NULL; } #endif @@ -6599,7 +6599,7 @@ key_acquire2(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) static int key_register(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) { - struct secreg *reg, *newreg = 0; + struct secreg *reg, *newreg = NULL; IPSEC_ASSERT(so != NULL, ("null socket")); IPSEC_ASSERT(m != NULL, ("null mbuf")); diff --git a/sys/netipsec/keysock.c b/sys/netipsec/keysock.c index 4d12957..73e54bb 100644 --- a/sys/netipsec/keysock.c +++ b/sys/netipsec/keysock.c @@ -92,7 +92,7 @@ key_output(struct mbuf *m, struct socket *so, ...) struct sadb_msg *msg; int len, error = 0; - if (m == 0) + if (m == NULL) panic("%s: NULL pointer was passed.\n", __func__); PFKEYSTAT_INC(out_total); @@ -106,7 +106,7 @@ key_output(struct mbuf *m, struct socket *so, ...) } if (m->m_len < sizeof(struct sadb_msg)) { - if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) { + if ((m = m_pullup(m, sizeof(struct sadb_msg))) == NULL) { PFKEYSTAT_INC(out_nomem); error = ENOBUFS; goto end; @@ -178,7 +178,7 @@ key_sendup(struct socket *so, struct sadb_msg *msg, u_int len, int target) int tlen; /* sanity check */ - if (so == 0 || msg == 0) + if (so == NULL || msg == NULL) panic("%s: NULL pointer was passed.\n", __func__); KEYDEBUG(KEYDEBUG_KEY_DUMP, @@ -388,7 +388,7 @@ key_attach(struct socket *so, int proto, struct thread *td) /* XXX */ kp = malloc(sizeof *kp, M_PCB, M_WAITOK | M_ZERO); - if (kp == 0) + if (kp == NULL) return ENOBUFS; so->so_pcb = (caddr_t)kp; diff --git a/sys/netipsec/xform_ipcomp.c b/sys/netipsec/xform_ipcomp.c index 122fc72..ae19d8d 100644 --- a/sys/netipsec/xform_ipcomp.c +++ b/sys/netipsec/xform_ipcomp.c @@ -283,7 +283,7 @@ ipcomp_input_cb(struct cryptop *crp) /* In case it's not done already, adjust the size of the mbuf chain */ m->m_pkthdr.len = clen + hlen + skip; - if (m->m_len < skip + hlen && (m = m_pullup(m, skip + hlen)) == 0) { + if (m->m_len < skip + hlen && (m = m_pullup(m, skip + hlen)) == NULL) { IPCOMPSTAT_INC(ipcomps_hdrops); /*XXX*/ DPRINTF(("%s: m_pullup failed\n", __func__)); error = EINVAL; /*XXX*/ diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c index 2d0d2f4..b0a7474 100644 --- a/sys/netpfil/ipfw/ip_fw2.c +++ b/sys/netpfil/ipfw/ip_fw2.c @@ -2542,6 +2542,11 @@ do { \ done = 1; /* exit outer loop */ break; } + case O_EXTERNAL_ACTION: + l = 0; /* in any case exit inner loop */ + retval = ipfw_run_eaction(chain, args, + cmd, &done); + break; default: panic("-- unknown opcode %d\n", cmd->opcode); @@ -2766,6 +2771,7 @@ vnet_ipfw_init(const void *unused) IPFW_LOCK_INIT(chain); ipfw_dyn_init(chain); + ipfw_eaction_init(chain, first); #ifdef LINEAR_SKIPTO ipfw_init_skipto_cache(chain); #endif @@ -2830,6 +2836,7 @@ vnet_ipfw_uninit(const void *unused) IPFW_WUNLOCK(chain); IPFW_UH_WUNLOCK(chain); ipfw_destroy_tables(chain, last); + ipfw_eaction_uninit(chain, last); if (reap != NULL) ipfw_reap_rules(reap); vnet_ipfw_iface_destroy(chain); diff --git a/sys/netpfil/ipfw/ip_fw_eaction.c b/sys/netpfil/ipfw/ip_fw_eaction.c new file mode 100644 index 0000000..144bf49d --- /dev/null +++ b/sys/netpfil/ipfw/ip_fw_eaction.c @@ -0,0 +1,369 @@ +/*- + * Copyright (c) 2016 Yandex LLC + * Copyright (c) 2016 Andrey V. Elsukov <ae@FreeBSD.org> + * + * 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/malloc.h> +#include <sys/kernel.h> +#include <sys/hash.h> +#include <sys/lock.h> +#include <sys/rwlock.h> +#include <sys/rmlock.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/queue.h> +#include <net/pfil.h> + +#include <net/if.h> /* ip_fw.h requires IFNAMSIZ */ +#include <netinet/in.h> +#include <netinet/ip_var.h> /* struct ipfw_rule_ref */ +#include <netinet/ip_fw.h> + +#include <netpfil/ipfw/ip_fw_private.h> + +#include "opt_ipfw.h" + +/* + * External actions support for ipfw. + * + * This code provides KPI for implementing loadable modules, that + * can provide handlers for external action opcodes in the ipfw's + * rules. + * Module should implement opcode handler with type ipfw_eaction_t. + * This handler will be called by ipfw_chk() function when + * O_EXTERNAL_ACTION opcode will be matched. The handler must return + * value used as return value in ipfw_chk(), i.e. IP_FW_PASS, + * IP_FW_DENY (see ip_fw_private.h). + * Also the last argument must be set by handler. If it is zero, + * the search continues to the next rule. If it has non zero value, + * the search terminates. + * + * The module that implements external action should register its + * handler and name with ipfw_add_eaction() function. + * This function will return eaction_id, that can be used by module. + * + * It is possible to pass some additional information to external + * action handler via the O_EXTERNAL_INSTANCE opcode. This opcode + * will be next after the O_EXTERNAL_ACTION opcode. cmd->arg1 will + * contain index of named object related to instance of external action. + * + * In case when eaction module uses named instances, it should register + * opcode rewriting routines for O_EXTERNAL_INSTANCE opcode. The + * classifier callback can look back into O_EXTERNAL_ACTION opcode (it + * must be in the (ipfw_insn *)(cmd - 1)). By arg1 from O_EXTERNAL_ACTION + * it can deteremine eaction_id and compare it with its own. + * The macro IPFW_TLV_EACTION_NAME(eaction_id) can be used to deteremine + * the type of named_object related to external action instance. + * + * On module unload handler should be deregistered with ipfw_del_eaction() + * function using known eaction_id. + */ + +struct eaction_obj { + struct named_object no; + ipfw_eaction_t *handler; + char name[64]; +}; + +#define EACTION_OBJ(ch, cmd) \ + ((struct eaction_obj *)SRV_OBJECT((ch), (cmd)->arg1)) + +#if 0 +#define EACTION_DEBUG(fmt, ...) do { \ + printf("%s: " fmt "\n", __func__, ## __VA_ARGS__); \ +} while (0) +#else +#define EACTION_DEBUG(fmt, ...) +#endif + +const char *default_eaction_typename = "drop"; +static int +default_eaction(struct ip_fw_chain *ch, struct ip_fw_args *args, + ipfw_insn *cmd, int *done) +{ + + *done = 1; /* terminate the search */ + return (IP_FW_DENY); +} + +/* + * Opcode rewriting callbacks. + */ +static int +eaction_classify(ipfw_insn *cmd, uint16_t *puidx, uint8_t *ptype) +{ + + EACTION_DEBUG("opcode %d, arg1 %d", cmd->opcode, cmd->arg1); + *puidx = cmd->arg1; + *ptype = 0; + return (0); +} + +static void +eaction_update(ipfw_insn *cmd, uint16_t idx) +{ + + cmd->arg1 = idx; + EACTION_DEBUG("opcode %d, arg1 -> %d", cmd->opcode, cmd->arg1); +} + +static int +eaction_findbyname(struct ip_fw_chain *ch, struct tid_info *ti, + struct named_object **pno) +{ + + EACTION_DEBUG("uidx %u, type %u", ti->uidx, ti->type); + return (ipfw_objhash_find_type(CHAIN_TO_SRV(ch), ti, + IPFW_TLV_EACTION, pno)); +} + +static struct named_object * +eaction_findbykidx(struct ip_fw_chain *ch, uint16_t idx) +{ + + EACTION_DEBUG("kidx %u", idx); + return (ipfw_objhash_lookup_kidx(CHAIN_TO_SRV(ch), idx)); +} + +static int +eaction_create_compat(struct ip_fw_chain *ch, struct tid_info *ti, + uint16_t *pkidx) +{ + + return (EOPNOTSUPP); +} + +static struct opcode_obj_rewrite eaction_opcodes[] = { + { + O_EXTERNAL_ACTION, IPFW_TLV_EACTION, + eaction_classify, eaction_update, + eaction_findbyname, eaction_findbykidx, + eaction_create_compat + }, +}; + +static int +create_eaction_obj(struct ip_fw_chain *ch, ipfw_eaction_t handler, + const char *name, uint16_t *eaction_id) +{ + struct namedobj_instance *ni; + struct eaction_obj *obj; + + IPFW_UH_UNLOCK_ASSERT(ch); + + ni = CHAIN_TO_SRV(ch); + obj = malloc(sizeof(*obj), M_IPFW, M_WAITOK | M_ZERO); + obj->no.name = obj->name; + obj->no.etlv = IPFW_TLV_EACTION; + obj->handler = handler; + strlcpy(obj->name, name, sizeof(obj->name)); + + IPFW_UH_WLOCK(ch); + if (ipfw_objhash_lookup_name_type(ni, 0, IPFW_TLV_EACTION, + name) != NULL) { + /* + * Object is already created. + * We don't allow eactions with the same name. + */ + IPFW_UH_WUNLOCK(ch); + free(obj, M_IPFW); + EACTION_DEBUG("External action with typename " + "'%s' already exists", name); + return (EEXIST); + } + if (ipfw_objhash_alloc_idx(ni, &obj->no.kidx) != 0) { + IPFW_UH_WUNLOCK(ch); + free(obj, M_IPFW); + EACTION_DEBUG("alloc_idx failed"); + return (ENOSPC); + } + ipfw_objhash_add(ni, &obj->no); + IPFW_WLOCK(ch); + SRV_OBJECT(ch, obj->no.kidx) = obj; + IPFW_WUNLOCK(ch); + obj->no.refcnt++; + IPFW_UH_WUNLOCK(ch); + + if (eaction_id != NULL) + *eaction_id = obj->no.kidx; + return (0); +} + +static void +destroy_eaction_obj(struct ip_fw_chain *ch, struct named_object *no) +{ + struct namedobj_instance *ni; + struct eaction_obj *obj; + + IPFW_UH_WLOCK_ASSERT(ch); + + ni = CHAIN_TO_SRV(ch); + IPFW_WLOCK(ch); + obj = SRV_OBJECT(ch, no->kidx); + SRV_OBJECT(ch, no->kidx) = NULL; + IPFW_WUNLOCK(ch); + ipfw_objhash_del(ni, no); + ipfw_objhash_free_idx(ni, no->kidx); + free(obj, M_IPFW); +} + +/* + * Resets all eaction opcodes to default handlers. + */ +static void +reset_eaction_obj(struct ip_fw_chain *ch, uint16_t eaction_id) +{ + struct named_object *no; + struct ip_fw *rule; + ipfw_insn *cmd; + int i; + + IPFW_UH_WLOCK_ASSERT(ch); + + no = ipfw_objhash_lookup_name_type(CHAIN_TO_SRV(ch), 0, + IPFW_TLV_EACTION, default_eaction_typename); + if (no == NULL) + panic("Default external action handler is not found"); + if (eaction_id == no->kidx) + panic("Wrong eaction_id"); + EACTION_DEBUG("replace id %u with %u", eaction_id, no->kidx); + IPFW_WLOCK(ch); + for (i = 0; i < ch->n_rules; i++) { + rule = ch->map[i]; + cmd = ACTION_PTR(rule); + if (cmd->opcode != O_EXTERNAL_ACTION) + continue; + if (cmd->arg1 != eaction_id) + continue; + cmd->arg1 = no->kidx; /* Set to default id */ + /* + * XXX: we only bump refcount on default_eaction. + * Refcount on the original object will be just + * ignored on destroy. But on default_eaction it + * will be decremented on rule deletion. + */ + no->refcnt++; + /* + * Since named_object related to this instance will be + * also destroyed, truncate the chain of opcodes to + * remove O_EXTERNAL_INSTANCE opcode. + */ + if (rule->act_ofs < rule->cmd_len - 1) { + EACTION_DEBUG("truncate rule %d", rule->rulenum); + rule->cmd_len--; + } + } + IPFW_WUNLOCK(ch); +} + +/* + * Initialize external actions framework. + * Create object with default eaction handler "drop". + */ +int +ipfw_eaction_init(struct ip_fw_chain *ch, int first) +{ + int error; + + error = create_eaction_obj(ch, default_eaction, + default_eaction_typename, NULL); + if (error != 0) + return (error); + IPFW_ADD_OBJ_REWRITER(first, eaction_opcodes); + EACTION_DEBUG("External actions support initialized"); + return (0); +} + +void +ipfw_eaction_uninit(struct ip_fw_chain *ch, int last) +{ + struct namedobj_instance *ni; + struct named_object *no; + + ni = CHAIN_TO_SRV(ch); + + IPFW_UH_WLOCK(ch); + no = ipfw_objhash_lookup_name_type(ni, 0, IPFW_TLV_EACTION, + default_eaction_typename); + if (no != NULL) + destroy_eaction_obj(ch, no); + IPFW_UH_WUNLOCK(ch); + IPFW_DEL_OBJ_REWRITER(last, eaction_opcodes); + EACTION_DEBUG("External actions support uninitialized"); +} + +/* + * Registers external action handler to the global array. + * On success it returns eaction id, otherwise - zero. + */ +uint16_t +ipfw_add_eaction(struct ip_fw_chain *ch, ipfw_eaction_t handler, + const char *name) +{ + uint16_t eaction_id; + + eaction_id = 0; + if (ipfw_check_object_name_generic(name) == 0) { + create_eaction_obj(ch, handler, name, &eaction_id); + EACTION_DEBUG("Registered external action '%s' with id %u", + name, eaction_id); + } + return (eaction_id); +} + +/* + * Deregisters external action handler with id eaction_id. + */ +int +ipfw_del_eaction(struct ip_fw_chain *ch, uint16_t eaction_id) +{ + struct named_object *no; + + IPFW_UH_WLOCK(ch); + no = ipfw_objhash_lookup_kidx(CHAIN_TO_SRV(ch), eaction_id); + if (no == NULL || no->etlv != IPFW_TLV_EACTION) { + IPFW_UH_WUNLOCK(ch); + return (EINVAL); + } + if (no->refcnt > 1) + reset_eaction_obj(ch, eaction_id); + EACTION_DEBUG("External action '%s' with id %u unregistered", + no->name, eaction_id); + destroy_eaction_obj(ch, no); + IPFW_UH_WUNLOCK(ch); + return (0); +} + +int +ipfw_run_eaction(struct ip_fw_chain *ch, struct ip_fw_args *args, + ipfw_insn *cmd, int *done) +{ + + return (EACTION_OBJ(ch, cmd)->handler(ch, args, cmd, done)); +} diff --git a/sys/netpfil/ipfw/ip_fw_iface.c b/sys/netpfil/ipfw/ip_fw_iface.c index b7c450c..07d24de 100644 --- a/sys/netpfil/ipfw/ip_fw_iface.c +++ b/sys/netpfil/ipfw/ip_fw_iface.c @@ -471,7 +471,7 @@ export_iface_internal(struct namedobj_instance *ii, struct named_object *no, da = (struct dump_iface_args *)arg; i = (ipfw_iface_info *)ipfw_get_sopt_space(da->sd, sizeof(*i)); - KASSERT(i != 0, ("previously checked buffer is not enough")); + KASSERT(i != NULL, ("previously checked buffer is not enough")); iif = (struct ipfw_iface *)no; diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h index 7be3d1e..62e1a9a 100644 --- a/sys/netpfil/ipfw/ip_fw_private.h +++ b/sys/netpfil/ipfw/ip_fw_private.h @@ -313,9 +313,9 @@ struct named_object { TAILQ_ENTRY(named_object) nn_next; /* namehash */ TAILQ_ENTRY(named_object) nv_next; /* valuehash */ char *name; /* object name */ - uint8_t subtype; /* object subtype within class */ - uint8_t etlv; /* Export TLV id */ - uint16_t spare[2]; + uint16_t etlv; /* Export TLV id */ + uint8_t subtype;/* object subtype within class */ + uint8_t spare[3]; uint16_t kidx; /* object kernel index */ uint32_t set; /* set object belongs to */ uint32_t refcnt; /* number of references */ @@ -516,9 +516,10 @@ struct ip_fw_bcounter0 { #define IPFW_TABLES_MAX 65536 #define IPFW_TABLES_DEFAULT 128 #define IPFW_OBJECTS_MAX 65536 -#define IPFW_OBJECTS_DEFAULT 128 +#define IPFW_OBJECTS_DEFAULT 1024 #define CHAIN_TO_SRV(ch) ((ch)->srvmap) +#define SRV_OBJECT(ch, idx) ((ch)->srvstate[(idx)]) struct tid_info { uint32_t set; /* table set */ @@ -650,9 +651,10 @@ caddr_t ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed); struct namedobj_instance; typedef void (objhash_cb_t)(struct namedobj_instance *ni, struct named_object *, void *arg); -typedef uint32_t (objhash_hash_f)(struct namedobj_instance *ni, void *key, +typedef uint32_t (objhash_hash_f)(struct namedobj_instance *ni, const void *key, + uint32_t kopt); +typedef int (objhash_cmp_f)(struct named_object *no, const void *key, uint32_t kopt); -typedef int (objhash_cmp_f)(struct named_object *no, void *key, uint32_t kopt); struct namedobj_instance *ipfw_objhash_create(uint32_t items); void ipfw_objhash_destroy(struct namedobj_instance *); void ipfw_objhash_bitmap_alloc(uint32_t items, void **idx, int *pblocks); @@ -665,7 +667,7 @@ void ipfw_objhash_set_hashf(struct namedobj_instance *ni, objhash_hash_f *f); struct named_object *ipfw_objhash_lookup_name(struct namedobj_instance *ni, uint32_t set, char *name); struct named_object *ipfw_objhash_lookup_name_type(struct namedobj_instance *ni, - uint32_t set, uint32_t type, char *name); + uint32_t set, uint32_t type, const char *name); struct named_object *ipfw_objhash_lookup_kidx(struct namedobj_instance *ni, uint16_t idx); int ipfw_objhash_same_name(struct namedobj_instance *ni, struct named_object *a, @@ -679,20 +681,14 @@ int ipfw_objhash_free_idx(struct namedobj_instance *ni, uint16_t idx); int ipfw_objhash_alloc_idx(void *n, uint16_t *pidx); void ipfw_objhash_set_funcs(struct namedobj_instance *ni, objhash_hash_f *hash_f, objhash_cmp_f *cmp_f); +int ipfw_objhash_find_type(struct namedobj_instance *ni, struct tid_info *ti, + uint32_t etlv, struct named_object **pno); void ipfw_export_obj_ntlv(struct named_object *no, ipfw_obj_ntlv *ntlv); void ipfw_init_obj_rewriter(void); void ipfw_destroy_obj_rewriter(void); void ipfw_add_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count); int ipfw_del_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count); -int ipfw_rewrite_rule_uidx(struct ip_fw_chain *chain, - struct rule_check_info *ci); -int ipfw_mark_object_kidx(struct ip_fw_chain *chain, struct ip_fw *rule, - uint32_t *bmask); -int ref_opcode_object(struct ip_fw_chain *ch, ipfw_insn *cmd, struct tid_info *ti, - struct obj_idx *pidx, int *found, int *unresolved); -void unref_oib_objects(struct ip_fw_chain *ch, ipfw_insn *cmd, - struct obj_idx *oib, struct obj_idx *end); int create_objects_compat(struct ip_fw_chain *ch, ipfw_insn *cmd, struct obj_idx *oib, struct obj_idx *pidx, struct tid_info *ti); void update_opcode_kidx(ipfw_insn *cmd, uint16_t idx); @@ -701,6 +697,18 @@ void ipfw_init_srv(struct ip_fw_chain *ch); void ipfw_destroy_srv(struct ip_fw_chain *ch); int ipfw_check_object_name_generic(const char *name); +/* In ip_fw_eaction.c */ +typedef int (ipfw_eaction_t)(struct ip_fw_chain *ch, struct ip_fw_args *args, + ipfw_insn *cmd, int *done); +int ipfw_eaction_init(struct ip_fw_chain *ch, int first); +void ipfw_eaction_uninit(struct ip_fw_chain *ch, int last); + +uint16_t ipfw_add_eaction(struct ip_fw_chain *ch, ipfw_eaction_t handler, + const char *name); +int ipfw_del_eaction(struct ip_fw_chain *ch, uint16_t eaction_id); +int ipfw_run_eaction(struct ip_fw_chain *ch, struct ip_fw_args *args, + ipfw_insn *cmd, int *done); + /* In ip_fw_table.c */ struct table_info; diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c index 857b465..c63a303 100644 --- a/sys/netpfil/ipfw/ip_fw_sockopt.c +++ b/sys/netpfil/ipfw/ip_fw_sockopt.c @@ -81,6 +81,8 @@ static int check_ipfw_rule1(struct ip_fw_rule *rule, int size, struct rule_check_info *ci); static int check_ipfw_rule0(struct ip_fw_rule0 *rule, int size, struct rule_check_info *ci); +static int rewrite_rule_uidx(struct ip_fw_chain *chain, + struct rule_check_info *ci); #define NAMEDOBJ_HASH_SIZE 32 @@ -98,10 +100,11 @@ struct namedobj_instance { }; #define BLOCK_ITEMS (8 * sizeof(u_long)) /* Number of items for ffsl() */ -static uint32_t objhash_hash_name(struct namedobj_instance *ni, void *key, - uint32_t kopt); +static uint32_t objhash_hash_name(struct namedobj_instance *ni, + const void *key, uint32_t kopt); static uint32_t objhash_hash_idx(struct namedobj_instance *ni, uint32_t val); -static int objhash_cmp_name(struct named_object *no, void *name, uint32_t set); +static int objhash_cmp_name(struct named_object *no, const void *name, + uint32_t set); MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's"); @@ -153,10 +156,17 @@ static struct ipfw_sopt_handler scodes[] = { static int set_legacy_obj_kidx(struct ip_fw_chain *ch, struct ip_fw_rule0 *rule); -struct opcode_obj_rewrite *ipfw_find_op_rw(uint16_t opcode); +static struct opcode_obj_rewrite *find_op_rw(ipfw_insn *cmd, + uint16_t *puidx, uint8_t *ptype); static int mark_object_kidx(struct ip_fw_chain *ch, struct ip_fw *rule, uint32_t *bmask); +static int ref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule, + struct rule_check_info *ci, struct obj_idx *oib, struct tid_info *ti); +static int ref_opcode_object(struct ip_fw_chain *ch, ipfw_insn *cmd, + struct tid_info *ti, struct obj_idx *pidx, int *unresolved); static void unref_rule_objects(struct ip_fw_chain *chain, struct ip_fw *rule); +static void unref_oib_objects(struct ip_fw_chain *ch, ipfw_insn *cmd, + struct obj_idx *oib, struct obj_idx *end); static int export_objhash_ntlv(struct namedobj_instance *ni, uint16_t kidx, struct sockopt_data *sd); @@ -675,7 +685,7 @@ commit_rules(struct ip_fw_chain *chain, struct rule_check_info *rci, int count) * We need to find (and create non-existing) * kernel objects, and reference existing ones. */ - error = ipfw_rewrite_rule_uidx(chain, ci); + error = rewrite_rule_uidx(chain, ci); if (error != 0) { /* @@ -1483,6 +1493,35 @@ check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, struct rule_check_info *ci) goto bad_size; break; + case O_EXTERNAL_ACTION: + if (cmd->arg1 == 0 || + cmdlen != F_INSN_SIZE(ipfw_insn)) { + printf("ipfw: invalid external " + "action opcode\n"); + return (EINVAL); + } + ci->object_opcodes++; + /* Do we have O_EXTERNAL_INSTANCE opcode? */ + if (l != cmdlen) { + l -= cmdlen; + cmd += cmdlen; + cmdlen = F_LEN(cmd); + if (cmd->opcode != O_EXTERNAL_INSTANCE) { + printf("ipfw: invalid opcode " + "next to external action %u\n", + cmd->opcode); + return (EINVAL); + } + if (cmd->arg1 == 0 || + cmdlen != F_INSN_SIZE(ipfw_insn)) { + printf("ipfw: invalid external " + "action instance opcode\n"); + return (EINVAL); + } + ci->object_opcodes++; + } + goto check_action; + case O_FIB: if (cmdlen != F_INSN_SIZE(ipfw_insn)) goto bad_size; @@ -2000,11 +2039,10 @@ static int mark_object_kidx(struct ip_fw_chain *ch, struct ip_fw *rule, uint32_t *bmask) { - int cmdlen, l, count; + struct opcode_obj_rewrite *rw; ipfw_insn *cmd; + int bidx, cmdlen, l, count; uint16_t kidx; - struct opcode_obj_rewrite *rw; - int bidx; uint8_t subtype; l = rule->cmd_len; @@ -2014,15 +2052,15 @@ mark_object_kidx(struct ip_fw_chain *ch, struct ip_fw *rule, for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { cmdlen = F_LEN(cmd); - rw = ipfw_find_op_rw(cmd->opcode); + rw = find_op_rw(cmd, &kidx, &subtype); if (rw == NULL) continue; - if (rw->classifier(cmd, &kidx, &subtype) != 0) - continue; - bidx = kidx / 32; - /* Maintain separate bitmasks for table and non-table objects */ + /* + * Maintain separate bitmasks for table and + * non-table objects. + */ if (rw->etlv != IPFW_TLV_TBL_NAME) bidx += IPFW_TABLES_MAX / 32; @@ -2194,7 +2232,7 @@ create_objects_compat(struct ip_fw_chain *ch, ipfw_insn *cmd, ti->type = p->type; ti->atype = 0; - rw = ipfw_find_op_rw((cmd + p->off)->opcode); + rw = find_op_rw(cmd + p->off, NULL, NULL); KASSERT(rw != NULL, ("Unable to find handler for op %d", (cmd + p->off)->opcode)); @@ -2229,14 +2267,14 @@ create_objects_compat(struct ip_fw_chain *ch, ipfw_insn *cmd, static int set_legacy_obj_kidx(struct ip_fw_chain *ch, struct ip_fw_rule0 *rule) { - int cmdlen, error, l; - ipfw_insn *cmd; - uint16_t kidx, uidx; - struct named_object *no; struct opcode_obj_rewrite *rw; - uint8_t subtype; + struct named_object *no; + ipfw_insn *cmd; char *end; long val; + int cmdlen, error, l; + uint16_t kidx, uidx; + uint8_t subtype; error = 0; @@ -2246,12 +2284,9 @@ set_legacy_obj_kidx(struct ip_fw_chain *ch, struct ip_fw_rule0 *rule) for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { cmdlen = F_LEN(cmd); - rw = ipfw_find_op_rw(cmd->opcode); - if (rw == NULL) - continue; - /* Check if is index in given opcode */ - if (rw->classifier(cmd, &kidx, &subtype) != 0) + rw = find_op_rw(cmd, &kidx, &subtype); + if (rw == NULL) continue; /* Try to find referenced kernel object */ @@ -2286,7 +2321,7 @@ set_legacy_obj_kidx(struct ip_fw_chain *ch, struct ip_fw_rule0 *rule) * * Used to rollback partially converted rule on error. */ -void +static void unref_oib_objects(struct ip_fw_chain *ch, ipfw_insn *cmd, struct obj_idx *oib, struct obj_idx *end) { @@ -2300,7 +2335,7 @@ unref_oib_objects(struct ip_fw_chain *ch, ipfw_insn *cmd, struct obj_idx *oib, if (p->kidx == 0) continue; - rw = ipfw_find_op_rw((cmd + p->off)->opcode); + rw = find_op_rw(cmd + p->off, NULL, NULL); KASSERT(rw != NULL, ("Unable to find handler for op %d", (cmd + p->off)->opcode)); @@ -2318,11 +2353,11 @@ unref_oib_objects(struct ip_fw_chain *ch, ipfw_insn *cmd, struct obj_idx *oib, static void unref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule) { - int cmdlen, l; - ipfw_insn *cmd; + struct opcode_obj_rewrite *rw; struct named_object *no; + ipfw_insn *cmd; + int cmdlen, l; uint16_t kidx; - struct opcode_obj_rewrite *rw; uint8_t subtype; IPFW_UH_WLOCK_ASSERT(ch); @@ -2333,12 +2368,9 @@ unref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule) for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { cmdlen = F_LEN(cmd); - rw = ipfw_find_op_rw(cmd->opcode); + rw = find_op_rw(cmd, &kidx, &subtype); if (rw == NULL) continue; - if (rw->classifier(cmd, &kidx, &subtype) != 0) - continue; - no = rw->find_bykidx(ch, kidx); KASSERT(no != NULL, ("table id %d not found", kidx)); @@ -2360,31 +2392,23 @@ unref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule) * Find and reference object (if any) stored in instruction @cmd. * * Saves object info in @pidx, sets - * - @found to 1 if object was found and references * - @unresolved to 1 if object should exists but not found * * Returns non-zero value in case of error. */ -int +static int ref_opcode_object(struct ip_fw_chain *ch, ipfw_insn *cmd, struct tid_info *ti, - struct obj_idx *pidx, int *found, int *unresolved) + struct obj_idx *pidx, int *unresolved) { struct named_object *no; struct opcode_obj_rewrite *rw; int error; - *found = 0; - *unresolved = 0; - /* Check if this opcode is candidate for rewrite */ - rw = ipfw_find_op_rw(cmd->opcode); + rw = find_op_rw(cmd, &ti->uidx, &ti->type); if (rw == NULL) return (0); - /* Check if we need to rewrite this opcode */ - if (rw->classifier(cmd, &ti->uidx, &ti->type) != 0) - return (0); - /* Need to rewrite. Save necessary fields */ pidx->uidx = ti->uidx; pidx->type = ti->type; @@ -2394,19 +2418,146 @@ ref_opcode_object(struct ip_fw_chain *ch, ipfw_insn *cmd, struct tid_info *ti, if (error != 0) return (error); if (no == NULL) { + /* + * Report about unresolved object for automaic + * creation. + */ *unresolved = 1; return (0); } - /* Found. bump refcount */ - *found = 1; + /* Found. Bump refcount and update kidx. */ no->refcnt++; - pidx->kidx = no->kidx; - + rw->update(cmd, no->kidx); return (0); } /* + * Finds and bumps refcount for objects referenced by given @rule. + * Auto-creates non-existing tables. + * Fills in @oib array with userland/kernel indexes. + * + * Returns 0 on success. + */ +static int +ref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule, + struct rule_check_info *ci, struct obj_idx *oib, struct tid_info *ti) +{ + struct obj_idx *pidx; + ipfw_insn *cmd; + int cmdlen, error, l, unresolved; + + pidx = oib; + l = rule->cmd_len; + cmd = rule->cmd; + cmdlen = 0; + error = 0; + + IPFW_UH_WLOCK(ch); + + /* Increase refcount on each existing referenced table. */ + for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { + cmdlen = F_LEN(cmd); + unresolved = 0; + + error = ref_opcode_object(ch, cmd, ti, pidx, &unresolved); + if (error != 0) + break; + /* + * Compability stuff for old clients: + * prepare to automaitcally create non-existing objects. + */ + if (unresolved != 0) { + pidx->off = rule->cmd_len - l; + pidx++; + } + } + + if (error != 0) { + /* Unref everything we have already done */ + unref_oib_objects(ch, rule->cmd, oib, pidx); + IPFW_UH_WUNLOCK(ch); + return (error); + } + IPFW_UH_WUNLOCK(ch); + + /* Perform auto-creation for non-existing objects */ + if (pidx != oib) + error = create_objects_compat(ch, rule->cmd, oib, pidx, ti); + + /* Calculate real number of dynamic objects */ + ci->object_opcodes = (uint16_t)(pidx - oib); + + return (error); +} + +/* + * Checks is opcode is referencing table of appropriate type. + * Adds reference count for found table if true. + * Rewrites user-supplied opcode values with kernel ones. + * + * Returns 0 on success and appropriate error code otherwise. + */ +static int +rewrite_rule_uidx(struct ip_fw_chain *chain, struct rule_check_info *ci) +{ + int error; + ipfw_insn *cmd; + uint8_t type; + struct obj_idx *p, *pidx_first, *pidx_last; + struct tid_info ti; + + /* + * Prepare an array for storing opcode indices. + * Use stack allocation by default. + */ + if (ci->object_opcodes <= (sizeof(ci->obuf)/sizeof(ci->obuf[0]))) { + /* Stack */ + pidx_first = ci->obuf; + } else + pidx_first = malloc( + ci->object_opcodes * sizeof(struct obj_idx), + M_IPFW, M_WAITOK | M_ZERO); + + error = 0; + type = 0; + memset(&ti, 0, sizeof(ti)); + + /* + * Use default set for looking up tables (old way) or + * use set rule is assigned to (new way). + */ + ti.set = (V_fw_tables_sets != 0) ? ci->krule->set : 0; + if (ci->ctlv != NULL) { + ti.tlvs = (void *)(ci->ctlv + 1); + ti.tlen = ci->ctlv->head.length - sizeof(ipfw_obj_ctlv); + } + + /* Reference all used tables and other objects */ + error = ref_rule_objects(chain, ci->krule, ci, pidx_first, &ti); + if (error != 0) + goto free; + /* + * Note that ref_rule_objects() might have updated ci->object_opcodes + * to reflect actual number of object opcodes. + */ + + /* Perform rewrite of remaining opcodes */ + p = pidx_first; + pidx_last = pidx_first + ci->object_opcodes; + for (p = pidx_first; p < pidx_last; p++) { + cmd = ci->krule->cmd + p->off; + update_opcode_kidx(cmd, p->kidx); + } + +free: + if (pidx_first != ci->obuf) + free(pidx_first, M_IPFW); + + return (error); +} + +/* * Adds one or more rules to ipfw @chain. * Data layout (version 0)(current): * Request: @@ -2646,7 +2797,7 @@ dump_soptcodes(struct ip_fw_chain *chain, ip_fw3_opheader *op3, for (n = 1; n <= count; n++) { i = (ipfw_sopt_info *)ipfw_get_sopt_space(sd, sizeof(*i)); - KASSERT(i != 0, ("previously checked buffer is not enough")); + KASSERT(i != NULL, ("previously checked buffer is not enough")); sh = &ctl3_handlers[n]; i->opcode = sh->opcode; i->version = sh->version; @@ -2680,35 +2831,73 @@ compare_opcodes(const void *_a, const void *_b) } /* - * Finds opcode object rewriter based on @code. - * - * Returns pointer to handler or NULL. + * XXX: Rewrite bsearch() */ -struct opcode_obj_rewrite * -ipfw_find_op_rw(uint16_t opcode) +static int +find_op_rw_range(uint16_t op, struct opcode_obj_rewrite **plo, + struct opcode_obj_rewrite **phi) { - struct opcode_obj_rewrite *rw, h; + struct opcode_obj_rewrite *ctl3_max, *lo, *hi, h, *rw; memset(&h, 0, sizeof(h)); - h.opcode = opcode; + h.opcode = op; rw = (struct opcode_obj_rewrite *)bsearch(&h, ctl3_rewriters, ctl3_rsize, sizeof(h), compare_opcodes); + if (rw == NULL) + return (1); + + /* Find the first element matching the same opcode */ + lo = rw; + for ( ; lo > ctl3_rewriters && (lo - 1)->opcode == op; lo--) + ; - return (rw); + /* Find the last element matching the same opcode */ + hi = rw; + ctl3_max = ctl3_rewriters + ctl3_rsize; + for ( ; (hi + 1) < ctl3_max && (hi + 1)->opcode == op; hi++) + ; + + *plo = lo; + *phi = hi; + + return (0); } +/* + * Finds opcode object rewriter based on @code. + * + * Returns pointer to handler or NULL. + */ +static struct opcode_obj_rewrite * +find_op_rw(ipfw_insn *cmd, uint16_t *puidx, uint8_t *ptype) +{ + struct opcode_obj_rewrite *rw, *lo, *hi; + uint16_t uidx; + uint8_t subtype; + + if (find_op_rw_range(cmd->opcode, &lo, &hi) != 0) + return (NULL); + + for (rw = lo; rw <= hi; rw++) { + if (rw->classifier(cmd, &uidx, &subtype) == 0) { + if (puidx != NULL) + *puidx = uidx; + if (ptype != NULL) + *ptype = subtype; + return (rw); + } + } + + return (NULL); +} int classify_opcode_kidx(ipfw_insn *cmd, uint16_t *puidx) { - struct opcode_obj_rewrite *rw; - uint8_t subtype; - rw = ipfw_find_op_rw(cmd->opcode); - if (rw == NULL) + if (find_op_rw(cmd, puidx, NULL) == 0) return (1); - - return (rw->classifier(cmd, puidx, &subtype)); + return (0); } void @@ -2716,7 +2905,7 @@ update_opcode_kidx(ipfw_insn *cmd, uint16_t idx) { struct opcode_obj_rewrite *rw; - rw = ipfw_find_op_rw(cmd->opcode); + rw = find_op_rw(cmd, NULL, NULL); KASSERT(rw != NULL, ("No handler to update opcode %d", cmd->opcode)); rw->update(cmd, idx); } @@ -2784,20 +2973,26 @@ int ipfw_del_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count) { size_t sz; - struct opcode_obj_rewrite *tmp, *h; + struct opcode_obj_rewrite *ctl3_max, *ktmp, *lo, *hi; int i; CTL3_LOCK(); for (i = 0; i < count; i++) { - tmp = &rw[i]; - h = ipfw_find_op_rw(tmp->opcode); - if (h == NULL) + if (find_op_rw_range(rw[i].opcode, &lo, &hi) != 0) continue; - sz = (ctl3_rewriters + ctl3_rsize - (h + 1)) * sizeof(*h); - memmove(h, h + 1, sz); - ctl3_rsize--; + for (ktmp = lo; ktmp <= hi; ktmp++) { + if (ktmp->classifier != rw[i].classifier) + continue; + + ctl3_max = ctl3_rewriters + ctl3_rsize; + sz = (ctl3_max - (ktmp + 1)) * sizeof(*ktmp); + memmove(ktmp, ktmp + 1, sz); + ctl3_rsize--; + break; + } + } if (ctl3_rsize == 0) { @@ -2828,7 +3023,7 @@ export_objhash_ntlv_internal(struct namedobj_instance *ni, /* * Lists all service objects. * Data layout (v0)(current): - * Request: [ ipfw_obj_lheader ] size = ipfw_cfg_lheader.size + * Request: [ ipfw_obj_lheader ] size = ipfw_obj_lheader.size * Reply: [ ipfw_obj_lheader [ ipfw_obj_ntlv x N ] (optional) ] * Returns 0 on success */ @@ -3843,17 +4038,17 @@ ipfw_objhash_set_funcs(struct namedobj_instance *ni, objhash_hash_f *hash_f, } static uint32_t -objhash_hash_name(struct namedobj_instance *ni, void *name, uint32_t set) +objhash_hash_name(struct namedobj_instance *ni, const void *name, uint32_t set) { - return (fnv_32_str((char *)name, FNV1_32_INIT)); + return (fnv_32_str((const char *)name, FNV1_32_INIT)); } static int -objhash_cmp_name(struct named_object *no, void *name, uint32_t set) +objhash_cmp_name(struct named_object *no, const void *name, uint32_t set) { - if ((strcmp(no->name, (char *)name) == 0) && (no->set == set)) + if ((strcmp(no->name, (const char *)name) == 0) && (no->set == set)) return (0); return (1); @@ -3886,11 +4081,90 @@ ipfw_objhash_lookup_name(struct namedobj_instance *ni, uint32_t set, char *name) } /* + * Find named object by @uid. + * Check @tlvs for valid data inside. + * + * Returns pointer to found TLV or NULL. + */ +static ipfw_obj_ntlv * +find_name_tlv_type(void *tlvs, int len, uint16_t uidx, uint32_t etlv) +{ + ipfw_obj_ntlv *ntlv; + uintptr_t pa, pe; + int l; + + pa = (uintptr_t)tlvs; + pe = pa + len; + l = 0; + for (; pa < pe; pa += l) { + ntlv = (ipfw_obj_ntlv *)pa; + l = ntlv->head.length; + + if (l != sizeof(*ntlv)) + return (NULL); + + if (ntlv->idx != uidx) + continue; + /* + * When userland has specified zero TLV type, do + * not compare it with eltv. In some cases userland + * doesn't know what type should it have. Use only + * uidx and name for search named_object. + */ + if (ntlv->head.type != 0 && + ntlv->head.type != (uint16_t)etlv) + continue; + + if (ipfw_check_object_name_generic(ntlv->name) != 0) + return (NULL); + + return (ntlv); + } + + return (NULL); +} + +/* + * Finds object config based on either legacy index + * or name in ntlv. + * Note @ti structure contains unchecked data from userland. + * + * Returns 0 in success and fills in @pno with found config + */ +int +ipfw_objhash_find_type(struct namedobj_instance *ni, struct tid_info *ti, + uint32_t etlv, struct named_object **pno) +{ + char *name; + ipfw_obj_ntlv *ntlv; + uint32_t set; + + if (ti->tlvs == NULL) + return (EINVAL); + + ntlv = find_name_tlv_type(ti->tlvs, ti->tlen, ti->uidx, etlv); + if (ntlv == NULL) + return (EINVAL); + name = ntlv->name; + + /* + * Use set provided by @ti instead of @ntlv one. + * This is needed due to different sets behavior + * controlled by V_fw_tables_sets. + */ + set = ti->set; + *pno = ipfw_objhash_lookup_name(ni, set, name); + if (*pno == NULL) + return (ESRCH); + return (0); +} + +/* * Find named object by name, considering also its TLV type. */ struct named_object * ipfw_objhash_lookup_name_type(struct namedobj_instance *ni, uint32_t set, - uint32_t type, char *name) + uint32_t type, const char *name) { struct named_object *no; uint32_t hash; @@ -3898,7 +4172,8 @@ ipfw_objhash_lookup_name_type(struct namedobj_instance *ni, uint32_t set, hash = ni->hash_f(ni, name, set) % ni->nn_size; TAILQ_FOREACH(no, &ni->names[hash], nn_next) { - if (ni->cmp_f(no, name, set) == 0 && no->etlv == type) + if (ni->cmp_f(no, name, set) == 0 && + no->etlv == (uint16_t)type) return (no); } diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c index a1ee5dd..175202a 100644 --- a/sys/netpfil/ipfw/ip_fw_table.c +++ b/sys/netpfil/ipfw/ip_fw_table.c @@ -2130,7 +2130,7 @@ export_table_internal(struct namedobj_instance *ni, struct named_object *no, dta = (struct dump_table_args *)arg; i = (ipfw_xtable_info *)ipfw_get_sopt_space(dta->sd, sizeof(*i)); - KASSERT(i != 0, ("previously checked buffer is not enough")); + KASSERT(i != NULL, ("previously checked buffer is not enough")); export_table_info(dta->ch, (struct table_config *)no, i); } @@ -2746,7 +2746,7 @@ list_table_algo(struct ip_fw_chain *ch, ip_fw3_opheader *op3, for (n = 1; n <= count; n++) { i = (ipfw_ta_info *)ipfw_get_sopt_space(sd, sizeof(*i)); - KASSERT(i != 0, ("previously checked buffer is not enough")); + KASSERT(i != NULL, ("previously checked buffer is not enough")); ta = tcfg->algo[n]; strlcpy(i->algoname, ta->name, sizeof(i->algoname)); i->type = ta->type; @@ -3336,136 +3336,6 @@ ipfw_move_tables_sets(struct ip_fw_chain *ch, ipfw_range_tlv *rt, return (bad); } -/* - * Finds and bumps refcount for objects referenced by given @rule. - * Auto-creates non-existing tables. - * Fills in @oib array with userland/kernel indexes. - * - * Returns 0 on success. - */ -static int -ref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule, - struct rule_check_info *ci, struct obj_idx *oib, struct tid_info *ti) -{ - int cmdlen, error, l, numnew; - ipfw_insn *cmd; - struct obj_idx *pidx; - int found, unresolved; - - pidx = oib; - l = rule->cmd_len; - cmd = rule->cmd; - cmdlen = 0; - error = 0; - numnew = 0; - found = 0; - unresolved = 0; - - IPFW_UH_WLOCK(ch); - - /* Increase refcount on each existing referenced table. */ - for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { - cmdlen = F_LEN(cmd); - - error = ref_opcode_object(ch, cmd, ti, pidx, &found, &unresolved); - if (error != 0) - break; - if (found || unresolved) { - pidx->off = rule->cmd_len - l; - pidx++; - } - /* - * Compability stuff for old clients: - * prepare to manually create non-existing objects. - */ - if (unresolved) - numnew++; - } - - if (error != 0) { - /* Unref everything we have already done */ - unref_oib_objects(ch, rule->cmd, oib, pidx); - IPFW_UH_WUNLOCK(ch); - return (error); - } - IPFW_UH_WUNLOCK(ch); - - /* Perform auto-creation for non-existing objects */ - if (numnew != 0) - error = create_objects_compat(ch, rule->cmd, oib, pidx, ti); - - /* Calculate real number of dynamic objects */ - ci->object_opcodes = (uint16_t)(pidx - oib); - - return (error); -} - -/* - * Checks is opcode is referencing table of appropriate type. - * Adds reference count for found table if true. - * Rewrites user-supplied opcode values with kernel ones. - * - * Returns 0 on success and appropriate error code otherwise. - */ -int -ipfw_rewrite_rule_uidx(struct ip_fw_chain *chain, - struct rule_check_info *ci) -{ - int error; - ipfw_insn *cmd; - uint8_t type; - struct obj_idx *p, *pidx_first, *pidx_last; - struct tid_info ti; - - /* - * Prepare an array for storing opcode indices. - * Use stack allocation by default. - */ - if (ci->object_opcodes <= (sizeof(ci->obuf)/sizeof(ci->obuf[0]))) { - /* Stack */ - pidx_first = ci->obuf; - } else - pidx_first = malloc(ci->object_opcodes * sizeof(struct obj_idx), - M_IPFW, M_WAITOK | M_ZERO); - - error = 0; - type = 0; - memset(&ti, 0, sizeof(ti)); - - /* - * Use default set for looking up tables (old way) or - * use set rule is assigned to (new way). - */ - ti.set = (V_fw_tables_sets != 0) ? ci->krule->set : 0; - if (ci->ctlv != NULL) { - ti.tlvs = (void *)(ci->ctlv + 1); - ti.tlen = ci->ctlv->head.length - sizeof(ipfw_obj_ctlv); - } - - /* Reference all used tables and other objects */ - error = ref_rule_objects(chain, ci->krule, ci, pidx_first, &ti); - if (error != 0) - goto free; - /* - * Note that ref_rule_objects() might have updated ci->object_opcodes - * to reflect actual number of object opcodes. - */ - - /* Perform rule rewrite */ - p = pidx_first; - pidx_last = pidx_first + ci->object_opcodes; - for (p = pidx_first; p < pidx_last; p++) { - cmd = ci->krule->cmd + p->off; - update_opcode_kidx(cmd, p->kidx); - } - -free: - if (pidx_first != ci->obuf) - free(pidx_first, M_IPFW); - - return (error); -} - static struct ipfw_sopt_handler scodes[] = { { IP_FW_TABLE_XCREATE, 0, HDIR_SET, create_table }, { IP_FW_TABLE_XDESTROY, 0, HDIR_SET, flush_table_v0 }, diff --git a/sys/netpfil/ipfw/ip_fw_table_value.c b/sys/netpfil/ipfw/ip_fw_table_value.c index a196b03..7e2f5cb 100644 --- a/sys/netpfil/ipfw/ip_fw_table_value.c +++ b/sys/netpfil/ipfw/ip_fw_table_value.c @@ -58,9 +58,10 @@ __FBSDID("$FreeBSD$"); #include <netpfil/ipfw/ip_fw_private.h> #include <netpfil/ipfw/ip_fw_table.h> -static uint32_t hash_table_value(struct namedobj_instance *ni, void *key, +static uint32_t hash_table_value(struct namedobj_instance *ni, const void *key, + uint32_t kopt); +static int cmp_table_value(struct named_object *no, const void *key, uint32_t kopt); -static int cmp_table_value(struct named_object *no, void *key, uint32_t kopt); static int list_table_values(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd); @@ -87,14 +88,14 @@ struct vdump_args { static uint32_t -hash_table_value(struct namedobj_instance *ni, void *key, uint32_t kopt) +hash_table_value(struct namedobj_instance *ni, const void *key, uint32_t kopt) { return (hash32_buf(key, 56, 0)); } static int -cmp_table_value(struct named_object *no, void *key, uint32_t kopt) +cmp_table_value(struct named_object *no, const void *key, uint32_t kopt) { return (memcmp(((struct table_val_link *)no)->pval, key, 56)); diff --git a/sys/ofed/drivers/infiniband/hw/mlx4/main.c b/sys/ofed/drivers/infiniband/hw/mlx4/main.c index 1f14e5c..5be92a2 100644 --- a/sys/ofed/drivers/infiniband/hw/mlx4/main.c +++ b/sys/ofed/drivers/infiniband/hw/mlx4/main.c @@ -1297,7 +1297,7 @@ static int del_gid_entry(struct ib_qp *ibqp, union ib_gid *gid) pr_warn("could not find mgid entry\n"); mutex_unlock(&mqp->mutex); - return ge != 0 ? 0 : -EINVAL; + return ge != NULL ? 0 : -EINVAL; } static int _mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid, diff --git a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c index 9a68b23..5bef672 100644 --- a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1485,7 +1485,7 @@ ipoib_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, e_addr = LLADDR(sdl); if (!IPOIB_IS_MULTICAST(e_addr)) return EADDRNOTAVAIL; - *llsa = 0; + *llsa = NULL; return 0; #ifdef INET diff --git a/sys/ofed/drivers/net/mlx4/en_netdev.c b/sys/ofed/drivers/net/mlx4/en_netdev.c index ae7f857..896b782 100644 --- a/sys/ofed/drivers/net/mlx4/en_netdev.c +++ b/sys/ofed/drivers/net/mlx4/en_netdev.c @@ -1243,10 +1243,6 @@ int mlx4_en_start_port(struct net_device *dev) /* Calculate Rx buf size */ dev->if_mtu = min(dev->if_mtu, priv->max_mtu); mlx4_en_calc_rx_buf(dev); - priv->rx_alloc_size = max_t(int, 2 * roundup_pow_of_two(priv->rx_mb_size), - PAGE_SIZE); - priv->rx_alloc_order = get_order(priv->rx_alloc_size); - priv->rx_buf_size = roundup_pow_of_two(priv->rx_mb_size); en_dbg(DRV, priv, "Rx buf size:%d\n", priv->rx_mb_size); /* Configure rx cq's and rings */ diff --git a/sys/ofed/drivers/net/mlx4/en_rx.c b/sys/ofed/drivers/net/mlx4/en_rx.c index b29096d..235a9ab 100644 --- a/sys/ofed/drivers/net/mlx4/en_rx.c +++ b/sys/ofed/drivers/net/mlx4/en_rx.c @@ -55,7 +55,7 @@ static void mlx4_en_init_rx_desc(struct mlx4_en_priv *priv, int i; /* Set size and memtype fields */ - rx_desc->data[0].byte_count = cpu_to_be32(priv->rx_mb_size); + rx_desc->data[0].byte_count = cpu_to_be32(priv->rx_mb_size - MLX4_NET_IP_ALIGN); rx_desc->data[0].lkey = cpu_to_be32(priv->mdev->mr.key); /* @@ -87,7 +87,10 @@ mlx4_en_alloc_buf(struct mlx4_en_rx_ring *ring, if (unlikely(mb == NULL)) return (-ENOMEM); /* setup correct length */ - mb->m_len = ring->rx_mb_size; + mb->m_pkthdr.len = mb->m_len = ring->rx_mb_size; + + /* make sure IP header gets aligned */ + m_adj(mb, MLX4_NET_IP_ALIGN); /* load spare mbuf into BUSDMA */ err = -bus_dmamap_load_mbuf_sg(ring->dma_tag, ring->spare.dma_map, @@ -117,7 +120,10 @@ mlx4_en_alloc_buf(struct mlx4_en_rx_ring *ring, goto use_spare; /* setup correct length */ - mb->m_len = ring->rx_mb_size; + mb->m_pkthdr.len = mb->m_len = ring->rx_mb_size; + + /* make sure IP header gets aligned */ + m_adj(mb, MLX4_NET_IP_ALIGN); err = -bus_dmamap_load_mbuf_sg(ring->dma_tag, mb_list->dma_map, mb, segs, &nsegs, BUS_DMA_NOWAIT); @@ -249,7 +255,8 @@ static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv, void mlx4_en_calc_rx_buf(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); - int eff_mtu = dev->if_mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN; + int eff_mtu = dev->if_mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN + + MLX4_NET_IP_ALIGN; if (eff_mtu > MJUM16BYTES) { en_err(priv, "MTU(%d) is too big\n", dev->if_mtu); @@ -384,9 +391,6 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv) ring->cons = 0; ring->actual_size = 0; ring->cqn = priv->rx_cq[ring_ind]->mcq.cqn; - ring->rx_alloc_order = priv->rx_alloc_order; - ring->rx_alloc_size = priv->rx_alloc_size; - ring->rx_buf_size = priv->rx_buf_size; ring->rx_mb_size = priv->rx_mb_size; ring->stride = stride; diff --git a/sys/ofed/drivers/net/mlx4/en_tx.c b/sys/ofed/drivers/net/mlx4/en_tx.c index 4358aa6..463efec 100644 --- a/sys/ofed/drivers/net/mlx4/en_tx.c +++ b/sys/ofed/drivers/net/mlx4/en_tx.c @@ -457,7 +457,7 @@ void mlx4_en_tx_irq(struct mlx4_cq *mcq) struct mlx4_en_priv *priv = netdev_priv(cq->dev); struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring]; - if (!spin_trylock(&ring->comp_lock)) + if (priv->port_up == 0 || !spin_trylock(&ring->comp_lock)) return; mlx4_en_process_tx_cq(cq->dev, cq); mod_timer(&cq->timer, jiffies + 1); @@ -473,6 +473,8 @@ void mlx4_en_poll_tx_cq(unsigned long data) INC_PERF_COUNTER(priv->pstats.tx_poll); + if (priv->port_up == 0) + return; if (!spin_trylock(&ring->comp_lock)) { mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT); return; @@ -494,6 +496,9 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind) struct mlx4_en_cq *cq = priv->tx_cq[tx_ind]; struct mlx4_en_tx_ring *ring = priv->tx_ring[tx_ind]; + if (priv->port_up == 0) + return; + /* If we don't have a pending timer, set one up to catch our recent post in case the interface becomes idle */ if (!timer_pending(&cq->timer)) @@ -1041,7 +1046,9 @@ mlx4_en_tx_que(void *context, int pending) priv = dev->if_softc; tx_ind = cq->ring; ring = priv->tx_ring[tx_ind]; - if (dev->if_drv_flags & IFF_DRV_RUNNING) { + + if (priv->port_up != 0 && + (dev->if_drv_flags & IFF_DRV_RUNNING) != 0) { mlx4_en_xmit_poll(priv, tx_ind); spin_lock(&ring->tx_lock); if (!drbr_empty(dev, ring->br)) @@ -1058,6 +1065,11 @@ mlx4_en_transmit(struct ifnet *dev, struct mbuf *m) struct mlx4_en_cq *cq; int i, err = 0; + if (priv->port_up == 0) { + m_freem(m); + return (ENETDOWN); + } + /* Compute which queue to use */ if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) { i = (m->m_pkthdr.flowid % 128) % priv->tx_ring_num; @@ -1091,6 +1103,9 @@ mlx4_en_qflush(struct ifnet *dev) struct mlx4_en_tx_ring *ring; struct mbuf *m; + if (priv->port_up == 0) + return; + for (int i = 0; i < priv->tx_ring_num; i++) { ring = priv->tx_ring[i]; spin_lock(&ring->tx_lock); diff --git a/sys/ofed/drivers/net/mlx4/mlx4_en.h b/sys/ofed/drivers/net/mlx4/mlx4_en.h index a584bad..17afa9e 100644 --- a/sys/ofed/drivers/net/mlx4/mlx4_en.h +++ b/sys/ofed/drivers/net/mlx4/mlx4_en.h @@ -69,6 +69,7 @@ #define MLX4_EN_PAGE_SHIFT 12 #define MLX4_EN_PAGE_SIZE (1 << MLX4_EN_PAGE_SHIFT) +#define MLX4_NET_IP_ALIGN 2 /* bytes */ #define DEF_RX_RINGS 16 #define MAX_RX_RINGS 128 #define MIN_RX_RINGS 4 @@ -315,9 +316,6 @@ struct mlx4_en_rx_ring { u32 cons; u32 buf_size; u8 fcs_del; - u16 rx_alloc_order; - u32 rx_alloc_size; - u32 rx_buf_size; u32 rx_mb_size; int qpn; u8 *buf; @@ -556,9 +554,6 @@ struct mlx4_en_priv { u32 tx_ring_num; u32 rx_ring_num; u32 rx_mb_size; - u16 rx_alloc_order; - u32 rx_alloc_size; - u32 rx_buf_size; struct mlx4_en_tx_ring **tx_ring; struct mlx4_en_rx_ring *rx_ring[MAX_RX_RINGS]; diff --git a/sys/powerpc/ofw/ofw_pcibus.c b/sys/powerpc/ofw/ofw_pcibus.c index 4ce6e73..01e2343 100644 --- a/sys/powerpc/ofw/ofw_pcibus.c +++ b/sys/powerpc/ofw/ofw_pcibus.c @@ -59,6 +59,7 @@ typedef uint32_t ofw_pci_intr_t; /* Methods */ static device_probe_t ofw_pcibus_probe; static device_attach_t ofw_pcibus_attach; +static pci_alloc_devinfo_t ofw_pcibus_alloc_devinfo; static pci_assign_interrupt_t ofw_pcibus_assign_interrupt; static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo; static bus_child_deleted_t ofw_pcibus_child_deleted; @@ -78,6 +79,7 @@ static device_method_t ofw_pcibus_methods[] = { DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_child_pnpinfo_str_method), /* PCI interface */ + DEVMETHOD(pci_alloc_devinfo, ofw_pcibus_alloc_devinfo), DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt), /* ofw_bus interface */ @@ -144,6 +146,15 @@ ofw_pcibus_attach(device_t dev) return (bus_generic_attach(dev)); } +struct pci_devinfo * +ofw_pcibus_alloc_devinfo(device_t dev) +{ + struct ofw_pcibus_devinfo *dinfo; + + dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); + return (&dinfo->opd_dinfo); +} + static void ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno) { @@ -185,8 +196,8 @@ ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno) * to the PCI bus. */ - dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, - domain, busno, slot, func, sizeof(*dinfo)); + dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, dev, + domain, busno, slot, func); if (dinfo == NULL) continue; if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) != @@ -244,7 +255,7 @@ ofw_pcibus_enum_bus(device_t dev, u_int domain, u_int busno) continue; dinfo = (struct ofw_pcibus_devinfo *)pci_read_device( - pcib, domain, busno, s, f, sizeof(*dinfo)); + pcib, dev, domain, busno, s, f); if (dinfo == NULL) continue; diff --git a/sys/powerpc/powerpc/db_disasm.c b/sys/powerpc/powerpc/db_disasm.c index 6d525b3..71c35c5 100644 --- a/sys/powerpc/powerpc/db_disasm.c +++ b/sys/powerpc/powerpc/db_disasm.c @@ -836,9 +836,9 @@ disasm_fields(const struct opcode *popcode, instr_t instr, vm_offset_t loc, reg = "tbu"; break; default: - reg = 0; + reg = NULL; } - if (reg == 0) + if (reg == NULL) pstr += sprintf(pstr, ", [unknown tbr %d ]", tbr); else pstr += sprintf(pstr, ", %s", reg); diff --git a/sys/powerpc/powerpc/elf32_machdep.c b/sys/powerpc/powerpc/elf32_machdep.c index eed76c9..9954a33 100644 --- a/sys/powerpc/powerpc/elf32_machdep.c +++ b/sys/powerpc/powerpc/elf32_machdep.c @@ -257,7 +257,7 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, void elf_reloc_self(Elf_Dyn *dynp, Elf_Addr relocbase) { - Elf_Rela *rela = 0, *relalim; + Elf_Rela *rela = NULL, *relalim; Elf_Addr relasz = 0; Elf_Addr *where; diff --git a/sys/powerpc/powerpc/elf64_machdep.c b/sys/powerpc/powerpc/elf64_machdep.c index 032728c..084200e 100644 --- a/sys/powerpc/powerpc/elf64_machdep.c +++ b/sys/powerpc/powerpc/elf64_machdep.c @@ -312,7 +312,7 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, void elf_reloc_self(Elf_Dyn *dynp, Elf_Addr relocbase) { - Elf_Rela *rela = 0, *relalim; + Elf_Rela *rela = NULL, *relalim; Elf_Addr relasz = 0; Elf_Addr *where; diff --git a/sys/powerpc/psim/iobus.c b/sys/powerpc/psim/iobus.c index ce4a93a..37a23d1 100644 --- a/sys/powerpc/psim/iobus.c +++ b/sys/powerpc/psim/iobus.c @@ -272,7 +272,7 @@ iobus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) { struct iobus_devinfo *dinfo; - if ((dinfo = device_get_ivars(child)) == 0) + if ((dinfo = device_get_ivars(child)) == NULL) return (ENOENT); switch (which) { diff --git a/sys/riscv/riscv/nexus.c b/sys/riscv/riscv/nexus.c index a4ced76..75e16b8 100644 --- a/sys/riscv/riscv/nexus.c +++ b/sys/riscv/riscv/nexus.c @@ -242,7 +242,7 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, } rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) + if (rv == NULL) return (NULL); rman_set_rid(rv, *rid); diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c index 81cb755..58bdd01 100644 --- a/sys/rpc/svc_vc.c +++ b/sys/rpc/svc_vc.c @@ -416,7 +416,7 @@ svc_vc_rendezvous_recv(SVCXPRT *xprt, struct rpc_msg *msg, sx_xunlock(&xprt->xp_lock); - sa = 0; + sa = NULL; error = soaccept(so, &sa); if (error) { diff --git a/sys/sparc64/ebus/ebus.c b/sys/sparc64/ebus/ebus.c index 49abe18..55a90a3 100644 --- a/sys/sparc64/ebus/ebus.c +++ b/sys/sparc64/ebus/ebus.c @@ -370,7 +370,7 @@ ebus_pci_attach(device_t dev) eri = &sc->sc_rinfo[i]; if (i < rnum) rman_fini(&eri->eri_rman); - if (eri->eri_res != 0) { + if (eri->eri_res != NULL) { bus_release_resource(dev, eri->eri_rtype, PCIR_BAR(rnum), eri->eri_res); } diff --git a/sys/sparc64/pci/ofw_pcibus.c b/sys/sparc64/pci/ofw_pcibus.c index 08ffa5d..11f19cf 100644 --- a/sys/sparc64/pci/ofw_pcibus.c +++ b/sys/sparc64/pci/ofw_pcibus.c @@ -70,6 +70,7 @@ static bus_child_pnpinfo_str_t ofw_pcibus_pnpinfo_str; static device_attach_t ofw_pcibus_attach; static device_probe_t ofw_pcibus_probe; static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo; +static pci_alloc_devinfo_t ofw_pcibus_alloc_devinfo; static pci_assign_interrupt_t ofw_pcibus_assign_interrupt; static device_method_t ofw_pcibus_methods[] = { @@ -82,6 +83,7 @@ static device_method_t ofw_pcibus_methods[] = { DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_pnpinfo_str), /* PCI interface */ + DEVMETHOD(pci_alloc_devinfo, ofw_pcibus_alloc_devinfo), DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt), /* ofw_bus interface */ @@ -250,8 +252,8 @@ ofw_pcibus_attach(device_t dev) if (strcmp(device_get_name(device_get_parent(pcib)), "nexus") == 0 && ofw_bus_get_type(pcib) != NULL && strcmp(ofw_bus_get_type(pcib), OFW_TYPE_PCIE) != 0 && - (dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, - domain, busno, 0, 0, sizeof(*dinfo))) != NULL) { + (dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, dev, + domain, busno, 0, 0)) != NULL) { if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, node) != 0) pci_freecfg((struct pci_devinfo *)dinfo); else @@ -270,8 +272,8 @@ ofw_pcibus_attach(device_t dev) if (pci_find_dbsf(domain, busno, slot, func) != NULL) continue; ofw_pcibus_setup_device(pcib, clock, busno, slot, func); - dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, - domain, busno, slot, func, sizeof(*dinfo)); + dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, dev, + domain, busno, slot, func); if (dinfo == NULL) continue; if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) != @@ -286,6 +288,15 @@ ofw_pcibus_attach(device_t dev) return (bus_generic_attach(dev)); } +struct pci_devinfo * +ofw_pcibus_alloc_devinfo(device_t dev) +{ + struct ofw_pcibus_devinfo *dinfo; + + dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); + return (&dinfo->opd_dinfo); +} + static int ofw_pcibus_assign_interrupt(device_t dev, device_t child) { diff --git a/sys/sys/bio.h b/sys/sys/bio.h index 8b3a5fc..37fefbf 100644 --- a/sys/sys/bio.h +++ b/sys/sys/bio.h @@ -77,10 +77,10 @@ typedef void bio_task_t(void *); * The bio structure describes an I/O operation in the kernel. */ struct bio { - uint8_t bio_cmd; /* I/O operation. */ - uint8_t bio_flags; /* General flags. */ - uint8_t bio_cflags; /* Private use by the consumer. */ - uint8_t bio_pflags; /* Private use by the provider. */ + uint16_t bio_cmd; /* I/O operation. */ + uint16_t bio_flags; /* General flags. */ + uint16_t bio_cflags; /* Private use by the consumer. */ + uint16_t bio_pflags; /* Private use by the provider. */ struct cdev *bio_dev; /* Device to do I/O on. */ struct disk *bio_disk; /* Valid below geom_disk.c only */ off_t bio_offset; /* Offset into file. */ diff --git a/sys/sys/buf.h b/sys/sys/buf.h index c85b88f..4255afd 100644 --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -98,8 +98,8 @@ struct buf { void *b_caller1; caddr_t b_data; int b_error; - uint8_t b_iocmd; - uint8_t b_ioflags; + uint16_t b_iocmd; /* BIO_* bio_cmd from bio.h */ + uint16_t b_ioflags; /* BIO_* bio_flags from bio.h */ off_t b_iooffset; long b_resid; void (*b_iodone)(struct buf *); diff --git a/sys/sys/conf.h b/sys/sys/conf.h index 6d2cac9..b7d9756 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -328,15 +328,18 @@ EVENTHANDLER_DECLARE(dev_clone, dev_clone_fn); struct dumperinfo { dumper_t *dumper; /* Dumping function. */ - void *priv; /* Private parts. */ - u_int blocksize; /* Size of block in bytes. */ + void *priv; /* Private parts. */ + u_int blocksize; /* Size of block in bytes. */ u_int maxiosize; /* Max size allowed for an individual I/O */ - off_t mediaoffset; /* Initial offset in bytes. */ - off_t mediasize; /* Space available in bytes. */ + off_t mediaoffset; /* Initial offset in bytes. */ + off_t mediasize; /* Space available in bytes. */ + void *blockbuf; /* Buffer for padding shorter dump blocks */ }; int set_dumper(struct dumperinfo *, const char *_devname, struct thread *td); int dump_write(struct dumperinfo *, void *, vm_offset_t, off_t, size_t); +int dump_write_pad(struct dumperinfo *, void *, vm_offset_t, off_t, size_t, + size_t *); int doadump(boolean_t); extern int dumping; /* system is dumping */ diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h index dddf087..02628ba 100644 --- a/sys/sys/kernel.h +++ b/sys/sys/kernel.h @@ -317,6 +317,44 @@ struct tunable_ulong { #define TUNABLE_ULONG_FETCH(path, var) getenv_ulong((path), (var)) /* + * int64_t + */ +extern void tunable_int64_init(void *); +struct tunable_int64 { + const char *path; + int64_t *var; +}; +#define TUNABLE_INT64(path, var) \ + static struct tunable_int64 __CONCAT(__tunable_int64_, __LINE__) = { \ + (path), \ + (var), \ + }; \ + SYSINIT(__CONCAT(__Tunable_init_, __LINE__), \ + SI_SUB_TUNABLES, SI_ORDER_MIDDLE, tunable_int64_init, \ + &__CONCAT(__tunable_int64_, __LINE__)) + +#define TUNABLE_INT64_FETCH(path, var) getenv_int64((path), (var)) + +/* + * uint64_t + */ +extern void tunable_uint64_init(void *); +struct tunable_uint64 { + const char *path; + uint64_t *var; +}; +#define TUNABLE_UINT64(path, var) \ + static struct tunable_ulong __CONCAT(__tunable_uint64_, __LINE__) = { \ + (path), \ + (var), \ + }; \ + SYSINIT(__CONCAT(__Tunable_init_, __LINE__), \ + SI_SUB_TUNABLES, SI_ORDER_MIDDLE, tunable_uint64_init, \ + &__CONCAT(__tunable_uint64_, __LINE__)) + +#define TUNABLE_UINT64_FETCH(path, var) getenv_uint64((path), (var)) + +/* * quad */ extern void tunable_quad_init(void *); diff --git a/sys/sys/module.h b/sys/sys/module.h index f0192d5..07464fc 100644 --- a/sys/sys/module.h +++ b/sys/sys/module.h @@ -166,7 +166,7 @@ struct mod_pnp_match_info /** * Generic macros to create pnp info hints that modules may export - * to allow external tools to parse their intenral device tables + * to allow external tools to parse their internal device tables * to make an informed guess about what driver(s) to load. */ #define MODULE_PNP_INFO(d, b, unique, t, l, n) \ diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 9c6e450..34ad5ba 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -322,6 +322,8 @@ int getenv_uint(const char *name, unsigned int *data); int getenv_long(const char *name, long *data); int getenv_ulong(const char *name, unsigned long *data); int getenv_string(const char *name, char *data, int size); +int getenv_int64(const char *name, int64_t *data); +int getenv_uint64(const char *name, uint64_t *data); int getenv_quad(const char *name, quad_t *data); int kern_setenv(const char *name, const char *value); int kern_unsetenv(const char *name); diff --git a/sys/x86/acpica/OsdEnvironment.c b/sys/x86/acpica/OsdEnvironment.c index be612b5..ab8a7fb 100644 --- a/sys/x86/acpica/OsdEnvironment.c +++ b/sys/x86/acpica/OsdEnvironment.c @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/bus.h> +#include <sys/kernel.h> #include <sys/sysctl.h> #include <contrib/dev/acpica/include/acpi.h> @@ -59,6 +60,16 @@ acpi_get_root_from_loader(void) { long acpi_root; + if (TUNABLE_ULONG_FETCH("acpi.rsdp", &acpi_root)) + return (acpi_root); + + /* + * The hints mechanism is unreliable (it fails if anybody ever + * compiled in hints to the kernel). It has been replaced + * by the tunable method, but is used here as a fallback to + * retain maximum compatibility between old loaders and new + * kernels. It can be removed after 11.0R. + */ if (resource_long_value("acpi", 0, "rsdp", &acpi_root) == 0) return (acpi_root); diff --git a/sys/x86/x86/busdma_bounce.c b/sys/x86/x86/busdma_bounce.c index 6e9aa70..78d04b9 100644 --- a/sys/x86/x86/busdma_bounce.c +++ b/sys/x86/x86/busdma_bounce.c @@ -476,7 +476,8 @@ _bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, while (buflen != 0) { sgsize = MIN(buflen, dmat->common.maxsegsz); if (bus_dma_run_filter(&dmat->common, curaddr)) { - sgsize = MIN(PAGE_SIZE, sgsize); + sgsize = MIN(sgsize, + PAGE_SIZE - (curaddr & PAGE_MASK)); map->pagesneeded++; } curaddr += sgsize; @@ -516,7 +517,8 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, else paddr = pmap_extract(pmap, vaddr); if (bus_dma_run_filter(&dmat->common, paddr) != 0) { - sg_len = PAGE_SIZE; + sg_len = roundup2(sg_len, + dmat->common.alignment); map->pagesneeded++; } vaddr += sg_len; @@ -552,7 +554,9 @@ _bus_dmamap_count_ma(bus_dma_tag_t dmat, bus_dmamap_t map, struct vm_page **ma, max_sgsize = MIN(buflen, dmat->common.maxsegsz); sg_len = MIN(sg_len, max_sgsize); if (bus_dma_run_filter(&dmat->common, paddr) != 0) { - sg_len = MIN(PAGE_SIZE, max_sgsize); + sg_len = roundup2(sg_len, + dmat->common.alignment); + sg_len = MIN(sg_len, max_sgsize); KASSERT((sg_len & (dmat->common.alignment - 1)) == 0, ("Segment size is not aligned")); map->pagesneeded++; @@ -648,7 +652,7 @@ bounce_bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, int *segp) { bus_size_t sgsize; - bus_addr_t curaddr, nextaddr; + bus_addr_t curaddr; int error; if (map == NULL) @@ -672,12 +676,9 @@ bounce_bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, if (((dmat->bounce_flags & BUS_DMA_COULD_BOUNCE) != 0) && map->pagesneeded != 0 && bus_dma_run_filter(&dmat->common, curaddr)) { - nextaddr = 0; - sgsize = MIN(PAGE_SIZE, sgsize); - if ((curaddr & PAGE_MASK) + sgsize > PAGE_SIZE) - nextaddr = roundup2(curaddr, PAGE_SIZE); - curaddr = add_bounce_page(dmat, map, 0, curaddr, - nextaddr, sgsize); + sgsize = MIN(sgsize, PAGE_SIZE - (curaddr & PAGE_MASK)); + curaddr = add_bounce_page(dmat, map, 0, curaddr, 0, + sgsize); } sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, segp); @@ -743,7 +744,8 @@ bounce_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, if (((dmat->bounce_flags & BUS_DMA_COULD_BOUNCE) != 0) && map->pagesneeded != 0 && bus_dma_run_filter(&dmat->common, curaddr)) { - sgsize = MIN(PAGE_SIZE, max_sgsize); + sgsize = roundup2(sgsize, dmat->common.alignment); + sgsize = MIN(sgsize, max_sgsize); curaddr = add_bounce_page(dmat, map, kvaddr, curaddr, 0, sgsize); } else { @@ -772,6 +774,17 @@ bounce_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map, int error, page_index; bus_size_t sgsize, max_sgsize; + if (dmat->common.flags & BUS_DMA_KEEP_PG_OFFSET) { + /* + * If we have to keep the offset of each page this function + * is not suitable, switch back to bus_dmamap_load_ma_triv + * which is going to do the right thing in this case. + */ + error = bus_dmamap_load_ma_triv(dmat, map, ma, buflen, ma_offs, + flags, segs, segp); + return (error); + } + if (map == NULL) map = &nobounce_dmamap; @@ -798,7 +811,10 @@ bounce_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map, if (((dmat->bounce_flags & BUS_DMA_COULD_BOUNCE) != 0) && map->pagesneeded != 0 && bus_dma_run_filter(&dmat->common, paddr)) { - sgsize = MIN(PAGE_SIZE, max_sgsize); + sgsize = roundup2(sgsize, dmat->common.alignment); + sgsize = MIN(sgsize, max_sgsize); + KASSERT((sgsize & (dmat->common.alignment - 1)) == 0, + ("Segment size is not aligned")); /* * Check if two pages of the user provided buffer * are used. @@ -1159,6 +1175,13 @@ add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, bz->active_bpages++; mtx_unlock(&bounce_lock); + if (dmat->common.flags & BUS_DMA_KEEP_PG_OFFSET) { + /* Page offset needs to be preserved. */ + bpage->vaddr |= addr1 & PAGE_MASK; + bpage->busaddr |= addr1 & PAGE_MASK; + KASSERT(addr2 == 0, + ("Trying to bounce multiple pages with BUS_DMA_KEEP_PG_OFFSET")); + } bpage->datavaddr = vaddr; bpage->datapage[0] = PHYS_TO_VM_PAGE(addr1); KASSERT((addr2 & PAGE_MASK) == 0, ("Second page is not aligned")); @@ -1178,6 +1201,15 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage) bz = dmat->bounce_zone; bpage->datavaddr = 0; bpage->datacount = 0; + if (dmat->common.flags & BUS_DMA_KEEP_PG_OFFSET) { + /* + * Reset the bounce page to start at offset 0. Other uses + * of this bounce page may need to store a full page of + * data and/or assume it starts on a page boundary. + */ + bpage->vaddr &= ~PAGE_MASK; + bpage->busaddr &= ~PAGE_MASK; + } mtx_lock(&bounce_lock); STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links); diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c index 5830b77..854bda4 100644 --- a/sys/x86/x86/local_apic.c +++ b/sys/x86/x86/local_apic.c @@ -170,7 +170,7 @@ vm_paddr_t lapic_paddr; int x2apic_mode; int lapic_eoi_suppression; static int lapic_timer_tsc_deadline; -static u_long lapic_timer_divisor; +static u_long lapic_timer_divisor, count_freq; static struct eventtimer lapic_et; #ifdef SMP static uint64_t lapic_ipi_wait_mult; @@ -814,20 +814,46 @@ lapic_calibrate_initcount(struct eventtimer *et, struct lapic *la) printf("lapic: Divisor %lu, Frequency %lu Hz\n", lapic_timer_divisor, value); } - et->et_frequency = value; + count_freq = value; } static void lapic_calibrate_deadline(struct eventtimer *et, struct lapic *la __unused) { - et->et_frequency = tsc_freq; if (bootverbose) { printf("lapic: deadline tsc mode, Frequency %ju Hz\n", - (uintmax_t)et->et_frequency); + (uintmax_t)tsc_freq); } } +static void +lapic_change_mode(struct eventtimer *et, struct lapic *la, + enum lat_timer_mode newmode) +{ + + if (la->la_timer_mode == newmode) + return; + switch (newmode) { + case LAT_MODE_PERIODIC: + lapic_timer_set_divisor(lapic_timer_divisor); + et->et_frequency = count_freq; + break; + case LAT_MODE_DEADLINE: + et->et_frequency = tsc_freq; + break; + case LAT_MODE_ONESHOT: + lapic_timer_set_divisor(lapic_timer_divisor); + et->et_frequency = count_freq; + break; + default: + panic("lapic_change_mode %d", newmode); + } + la->la_timer_mode = newmode; + et->et_min_period = (0x00000002LLU << 32) / et->et_frequency; + et->et_max_period = (0xfffffffeLLU << 32) / et->et_frequency; +} + static int lapic_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period) { @@ -835,28 +861,21 @@ lapic_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period) la = &lapics[PCPU_GET(apic_id)]; if (et->et_frequency == 0) { + lapic_calibrate_initcount(et, la); if (lapic_timer_tsc_deadline) lapic_calibrate_deadline(et, la); - else - lapic_calibrate_initcount(et, la); - et->et_min_period = (0x00000002LLU << 32) / et->et_frequency; - et->et_max_period = (0xfffffffeLLU << 32) / et->et_frequency; } if (period != 0) { - if (la->la_timer_mode == LAT_MODE_UNDEF) - lapic_timer_set_divisor(lapic_timer_divisor); - la->la_timer_mode = LAT_MODE_PERIODIC; + lapic_change_mode(et, la, LAT_MODE_PERIODIC); la->la_timer_period = ((uint32_t)et->et_frequency * period) >> 32; lapic_timer_periodic(la); } else if (lapic_timer_tsc_deadline) { - la->la_timer_mode = LAT_MODE_DEADLINE; + lapic_change_mode(et, la, LAT_MODE_DEADLINE); la->la_timer_period = (et->et_frequency * first) >> 32; lapic_timer_deadline(la); } else { - if (la->la_timer_mode == LAT_MODE_UNDEF) - lapic_timer_set_divisor(lapic_timer_divisor); - la->la_timer_mode = LAT_MODE_ONESHOT; + lapic_change_mode(et, la, LAT_MODE_ONESHOT); la->la_timer_period = ((uint32_t)et->et_frequency * first) >> 32; lapic_timer_oneshot(la); diff --git a/sys/x86/x86/nexus.c b/sys/x86/x86/nexus.c index 8b49d41..5d4c37e 100644 --- a/sys/x86/x86/nexus.c +++ b/sys/x86/x86/nexus.c @@ -397,7 +397,7 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, return (NULL); rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) + if (rv == NULL) return 0; rman_set_rid(rv, *rid); @@ -526,7 +526,7 @@ nexus_setup_intr(device_t bus, device_t child, struct resource *irq, if (irq == NULL) panic("nexus_setup_intr: NULL irq resource!"); - *cookiep = 0; + *cookiep = NULL; if ((rman_get_flags(irq) & RF_SHAREABLE) == 0) flags |= INTR_EXCL; diff --git a/sys/xdr/xdr_mem.c b/sys/xdr/xdr_mem.c index 74bab3b..8a14f17 100644 --- a/sys/xdr/xdr_mem.c +++ b/sys/xdr/xdr_mem.c @@ -214,7 +214,7 @@ xdrmem_setpos(XDR *xdrs, u_int pos) static int32_t * xdrmem_inline_aligned(XDR *xdrs, u_int len) { - int32_t *buf = 0; + int32_t *buf = NULL; if (xdrs->x_handy >= len) { xdrs->x_handy -= len; |