summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/apic_vector.S16
-rw-r--r--sys/amd64/amd64/exception.S1
-rw-r--r--sys/amd64/amd64/minidump_machdep.c16
-rw-r--r--sys/amd64/conf/GENERIC2
-rw-r--r--sys/amd64/conf/NOTES1
-rw-r--r--sys/arm/allwinner/a10_common.c4
-rw-r--r--sys/arm/altera/socfpga/socfpga_common.c2
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_machdep.c4
-rw-r--r--sys/arm/annapurna/alpine/common.c2
-rw-r--r--sys/arm/arm/gic.c347
-rw-r--r--sys/arm/arm/machdep_intr.c4
-rw-r--r--sys/arm/arm/mp_machdep.c18
-rw-r--r--sys/arm/arm/nexus.c18
-rw-r--r--sys/arm/arm/pmap-v4.c4
-rw-r--r--sys/arm/arm/pmap-v6.c6
-rw-r--r--sys/arm/at91/at91_common.c2
-rw-r--r--sys/arm/at91/at91_mci.c6
-rw-r--r--sys/arm/at91/at91_pio.c6
-rw-r--r--sys/arm/at91/at91_pmc.c2
-rw-r--r--sys/arm/at91/at91_rtc.c6
-rw-r--r--sys/arm/at91/at91_ssc.c6
-rw-r--r--sys/arm/at91/at91_twi.c6
-rw-r--r--sys/arm/at91/if_ate.c2
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_common.c4
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_gpio.c20
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_intr.c20
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2836.c4
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2836.h2
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2836_mp.c2
-rw-r--r--sys/arm/cavium/cns11xx/if_ece.c6
-rw-r--r--sys/arm/conf/A202
-rw-r--r--sys/arm/conf/ALPINE2
-rw-r--r--sys/arm/conf/ARMADA38X2
-rw-r--r--sys/arm/conf/BEAGLEBONE2
-rw-r--r--sys/arm/conf/EXYNOS5.common2
-rw-r--r--sys/arm/conf/IMX62
-rw-r--r--sys/arm/conf/ODROIDC12
-rw-r--r--sys/arm/conf/PANDABOARD2
-rw-r--r--sys/arm/conf/RK31882
-rw-r--r--sys/arm/conf/RPI-B2
-rw-r--r--sys/arm/conf/RPI22
-rw-r--r--sys/arm/conf/SOCKIT.common2
-rw-r--r--sys/arm/conf/VIRT2
-rw-r--r--sys/arm/conf/VSATV1022
-rw-r--r--sys/arm/conf/VYBRID2
-rw-r--r--sys/arm/conf/ZEDBOARD2
-rw-r--r--sys/arm/freescale/imx/imx6_machdep.c2
-rw-r--r--sys/arm/freescale/imx/imx_common.c4
-rw-r--r--sys/arm/freescale/imx/imx_gpio.c14
-rw-r--r--sys/arm/freescale/vybrid/vf_common.c2
-rw-r--r--sys/arm/include/intr.h6
-rw-r--r--sys/arm/include/smp.h4
-rw-r--r--sys/arm/lpc/lpc_intc.c2
-rw-r--r--sys/arm/mv/mpic.c20
-rw-r--r--sys/arm/mv/mv_common.c2
-rw-r--r--sys/arm/nvidia/tegra124/std.tegra1242
-rw-r--r--sys/arm/qemu/virt_common.c2
-rw-r--r--sys/arm/rockchip/rk30xx_common.c2
-rw-r--r--sys/arm/samsung/exynos/exynos5_common.c2
-rw-r--r--sys/arm/ti/aintc.c14
-rw-r--r--sys/arm/ti/omap4/omap4_prcm_clks.c4
-rw-r--r--sys/arm/ti/ti_common.c4
-rw-r--r--sys/arm/ti/ti_gpio.c16
-rw-r--r--sys/arm/ti/ti_gpio.h6
-rw-r--r--sys/arm/versatile/versatile_common.c2
-rw-r--r--sys/arm/xilinx/zy7_machdep.c2
-rw-r--r--sys/arm/xscale/ixp425/ixp425_qmgr.c2
-rw-r--r--sys/arm64/arm64/gic_fdt.c2
-rw-r--r--sys/arm64/arm64/gic_v3_its.c2
-rw-r--r--sys/arm64/arm64/nexus.c2
-rw-r--r--sys/arm64/arm64/pmap.c21
-rw-r--r--sys/arm64/include/vmparam.h8
-rw-r--r--sys/boot/efi/loader/arch/amd64/elf64_freebsd.c17
-rw-r--r--sys/boot/fdt/dts/mips/fbsd-mt7620a.dtsi52
-rw-r--r--sys/boot/fdt/dts/mips/fbsd-mt7620n.dtsi38
-rw-r--r--sys/boot/fdt/dts/mips/fbsd-mt7621.dtsi102
-rw-r--r--sys/boot/fdt/dts/mips/fbsd-mt7628an.dtsi88
-rw-r--r--sys/boot/fdt/dts/mips/fbsd-rt2880.dtsi33
-rw-r--r--sys/boot/fdt/dts/mips/fbsd-rt3050.dtsi41
-rw-r--r--sys/boot/fdt/dts/mips/fbsd-rt3352.dtsi38
-rw-r--r--sys/boot/fdt/dts/mips/fbsd-rt3883.dtsi50
-rw-r--r--sys/boot/fdt/dts/mips/fbsd-rt5350.dtsi38
-rw-r--r--sys/boot/i386/libi386/biosacpi.c17
-rw-r--r--sys/cam/ata/ata_all.c66
-rw-r--r--sys/cam/ata/ata_all.h4
-rw-r--r--sys/cam/ata/ata_da.c472
-rw-r--r--sys/cam/cam.c3
-rw-r--r--sys/cam/cam_ccb.h1
-rw-r--r--sys/cam/cam_iosched.c1603
-rw-r--r--sys/cam/cam_iosched.h64
-rw-r--r--sys/cam/cam_periph.c102
-rw-r--r--sys/cam/cam_xpt.c5
-rw-r--r--sys/cam/scsi/scsi_da.c305
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c37
-rw-r--r--sys/compat/linux/linux_ioctl.c2
-rw-r--r--sys/conf/NOTES2
-rw-r--r--sys/conf/files4
-rw-r--r--sys/conf/files.amd641
-rw-r--r--sys/conf/files.arm6
-rw-r--r--sys/conf/files.i3861
-rw-r--r--sys/conf/kern.post.mk2
-rw-r--r--sys/conf/options1
-rw-r--r--sys/conf/options.amd642
-rw-r--r--sys/conf/options.arm2
-rw-r--r--sys/conf/options.i3862
-rw-r--r--sys/conf/options.mips3
-rw-r--r--sys/contrib/ipfilter/netinet/ip_fil_freebsd.c4
-rw-r--r--sys/contrib/rdma/krping/krping.c124
-rw-r--r--sys/contrib/rdma/krping/krping.h1
-rw-r--r--sys/contrib/rdma/krping/krping_dev.c10
-rw-r--r--sys/ddb/db_command.c4
-rw-r--r--sys/ddb/db_ps.c3
-rw-r--r--sys/ddb/db_sym.c6
-rw-r--r--sys/dev/acpica/acpi_pci.c77
-rw-r--r--sys/dev/ahci/ahci.c5
-rw-r--r--sys/dev/cardbus/cardbus.c15
-rw-r--r--sys/dev/fdt/fdt_common.h2
-rw-r--r--sys/dev/fdt/fdt_powerpc.c65
-rw-r--r--sys/dev/flash/mx25l.c8
-rw-r--r--sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c13
-rw-r--r--sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c11
-rw-r--r--sys/dev/hyperv/vmbus/amd64/hv_vector.S46
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel_mgmt.c10
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c6
-rw-r--r--sys/dev/hyperv/vmbus/i386/hv_vector.S49
-rw-r--r--sys/dev/isp/isp.c16
-rw-r--r--sys/dev/isp/isp_library.c5
-rw-r--r--sys/dev/isp/ispvar.h17
-rw-r--r--sys/dev/pci/pci.c62
-rw-r--r--sys/dev/pci/pci_if.m4
-rw-r--r--sys/dev/pci/pci_iov.c2
-rw-r--r--sys/dev/pci/pci_private.h12
-rw-r--r--sys/dev/pci/pcivar.h1
-rw-r--r--sys/dev/rt/if_rt.c15
-rw-r--r--sys/dev/wbwd/wbwd.c17
-rw-r--r--sys/fs/cd9660/cd9660_vfsops.c4
-rw-r--r--sys/fs/msdosfs/msdosfs_conv.c4
-rw-r--r--sys/fs/msdosfs/msdosfs_fat.c4
-rw-r--r--sys/fs/msdosfs/msdosfs_lookup.c2
-rw-r--r--sys/geom/gate/g_gate.c2
-rw-r--r--sys/geom/geom_io.c4
-rw-r--r--sys/geom/geom_subr.c4
-rw-r--r--sys/geom/mirror/g_mirror.c2
-rw-r--r--sys/geom/raid3/g_raid3.c2
-rw-r--r--sys/i386/conf/GENERIC2
-rw-r--r--sys/i386/i386/apic_vector.s19
-rw-r--r--sys/i386/i386/db_disasm.c14
-rw-r--r--sys/i386/i386/exception.s1
-rw-r--r--sys/i386/i386/pmap.c6
-rw-r--r--sys/i386/ibcs2/imgact_coff.c6
-rw-r--r--sys/isa/pnp.c10
-rw-r--r--sys/kern/kern_dump.c36
-rw-r--r--sys/kern/kern_environment.c46
-rw-r--r--sys/kern/kern_kthread.c2
-rw-r--r--sys/kern/kern_proc.c2
-rw-r--r--sys/kern/kern_racct.c15
-rw-r--r--sys/kern/kern_rctl.c66
-rw-r--r--sys/kern/kern_shutdown.c32
-rw-r--r--sys/kern/kern_sysctl.c4
-rw-r--r--sys/kern/link_elf.c4
-rw-r--r--sys/kern/link_elf_obj.c4
-rw-r--r--sys/kern/sysv_sem.c4
-rw-r--r--sys/kern/uipc_mbuf.c2
-rw-r--r--sys/kern/uipc_mqueue.c127
-rw-r--r--sys/kern/uipc_sem.c37
-rw-r--r--sys/kern/uipc_shm.c38
-rw-r--r--sys/kern/uipc_sockbuf.c6
-rw-r--r--sys/kern/uipc_syscalls.c2
-rw-r--r--sys/kern/vfs_cluster.c2
-rw-r--r--sys/kern/vfs_export.c2
-rw-r--r--sys/kern/vfs_lookup.c4
-rw-r--r--sys/libkern/strtol.c2
-rw-r--r--sys/libkern/strtoq.c2
-rw-r--r--sys/libkern/strtoul.c2
-rw-r--r--sys/libkern/strtouq.c2
-rw-r--r--sys/mips/adm5120/obio.c2
-rw-r--r--sys/mips/alchemy/obio.c2
-rw-r--r--sys/mips/atheros/apb.c2
-rw-r--r--sys/mips/conf/MEDIATEK81
-rw-r--r--sys/mips/conf/MEDIATEK_BASE89
-rw-r--r--sys/mips/conf/MT7620A_FDT30
-rw-r--r--sys/mips/conf/MT7620N_FDT30
-rw-r--r--sys/mips/conf/MT7621_FDT30
-rw-r--r--sys/mips/conf/MT7628_FDT30
-rw-r--r--sys/mips/conf/RT3050_FDT31
-rw-r--r--sys/mips/conf/RT3352_FDT30
-rw-r--r--sys/mips/conf/RT3883_FDT30
-rw-r--r--sys/mips/conf/RT5350_FDT30
-rw-r--r--sys/mips/idt/obio.c2
-rw-r--r--sys/mips/include/intr.h12
-rw-r--r--sys/mips/include/smp.h2
-rw-r--r--sys/mips/mediatek/mtk_ehci.c2
-rw-r--r--sys/mips/mediatek/mtk_gpio_v1.c4
-rw-r--r--sys/mips/mediatek/mtk_gpio_v2.c6
-rw-r--r--sys/mips/mediatek/mtk_intr_gic.c4
-rw-r--r--sys/mips/mediatek/mtk_ohci.c2
-rw-r--r--sys/mips/mediatek/mtk_pcie.c41
-rw-r--r--sys/mips/mediatek/mtk_soc.c1
-rw-r--r--sys/mips/mediatek/mtk_usb_phy.c5
-rw-r--r--sys/mips/mediatek/mtk_xhci.c3
-rw-r--r--sys/mips/mips/exception.S8
-rw-r--r--sys/mips/mips/machdep.c2
-rw-r--r--sys/mips/mips/nexus.c16
-rw-r--r--sys/mips/mips/tick.c6
-rw-r--r--sys/mips/nlm/xlp_pci.c4
-rw-r--r--sys/mips/nlm/xlp_simplebus.c2
-rw-r--r--sys/mips/rmi/xlr_pci.c2
-rw-r--r--sys/mips/rt305x/obio.c2
-rw-r--r--sys/mips/rt305x/rt305x_gpio.c2
-rw-r--r--sys/modules/cam/Makefile2
-rw-r--r--sys/modules/hyperv/vmbus/Makefile15
-rw-r--r--sys/modules/ipfw/Makefile2
-rw-r--r--sys/net/bpf_filter.c8
-rw-r--r--sys/net/if.c6
-rw-r--r--sys/net/if_arcsubr.c16
-rw-r--r--sys/net/if_atmsubr.c4
-rw-r--r--sys/net/if_bridge.c4
-rw-r--r--sys/net/if_disc.c2
-rw-r--r--sys/net/if_ethersubr.c4
-rw-r--r--sys/net/if_fddisubr.c8
-rw-r--r--sys/net/if_fwsubr.c12
-rw-r--r--sys/net/if_iso88025subr.c8
-rw-r--r--sys/net/if_loop.c2
-rw-r--r--sys/net/if_spppsubr.c6
-rw-r--r--sys/net/radix.c18
-rw-r--r--sys/net/raw_usrreq.c2
-rw-r--r--sys/netgraph/atm/ccatm/ng_ccatm.c2
-rw-r--r--sys/netgraph/ng_socket.c4
-rw-r--r--sys/netgraph/ng_source.c2
-rw-r--r--sys/netinet/if_ether.c2
-rw-r--r--sys/netinet/igmp.c2
-rw-r--r--sys/netinet/in_mcast.c4
-rw-r--r--sys/netinet/ip_divert.c6
-rw-r--r--sys/netinet/ip_fw.h8
-rw-r--r--sys/netinet/ip_icmp.c21
-rw-r--r--sys/netinet/ip_icmp.h7
-rw-r--r--sys/netinet/ip_input.c3
-rw-r--r--sys/netinet/ip_mroute.c2
-rw-r--r--sys/netinet/ip_options.c2
-rw-r--r--sys/netinet/ip_output.c2
-rw-r--r--sys/netinet/libalias/alias_db.c6
-rw-r--r--sys/netinet/raw_ip.c2
-rw-r--r--sys/netinet/sctp_syscalls.c2
-rw-r--r--sys/netinet/sctp_usrreq.c74
-rw-r--r--sys/netinet/udp_usrreq.c4
-rw-r--r--sys/netinet6/in6.c2
-rw-r--r--sys/netinet6/ip6_output.c10
-rw-r--r--sys/netinet6/nd6_rtr.c2
-rw-r--r--sys/netinet6/raw_ip6.c2
-rw-r--r--sys/netinet6/udp6_usrreq.c4
-rw-r--r--sys/netipsec/ipsec_mbuf.c2
-rw-r--r--sys/netipsec/key.c12
-rw-r--r--sys/netipsec/keysock.c8
-rw-r--r--sys/netipsec/xform_ipcomp.c2
-rw-r--r--sys/netpfil/ipfw/ip_fw2.c7
-rw-r--r--sys/netpfil/ipfw/ip_fw_eaction.c369
-rw-r--r--sys/netpfil/ipfw/ip_fw_iface.c2
-rw-r--r--sys/netpfil/ipfw/ip_fw_private.h38
-rw-r--r--sys/netpfil/ipfw/ip_fw_sockopt.c431
-rw-r--r--sys/netpfil/ipfw/ip_fw_table.c134
-rw-r--r--sys/netpfil/ipfw/ip_fw_table_value.c9
-rw-r--r--sys/ofed/drivers/infiniband/hw/mlx4/main.c2
-rw-r--r--sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c2
-rw-r--r--sys/ofed/drivers/net/mlx4/en_netdev.c4
-rw-r--r--sys/ofed/drivers/net/mlx4/en_rx.c18
-rw-r--r--sys/ofed/drivers/net/mlx4/en_tx.c19
-rw-r--r--sys/ofed/drivers/net/mlx4/mlx4_en.h7
-rw-r--r--sys/powerpc/ofw/ofw_pcibus.c17
-rw-r--r--sys/powerpc/powerpc/db_disasm.c4
-rw-r--r--sys/powerpc/powerpc/elf32_machdep.c2
-rw-r--r--sys/powerpc/powerpc/elf64_machdep.c2
-rw-r--r--sys/powerpc/psim/iobus.c2
-rw-r--r--sys/riscv/riscv/nexus.c2
-rw-r--r--sys/rpc/svc_vc.c2
-rw-r--r--sys/sparc64/ebus/ebus.c2
-rw-r--r--sys/sparc64/pci/ofw_pcibus.c19
-rw-r--r--sys/sys/bio.h8
-rw-r--r--sys/sys/buf.h4
-rw-r--r--sys/sys/conf.h11
-rw-r--r--sys/sys/kernel.h38
-rw-r--r--sys/sys/module.h2
-rw-r--r--sys/sys/systm.h2
-rw-r--r--sys/x86/acpica/OsdEnvironment.c11
-rw-r--r--sys/x86/x86/busdma_bounce.c56
-rw-r--r--sys/x86/x86/local_apic.c49
-rw-r--r--sys/x86/x86/nexus.c4
-rw-r--r--sys/xdr/xdr_mem.c2
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;
- 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;
OpenPOWER on IntegriCloud