summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2008-12-20 01:29:19 +0000
committersam <sam@FreeBSD.org>2008-12-20 01:29:19 +0000
commitc3f1faeb23e27c2ffda030cf892c5df698734622 (patch)
tree0b964e87f3cbd93269e72d591d2eb44bc6ace51c /sys
parentcd99ae6c06463359389c703ff069f25d28878ad7 (diff)
parent3fcef6d9c20b6c3577c741e4a0fe24807fd08a66 (diff)
downloadFreeBSD-src-c3f1faeb23e27c2ffda030cf892c5df698734622.zip
FreeBSD-src-c3f1faeb23e27c2ffda030cf892c5df698734622.tar.gz
MFH @ 186335
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/exception.S24
-rw-r--r--sys/amd64/amd64/identcpu.c16
-rw-r--r--sys/amd64/conf/DEFAULTS4
-rw-r--r--sys/amd64/include/elf.h12
-rw-r--r--sys/amd64/include/specialreg.h8
-rw-r--r--sys/amd64/linux32/linux32_sysvec.c2
-rw-r--r--sys/arm/conf/DEFAULTS4
-rw-r--r--sys/arm/conf/EP802191
-rw-r--r--sys/arm/include/elf.h4
-rw-r--r--sys/boot/Makefile2
-rw-r--r--sys/boot/i386/gptzfsboot/Makefile2
-rw-r--r--sys/boot/i386/zfsboot/Makefile2
-rw-r--r--sys/boot/powerpc/uboot/conf.c8
-rw-r--r--sys/boot/uboot/common/main.c1
-rw-r--r--sys/boot/uboot/lib/devicename.c17
-rw-r--r--sys/boot/zfs/zfsimpl.c13
-rw-r--r--sys/cam/cam_periph.c23
-rw-r--r--sys/cam/cam_periph.h1
-rw-r--r--sys/cam/cam_sim.c31
-rw-r--r--sys/cam/cam_sim.h3
-rw-r--r--sys/cam/cam_xpt.c109
-rw-r--r--sys/cam/scsi/scsi_da.c2
-rw-r--r--sys/compat/svr4/svr4_sysvec.c2
-rw-r--r--sys/conf/NOTES2
-rw-r--r--sys/conf/files1
-rw-r--r--sys/conf/files.powerpc2
-rw-r--r--sys/conf/files.sparc643
-rw-r--r--sys/conf/files.sun4v3
-rw-r--r--sys/contrib/pf/net/pf.c12
-rw-r--r--sys/contrib/pf/net/pf_if.c2
-rw-r--r--sys/contrib/pf/net/pf_subr.c20
-rw-r--r--sys/contrib/rdma/rdma_addr.c6
-rw-r--r--sys/crypto/rc4/rc4.c8
-rw-r--r--sys/dev/acpica/acpi_smbat.c34
-rw-r--r--sys/dev/ata/ata-pci.c30
-rw-r--r--sys/dev/ata/ata-pci.h1
-rw-r--r--sys/dev/ata/chipsets/ata-ahci.c16
-rw-r--r--sys/dev/ata/chipsets/ata-sis.c3
-rw-r--r--sys/dev/ath/ath_hal/ah.c8
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v14.c12
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v3.c6
-rw-r--r--sys/dev/ath/ath_hal/ah_internal.h25
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5111.c4
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_ani.c20
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5312.h4
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5312_attach.c5
-rw-r--r--sys/dev/atkbdc/psm.c35
-rw-r--r--sys/dev/bce/if_bce.c3
-rw-r--r--sys/dev/cxgb/common/cxgb_ael1002.c134
-rw-r--r--sys/dev/cxgb/cxgb_main.c77
-rw-r--r--sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c3
-rw-r--r--sys/dev/cxgb/ulp/tom/cxgb_l2t.c48
-rw-r--r--sys/dev/cxgb/ulp/tom/cxgb_l2t.h2
-rw-r--r--sys/dev/drm/drmP.h22
-rw-r--r--sys/dev/drm/drm_drv.c4
-rw-r--r--sys/dev/drm/drm_scatter.c110
-rw-r--r--sys/dev/fxp/if_fxp.c8
-rw-r--r--sys/dev/hwpmc/hwpmc_core.c13
-rw-r--r--sys/dev/hwpmc/hwpmc_logging.c72
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c76
-rw-r--r--sys/dev/isp/isp.c21
-rw-r--r--sys/dev/md/md.c5
-rw-r--r--sys/dev/mfi/mfi.c3
-rw-r--r--sys/dev/mfi/mfi_pci.c2
-rw-r--r--sys/dev/nfe/if_nfe.c2
-rw-r--r--sys/dev/ofw/ofw_bus_subr.c151
-rw-r--r--sys/dev/ofw/ofw_bus_subr.h21
-rw-r--r--sys/dev/ofw/ofw_if.m357
-rw-r--r--sys/dev/ofw/ofw_standard.c763
-rw-r--r--sys/dev/ofw/ofwvar.h89
-rw-r--r--sys/dev/ofw/openfirm.c655
-rw-r--r--sys/dev/ofw/openfirm.h88
-rw-r--r--sys/dev/ofw/openfirmio.c2
-rw-r--r--sys/dev/ofw/openpromio.c2
-rw-r--r--sys/dev/re/if_re.c54
-rw-r--r--sys/dev/snp/snp.c3
-rw-r--r--sys/dev/sound/pci/hda/hdac.c35
-rw-r--r--sys/dev/usb/ucom.c42
-rw-r--r--sys/dev/usb/ucomvar.h1
-rw-r--r--sys/dev/usb/uftdi.c51
-rw-r--r--sys/fs/hpfs/hpfs_vnops.c2
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c2
-rw-r--r--sys/fs/ntfs/ntfs_vnops.c2
-rw-r--r--sys/fs/nwfs/nwfs_vnops.c2
-rw-r--r--sys/fs/smbfs/smbfs_vnops.c2
-rw-r--r--sys/geom/geom_vfs.c35
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vnops.c2
-rw-r--r--sys/gnu/fs/reiserfs/reiserfs_vnops.c7
-rw-r--r--sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c2
-rw-r--r--sys/i386/conf/DEFAULTS4
-rw-r--r--sys/i386/i386/exception.s11
-rw-r--r--sys/i386/i386/identcpu.c16
-rw-r--r--sys/i386/include/elf.h12
-rw-r--r--sys/i386/include/specialreg.h8
-rw-r--r--sys/i386/linux/linux_sysvec.c2
-rw-r--r--sys/ia64/include/elf.h12
-rw-r--r--sys/kern/imgact_elf.c10
-rw-r--r--sys/kern/kern_cpu.c9
-rw-r--r--sys/kern/kern_mbuf.c1
-rw-r--r--sys/kern/subr_kobj.c59
-rw-r--r--sys/kern/subr_param.c45
-rw-r--r--sys/kern/subr_trap.c8
-rw-r--r--sys/kern/tty.c25
-rw-r--r--sys/kern/tty_pts.c10
-rw-r--r--sys/kern/vfs_lookup.c4
-rw-r--r--sys/kern/vfs_mount.c45
-rw-r--r--sys/kern/vfs_subr.c2
-rw-r--r--sys/kern/vfs_syscalls.c24
-rw-r--r--sys/mips/conf/DEFAULTS4
-rw-r--r--sys/mips/include/elf.h76
-rw-r--r--sys/mips/mips/elf_machdep.c16
-rw-r--r--sys/modules/Makefile3
-rw-r--r--sys/modules/ath/Makefile86
-rw-r--r--sys/modules/ath_rate_amrr/Makefile40
-rw-r--r--sys/modules/ath_rate_onoe/Makefile40
-rw-r--r--sys/modules/ath_rate_sample/Makefile40
-rw-r--r--sys/modules/cxgb/Makefile2
-rw-r--r--sys/net/ieee8023ad_lacp.c2
-rw-r--r--sys/net/if.c25
-rw-r--r--sys/net/if_arcsubr.c6
-rw-r--r--sys/net/if_atmsubr.c13
-rw-r--r--sys/net/if_ethersubr.c19
-rw-r--r--sys/net/if_fddisubr.c6
-rw-r--r--sys/net/if_fwsubr.c16
-rw-r--r--sys/net/if_iso88025subr.c15
-rw-r--r--sys/net/if_lagg.c27
-rw-r--r--sys/net/if_llatbl.c311
-rw-r--r--sys/net/if_llatbl.h192
-rw-r--r--sys/net/if_media.h12
-rw-r--r--sys/net/if_var.h86
-rw-r--r--sys/net/pfil.c42
-rw-r--r--sys/net/pfil.h3
-rw-r--r--sys/net/radix.c1
-rw-r--r--sys/net/radix_mpath.c4
-rw-r--r--sys/net/route.c602
-rw-r--r--sys/net/route.h19
-rw-r--r--sys/net/rtsock.c46
-rw-r--r--sys/net80211/_ieee80211.h2
-rw-r--r--sys/net80211/ieee80211.c4
-rw-r--r--sys/net80211/ieee80211_acl.c14
-rw-r--r--sys/net80211/ieee80211_crypto.h2
-rw-r--r--sys/net80211/ieee80211_crypto_ccmp.c4
-rw-r--r--sys/net80211/ieee80211_crypto_tkip.c4
-rw-r--r--sys/net80211/ieee80211_crypto_wep.c4
-rw-r--r--sys/net80211/ieee80211_ddb.c5
-rw-r--r--sys/net80211/ieee80211_dfs.h2
-rw-r--r--sys/net80211/ieee80211_freebsd.c4
-rw-r--r--sys/net80211/ieee80211_hostap.c14
-rw-r--r--sys/net80211/ieee80211_input.c10
-rw-r--r--sys/net80211/ieee80211_ioctl.c48
-rw-r--r--sys/net80211/ieee80211_node.c40
-rw-r--r--sys/net80211/ieee80211_node.h1
-rw-r--r--sys/net80211/ieee80211_output.c4
-rw-r--r--sys/net80211/ieee80211_power.c4
-rw-r--r--sys/net80211/ieee80211_proto.c2
-rw-r--r--sys/net80211/ieee80211_regdomain.c2
-rw-r--r--sys/net80211/ieee80211_scan.c4
-rw-r--r--sys/net80211/ieee80211_scan_sta.c17
-rw-r--r--sys/net80211/ieee80211_sta.c2
-rw-r--r--sys/net80211/ieee80211_var.h2
-rw-r--r--sys/netgraph/netflow/netflow.c4
-rw-r--r--sys/netgraph/netgraph.h1
-rw-r--r--sys/netgraph/ng_base.c55
-rw-r--r--sys/netgraph/ng_mppc.c21
-rw-r--r--sys/netgraph/ng_tty.c21
-rw-r--r--sys/netinet/icmp6.h2
-rw-r--r--sys/netinet/icmp_var.h2
-rw-r--r--sys/netinet/if_atm.c6
-rw-r--r--sys/netinet/if_ether.c847
-rw-r--r--sys/netinet/if_ether.h5
-rw-r--r--sys/netinet/in.c242
-rw-r--r--sys/netinet/in_mcast.c2
-rw-r--r--sys/netinet/in_pcb.c8
-rw-r--r--sys/netinet/in_pcb.h8
-rw-r--r--sys/netinet/in_proto.c5
-rw-r--r--sys/netinet/in_rmx.c34
-rw-r--r--sys/netinet/in_var.h16
-rw-r--r--sys/netinet/ip_carp.c8
-rw-r--r--sys/netinet/ip_fastfwd.c2
-rw-r--r--sys/netinet/ip_fw.h2
-rw-r--r--sys/netinet/ip_fw2.c16
-rw-r--r--sys/netinet/ip_fw_pfil.c24
-rw-r--r--sys/netinet/ip_input.c4
-rw-r--r--sys/netinet/ip_output.c1
-rw-r--r--sys/netinet/raw_ip.c5
-rw-r--r--sys/netinet/tcp_hostcache.c8
-rw-r--r--sys/netinet/tcp_input.c7
-rw-r--r--sys/netinet/tcp_subr.c36
-rw-r--r--sys/netinet/tcp_syncache.c39
-rw-r--r--sys/netinet/tcp_timewait.c2
-rw-r--r--sys/netinet/tcp_usrreq.c8
-rw-r--r--sys/netinet/tcp_var.h4
-rw-r--r--sys/netinet/vinet.h2
-rw-r--r--sys/netinet6/icmp6.c60
-rw-r--r--sys/netinet6/in6.c448
-rw-r--r--sys/netinet6/in6_pcb.c12
-rw-r--r--sys/netinet6/in6_rmx.c66
-rw-r--r--sys/netinet6/in6_src.c67
-rw-r--r--sys/netinet6/in6_var.h7
-rw-r--r--sys/netinet6/ip6_input.c40
-rw-r--r--sys/netinet6/ip6_output.c50
-rw-r--r--sys/netinet6/ip6_var.h11
-rw-r--r--sys/netinet6/nd6.c1077
-rw-r--r--sys/netinet6/nd6.h40
-rw-r--r--sys/netinet6/nd6_nbr.c98
-rw-r--r--sys/netinet6/nd6_rtr.c79
-rw-r--r--sys/netinet6/raw_ip6.c40
-rw-r--r--sys/netinet6/raw_ip6.h2
-rw-r--r--sys/netinet6/udp6_usrreq.c18
-rw-r--r--sys/netinet6/vinet6.h1
-rw-r--r--sys/netipsec/ipip_var.h2
-rw-r--r--sys/netipsec/ipsec.c40
-rw-r--r--sys/netipsec/key.c26
-rw-r--r--sys/nfsserver/nfs_serv.c9
-rw-r--r--sys/pc98/conf/DEFAULTS4
-rw-r--r--sys/pci/if_rl.c12
-rw-r--r--sys/pci/if_rlreg.h4
-rw-r--r--sys/powerpc/aim/locore.S11
-rw-r--r--sys/powerpc/aim/machdep.c12
-rw-r--r--sys/powerpc/aim/ofw_machdep.c47
-rw-r--r--sys/powerpc/booke/interrupt.c1
-rw-r--r--sys/powerpc/booke/locore.S450
-rw-r--r--sys/powerpc/booke/machdep.c54
-rw-r--r--sys/powerpc/include/elf.h3
-rw-r--r--sys/powerpc/include/ofw_machdep.h9
-rw-r--r--sys/powerpc/include/param.h3
-rw-r--r--sys/powerpc/include/spr.h18
-rw-r--r--sys/powerpc/mpc85xx/lbc.c268
-rw-r--r--sys/powerpc/mpc85xx/lbc.h44
-rw-r--r--sys/powerpc/mpc85xx/mpc85xx.c101
-rw-r--r--sys/powerpc/mpc85xx/mpc85xx.h37
-rw-r--r--sys/powerpc/mpc85xx/nexus.c8
-rw-r--r--sys/powerpc/mpc85xx/ocpbus.c58
-rw-r--r--sys/powerpc/ofw/ofw_pcib_pci.c64
-rw-r--r--sys/powerpc/ofw/ofw_pcibus.c353
-rw-r--r--sys/powerpc/ofw/ofw_syscons.c149
-rw-r--r--sys/powerpc/ofw/ofw_syscons.h1
-rw-r--r--sys/powerpc/powermac/cuda.c38
-rw-r--r--sys/powerpc/powermac/cudavar.h3
-rw-r--r--sys/powerpc/powermac/grackle.c32
-rw-r--r--sys/powerpc/powermac/gracklevar.h3
-rw-r--r--sys/powerpc/powermac/macio.c2
-rw-r--r--sys/powerpc/powermac/uninorth.c31
-rw-r--r--sys/powerpc/powermac/uninorthvar.h2
-rw-r--r--sys/powerpc/powerpc/pmap_dispatch.c5
-rw-r--r--sys/sparc64/conf/DEFAULTS4
-rw-r--r--sys/sparc64/ebus/ebus.c2
-rw-r--r--sys/sparc64/include/elf.h12
-rw-r--r--sys/sparc64/include/ofw_bus.h53
-rw-r--r--sys/sparc64/include/ofw_machdep.h7
-rw-r--r--sys/sparc64/isa/ofw_isa.c2
-rw-r--r--sys/sparc64/pci/apb.c1
-rw-r--r--sys/sparc64/pci/ofw_pci.h2
-rw-r--r--sys/sparc64/pci/ofw_pcib.c1
-rw-r--r--sys/sparc64/pci/ofw_pcib_subr.c1
-rw-r--r--sys/sparc64/pci/ofw_pcibus.c19
-rw-r--r--sys/sparc64/pci/psycho.c1
-rw-r--r--sys/sparc64/pci/schizo.c46
-rw-r--r--sys/sparc64/sbus/sbus.c1
-rw-r--r--sys/sparc64/sparc64/machdep.c21
-rw-r--r--sys/sparc64/sparc64/mp_machdep.c4
-rw-r--r--sys/sparc64/sparc64/ofw_bus.c198
-rw-r--r--sys/sparc64/sparc64/ofw_machdep.c1
-rw-r--r--sys/sparc64/sparc64/support.S12
-rw-r--r--sys/sparc64/sparc64/trap.c3
-rw-r--r--sys/sparc64/sparc64/vm_machdep.c2
-rw-r--r--sys/sun4v/conf/DEFAULTS4
-rw-r--r--sys/sun4v/include/elf.h12
-rw-r--r--sys/sun4v/include/ofw_bus.h53
-rw-r--r--sys/sun4v/sun4v/machdep.c25
-rw-r--r--sys/sun4v/sun4v/mp_machdep.c2
-rw-r--r--sys/sun4v/sun4v/support.S10
-rw-r--r--sys/sun4v/sun4v/trap.c2
-rw-r--r--sys/sys/buf_ring.h3
-rw-r--r--sys/sys/elf_common.h60
-rw-r--r--sys/sys/imgact_elf.h1
-rw-r--r--sys/sys/kobj.h5
-rw-r--r--sys/sys/mount.h1
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/ttyhook.h2
-rw-r--r--sys/sys/vtoc.h2
-rw-r--r--sys/ufs/ufs/ufs_vfsops.c4
-rw-r--r--sys/ufs/ufs/ufs_vnops.c2
283 files changed, 6678 insertions, 5156 deletions
diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S
index fd0a7ca..80308a9 100644
--- a/sys/amd64/amd64/exception.S
+++ b/sys/amd64/amd64/exception.S
@@ -459,9 +459,9 @@ nmi_calltrap:
*/
movq %rsp,%rsi /* source stack pointer */
movq $TF_SIZE,%rcx
- movq PCPU(RSP0),%rbx
- subq %rcx,%rbx
- movq %rbx,%rdi /* destination stack pointer */
+ movq PCPU(RSP0),%rdx
+ subq %rcx,%rdx
+ movq %rdx,%rdi /* destination stack pointer */
shrq $3,%rcx /* trap frame size in long words */
cld
@@ -470,7 +470,7 @@ nmi_calltrap:
movl %ss,%eax
pushq %rax /* tf_ss */
- pushq %rbx /* tf_rsp (on kernel stack) */
+ pushq %rdx /* tf_rsp (on kernel stack) */
pushfq /* tf_rflags */
movl %cs,%eax
pushq %rax /* tf_cs */
@@ -480,16 +480,20 @@ outofnmi:
/*
* At this point the processor has exited NMI mode and is running
* with interrupts turned off on the normal kernel stack.
- * We turn interrupts back on, and take the usual 'doreti' exit
- * path.
*
* If a pending NMI gets recognized at or after this point, it
- * will cause a kernel callchain to be traced. Since this path
- * is only taken for NMI interrupts from user space, our `swapgs'
- * state is correct for taking the doreti path.
+ * will cause a kernel callchain to be traced.
+ *
+ * We turn interrupts back on, and call the user callchain capture hook.
*/
+ movq pmc_hook,%rax
+ orq %rax,%rax
+ jz nocallchain
+ movq PCPU(CURTHREAD),%rdi /* thread */
+ movq $PMC_FN_USER_CALLCHAIN,%rsi /* command */
+ movq %rsp,%rdx /* frame */
sti
- jmp doreti
+ call *%rax
nocallchain:
#endif
testl %ebx,%ebx
diff --git a/sys/amd64/amd64/identcpu.c b/sys/amd64/amd64/identcpu.c
index c63339d..f417e0f 100644
--- a/sys/amd64/amd64/identcpu.c
+++ b/sys/amd64/amd64/identcpu.c
@@ -322,15 +322,15 @@ printcpuinfo(void)
"\003SVM" /* Secure Virtual Mode */
"\004ExtAPIC" /* Extended APIC register */
"\005CR8" /* CR8 in legacy mode */
- "\006<b5>"
- "\007<b6>"
- "\010<b7>"
+ "\006ABM" /* LZCNT instruction */
+ "\007SSE4A" /* SSE4A */
+ "\010MAS" /* Misaligned SSE mode */
"\011Prefetch" /* 3DNow! Prefetch/PrefetchW */
- "\012<b9>"
- "\013<b10>"
- "\014<b11>"
- "\015<b12>"
- "\016<b13>"
+ "\012OSVW" /* OS visible workaround */
+ "\013IBS" /* Instruction based sampling */
+ "\014SSE5" /* SSE5 */
+ "\015SKINIT" /* SKINIT/STGI */
+ "\016WDT" /* Watchdog timer */
"\017<b14>"
"\020<b15>"
"\021<b16>"
diff --git a/sys/amd64/conf/DEFAULTS b/sys/amd64/conf/DEFAULTS
index 3477caf..fac8dce 100644
--- a/sys/amd64/conf/DEFAULTS
+++ b/sys/amd64/conf/DEFAULTS
@@ -16,5 +16,5 @@ device io # I/O device
device uart_ns8250
# Default partitioning schemes
-options GEOM_BSD
-options GEOM_MBR
+options GEOM_PART_BSD
+options GEOM_PART_MBR
diff --git a/sys/amd64/include/elf.h b/sys/amd64/include/elf.h
index 0a386be..a4c7f79 100644
--- a/sys/amd64/include/elf.h
+++ b/sys/amd64/include/elf.h
@@ -81,18 +81,6 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused for i386). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-
-/*
- * The following non-standard values are used for passing information
- * from John Polstra's testbed program to the dynamic linker. These
- * are expected to go away soon.
- *
- * Unfortunately, these overlap the Linux non-standard values, so they
- * must not be used in the same context.
- */
-#define AT_BRK 10 /* Starting point for sbrk and brk. */
-#define AT_DEBUG 11 /* Debugging level. */
-
/*
* The following non-standard values are used in Linux ELF binaries.
*/
diff --git a/sys/amd64/include/specialreg.h b/sys/amd64/include/specialreg.h
index cd9da86..674638c 100644
--- a/sys/amd64/include/specialreg.h
+++ b/sys/amd64/include/specialreg.h
@@ -150,7 +150,15 @@
#define AMDID2_SVM 0x00000004
#define AMDID2_EXT_APIC 0x00000008
#define AMDID2_CR8 0x00000010
+#define AMDID2_ABM 0x00000020
+#define AMDID2_SSE4A 0x00000040
+#define AMDID2_MAS 0x00000080
#define AMDID2_PREFETCH 0x00000100
+#define AMDID2_OSVW 0x00000200
+#define AMDID2_IBS 0x00000400
+#define AMDID2_SSE5 0x00000800
+#define AMDID2_SKINIT 0x00001000
+#define AMDID2_WDT 0x00002000
/*
* CPUID instruction 1 eax info
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index 3acee30..aaa7458 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -254,8 +254,6 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
args = (Elf32_Auxargs *)imgp->auxargs;
pos = base + (imgp->args->argc + imgp->args->envc + 2);
- if (args->trace)
- AUXARGS_ENTRY_32(pos, AT_DEBUG, 1);
if (args->execfd != -1)
AUXARGS_ENTRY_32(pos, AT_EXECFD, args->execfd);
AUXARGS_ENTRY_32(pos, AT_PHDR, args->phdr);
diff --git a/sys/arm/conf/DEFAULTS b/sys/arm/conf/DEFAULTS
index 606e962..591a0a1 100644
--- a/sys/arm/conf/DEFAULTS
+++ b/sys/arm/conf/DEFAULTS
@@ -7,5 +7,5 @@ machine arm
device mem
-options GEOM_BSD
-options GEOM_MBR
+options GEOM_PART_BSD
+options GEOM_PART_MBR
diff --git a/sys/arm/conf/EP80219 b/sys/arm/conf/EP80219
index 8e2d6cb..8ce5b164 100644
--- a/sys/arm/conf/EP80219
+++ b/sys/arm/conf/EP80219
@@ -57,7 +57,6 @@ options SYSVSEM #SYSV-style semaphores
options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
options GEOM_PART_GPT # GUID Partition Tables.
-options GEOM_MBR # DOS/MBR partitioning
options GEOM_LABEL # Providers labelization.
options BOOTP
diff --git a/sys/arm/include/elf.h b/sys/arm/include/elf.h
index 353be7c..c516864 100644
--- a/sys/arm/include/elf.h
+++ b/sys/arm/include/elf.h
@@ -70,10 +70,6 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-
-#define AT_BRK 10 /* Starting point for sbrk and brk. */
-#define AT_DEBUG 11 /* Debugging level. */
-
#define AT_NOTELF 10 /* Program is not ELF ?? */
#define AT_UID 11 /* Real uid. */
#define AT_EUID 12 /* Effective uid. */
diff --git a/sys/boot/Makefile b/sys/boot/Makefile
index 27cb7e3..7020ebb 100644
--- a/sys/boot/Makefile
+++ b/sys/boot/Makefile
@@ -12,7 +12,7 @@ SUBDIR+= ficl
.endif
# Build EFI library.
-.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "ia64"
+.if ${MACHINE_ARCH} == "amd64" || ${MACHINE} == "i386" || ${MACHINE_ARCH} == "ia64"
SUBDIR+= efi
.endif
diff --git a/sys/boot/i386/gptzfsboot/Makefile b/sys/boot/i386/gptzfsboot/Makefile
index 930061f..467d312 100644
--- a/sys/boot/i386/gptzfsboot/Makefile
+++ b/sys/boot/i386/gptzfsboot/Makefile
@@ -60,7 +60,7 @@ gptzfsboot.bin: gptzfsboot.out
objcopy -S -O binary gptzfsboot.out ${.TARGET}
gptzfsboot.out: ${BTXCRT} zfsboot.o sio.o
- ${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC}
+ ${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSTAND}
zfsboot.o: ${.CURDIR}/../../zfs/zfsimpl.c
diff --git a/sys/boot/i386/zfsboot/Makefile b/sys/boot/i386/zfsboot/Makefile
index 41f1672..1653534 100644
--- a/sys/boot/i386/zfsboot/Makefile
+++ b/sys/boot/i386/zfsboot/Makefile
@@ -80,7 +80,7 @@ zfsboot.bin: zfsboot.out
objcopy -S -O binary zfsboot.out ${.TARGET}
zfsboot.out: ${BTXCRT} zfsboot.o sio.o
- ${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC}
+ ${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSTAND}
zfsboot.o: zfsboot.s
diff --git a/sys/boot/powerpc/uboot/conf.c b/sys/boot/powerpc/uboot/conf.c
index 8bc307a..5a9515a 100644
--- a/sys/boot/powerpc/uboot/conf.c
+++ b/sys/boot/powerpc/uboot/conf.c
@@ -94,8 +94,8 @@ struct netif_driver *netif_drivers[] = {
*/
struct file_format *file_formats[] = {
- &uboot_elf,
- NULL
+ &uboot_elf,
+ NULL
};
/*
@@ -104,6 +104,6 @@ struct file_format *file_formats[] = {
extern struct console uboot_console;
struct console *consoles[] = {
- &uboot_console,
- NULL
+ &uboot_console,
+ NULL
};
diff --git a/sys/boot/uboot/common/main.c b/sys/boot/uboot/common/main.c
index f7a0745..1ebb097 100644
--- a/sys/boot/uboot/common/main.c
+++ b/sys/boot/uboot/common/main.c
@@ -216,6 +216,7 @@ COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
static int
command_reboot(int argc, char *argv[])
{
+
printf("Resetting...\n");
ub_reset();
diff --git a/sys/boot/uboot/lib/devicename.c b/sys/boot/uboot/lib/devicename.c
index 3183ae1..5d91550 100644
--- a/sys/boot/uboot/lib/devicename.c
+++ b/sys/boot/uboot/lib/devicename.c
@@ -35,7 +35,8 @@ __FBSDID("$FreeBSD$");
#include "bootstrap.h"
#include "libuboot.h"
-static int uboot_parsedev(struct uboot_devdesc **dev, const char *devspec, const char **path);
+static int uboot_parsedev(struct uboot_devdesc **dev, const char *devspec,
+ const char **path);
/*
* Point (dev) at an allocated device specifier for the device matching the
@@ -178,11 +179,11 @@ uboot_parsedev(struct uboot_devdesc **dev, const char *devspec,
} else {
*dev = idev;
}
- return(0);
+ return (0);
fail:
free(idev);
- return(err);
+ return (err);
}
@@ -191,7 +192,7 @@ uboot_fmtdev(void *vdev)
{
struct uboot_devdesc *dev = (struct uboot_devdesc *)vdev;
char *cp;
- static char buf[128]; /* XXX device length constant? */
+ static char buf[128];
switch(dev->d_type) {
case DEVT_NONE:
@@ -220,12 +221,12 @@ uboot_fmtdev(void *vdev)
int
uboot_setcurrdev(struct env_var *ev, int flags, const void *value)
{
- struct uboot_devdesc *ncurr;
- int rv;
+ struct uboot_devdesc *ncurr;
+ int rv;
if ((rv = uboot_parsedev(&ncurr, value, NULL)) != 0)
- return(rv);
+ return (rv);
free(ncurr);
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
- return(0);
+ return (0);
}
diff --git a/sys/boot/zfs/zfsimpl.c b/sys/boot/zfs/zfsimpl.c
index a6dc99e..e6695cf 100644
--- a/sys/boot/zfs/zfsimpl.c
+++ b/sys/boot/zfs/zfsimpl.c
@@ -873,17 +873,12 @@ dnode_read(spa_t *spa, const dnode_phys_t *dnode, off_t offset, void *buf, size_
int i, rc;
/*
- * We truncate the offset to 32bits, mainly so that I don't
- * have to find a copy of __divdi3 to put into the bootstrap.
- * I don't think the bootstrap needs to access anything bigger
- * than 2G anyway. Note that block addresses are still 64bit
- * so it doesn't affect the possible size of the media.
- * We still use 64bit block numbers so that the bitshifts
- * work correctly. Note: bsize may not be a power of two here.
+ * Note: bsize may not be a power of two here so we need to do an
+ * actual divide rather than a bitshift.
*/
while (buflen > 0) {
- uint64_t bn = ((int) offset) / bsize;
- int boff = ((int) offset) % bsize;
+ uint64_t bn = offset / bsize;
+ int boff = offset % bsize;
int ibn;
const blkptr_t *indbp;
blkptr_t bp;
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 26fbc6e..3abeed8 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -290,7 +290,7 @@ cam_periph_acquire(struct cam_periph *periph)
}
void
-cam_periph_release(struct cam_periph *periph)
+cam_periph_release_locked(struct cam_periph *periph)
{
if (periph == NULL)
@@ -302,7 +302,21 @@ cam_periph_release(struct cam_periph *periph)
camperiphfree(periph);
}
xpt_unlock_buses();
+}
+
+void
+cam_periph_release(struct cam_periph *periph)
+{
+ struct cam_sim *sim;
+ if (periph == NULL)
+ return;
+
+ sim = periph->sim;
+ mtx_assert(sim->mtx, MA_NOTOWNED);
+ mtx_lock(sim->mtx);
+ cam_periph_release_locked(periph);
+ mtx_unlock(sim->mtx);
}
int
@@ -311,8 +325,6 @@ cam_periph_hold(struct cam_periph *periph, int priority)
struct mtx *mtx;
int error;
- mtx_assert(periph->sim->mtx, MA_OWNED);
-
/*
* Increment the reference count on the peripheral
* while we wait for our lock attempt to succeed
@@ -324,13 +336,14 @@ cam_periph_hold(struct cam_periph *periph, int priority)
return (ENXIO);
mtx = periph->sim->mtx;
+ mtx_assert(mtx, MA_OWNED);
if (mtx == &Giant)
mtx = NULL;
while ((periph->flags & CAM_PERIPH_LOCKED) != 0) {
periph->flags |= CAM_PERIPH_LOCK_WANTED;
if ((error = msleep(periph, mtx, priority, "caplck", 0)) != 0) {
- cam_periph_release(periph);
+ cam_periph_release_locked(periph);
return (error);
}
}
@@ -351,7 +364,7 @@ cam_periph_unhold(struct cam_periph *periph)
wakeup(periph);
}
- cam_periph_release(periph);
+ cam_periph_release_locked(periph);
}
/*
diff --git a/sys/cam/cam_periph.h b/sys/cam/cam_periph.h
index e6073d9..8a45806 100644
--- a/sys/cam/cam_periph.h
+++ b/sys/cam/cam_periph.h
@@ -141,6 +141,7 @@ cam_status cam_periph_alloc(periph_ctor_t *periph_ctor,
struct cam_periph *cam_periph_find(struct cam_path *path, char *name);
cam_status cam_periph_acquire(struct cam_periph *periph);
void cam_periph_release(struct cam_periph *periph);
+void cam_periph_release_locked(struct cam_periph *periph);
int cam_periph_hold(struct cam_periph *periph, int priority);
void cam_periph_unhold(struct cam_periph *periph);
void cam_periph_invalidate(struct cam_periph *periph);
diff --git a/sys/cam/cam_sim.c b/sys/cam/cam_sim.c
index cfc2044..adccfa8 100644
--- a/sys/cam/cam_sim.c
+++ b/sys/cam/cam_sim.c
@@ -84,6 +84,7 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
sim->max_tagged_dev_openings = max_tagged_dev_transactions;
sim->max_dev_openings = max_dev_transactions;
sim->flags = 0;
+ sim->refcount = 1;
sim->devq = queue;
sim->mtx = mtx;
if (mtx == &Giant) {
@@ -103,12 +104,42 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
void
cam_sim_free(struct cam_sim *sim, int free_devq)
{
+ int error;
+
+ sim->refcount--;
+ if (sim->refcount > 0) {
+ error = msleep(sim, sim->mtx, PRIBIO, "simfree", 0);
+ KASSERT(error == 0, ("invalid error value for msleep(9)"));
+ }
+
+ KASSERT(sim->refcount == 0, ("sim->refcount == 0"));
+
if (free_devq)
cam_simq_free(sim->devq);
free(sim, M_CAMSIM);
}
void
+cam_sim_release(struct cam_sim *sim)
+{
+ KASSERT(sim->refcount >= 1, ("sim->refcount >= 1"));
+ mtx_assert(sim->mtx, MA_OWNED);
+
+ sim->refcount--;
+ if (sim->refcount == 0)
+ wakeup(sim);
+}
+
+void
+cam_sim_hold(struct cam_sim *sim)
+{
+ KASSERT(sim->refcount >= 1, ("sim->refcount >= 1"));
+ mtx_assert(sim->mtx, MA_OWNED);
+
+ sim->refcount++;
+}
+
+void
cam_sim_set_path(struct cam_sim *sim, u_int32_t path_id)
{
sim->path_id = path_id;
diff --git a/sys/cam/cam_sim.h b/sys/cam/cam_sim.h
index c2d3c5f..f37c5d5 100644
--- a/sys/cam/cam_sim.h
+++ b/sys/cam/cam_sim.h
@@ -61,6 +61,8 @@ struct cam_sim * cam_sim_alloc(sim_action_func sim_action,
int max_tagged_dev_transactions,
struct cam_devq *queue);
void cam_sim_free(struct cam_sim *sim, int free_devq);
+void cam_sim_hold(struct cam_sim *sim);
+void cam_sim_release(struct cam_sim *sim);
/* Optional sim attributes may be set with these. */
void cam_sim_set_path(struct cam_sim *sim, u_int32_t path_id);
@@ -105,6 +107,7 @@ struct cam_sim {
#define CAM_SIM_ON_DONEQ 0x04
struct callout callout;
struct cam_devq *devq; /* Device Queue to use for this SIM */
+ int refcount; /* References to the SIM. */
/* "Pool" of inactive ccbs managed by xpt_alloc_ccb and xpt_free_ccb */
SLIST_HEAD(,ccb_hdr) ccb_freeq;
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index b400e42..f2a2d9d 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -698,19 +698,6 @@ static struct cdevsw xpt_cdevsw = {
};
-static void dead_sim_action(struct cam_sim *sim, union ccb *ccb);
-static void dead_sim_poll(struct cam_sim *sim);
-
-/* Dummy SIM that is used when the real one has gone. */
-static struct cam_sim cam_dead_sim = {
- .sim_action = dead_sim_action,
- .sim_poll = dead_sim_poll,
- .sim_name = "dead_sim",
-};
-
-#define SIM_DEAD(sim) ((sim) == &cam_dead_sim)
-
-
/* Storage for debugging datastructures */
#ifdef CAMDEBUG
struct cam_path *cam_dpath;
@@ -3023,19 +3010,10 @@ xpt_action(union ccb *start_ccb)
case XPT_ENG_EXEC:
{
struct cam_path *path;
- struct cam_sim *sim;
int runq;
path = start_ccb->ccb_h.path;
- sim = path->bus->sim;
- if (SIM_DEAD(sim)) {
- /* The SIM has gone; just execute the CCB directly. */
- cam_ccbq_send_ccb(&path->device->ccbq, start_ccb);
- (*(sim->sim_action))(sim, start_ccb);
- break;
- }
-
cam_ccbq_insert_ccb(&path->device->ccbq, start_ccb);
if (path->device->qfrozen_cnt == 0)
runq = xpt_schedule_dev_sendq(path->bus, path->device);
@@ -3623,7 +3601,6 @@ void
xpt_schedule(struct cam_periph *perph, u_int32_t new_priority)
{
struct cam_ed *device;
- union ccb *work_ccb;
int runq;
mtx_assert(perph->sim->mtx, MA_OWNED);
@@ -3640,15 +3617,6 @@ xpt_schedule(struct cam_periph *perph, u_int32_t new_priority)
new_priority);
}
runq = 0;
- } else if (SIM_DEAD(perph->path->bus->sim)) {
- /* The SIM is gone so just call periph_start directly. */
- work_ccb = xpt_get_ccb(perph->path->device);
- if (work_ccb == NULL)
- return; /* XXX */
- xpt_setup_ccb(&work_ccb->ccb_h, perph->path, new_priority);
- perph->pinfo.priority = new_priority;
- perph->periph_start(perph, work_ccb);
- return;
} else {
/* New entry on the queue */
CAM_DEBUG(perph->path, CAM_DEBUG_SUBTRACE,
@@ -4336,6 +4304,7 @@ xpt_bus_register(struct cam_sim *sim, device_t parent, u_int32_t bus)
TAILQ_INIT(&new_bus->et_entries);
new_bus->path_id = sim->path_id;
+ cam_sim_hold(sim);
new_bus->sim = sim;
timevalclear(&new_bus->last_reset);
new_bus->flags = 0;
@@ -4372,15 +4341,8 @@ int32_t
xpt_bus_deregister(path_id_t pathid)
{
struct cam_path bus_path;
- struct cam_ed *device;
- struct cam_ed_qinfo *qinfo;
- struct cam_devq *devq;
- struct cam_periph *periph;
- struct cam_sim *ccbsim;
- union ccb *work_ccb;
cam_status status;
-
status = xpt_compile_path(&bus_path, NULL, pathid,
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
if (status != CAM_REQ_CMP)
@@ -4389,42 +4351,6 @@ xpt_bus_deregister(path_id_t pathid)
xpt_async(AC_LOST_DEVICE, &bus_path, NULL);
xpt_async(AC_PATH_DEREGISTERED, &bus_path, NULL);
- /* The SIM may be gone, so use a dummy SIM for any stray operations. */
- devq = bus_path.bus->sim->devq;
- ccbsim = bus_path.bus->sim;
- bus_path.bus->sim = &cam_dead_sim;
-
- /* Execute any pending operations now. */
- while ((qinfo = (struct cam_ed_qinfo *)camq_remove(&devq->send_queue,
- CAMQ_HEAD)) != NULL ||
- (qinfo = (struct cam_ed_qinfo *)camq_remove(&devq->alloc_queue,
- CAMQ_HEAD)) != NULL) {
- do {
- device = qinfo->device;
- work_ccb = cam_ccbq_peek_ccb(&device->ccbq, CAMQ_HEAD);
- if (work_ccb != NULL) {
- devq->active_dev = device;
- cam_ccbq_remove_ccb(&device->ccbq, work_ccb);
- cam_ccbq_send_ccb(&device->ccbq, work_ccb);
- (*(ccbsim->sim_action))(ccbsim, work_ccb);
- }
-
- periph = (struct cam_periph *)camq_remove(&device->drvq,
- CAMQ_HEAD);
- if (periph != NULL)
- xpt_schedule(periph, periph->pinfo.priority);
- } while (work_ccb != NULL || periph != NULL);
- }
-
- /* Make sure all completed CCBs are processed. */
- while (!TAILQ_EMPTY(&ccbsim->sim_doneq)) {
- camisr_runqueue(&ccbsim->sim_doneq);
-
- /* Repeat the async's for the benefit of any new devices. */
- xpt_async(AC_LOST_DEVICE, &bus_path, NULL);
- xpt_async(AC_PATH_DEREGISTERED, &bus_path, NULL);
- }
-
/* Release the reference count held while registered. */
xpt_release_bus(bus_path.bus);
xpt_release_path(&bus_path);
@@ -4921,6 +4847,7 @@ xpt_release_bus(struct cam_eb *bus)
TAILQ_REMOVE(&xsoftc.xpt_busses, bus, links);
xsoftc.bus_generation++;
mtx_unlock(&xsoftc.xpt_topo_lock);
+ cam_sim_release(bus->sim);
free(bus, M_CAMXPT);
}
}
@@ -4982,9 +4909,6 @@ xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
struct cam_devq *devq;
cam_status status;
- if (SIM_DEAD(bus->sim))
- return (NULL);
-
/* Make space for us in the device queue on our bus */
devq = bus->sim->devq;
status = cam_devq_resize(devq, devq->alloc_queue.array_size + 1);
@@ -5094,11 +5018,9 @@ xpt_release_device(struct cam_eb *bus, struct cam_et *target,
TAILQ_REMOVE(&target->ed_entries, device,links);
target->generation++;
bus->sim->max_ccbs -= device->ccbq.devq_openings;
- if (!SIM_DEAD(bus->sim)) {
- /* Release our slot in the devq */
- devq = bus->sim->devq;
- cam_devq_resize(devq, devq->alloc_queue.array_size - 1);
- }
+ /* Release our slot in the devq */
+ devq = bus->sim->devq;
+ cam_devq_resize(devq, devq->alloc_queue.array_size - 1);
camq_fini(&device->drvq);
camq_fini(&device->ccbq.queue);
free(device, M_CAMXPT);
@@ -6392,7 +6314,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
xpt_done(done_ccb);
if (TAILQ_FIRST(&softc->request_ccbs) == NULL) {
cam_periph_invalidate(periph);
- cam_periph_release(periph);
+ cam_periph_release_locked(periph);
} else {
probeschedule(periph);
}
@@ -7269,11 +7191,8 @@ camisr_runqueue(void *V_queue)
dev = ccb_h->path->device;
cam_ccbq_ccb_done(&dev->ccbq, (union ccb *)ccb_h);
-
- if (!SIM_DEAD(ccb_h->path->bus->sim)) {
- ccb_h->path->bus->sim->devq->send_active--;
- ccb_h->path->bus->sim->devq->send_openings++;
- }
+ ccb_h->path->bus->sim->devq->send_active--;
+ ccb_h->path->bus->sim->devq->send_openings++;
if (((dev->flags & CAM_DEV_REL_ON_COMPLETE) != 0
&& (ccb_h->status&CAM_STATUS_MASK) != CAM_REQUEUE_REQ)
@@ -7317,15 +7236,3 @@ camisr_runqueue(void *V_queue)
}
}
-static void
-dead_sim_action(struct cam_sim *sim, union ccb *ccb)
-{
-
- ccb->ccb_h.status = CAM_DEV_NOT_THERE;
- xpt_done(ccb);
-}
-
-static void
-dead_sim_poll(struct cam_sim *sim)
-{
-}
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index f63a9b0..8797a08 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -772,8 +772,8 @@ daclose(struct disk *dp)
softc->flags &= ~DA_FLAG_OPEN;
cam_periph_unhold(periph);
- cam_periph_release(periph);
cam_periph_unlock(periph);
+ cam_periph_release(periph);
return (0);
}
diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c
index 63e8e54..0030e3a 100644
--- a/sys/compat/svr4/svr4_sysvec.c
+++ b/sys/compat/svr4/svr4_sysvec.c
@@ -218,8 +218,6 @@ svr4_fixup(register_t **stack_base, struct image_params *imgp)
args = (Elf32_Auxargs *)imgp->auxargs;
pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2);
- if (args->trace)
- AUXARGS_ENTRY(pos, AT_DEBUG, 1);
if (args->execfd != -1)
AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 4c66d14..6825dd4 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -1958,7 +1958,7 @@ device fatm #Fore PCA200E
device hatm #Fore/Marconi HE155/622
device patm #IDT77252 cards (ProATM and IDT)
device utopia #ATM PHY driver
-options NATM #native ATM
+#options NATM #native ATM
options LIBMBPOOL #needed by patm, iatm
diff --git a/sys/conf/files b/sys/conf/files
index 8c2316fa..68fb14e 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -2173,6 +2173,7 @@ net/if_gre.c optional gre
net/if_iso88025subr.c optional token
net/if_lagg.c optional lagg
net/if_loop.c optional loop
+net/if_llatbl.c standard
net/if_media.c standard
net/if_mib.c standard
net/if_ppp.c optional ppp
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 7570d93..901e36d 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -30,9 +30,11 @@ dev/kbd/kbd.c optional sc
dev/ofw/openfirm.c optional aim
dev/ofw/openfirmio.c optional aim
dev/ofw/ofw_bus_if.m optional aim
+dev/ofw/ofw_if.m optional aim
dev/ofw/ofw_bus_subr.c optional aim
dev/ofw/ofw_console.c optional aim
dev/ofw/ofw_disk.c optional ofwd aim
+dev/ofw/ofw_standard.c optional aim
dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac
dev/quicc/quicc_bfe_ocp.c optional quicc mpc85xx
dev/scc/scc_bfe_macio.c optional scc powermac
diff --git a/sys/conf/files.sparc64 b/sys/conf/files.sparc64
index 93f07ed..311027c 100644
--- a/sys/conf/files.sparc64
+++ b/sys/conf/files.sparc64
@@ -42,8 +42,10 @@ dev/kbd/kbd.c optional atkbd | sc | ukbd
dev/le/if_le_lebuffer.c optional le sbus
dev/le/if_le_ledma.c optional le sbus
dev/le/lebuffer_sbus.c optional le sbus
+dev/ofw/ofw_if.m standard
dev/ofw/ofw_bus_if.m standard
dev/ofw/ofw_bus_subr.c standard
+dev/ofw/ofw_standard.c standard
dev/ofw/ofw_console.c optional ofw_console
dev/ofw/openfirm.c standard
dev/ofw/openfirmio.c standard
@@ -111,7 +113,6 @@ sparc64/sparc64/mp_exception.S optional smp \
sparc64/sparc64/mp_locore.S optional smp
sparc64/sparc64/mp_machdep.c optional smp
sparc64/sparc64/nexus.c standard
-sparc64/sparc64/ofw_bus.c standard
sparc64/sparc64/ofw_machdep.c standard
sparc64/sparc64/pmap.c standard
sparc64/sparc64/prof_machdep.c optional profiling-routine
diff --git a/sys/conf/files.sun4v b/sys/conf/files.sun4v
index 03fca35..384c13a 100644
--- a/sys/conf/files.sun4v
+++ b/sys/conf/files.sun4v
@@ -21,8 +21,10 @@ ukbdmap.h optional ukbd_dflt_keymap \
crypto/blowfish/bf_enc.c optional crypto | ipsec
crypto/des/des_enc.c optional crypto | ipsec | netsmb
dev/ofw/ofw_bus_if.m standard
+dev/ofw/ofw_if.m standard
dev/ofw/ofw_bus_subr.c standard
dev/ofw/ofw_console.c optional ofw_console
+dev/ofw/ofw_standard.c standard
dev/ofw/openfirm.c standard
dev/ofw/openfirmio.c standard
dev/ofw/openpromio.c standard
@@ -65,7 +67,6 @@ sun4v/sun4v/mp_locore.S optional smp
sun4v/sun4v/mp_machdep.c optional smp
sun4v/sun4v/nexus.c standard
sun4v/cddl/t1_copy.S standard
-sparc64/sparc64/ofw_bus.c standard
sparc64/sparc64/ofw_machdep.c standard
sun4v/sun4v/pmap.c standard
sparc64/sparc64/prof_machdep.c optional profiling-routine
diff --git a/sys/contrib/pf/net/pf.c b/sys/contrib/pf/net/pf.c
index 2959830..d69372b 100644
--- a/sys/contrib/pf/net/pf.c
+++ b/sys/contrib/pf/net/pf.c
@@ -3162,7 +3162,7 @@ pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer)
#ifdef RTF_PRCLONING
rtalloc_ign(&ro, (RTF_CLONING | RTF_PRCLONING));
#else /* !RTF_PRCLONING */
- in_rtalloc_ign(&ro, RTF_CLONING, 0);
+ in_rtalloc_ign(&ro, 0, 0);
#endif
#else /* ! __FreeBSD__ */
rtalloc_noclone(&ro, NO_CLONING);
@@ -3183,7 +3183,7 @@ pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer)
rtalloc_ign((struct route *)&ro6,
(RTF_CLONING | RTF_PRCLONING));
#else /* !RTF_PRCLONING */
- rtalloc_ign((struct route *)&ro6, RTF_CLONING);
+ rtalloc_ign((struct route *)&ro6, 0);
#endif
#else /* ! __FreeBSD__ */
rtalloc_noclone((struct route *)&ro6, NO_CLONING);
@@ -5986,9 +5986,9 @@ pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif)
#ifdef __FreeBSD__
/* XXX MRT not always INET */ /* stick with table 0 though */
if (af == AF_INET)
- in_rtalloc_ign((struct route *)&ro, RTF_CLONING, 0);
+ in_rtalloc_ign((struct route *)&ro, 0, 0);
else
- rtalloc_ign((struct route *)&ro, RTF_CLONING);
+ rtalloc_ign((struct route *)&ro, 0);
#else /* ! __FreeBSD__ */
rtalloc_noclone((struct route *)&ro, NO_CLONING);
#endif
@@ -6068,9 +6068,9 @@ pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw)
rtalloc_ign((struct route *)&ro, (RTF_CLONING|RTF_PRCLONING));
# else /* !RTF_PRCLONING */
if (af == AF_INET)
- in_rtalloc_ign((struct route *)&ro, RTF_CLONING, 0);
+ in_rtalloc_ign((struct route *)&ro, 0, 0);
else
- rtalloc_ign((struct route *)&ro, RTF_CLONING);
+ rtalloc_ign((struct route *)&ro, 0);
# endif
#else /* ! __FreeBSD__ */
rtalloc_noclone((struct route *)&ro, NO_CLONING);
diff --git a/sys/contrib/pf/net/pf_if.c b/sys/contrib/pf/net/pf_if.c
index 62dbbf2..1972edc 100644
--- a/sys/contrib/pf/net/pf_if.c
+++ b/sys/contrib/pf/net/pf_if.c
@@ -115,8 +115,10 @@ void pfi_change_group_event(void * __unused, char *);
void pfi_detach_group_event(void * __unused, struct ifg_group *);
void pfi_ifaddr_event(void * __unused, struct ifnet *);
+#ifdef VIMAGE_GLOBALS
extern struct ifgrouphead ifg_head;
#endif
+#endif
RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
diff --git a/sys/contrib/pf/net/pf_subr.c b/sys/contrib/pf/net/pf_subr.c
index 1ac8b40..a722aef 100644
--- a/sys/contrib/pf/net/pf_subr.c
+++ b/sys/contrib/pf/net/pf_subr.c
@@ -116,22 +116,22 @@ __FBSDID("$FreeBSD$");
#define ISN_STATIC_INCREMENT 4096
#define ISN_RANDOM_INCREMENT (4096 - 1)
-static u_char isn_secret[32];
-static int isn_last_reseed;
-static u_int32_t isn_offset;
-static MD5_CTX isn_ctx;
+static u_char pf_isn_secret[32];
+static int pf_isn_last_reseed;
+static u_int32_t pf_isn_offset;
u_int32_t
pf_new_isn(struct pf_state *s)
{
+ MD5_CTX isn_ctx;
u_int32_t md5_buffer[4];
u_int32_t new_isn;
struct pf_state_host *src, *dst;
/* Seed if this is the first use, reseed if requested. */
- if (isn_last_reseed == 0) {
- read_random(&isn_secret, sizeof(isn_secret));
- isn_last_reseed = ticks;
+ if (pf_isn_last_reseed == 0) {
+ read_random(&pf_isn_secret, sizeof(pf_isn_secret));
+ pf_isn_last_reseed = ticks;
}
if (s->direction == PF_IN) {
@@ -160,11 +160,11 @@ pf_new_isn(struct pf_state *s)
MD5Update(&isn_ctx, (u_char *) &src->addr,
sizeof(struct in_addr));
}
- MD5Update(&isn_ctx, (u_char *) &isn_secret, sizeof(isn_secret));
+ MD5Update(&isn_ctx, (u_char *) &pf_isn_secret, sizeof(pf_isn_secret));
MD5Final((u_char *) &md5_buffer, &isn_ctx);
new_isn = (tcp_seq) md5_buffer[0];
- isn_offset += ISN_STATIC_INCREMENT +
+ pf_isn_offset += ISN_STATIC_INCREMENT +
(arc4random() & ISN_RANDOM_INCREMENT);
- new_isn += isn_offset;
+ new_isn += pf_isn_offset;
return (new_isn);
}
diff --git a/sys/contrib/rdma/rdma_addr.c b/sys/contrib/rdma/rdma_addr.c
index e052b80..971b4de 100644
--- a/sys/contrib/rdma/rdma_addr.c
+++ b/sys/contrib/rdma/rdma_addr.c
@@ -163,6 +163,7 @@ static void addr_send_arp(struct sockaddr_in *dst_in)
struct route iproute;
struct sockaddr_in *dst = (struct sockaddr_in *)&iproute.ro_dst;
char dmac[ETHER_ADDR_LEN];
+ struct llentry *lle;
bzero(&iproute, sizeof iproute);
*dst = *dst_in;
@@ -172,7 +173,7 @@ static void addr_send_arp(struct sockaddr_in *dst_in)
return;
arpresolve(iproute.ro_rt->rt_ifp, iproute.ro_rt, NULL,
- rt_key(iproute.ro_rt), dmac);
+ rt_key(iproute.ro_rt), dmac, &lle);
RTFREE(iproute.ro_rt);
}
@@ -186,6 +187,7 @@ static int addr_resolve_remote(struct sockaddr_in *src_in,
struct route iproute;
struct sockaddr_in *dst = (struct sockaddr_in *)&iproute.ro_dst;
char dmac[ETHER_ADDR_LEN];
+ struct llentry *lle;
bzero(&iproute, sizeof iproute);
*dst = *dst_in;
@@ -202,7 +204,7 @@ static int addr_resolve_remote(struct sockaddr_in *src_in,
goto put;
}
ret = arpresolve(iproute.ro_rt->rt_ifp, iproute.ro_rt, NULL,
- rt_key(iproute.ro_rt), dmac);
+ rt_key(iproute.ro_rt), dmac, &lle);
if (ret) {
goto put;
}
diff --git a/sys/crypto/rc4/rc4.c b/sys/crypto/rc4/rc4.c
index f94a554..dbdbd7a 100644
--- a/sys/crypto/rc4/rc4.c
+++ b/sys/crypto/rc4/rc4.c
@@ -61,7 +61,7 @@ void
rc4_init(struct rc4_state *const state, const u_char *key, int keylen)
{
u_char j;
- int i;
+ int i, k;
/* Initialize state with identity permutation */
for (i = 0; i < 256; i++)
@@ -70,9 +70,11 @@ rc4_init(struct rc4_state *const state, const u_char *key, int keylen)
state->index2 = 0;
/* Randomize the permutation using key data */
- for (j = i = 0; i < 256; i++) {
- j += state->perm[i] + key[i % keylen];
+ for (j = i = k = 0; i < 256; i++) {
+ j += state->perm[i] + key[k];
swap_bytes(&state->perm[i], &state->perm[j]);
+ if (++k >= keylen)
+ k = 0;
}
}
diff --git a/sys/dev/acpica/acpi_smbat.c b/sys/dev/acpica/acpi_smbat.c
index 5e1c66e..3935a9f 100644
--- a/sys/dev/acpica/acpi_smbat.c
+++ b/sys/dev/acpica/acpi_smbat.c
@@ -61,6 +61,23 @@ static int acpi_smbat_get_bst(device_t dev, struct acpi_bst *bst);
ACPI_SERIAL_DECL(smbat, "ACPI Smart Battery");
+SYSCTL_DECL(_debug_acpi);
+SYSCTL_NODE(_debug_acpi, OID_AUTO, batt, CTLFLAG_RD, NULL, "Battery debugging");
+
+/* On some laptops with smart batteries, enabling battery monitoring
+ * software causes keystrokes from atkbd to be lost. This has also been
+ * reported on Linux, and is apparently due to the keyboard and I2C line
+ * for the battery being routed through the same chip. Whether that's
+ * accurate or not, adding extra sleeps to the status checking code
+ * causes the problem to go away.
+ *
+ * If you experience that problem, try a value of 10ms and move up
+ * from there.
+ */
+static int batt_sleep_ms;
+SYSCTL_INT(_debug_acpi_batt, OID_AUTO, batt_sleep_ms, CTLFLAG_RW, &batt_sleep_ms, 0,
+ "Sleep during battery status updates to prevent keystroke loss.");
+
static device_method_t acpi_smbat_methods[] = {
/* device interface */
DEVMETHOD(device_probe, acpi_smbat_probe),
@@ -176,6 +193,9 @@ acpi_smbus_read_2(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
ACPI_SERIAL_ASSERT(smbat);
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
val = addr;
error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_ADDR,
val, 1);
@@ -194,6 +214,9 @@ acpi_smbus_read_2(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
if (error)
goto out;
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
for (to = SMBUS_TIMEOUT; to != 0; to--) {
error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL,
&val, 1);
@@ -239,6 +262,9 @@ acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
ACPI_SERIAL_ASSERT(smbat);
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
val = addr;
error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_ADDR,
val, 1);
@@ -257,6 +283,9 @@ acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
if (error)
goto out;
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
for (to = SMBUS_TIMEOUT; to != 0; to--) {
error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL,
&val, 1);
@@ -292,6 +321,9 @@ acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
if (len > val)
len = val;
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
while (len--) {
error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_DATA
+ len, &val, 1);
@@ -299,6 +331,8 @@ acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
goto out;
ptr[len] = val;
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
}
out:
diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c
index 855a1d0..f2e4805 100644
--- a/sys/dev/ata/ata-pci.c
+++ b/sys/dev/ata/ata-pci.c
@@ -92,7 +92,8 @@ ata_pci_attach(device_t dev)
int unit;
/* do chipset specific setups only needed once */
- if (ata_legacy(dev) || pci_read_config(dev, PCIR_BAR(2), 4) & IOMASK)
+ ctlr->legacy = ata_legacy(dev);
+ if (ctlr->legacy || pci_read_config(dev, PCIR_BAR(2), 4) & IOMASK)
ctlr->channels = 2;
else
ctlr->channels = 1;
@@ -120,7 +121,7 @@ ata_pci_attach(device_t dev)
/* attach all channels on this controller */
for (unit = 0; unit < ctlr->channels; unit++) {
- if ((unit == 0 || unit == 1) && ata_legacy(dev)) {
+ if ((unit == 0 || unit == 1) && ctlr->legacy) {
device_add_child(dev, "ata", unit);
continue;
}
@@ -192,7 +193,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
if (type == SYS_RES_IOPORT) {
switch (*rid) {
case ATA_IOADDR_RID:
- if (ata_legacy(dev)) {
+ if (controller->legacy) {
start = (unit ? ATA_SECONDARY : ATA_PRIMARY);
count = ATA_IOSIZE;
end = start + count - 1;
@@ -204,7 +205,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
break;
case ATA_CTLADDR_RID:
- if (ata_legacy(dev)) {
+ if (controller->legacy) {
start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_CTLOFFSET;
count = ATA_CTLIOSIZE;
end = start + count - 1;
@@ -217,7 +218,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
}
}
if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
- if (ata_legacy(dev)) {
+ if (controller->legacy) {
int irq = (unit == 0 ? 14 : 15);
res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
@@ -233,6 +234,7 @@ int
ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
+ struct ata_pci_controller *controller = device_get_softc(dev);
int unit = ((struct ata_channel *)device_get_softc(child))->unit;
if (type == SYS_RES_IOPORT) {
@@ -256,7 +258,7 @@ ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
if (rid != ATA_IRQ_RID)
return ENOENT;
- if (ata_legacy(dev)) {
+ if (controller->legacy) {
return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
SYS_RES_IRQ, rid, r);
}
@@ -271,7 +273,9 @@ ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq,
int flags, driver_filter_t *filter, driver_intr_t *function,
void *argument, void **cookiep)
{
- if (ata_legacy(dev)) {
+ struct ata_pci_controller *controller = device_get_softc(dev);
+
+ if (controller->legacy) {
return BUS_SETUP_INTR(device_get_parent(dev), child, irq,
flags, filter, function, argument, cookiep);
}
@@ -294,7 +298,9 @@ int
ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
void *cookie)
{
- if (ata_legacy(dev)) {
+ struct ata_pci_controller *controller = device_get_softc(dev);
+
+ if (controller->legacy) {
return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie);
}
else {
@@ -352,7 +358,7 @@ ata_pci_allocate(device_t dev)
ch->r_io[i].offset = i;
}
ch->r_io[ATA_CONTROL].res = ctlio;
- ch->r_io[ATA_CONTROL].offset = ata_legacy(device_get_parent(dev)) ? 0 : 2;
+ ch->r_io[ATA_CONTROL].offset = ctlr->legacy ? 0 : 2;
ch->r_io[ATA_IDX_ADDR].res = io;
ata_default_registers(dev);
if (ctlr->r_res1) {
@@ -369,9 +375,11 @@ ata_pci_allocate(device_t dev)
int
ata_pci_status(device_t dev)
{
+ struct ata_pci_controller *controller =
+ device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
- if ((dumping || !ata_legacy(device_get_parent(dev))) &&
+ if ((dumping || !controller->legacy) &&
((ch->flags & ATA_ALWAYS_DMASTAT) ||
(ch->dma.flags & ATA_DMA_ACTIVE))) {
int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
@@ -652,7 +660,7 @@ ata_setup_interrupt(device_t dev, void *intr_func)
struct ata_pci_controller *ctlr = device_get_softc(dev);
int rid = ATA_IRQ_RID;
- if (!ata_legacy(dev)) {
+ if (!ctlr->legacy) {
if (!(ctlr->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE))) {
device_printf(dev, "unable to map interrupt\n");
diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h
index 0cbb0d5..e5edd87 100644
--- a/sys/dev/ata/ata-pci.h
+++ b/sys/dev/ata/ata-pci.h
@@ -48,6 +48,7 @@ struct ata_pci_controller {
struct resource *r_irq;
void *handle;
struct ata_chip_id *chip;
+ int legacy;
int channels;
int (*chipinit)(device_t);
int (*suspend)(device_t);
diff --git a/sys/dev/ata/chipsets/ata-ahci.c b/sys/dev/ata/chipsets/ata-ahci.c
index 4481d9a..4028466 100644
--- a/sys/dev/ata/chipsets/ata-ahci.c
+++ b/sys/dev/ata/chipsets/ata-ahci.c
@@ -73,8 +73,9 @@ ata_ahci_probe(device_t dev)
char buffer[64];
/* is this a possible AHCI candidate ? */
- if (pci_get_subclass(dev) != PCIS_STORAGE_SATA)
- return ENXIO;
+ if (pci_get_class(dev) != PCIC_STORAGE ||
+ pci_get_subclass(dev) != PCIS_STORAGE_SATA)
+ return (ENXIO);
/* is this PCI device flagged as an AHCI compliant chip ? */
if (pci_read_config(dev, PCIR_PROGIF, 1) != PCIP_STORAGE_SATA_AHCI_1_0)
@@ -94,6 +95,7 @@ int
ata_ahci_chipinit(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
+ int error;
u_int32_t version;
/* if we have a memory BAR(5) we are likely on an AHCI part */
@@ -105,14 +107,19 @@ ata_ahci_chipinit(device_t dev)
/* setup interrupt delivery if not done allready by a vendor driver */
if (!ctlr->r_irq) {
- if (ata_setup_interrupt(dev, ata_generic_intr))
+ if (ata_setup_interrupt(dev, ata_generic_intr)) {
+ bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2);
return ENXIO;
+ }
}
else
device_printf(dev, "AHCI called from vendor specific driver\n");
/* reset controller */
- ata_ahci_ctlr_reset(dev);
+ if ((error = ata_ahci_ctlr_reset(dev)) != 0) {
+ bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2);
+ return (error);
+ };
/* get the number of HW channels */
ctlr->channels =
@@ -154,7 +161,6 @@ ata_ahci_ctlr_reset(device_t dev)
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_HR);
DELAY(1000000);
if (ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & ATA_AHCI_GHC_HR) {
- bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2);
device_printf(dev, "AHCI controller reset failure\n");
return ENXIO;
}
diff --git a/sys/dev/ata/chipsets/ata-sis.c b/sys/dev/ata/chipsets/ata-sis.c
index e94bef5..56b194d 100644
--- a/sys/dev/ata/chipsets/ata-sis.c
+++ b/sys/dev/ata/chipsets/ata-sis.c
@@ -105,6 +105,9 @@ ata_sis_probe(device_t dev)
char buffer[64];
int found = 0;
+ if (pci_get_class(dev) != PCIC_STORAGE)
+ return (ENXIO);
+
if (pci_get_vendor(dev) != ATA_SIS_ID)
return ENXIO;
diff --git a/sys/dev/ath/ath_hal/ah.c b/sys/dev/ath/ath_hal/ah.c
index 18d31ec..668ace7 100644
--- a/sys/dev/ath/ath_hal/ah.c
+++ b/sys/dev/ath/ath_hal/ah.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: ah.c,v 1.15 2008/11/15 22:15:44 sam Exp $
+ * $FreeBSD$
*/
#include "opt_ah.h"
@@ -32,7 +32,7 @@ OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
const char*
ath_hal_probe(uint16_t vendorid, uint16_t devid)
{
- struct ath_hal_chip **pchip;
+ struct ath_hal_chip * const *pchip;
OS_SET_FOREACH(pchip, ah_chips) {
const char *name = (*pchip)->probe(vendorid, devid);
@@ -53,7 +53,7 @@ struct ath_hal*
ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *error)
{
- struct ath_hal_chip **pchip;
+ struct ath_hal_chip * const *pchip;
OS_SET_FOREACH(pchip, ah_chips) {
struct ath_hal_chip *chip = *pchip;
@@ -88,7 +88,7 @@ OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
struct ath_hal_rf *
ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
{
- struct ath_hal_rf **prf;
+ struct ath_hal_rf * const *prf;
OS_SET_FOREACH(prf, ah_rfs) {
struct ath_hal_rf *rf = *prf;
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v14.c b/sys/dev/ath/ath_hal/ah_eeprom_v14.c
index 45f998f..8793d3b 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v14.c
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v14.c
@@ -160,18 +160,6 @@ v14EepromDiag(struct ath_hal *ah, int request,
return AH_FALSE;
}
-/* XXX conditionalize by target byte order */
-#ifndef bswap16
-static __inline__ uint16_t
-__bswap16(uint16_t _x)
-{
- return ((uint16_t)(
- (((const uint8_t *)(&_x))[0] ) |
- (((const uint8_t *)(&_x))[1]<< 8))
- );
-}
-#endif
-
/* Do structure specific swaps if Eeprom format is non native to host */
static void
eepromSwap(struct ar5416eeprom *ee)
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v3.c b/sys/dev/ath/ath_hal/ah_eeprom_v3.c
index b2c304b..20adb31 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v3.c
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v3.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: ah_eeprom_v3.c,v 1.4 2008/11/27 22:39:42 sam Exp $
+ * $FreeBSD$
*/
#include "opt_ah.h"
@@ -26,9 +26,9 @@ static void
getPcdacInterceptsFromPcdacMinMax(HAL_EEPROM *ee,
uint16_t pcdacMin, uint16_t pcdacMax, uint16_t *vp)
{
- const static uint16_t intercepts3[] =
+ static const uint16_t intercepts3[] =
{ 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
- const static uint16_t intercepts3_2[] =
+ static const uint16_t intercepts3_2[] =
{ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
const uint16_t *ip = ee->ee_version < AR_EEPROM_VER3_2 ?
intercepts3 : intercepts3_2;
diff --git a/sys/dev/ath/ath_hal/ah_internal.h b/sys/dev/ath/ath_hal/ah_internal.h
index da09c68..9feb295 100644
--- a/sys/dev/ath/ath_hal/ah_internal.h
+++ b/sys/dev/ath/ath_hal/ah_internal.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: ah_internal.h,v 1.21 2008/11/27 22:29:27 sam Exp $
+ * $FreeBSD$
*/
#ifndef _ATH_AH_INTERAL_H_
#define _ATH_AH_INTERAL_H_
@@ -42,23 +42,6 @@
#define offsetof(type, field) ((size_t)(&((type *)0)->field))
#endif
-/*
- * Remove const in a way that keeps the compiler happy.
- * This works for gcc but may require other magic for
- * other compilers (not sure where this should reside).
- * Note that uintptr_t is C99.
- */
-#ifndef __DECONST
-#ifndef _UINTPTR_T
-#if AH_WORDSIZE == 64
-typedef unsigned long int uintptr_t;
-#else
-typedef unsigned int uintptr_t;
-#endif
-#endif
-#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
-#endif
-
typedef struct {
uint16_t start; /* first register */
uint16_t end; /* ending register or zero */
@@ -114,12 +97,12 @@ struct ath_hal_rf {
};
#ifndef AH_RF
#define AH_RF(_name, _probe, _attach) \
-static struct ath_hal_rf name##_rf = { \
- .name = #_name, \
+static struct ath_hal_rf _name##_rf = { \
+ .name = __STRING(_name), \
.probe = _probe, \
.attach = _attach \
}; \
-OS_DATA_SET(ah_rfs, name##_rf)
+OS_DATA_SET(ah_rfs, _name##_rf)
#endif
struct ath_hal_rf *ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode);
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5111.c b/sys/dev/ath/ath_hal/ar5212/ar5111.c
index 95dbbd5..f009ebe 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5111.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5111.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: ar5111.c,v 1.7 2008/11/10 04:08:03 sam Exp $
+ * $FreeBSD$
*/
#include "opt_ah.h"
@@ -90,7 +90,7 @@ ar5111SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
uint16_t channel5111; /* 11a channel for 5111 */
} CHAN_INFO_2GHZ;
- const static CHAN_INFO_2GHZ chan2GHzData[] = {
+ static const CHAN_INFO_2GHZ chan2GHzData[] = {
{ 1, 0x46, 96 }, /* 2312 -19 */
{ 1, 0x46, 97 }, /* 2317 -18 */
{ 1, 0x46, 98 }, /* 2322 -17 */
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c b/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c
index 645c56c..bef9c28e 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: ar5212_ani.c,v 1.7 2008/11/21 00:16:21 sam Exp $
+ * $FreeBSD$
*/
#include "opt_ah.h"
@@ -267,7 +267,7 @@ ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
case HAL_ANI_NOISE_IMMUNITY_LEVEL: {
u_int level = param;
- if (level >= params->maxNoiseImmunityLevel) {
+ if (level > params->maxNoiseImmunityLevel) {
HALDEBUG(ah, HAL_DEBUG_ANY,
"%s: level out of range (%u > %u)\n",
__func__, level, params->maxNoiseImmunityLevel);
@@ -342,7 +342,7 @@ ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
case HAL_ANI_FIRSTEP_LEVEL: {
u_int level = param;
- if (level >= params->maxFirstepLevel) {
+ if (level > params->maxFirstepLevel) {
HALDEBUG(ah, HAL_DEBUG_ANY,
"%s: level out of range (%u > %u)\n",
__func__, level, params->maxFirstepLevel);
@@ -360,7 +360,7 @@ ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
case HAL_ANI_SPUR_IMMUNITY_LEVEL: {
u_int level = param;
- if (level >= params->maxSpurImmunityLevel) {
+ if (level > params->maxSpurImmunityLevel) {
HALDEBUG(ah, HAL_DEBUG_ANY,
"%s: level out of range (%u > %u)\n",
__func__, level, params->maxSpurImmunityLevel);
@@ -433,7 +433,7 @@ ar5212AniOfdmErrTrigger(struct ath_hal *ah)
aniState = ahp->ah_curani;
params = aniState->params;
/* First, raise noise immunity level, up to max */
- if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) {
+ if (aniState->noiseImmunityLevel+1 <= params->maxNoiseImmunityLevel) {
HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__,
aniState->noiseImmunityLevel + 1);
ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
@@ -441,7 +441,7 @@ ar5212AniOfdmErrTrigger(struct ath_hal *ah)
return;
}
/* then, raise spur immunity level, up to max */
- if (aniState->spurImmunityLevel+1 < params->maxSpurImmunityLevel) {
+ if (aniState->spurImmunityLevel+1 <= params->maxSpurImmunityLevel) {
HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise SI to %u\n", __func__,
aniState->spurImmunityLevel + 1);
ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
@@ -470,7 +470,7 @@ ar5212AniOfdmErrTrigger(struct ath_hal *ah)
* If weak sig detect is already off, as last resort,
* raise firstep level
*/
- if (aniState->firstepLevel+1 < params->maxFirstepLevel) {
+ if (aniState->firstepLevel+1 <= params->maxFirstepLevel) {
HALDEBUG(ah, HAL_DEBUG_ANI,
"%s: rssi %d raise ST %u\n", __func__, rssi,
aniState->firstepLevel+1);
@@ -490,7 +490,7 @@ ar5212AniOfdmErrTrigger(struct ath_hal *ah)
HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
AH_TRUE);
}
- if (aniState->firstepLevel+1 < params->maxFirstepLevel) {
+ if (aniState->firstepLevel+1 <= params->maxFirstepLevel) {
HALDEBUG(ah, HAL_DEBUG_ANI,
"%s: rssi %d raise ST %u\n", __func__, rssi,
aniState->firstepLevel+1);
@@ -544,7 +544,7 @@ ar5212AniCckErrTrigger(struct ath_hal *ah)
/* first, raise noise immunity level, up to max */
aniState = ahp->ah_curani;
params = aniState->params;
- if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) {
+ if (aniState->noiseImmunityLevel+1 <= params->maxNoiseImmunityLevel) {
HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__,
aniState->noiseImmunityLevel + 1);
ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
@@ -559,7 +559,7 @@ ar5212AniCckErrTrigger(struct ath_hal *ah)
* Beacon signal in mid and high range,
* raise firstep level.
*/
- if (aniState->firstepLevel+1 < params->maxFirstepLevel) {
+ if (aniState->firstepLevel+1 <= params->maxFirstepLevel) {
HALDEBUG(ah, HAL_DEBUG_ANI,
"%s: rssi %d raise ST %u\n", __func__, rssi,
aniState->firstepLevel+1);
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312.h b/sys/dev/ath/ath_hal/ar5312/ar5312.h
index 4714ea1..4943891 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5312.h
+++ b/sys/dev/ath/ath_hal/ar5312/ar5312.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: ar5312.h,v 1.5 2008/11/22 07:37:40 sam Exp $
+ * $FreeBSD$
*/
#ifndef _ATH_AR5312_H_
#define _ATH_AR5312_H_
@@ -38,8 +38,6 @@
AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV1 || \
AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV2)
-extern struct ath_hal * ar5312Attach(uint16_t devid, HAL_SOFTC sc,
- HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status);
extern HAL_BOOL ar5312IsInterruptPending(struct ath_hal *ah);
/* AR5312 */
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c b/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c
index b5a2dde..e38c50c 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c
+++ b/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: ar5312_attach.c,v 1.8 2008/11/27 22:30:03 sam Exp $
+ * $FreeBSD$
*/
#include "opt_ah.h"
@@ -122,7 +122,7 @@ ar5312Attach(uint16_t devid, HAL_SOFTC sc,
/* setup common ini data; rf backends handle remainder */
HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6);
- HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 6);
+ HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 2);
if (!ar5312ChipReset(ah, AH_NULL)) { /* reset chip */
HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
@@ -318,7 +318,6 @@ ar5312Probe(uint16_t vendorid, uint16_t devid)
case AR5212_AR2313_REV8:
return "Atheros 2313 WiSoC";
case AR5212_AR2315_REV6:
- case AR5212_AR2315_REV6:
case AR5212_AR2315_REV7:
return "Atheros 2315 WiSoC";
case AR5212_AR2317_REV1:
diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c
index 2b1117f..338d8f2 100644
--- a/sys/dev/atkbdc/psm.c
+++ b/sys/dev/atkbdc/psm.c
@@ -3956,6 +3956,9 @@ static void
synaptics_sysctl_create_tree(struct psm_softc *sc)
{
+ if (sc->syninfo.sysctl_tree != NULL)
+ return;
+
/* Attach extra synaptics sysctl nodes under hw.psm.synaptics */
sysctl_ctx_init(&sc->syninfo.sysctl_ctx);
sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx,
@@ -4263,14 +4266,18 @@ enable_synaptics(struct psm_softc *sc)
kbdc = sc->kbdc;
VLOG(3, (LOG_DEBUG, "synaptics: BEGIN init\n"));
- disable_aux_dev(kbdc);
sc->hw.buttons = 3;
sc->squelch = 0;
- /* Just to be on the safe side */
+ /*
+ * Just to be on the safe side: this avoids troubles with
+ * following mouse_ext_command() when the previous command
+ * was PSMC_SET_RESOLUTION. Set Scaling has no effect on
+ * Synaptics Touchpad behaviour.
+ */
set_mouse_scaling(kbdc, 1);
- /* Identify the Touchpad version */
+ /* Identify the Touchpad version. */
if (mouse_ext_command(kbdc, 0) == 0)
return (FALSE);
if (get_mouse_status(kbdc, status, 0, 3) != 3)
@@ -4290,7 +4297,7 @@ enable_synaptics(struct psm_softc *sc)
return (FALSE);
}
- /* Get the Touchpad model information */
+ /* Get the Touchpad model information. */
if (mouse_ext_command(kbdc, 3) == 0)
return (FALSE);
if (get_mouse_status(kbdc, status, 0, 3) != 3)
@@ -4321,7 +4328,7 @@ enable_synaptics(struct psm_softc *sc)
printf(" infoGeometry: %d\n", sc->synhw.infoGeometry);
}
- /* Read the extended capability bits */
+ /* Read the extended capability bits. */
if (mouse_ext_command(kbdc, 2) == 0)
return (FALSE);
if (get_mouse_status(kbdc, status, 0, 3) != 3)
@@ -4331,7 +4338,7 @@ enable_synaptics(struct psm_softc *sc)
return (FALSE);
}
- /* Set the different capabilities when they exist */
+ /* Set the different capabilities when they exist. */
if ((status[0] & 0x80) >> 7) {
sc->synhw.capExtended = (status[0] & 0x80) >> 7;
sc->synhw.capPassthrough = (status[2] & 0x80) >> 7;
@@ -4355,8 +4362,8 @@ enable_synaptics(struct psm_softc *sc)
}
/*
- * if we have bits set in status[0] & 0x70 - then we can load
- * more information about buttons using query 0x09
+ * If we have bits set in status[0] & 0x70, then we can load
+ * more information about buttons using query 0x09.
*/
if (status[0] & 0x70) {
if (mouse_ext_command(kbdc, 0x09) == 0)
@@ -4376,7 +4383,7 @@ enable_synaptics(struct psm_softc *sc)
}
/*
- * Read the mode byte
+ * Read the mode byte.
*
* XXX: Note the Synaptics documentation also defines the first
* byte of the response to this query to be a constant 0x3b, this
@@ -4391,13 +4398,13 @@ enable_synaptics(struct psm_softc *sc)
return (FALSE);
}
- /* Set the mode byte -- request wmode where available */
+ /* Set the mode byte; request wmode where available. */
if (sc->synhw.capExtended)
mouse_ext_command(kbdc, 0xc1);
else
mouse_ext_command(kbdc, 0xc0);
- /* Reset the sampling rate */
+ /* "Commit" the Set Mode Byte command sent above. */
set_mouse_sampling_rate(kbdc, 20);
/*
@@ -4414,6 +4421,12 @@ enable_synaptics(struct psm_softc *sc)
/* Create sysctl tree. */
synaptics_sysctl_create_tree(sc);
+ /*
+ * The touchpad will have to be reinitialized after
+ * suspend/resume.
+ */
+ sc->config |= PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND;
+
return (TRUE);
}
diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c
index 15dc633..ff78453 100644
--- a/sys/dev/bce/if_bce.c
+++ b/sys/dev/bce/if_bce.c
@@ -5114,7 +5114,7 @@ bce_free_tx_chain(struct bce_softc *sc)
/* Unmap, unload, and free any mbufs still in the TX mbuf chain. */
for (i = 0; i < TOTAL_TX_BD; i++) {
if (sc->tx_mbuf_ptr[i] != NULL) {
- if (sc->tx_mbuf_map != NULL)
+ if (sc->tx_mbuf_map[i] != NULL)
bus_dmamap_sync(sc->tx_mbuf_tag, sc->tx_mbuf_map[i],
BUS_DMASYNC_POSTWRITE);
m_freem(sc->tx_mbuf_ptr[i]);
@@ -7408,7 +7408,6 @@ bce_stats_update(struct bce_softc *sc)
(u_long) sc->stat_IfInMBUFDiscards +
(u_long) sc->stat_Dot3StatsAlignmentErrors +
(u_long) sc->stat_Dot3StatsFCSErrors +
- (u_long) sc->stat_IfInFramesL2FilterDiscards +
(u_long) sc->stat_IfInRuleCheckerDiscards +
(u_long) sc->stat_IfInFTQDiscards +
(u_long) sc->com_no_buffers;
diff --git a/sys/dev/cxgb/common/cxgb_ael1002.c b/sys/dev/cxgb/common/cxgb_ael1002.c
index 55c6421..97d4419 100644
--- a/sys/dev/cxgb/common/cxgb_ael1002.c
+++ b/sys/dev/cxgb/common/cxgb_ael1002.c
@@ -71,6 +71,74 @@ struct reg_val {
unsigned short set_bits;
};
+static int ael2005_i2c_rd(struct cphy *phy, int dev_addr, int word_addr);
+
+static int get_module_type (struct cphy *phy, int hint)
+{
+ int v;
+
+ v = hint ? hint : ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 0);
+ if (v < 0)
+ return v;
+
+ if (v == 0x3) {
+ /* SFP: see SFF-8472 for below */
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 3);
+ if (v < 0)
+ return v;
+
+ if (v == 0x1)
+ return phy_modtype_twinax;
+ if (v == 0x10)
+ return phy_modtype_sr;
+ if (v == 0x20)
+ return phy_modtype_lr;
+ if (v == 0x40)
+ return phy_modtype_lrm;
+
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 6);
+ if (v < 0)
+ return v;
+ if (v != 4)
+ return phy_modtype_unknown;
+
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 10);
+ if (v < 0)
+ return v;
+
+ if (v & 0x80) {
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
+ if (v < 0)
+ return v;
+ return v > 10 ? phy_modtype_twinax_long :
+ phy_modtype_twinax;
+ }
+ } else if (v == 0x6) {
+ /* XFP: See INF-8077i for details. */
+
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 127);
+ if (v < 0)
+ return v;
+
+ if (v != 1) {
+ /* XXX: set page select to table 1 yourself */
+ return phy_modtype_unknown;
+ }
+
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 131);
+ if (v < 0)
+ return v;
+ if (v == 0x10)
+ return phy_modtype_lrm;
+ if (v == 0x40)
+ return phy_modtype_lr;
+ if (v == 0x80)
+ return phy_modtype_sr;
+ }
+
+ return phy_modtype_unknown;
+}
+
static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)
{
int err;
@@ -107,6 +175,18 @@ static int ael1002_power_down(struct cphy *phy, int enable)
return err;
}
+static int ael1002_get_module_type(struct cphy *phy, int delay_ms)
+{
+ int v;
+
+ if (delay_ms)
+ msleep(delay_ms);
+
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 0);
+
+ return v == -ETIMEDOUT ? phy_modtype_none : get_module_type(phy, v);
+}
+
static int ael1002_reset(struct cphy *phy, int wait)
{
int err;
@@ -119,6 +199,11 @@ static int ael1002_reset(struct cphy *phy, int wait)
(err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN,
0, 1 << 5)))
return err;
+
+ err = ael1002_get_module_type(phy, 300);
+ if (err >= 0)
+ phy->modtype = err;
+
return 0;
}
@@ -182,10 +267,17 @@ static struct cphy_ops ael1002_ops = {
int t3_ael1002_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
const struct mdio_ops *mdio_ops)
{
+ int err;
+
cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops,
SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
"10GBASE-R");
ael100x_txon(phy);
+
+ err = ael1002_get_module_type(phy, 0);
+ if (err >= 0)
+ phy->modtype = err;
+
return 0;
}
@@ -983,7 +1075,7 @@ static int ael2005_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
return -ETIMEDOUT;
}
-static int get_module_type(struct cphy *phy, int delay_ms)
+static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
{
int v;
unsigned int stat;
@@ -998,36 +1090,8 @@ static int get_module_type(struct cphy *phy, int delay_ms)
if (delay_ms)
msleep(delay_ms);
- /* see SFF-8472 for below */
- v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 3);
- if (v < 0)
- return v;
-
- if (v == 0x10)
- return phy_modtype_sr;
- if (v == 0x20)
- return phy_modtype_lr;
- if (v == 0x40)
- return phy_modtype_lrm;
-
- v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 6);
- if (v < 0)
- return v;
- if (v != 4)
- goto unknown;
-
- v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 10);
- if (v < 0)
- return v;
+ return get_module_type(phy, 0);
- if (v & 0x80) {
- v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
- if (v < 0)
- return v;
- return v > 10 ? phy_modtype_twinax_long : phy_modtype_twinax;
- }
-unknown:
- return phy_modtype_unknown;
}
static int ael2005_intr_enable(struct cphy *phy)
@@ -1084,7 +1148,7 @@ static int ael2005_reset(struct cphy *phy, int wait)
msleep(50);
- err = get_module_type(phy, 0);
+ err = ael2005_get_module_type(phy, 0);
if (err < 0)
return err;
phy->modtype = (u8)err;
@@ -1122,7 +1186,7 @@ static int ael2005_intr_handler(struct cphy *phy)
return ret;
/* modules have max 300 ms init time after hot plug */
- ret = get_module_type(phy, 300);
+ ret = ael2005_get_module_type(phy, 300);
if (ret < 0)
return ret;
@@ -1176,10 +1240,16 @@ static struct cphy_ops ael2005_ops = {
int t3_ael2005_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
const struct mdio_ops *mdio_ops)
{
+ int err;
cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops,
SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
SUPPORTED_IRQ, "10GBASE-R");
msleep(125);
+
+ err = ael2005_get_module_type(phy, 0);
+ if (err >= 0)
+ phy->modtype = err;
+
return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
1 << 5);
}
diff --git a/sys/dev/cxgb/cxgb_main.c b/sys/dev/cxgb/cxgb_main.c
index 2cbd801..90df817 100644
--- a/sys/dev/cxgb/cxgb_main.c
+++ b/sys/dev/cxgb/cxgb_main.c
@@ -90,6 +90,7 @@ static void cxgb_stop_locked(struct port_info *);
static void cxgb_set_rxmode(struct port_info *);
static int cxgb_ioctl(struct ifnet *, unsigned long, caddr_t);
static int cxgb_media_change(struct ifnet *);
+static int cxgb_ifm_type(int);
static void cxgb_media_status(struct ifnet *, struct ifmediareq *);
static int setup_sge_qsets(adapter_t *);
static void cxgb_async_intr(void *);
@@ -976,7 +977,7 @@ cxgb_port_attach(device_t dev)
} else if (!strcmp(p->phy.desc, "10GBASE-SR")) {
media_flags = IFM_ETHER | IFM_10G_SR | IFM_FDX;
} else if (!strcmp(p->phy.desc, "10GBASE-R")) {
- media_flags = IFM_ETHER | IFM_10G_LR | IFM_FDX;
+ media_flags = cxgb_ifm_type(p->phy.modtype);
} else if (!strcmp(p->phy.desc, "10/100/1000BASE-T")) {
ifmedia_add(&p->media, IFM_ETHER | IFM_10_T, 0, NULL);
ifmedia_add(&p->media, IFM_ETHER | IFM_10_T | IFM_FDX,
@@ -992,6 +993,9 @@ cxgb_port_attach(device_t dev)
/*
* XXX: This is not very accurate. Fix when common code
* returns more specific value - eg 1000BASE-SX, LX, etc.
+ *
+ * XXX: In the meantime, don't lie. Consider setting IFM_AUTO
+ * instead of SX.
*/
media_flags = IFM_ETHER | IFM_1000_SX | IFM_FDX;
} else {
@@ -999,7 +1003,13 @@ cxgb_port_attach(device_t dev)
return (ENXIO);
}
if (media_flags) {
- ifmedia_add(&p->media, media_flags, 0, NULL);
+ /*
+ * Note the modtype on which we based our flags. If modtype
+ * changes, we'll redo the ifmedia for this ifp. modtype may
+ * change when transceivers are plugged in/out, and in other
+ * situations.
+ */
+ ifmedia_add(&p->media, media_flags, p->phy.modtype, NULL);
ifmedia_set(&p->media, media_flags);
} else {
ifmedia_add(&p->media, IFM_ETHER | IFM_AUTO, 0, NULL);
@@ -1827,7 +1837,7 @@ cxgb_init_locked(struct port_info *p)
cxgb_link_start(p);
t3_link_changed(sc, p->port_id);
#endif
- ifp->if_baudrate = p->link_config.speed * 1000000;
+ ifp->if_baudrate = IF_Mbps(p->link_config.speed);
device_printf(sc->dev, "enabling interrupts on port=%d\n", p->port_id);
t3_port_intr_enable(sc, p->port_id);
@@ -1990,7 +2000,9 @@ cxgb_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data)
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
+ PORT_LOCK(p);
error = ifmedia_ioctl(ifp, ifr, &p->media, command);
+ PORT_UNLOCK(p);
break;
case SIOCSIFCAP:
PORT_LOCK(p);
@@ -2066,10 +2078,64 @@ cxgb_media_change(struct ifnet *ifp)
return (ENXIO);
}
+/*
+ * Translates from phy->modtype to IFM_TYPE.
+ */
+static int
+cxgb_ifm_type(int phymod)
+{
+ int rc = IFM_ETHER | IFM_FDX;
+
+ switch (phymod) {
+ case phy_modtype_sr:
+ rc |= IFM_10G_SR;
+ break;
+ case phy_modtype_lr:
+ rc |= IFM_10G_LR;
+ break;
+ case phy_modtype_lrm:
+#ifdef IFM_10G_LRM
+ rc |= IFM_10G_LRM;
+#endif
+ break;
+ case phy_modtype_twinax:
+#ifdef IFM_10G_TWINAX
+ rc |= IFM_10G_TWINAX;
+#endif
+ break;
+ case phy_modtype_twinax_long:
+#ifdef IFM_10G_TWINAX_LONG
+ rc |= IFM_10G_TWINAX_LONG;
+#endif
+ break;
+ case phy_modtype_none:
+ rc = IFM_ETHER | IFM_NONE;
+ break;
+ case phy_modtype_unknown:
+ break;
+ }
+
+ return (rc);
+}
+
static void
cxgb_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
{
struct port_info *p = ifp->if_softc;
+ struct ifmedia_entry *cur = p->media.ifm_cur;
+ int m;
+
+ if (cur->ifm_data != p->phy.modtype) {
+ /* p->media about to be rebuilt, must hold lock */
+ PORT_LOCK_ASSERT_OWNED(p);
+
+ m = cxgb_ifm_type(p->phy.modtype);
+ ifmedia_removeall(&p->media);
+ ifmedia_add(&p->media, m, p->phy.modtype, NULL);
+ ifmedia_set(&p->media, m);
+ cur = p->media.ifm_cur; /* ifmedia_set modified ifm_cur */
+ ifmr->ifm_current = m;
+ }
ifmr->ifm_status = IFM_AVALID;
ifmr->ifm_active = IFM_ETHER;
@@ -2089,6 +2155,9 @@ cxgb_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
case 1000:
ifmr->ifm_active |= IFM_1000_T;
break;
+ case 10000:
+ ifmr->ifm_active |= IFM_SUBTYPE(cur->ifm_media);
+ break;
}
if (p->link_config.duplex)
@@ -2140,7 +2209,7 @@ check_link_status(adapter_t *sc)
if (!(p->phy.caps & SUPPORTED_IRQ))
t3_link_changed(sc, i);
- p->ifp->if_baudrate = p->link_config.speed * 1000000;
+ p->ifp->if_baudrate = IF_Mbps(p->link_config.speed);
}
}
diff --git a/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c b/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
index 334f315..f11aaf0 100644
--- a/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
+++ b/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
@@ -3269,8 +3269,6 @@ syncache_add_accept_req(struct cpl_pass_accept_req *req, struct socket *lso, str
toep->tp_iss = toep->tp_delack_seq = toep->tp_rcv_wup = toep->tp_copied_seq = rcv_isn + 1;
-
- inc.inc_isipv6 = 0;
inc.inc_len = 0;
inc.inc_faddr.s_addr = req->peer_ip;
inc.inc_laddr.s_addr = req->local_ip;
@@ -3610,7 +3608,6 @@ syncache_expand_establish_req(struct cpl_pass_establish *req, struct socket **so
th.th_seq = req->rcv_isn;
th.th_flags = TH_ACK;
- inc.inc_isipv6 = 0;
inc.inc_len = 0;
inc.inc_faddr.s_addr = req->peer_ip;
inc.inc_laddr.s_addr = req->local_ip;
diff --git a/sys/dev/cxgb/ulp/tom/cxgb_l2t.c b/sys/dev/cxgb/ulp/tom/cxgb_l2t.c
index 67856e6..2484923 100644
--- a/sys/dev/cxgb/ulp/tom/cxgb_l2t.c
+++ b/sys/dev/cxgb/ulp/tom/cxgb_l2t.c
@@ -93,15 +93,15 @@ arp_hash(u32 key, int ifindex, const struct l2t_data *d)
}
static inline void
-neigh_replace(struct l2t_entry *e, struct rtentry *rt)
+neigh_replace(struct l2t_entry *e, struct llentry *neigh)
{
- RT_LOCK(rt);
- RT_ADDREF(rt);
- RT_UNLOCK(rt);
+ LLE_WLOCK(neigh);
+ LLE_ADDREF(neigh);
+ LLE_WUNLOCK(neigh);
if (e->neigh)
- RTFREE(e->neigh);
- e->neigh = rt;
+ LLE_FREE(e->neigh);
+ e->neigh = neigh;
}
/*
@@ -164,7 +164,7 @@ arpq_enqueue(struct l2t_entry *e, struct mbuf *m)
int
t3_l2t_send_slow(struct t3cdev *dev, struct mbuf *m, struct l2t_entry *e)
{
- struct rtentry *rt = e->neigh;
+ struct llentry *lle = e->neigh;
struct sockaddr_in sin;
bzero(&sin, sizeof(struct sockaddr_in));
@@ -177,7 +177,7 @@ again:
switch (e->state) {
case L2T_STATE_STALE: /* entry is stale, kick off revalidation */
arpresolve(rt->rt_ifp, rt, NULL,
- (struct sockaddr *)&sin, e->dmac);
+ (struct sockaddr *)&sin, e->dmac, &lle);
mtx_lock(&e->lock);
if (e->state == L2T_STATE_STALE)
e->state = L2T_STATE_VALID;
@@ -201,7 +201,7 @@ again:
* entries when there's no memory.
*/
if (arpresolve(rt->rt_ifp, rt, NULL,
- (struct sockaddr *)&sin, e->dmac) == 0) {
+ (struct sockaddr *)&sin, e->dmac, &lle) == 0) {
CTR6(KTR_CXGB, "mac=%x:%x:%x:%x:%x:%x\n",
e->dmac[0], e->dmac[1], e->dmac[2], e->dmac[3], e->dmac[4], e->dmac[5]);
@@ -222,12 +222,12 @@ again:
void
t3_l2t_send_event(struct t3cdev *dev, struct l2t_entry *e)
{
- struct rtentry *rt;
struct mbuf *m0;
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_addr.s_addr = e->addr;
+ struct llentry *lle;
if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
return;
@@ -237,7 +237,7 @@ again:
switch (e->state) {
case L2T_STATE_STALE: /* entry is stale, kick off revalidation */
arpresolve(rt->rt_ifp, rt, NULL,
- (struct sockaddr *)&sin, e->dmac);
+ (struct sockaddr *)&sin, e->dmac, &lle);
mtx_lock(&e->lock);
if (e->state == L2T_STATE_STALE) {
e->state = L2T_STATE_VALID;
@@ -263,7 +263,7 @@ again:
* entries when there's no memory.
*/
arpresolve(rt->rt_ifp, rt, NULL,
- (struct sockaddr *)&sin, e->dmac);
+ (struct sockaddr *)&sin, e->dmac, &lle);
}
return;
@@ -321,18 +321,18 @@ found:
void
t3_l2e_free(struct l2t_data *d, struct l2t_entry *e)
{
- struct rtentry *rt = NULL;
-
+ struct llentry *lle;
+
mtx_lock(&e->lock);
if (atomic_load_acq_int(&e->refcnt) == 0) { /* hasn't been recycled */
- rt = e->neigh;
+ lle = e->neigh;
e->neigh = NULL;
}
mtx_unlock(&e->lock);
atomic_add_int(&d->nfree, 1);
- if (rt)
- RTFREE(rt);
+ if (lle)
+ LLE_FREE(lle);
}
@@ -341,11 +341,8 @@ t3_l2e_free(struct l2t_data *d, struct l2t_entry *e)
* Must be called with softirqs disabled.
*/
static inline void
-reuse_entry(struct l2t_entry *e, struct rtentry *neigh)
+reuse_entry(struct l2t_entry *e, struct llentry *neigh)
{
- struct llinfo_arp *la;
-
- la = (struct llinfo_arp *)neigh->rt_llinfo;
mtx_lock(&e->lock); /* avoid race with t3_l2t_free */
if (neigh != e->neigh)
@@ -362,13 +359,13 @@ reuse_entry(struct l2t_entry *e, struct rtentry *neigh)
}
struct l2t_entry *
-t3_l2t_get(struct t3cdev *dev, struct rtentry *neigh, struct ifnet *ifp,
+t3_l2t_get(struct t3cdev *dev, struct llentry *neigh, struct ifnet *ifp,
struct sockaddr *sa)
{
struct l2t_entry *e;
struct l2t_data *d = L2DATA(dev);
u32 addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
- int ifidx = neigh->rt_ifp->if_index;
+ int ifidx = ifp->if_index;
int hash = arp_hash(addr, ifidx, d);
unsigned int smt_idx = ((struct port_info *)ifp->if_softc)->port_id;
@@ -448,20 +445,19 @@ handle_failed_resolution(struct t3cdev *dev, struct mbuf *arpq)
}
void
-t3_l2t_update(struct t3cdev *dev, struct rtentry *neigh,
+t3_l2t_update(struct t3cdev *dev, struct llentry *neigh,
uint8_t *enaddr, struct sockaddr *sa)
{
struct l2t_entry *e;
struct mbuf *arpq = NULL;
struct l2t_data *d = L2DATA(dev);
u32 addr = *(u32 *) &((struct sockaddr_in *)sa)->sin_addr;
- int ifidx = neigh->rt_ifp->if_index;
int hash = arp_hash(addr, ifidx, d);
struct llinfo_arp *la;
rw_rlock(&d->lock);
for (e = d->l2tab[hash].first; e; e = e->next)
- if (e->addr == addr && e->ifindex == ifidx) {
+ if (e->addr == addr) {
mtx_lock(&e->lock);
goto found;
}
diff --git a/sys/dev/cxgb/ulp/tom/cxgb_l2t.h b/sys/dev/cxgb/ulp/tom/cxgb_l2t.h
index 1d547d3..308ba66 100644
--- a/sys/dev/cxgb/ulp/tom/cxgb_l2t.h
+++ b/sys/dev/cxgb/ulp/tom/cxgb_l2t.h
@@ -68,7 +68,7 @@ struct l2t_entry {
int ifindex; /* neighbor's net_device's ifindex */
uint16_t smt_idx; /* SMT index */
uint16_t vlan; /* VLAN TCI (id: bits 0-11, prio: 13-15 */
- struct rtentry *neigh; /* associated neighbour */
+ struct llentry *neigh; /* associated neighbour */
struct l2t_entry *first; /* start of hash chain */
struct l2t_entry *next; /* next l2t_entry on chain */
struct mbuf *arpq_head; /* queue of packets awaiting resolution */
diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h
index eb91214..25a3fa8 100644
--- a/sys/dev/drm/drmP.h
+++ b/sys/dev/drm/drmP.h
@@ -87,6 +87,7 @@ struct drm_file;
#include <sys/agpio.h>
#include <sys/mutex.h>
#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
#include <sys/selinfo.h>
#include <sys/bus.h>
@@ -211,15 +212,6 @@ enum {
#define DRM_MTRR_WC MDF_WRITECOMBINE
#define jiffies ticks
-/* Capabilities taken from src/sys/dev/pci/pcireg.h. */
-#ifndef PCIY_AGP
-#define PCIY_AGP 0x02
-#endif
-
-#ifndef PCIY_EXPRESS
-#define PCIY_EXPRESS 0x10
-#endif
-
typedef unsigned long dma_addr_t;
typedef u_int64_t u64;
typedef u_int32_t u32;
@@ -473,11 +465,13 @@ typedef struct drm_agp_head {
} drm_agp_head_t;
typedef struct drm_sg_mem {
- unsigned long handle;
- void *virtual;
- int pages;
- dma_addr_t *busaddr;
- drm_dma_handle_t *dmah; /* Handle to PCI memory for ATI PCIGART table */
+ unsigned long handle;
+ void *virtual;
+ int pages;
+ dma_addr_t *busaddr;
+ struct drm_dma_handle *sg_dmah; /* Handle for sg_pages */
+ struct drm_dma_handle *dmah; /* Handle to PCI memory */
+ /* for ATI PCIGART table */
} drm_sg_mem_t;
typedef TAILQ_HEAD(drm_map_list, drm_local_map) drm_map_list_t;
diff --git a/sys/dev/drm/drm_drv.c b/sys/dev/drm/drm_drv.c
index 8a0cdf4..63be19b 100644
--- a/sys/dev/drm/drm_drv.c
+++ b/sys/dev/drm/drm_drv.c
@@ -152,6 +152,10 @@ int drm_probe(device_t dev, drm_pci_id_list_t *idlist)
device = pci_get_device(dev);
#endif
+ if (pci_get_class(dev) != PCIC_DISPLAY
+ || pci_get_subclass(dev) != PCIS_DISPLAY_VGA)
+ return ENXIO;
+
id_entry = drm_find_description(vendor, device, idlist);
if (id_entry != NULL) {
device_set_desc(dev, id_entry->name);
diff --git a/sys/dev/drm/drm_scatter.c b/sys/dev/drm/drm_scatter.c
index c94976a..bf0cbeb 100644
--- a/sys/dev/drm/drm_scatter.c
+++ b/sys/dev/drm/drm_scatter.c
@@ -39,20 +39,16 @@ __FBSDID("$FreeBSD$");
#include "dev/drm/drmP.h"
-#define DEBUG_SCATTER 0
+static void drm_sg_alloc_cb(void *arg, bus_dma_segment_t *segs,
+ int nsegs, int error);
-void drm_sg_cleanup(drm_sg_mem_t *entry)
+int
+drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather *request)
{
- free((void *)entry->handle, DRM_MEM_PAGES);
- free(entry->busaddr, DRM_MEM_PAGES);
- free(entry, DRM_MEM_SGLISTS);
-}
-
-int drm_sg_alloc(struct drm_device * dev, struct drm_scatter_gather * request)
-{
- drm_sg_mem_t *entry;
+ struct drm_sg_mem *entry;
+ struct drm_dma_handle *dmah;
unsigned long pages;
- int i;
+ int ret;
if (dev->sg)
return EINVAL;
@@ -69,21 +65,56 @@ int drm_sg_alloc(struct drm_device * dev, struct drm_scatter_gather * request)
entry->busaddr = malloc(pages * sizeof(*entry->busaddr), DRM_MEM_PAGES,
M_WAITOK | M_ZERO);
if (!entry->busaddr) {
- drm_sg_cleanup(entry);
+ free(entry, DRM_MEM_SGLISTS);
return ENOMEM;
}
- entry->handle = (long)malloc(pages << PAGE_SHIFT, DRM_MEM_PAGES,
- M_WAITOK | M_ZERO);
- if (entry->handle == 0) {
- drm_sg_cleanup(entry);
+ dmah = malloc(sizeof(struct drm_dma_handle), DRM_MEM_DMA,
+ M_ZERO | M_NOWAIT);
+ if (dmah == NULL) {
+ free(entry->busaddr, DRM_MEM_PAGES);
+ free(entry, DRM_MEM_SGLISTS);
+ return ENOMEM;
+ }
+
+ ret = bus_dma_tag_create(NULL, PAGE_SIZE, 0, /* tag, align, boundary */
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, /* lowaddr, highaddr */
+ NULL, NULL, /* filtfunc, filtfuncargs */
+ request->size, pages, /* maxsize, nsegs */
+ PAGE_SIZE, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockfuncargs */
+ &dmah->tag);
+ if (ret != 0) {
+ free(dmah, DRM_MEM_DMA);
+ free(entry->busaddr, DRM_MEM_PAGES);
+ free(entry, DRM_MEM_SGLISTS);
return ENOMEM;
}
- for (i = 0; i < pages; i++) {
- entry->busaddr[i] = vtophys(entry->handle + i * PAGE_SIZE);
+ ret = bus_dmamem_alloc(dmah->tag, &dmah->vaddr,
+ BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_NOCACHE, &dmah->map);
+ if (ret != 0) {
+ bus_dma_tag_destroy(dmah->tag);
+ free(dmah, DRM_MEM_DMA);
+ free(entry->busaddr, DRM_MEM_PAGES);
+ free(entry, DRM_MEM_SGLISTS);
+ return ENOMEM;
}
+ ret = bus_dmamap_load(dmah->tag, dmah->map, dmah->vaddr,
+ request->size, drm_sg_alloc_cb, entry, 0);
+ if (ret != 0) {
+ bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
+ bus_dma_tag_destroy(dmah->tag);
+ free(dmah, DRM_MEM_DMA);
+ free(entry->busaddr, DRM_MEM_PAGES);
+ free(entry, DRM_MEM_SGLISTS);
+ return ENOMEM;
+ }
+
+ entry->sg_dmah = dmah;
+ entry->handle = (unsigned long)dmah->vaddr;
+
DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle);
entry->virtual = (void *)entry->handle;
@@ -101,22 +132,49 @@ int drm_sg_alloc(struct drm_device * dev, struct drm_scatter_gather * request)
return 0;
}
-int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+static void
+drm_sg_alloc_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct drm_sg_mem *entry = arg;
+ int i;
+
+ if (error != 0)
+ return;
+
+ for(i = 0 ; i < nsegs ; i++) {
+ entry->busaddr[i] = segs[i].ds_addr;
+ }
+}
+
+int
+drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_scatter_gather *request = data;
- int ret;
- DRM_DEBUG("%s\n", __FUNCTION__);
+ DRM_DEBUG("\n");
+
+ return drm_sg_alloc(dev, request);
+}
- ret = drm_sg_alloc(dev, request);
- return ret;
+void
+drm_sg_cleanup(struct drm_sg_mem *entry)
+{
+ struct drm_dma_handle *dmah = entry->sg_dmah;
+
+ bus_dmamap_unload(dmah->tag, dmah->map);
+ bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
+ bus_dma_tag_destroy(dmah->tag);
+ free(dmah, DRM_MEM_DMA);
+ free(entry->busaddr, DRM_MEM_PAGES);
+ free(entry, DRM_MEM_SGLISTS);
}
-int drm_sg_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int
+drm_sg_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
struct drm_scatter_gather *request = data;
- drm_sg_mem_t *entry;
+ struct drm_sg_mem *entry;
DRM_LOCK();
entry = dev->sg;
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index f79282e..9a6851c 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -1540,8 +1540,8 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head)
* the chip is an 82550/82551 or not.
*/
if (sc->flags & FXP_FLAG_EXT_RFA) {
- cbp->tbd[i + 2].tb_addr = htole32(segs[i].ds_addr);
- cbp->tbd[i + 2].tb_size = htole32(segs[i].ds_len);
+ cbp->tbd[i + 1].tb_addr = htole32(segs[i].ds_addr);
+ cbp->tbd[i + 1].tb_size = htole32(segs[i].ds_len);
} else {
cbp->tbd[i].tb_addr = htole32(segs[i].ds_addr);
cbp->tbd[i].tb_size = htole32(segs[i].ds_len);
@@ -1550,13 +1550,13 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head)
if (sc->flags & FXP_FLAG_EXT_RFA) {
/* Configure dynamic TBD for 82550/82551. */
cbp->tbd_number = 0xFF;
- cbp->tbd[nseg + 1].tb_size |= htole32(0x8000);
+ cbp->tbd[nseg].tb_size |= htole32(0x8000);
} else
cbp->tbd_number = nseg;
/* Configure TSO. */
if (m->m_pkthdr.csum_flags & CSUM_TSO) {
cbp->tbd[-1].tb_size = htole32(m->m_pkthdr.tso_segsz << 16);
- cbp->tbd[1].tb_size = htole32(tcp_payload << 16);
+ cbp->tbd[1].tb_size |= htole32(tcp_payload << 16);
cbp->ipcb_ip_schedule |= FXP_IPCB_LARGESEND_ENABLE |
FXP_IPCB_IP_CHECKSUM_ENABLE |
FXP_IPCB_TCP_PACKET |
diff --git a/sys/dev/hwpmc/hwpmc_core.c b/sys/dev/hwpmc/hwpmc_core.c
index c34a969..8d17679 100644
--- a/sys/dev/hwpmc/hwpmc_core.c
+++ b/sys/dev/hwpmc/hwpmc_core.c
@@ -1491,17 +1491,18 @@ core_intr(int cpu, struct trapframe *tf)
PMCDBG(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", cpu, (void *) tf,
TRAPF_USERMODE(tf));
+ found_interrupt = 0;
cc = core_pcpu[cpu];
for (ri = 0; ri < core_iap_npmc; ri++) {
- if (!iap_pmc_has_overflowed(ri))
- continue;
-
if ((pm = cc->pc_corepmcs[ri].phw_pmc) == NULL ||
!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
continue;
+ if (!iap_pmc_has_overflowed(ri))
+ continue;
+
found_interrupt = 1;
if (pm->pm_state != PMC_STATE_RUNNING)
@@ -1560,7 +1561,9 @@ core2_intr(int cpu, struct trapframe *tf)
PMCDBG(MDP,INT, 1, "cpu=%d intrstatus=%jx", cpu,
(uintmax_t) intrstatus);
+ found_interrupt = 0;
cc = core_pcpu[cpu];
+
KASSERT(cc != NULL, ("[core,%d] null pcpu", __LINE__));
cc->pc_globalctrl &= ~intrenable;
@@ -1574,7 +1577,6 @@ core2_intr(int cpu, struct trapframe *tf)
IA_GLOBAL_STATUS_FLAG_OVFBUF |
IA_GLOBAL_STATUS_FLAG_CONDCHG);
-
/*
* Look for interrupts from fixed function PMCs.
*/
@@ -1634,9 +1636,6 @@ core2_intr(int cpu, struct trapframe *tf)
wrmsr(IAP_PMC0 + n, v);
}
- KASSERT(found_interrupt,
- ("[core,%d] no interrupting PMCs were found", __LINE__));
-
/*
* Reenable all non-stalled PMCs.
*/
diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c
index cef1453..6612203 100644
--- a/sys/dev/hwpmc/hwpmc_logging.c
+++ b/sys/dev/hwpmc/hwpmc_logging.c
@@ -199,7 +199,7 @@ pmclog_get_buffer(struct pmc_owner *po)
mtx_assert(&po->po_mtx, MA_OWNED);
KASSERT(po->po_curbuf == NULL,
- ("[pmc,%d] po=%p current buffer still valid", __LINE__, po));
+ ("[pmclog,%d] po=%p current buffer still valid", __LINE__, po));
mtx_lock_spin(&pmc_bufferlist_mtx);
if ((plb = TAILQ_FIRST(&pmc_bufferlist)) != NULL)
@@ -212,7 +212,7 @@ pmclog_get_buffer(struct pmc_owner *po)
if (plb)
KASSERT(plb->plb_ptr == plb->plb_base &&
plb->plb_base < plb->plb_fence,
- ("[pmc,%d] po=%p buffer invariants: ptr=%p "
+ ("[pmclog,%d] po=%p buffer invariants: ptr=%p "
"base=%p fence=%p", __LINE__, po, plb->plb_ptr,
plb->plb_base, plb->plb_fence));
#endif
@@ -224,7 +224,7 @@ pmclog_get_buffer(struct pmc_owner *po)
if (plb == NULL)
atomic_add_int(&pmc_stats.pm_buffer_requests_failed, 1);
- return plb ? 0 : ENOMEM;
+ return (plb ? 0 : ENOMEM);
}
/*
@@ -256,7 +256,7 @@ pmclog_loop(void *arg)
PMCDBG(LOG,INI,1, "po=%p kt=%p", po, po->po_kthread);
KASSERT(po->po_kthread == curthread->td_proc,
- ("[pmc,%d] proc mismatch po=%p po/kt=%p curproc=%p", __LINE__,
+ ("[pmclog,%d] proc mismatch po=%p po/kt=%p curproc=%p", __LINE__,
po, po->po_kthread, curthread->td_proc));
lb = NULL;
@@ -381,10 +381,10 @@ static void
pmclog_release(struct pmc_owner *po)
{
KASSERT(po->po_curbuf->plb_ptr >= po->po_curbuf->plb_base,
- ("[pmc,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__,
+ ("[pmclog,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__,
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_base));
KASSERT(po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence,
- ("[pmc,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__,
+ ("[pmclog,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__,
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_fence));
/* schedule an I/O if we've filled a buffer */
@@ -423,15 +423,15 @@ pmclog_reserve(struct pmc_owner *po, int length)
if (po->po_curbuf == NULL)
if (pmclog_get_buffer(po) != 0) {
mtx_unlock_spin(&po->po_mtx);
- return NULL;
+ return (NULL);
}
KASSERT(po->po_curbuf != NULL,
- ("[pmc,%d] po=%p no current buffer", __LINE__, po));
+ ("[pmclog,%d] po=%p no current buffer", __LINE__, po));
KASSERT(po->po_curbuf->plb_ptr >= po->po_curbuf->plb_base &&
po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence,
- ("[pmc,%d] po=%p buffer invariants: ptr=%p base=%p fence=%p",
+ ("[pmclog,%d] po=%p buffer invariants: ptr=%p base=%p fence=%p",
__LINE__, po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_base,
po->po_curbuf->plb_fence));
@@ -439,7 +439,7 @@ pmclog_reserve(struct pmc_owner *po, int length)
newptr = oldptr + length;
KASSERT(oldptr != (uintptr_t) NULL,
- ("[pmc,%d] po=%p Null log buffer pointer", __LINE__, po));
+ ("[pmclog,%d] po=%p Null log buffer pointer", __LINE__, po));
/*
* If we have space in the current buffer, return a pointer to
@@ -458,18 +458,18 @@ pmclog_reserve(struct pmc_owner *po, int length)
if (pmclog_get_buffer(po) != 0) {
mtx_unlock_spin(&po->po_mtx);
- return NULL;
+ return (NULL);
}
KASSERT(po->po_curbuf != NULL,
- ("[pmc,%d] po=%p no current buffer", __LINE__, po));
+ ("[pmclog,%d] po=%p no current buffer", __LINE__, po));
KASSERT(po->po_curbuf->plb_ptr != NULL,
- ("[pmc,%d] null return from pmc_get_log_buffer", __LINE__));
+ ("[pmclog,%d] null return from pmc_get_log_buffer", __LINE__));
KASSERT(po->po_curbuf->plb_ptr == po->po_curbuf->plb_base &&
po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence,
- ("[pmc,%d] po=%p buffer invariants: ptr=%p base=%p fence=%p",
+ ("[pmclog,%d] po=%p buffer invariants: ptr=%p base=%p fence=%p",
__LINE__, po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_base,
po->po_curbuf->plb_fence));
@@ -481,7 +481,7 @@ pmclog_reserve(struct pmc_owner *po, int length)
getnanotime(&ts); /* fill in the timestamp */
*lh++ = ts.tv_sec & 0xFFFFFFFF;
*lh++ = ts.tv_nsec & 0xFFFFFFF;
- return (uint32_t *) oldptr;
+ return ((uint32_t *) oldptr);
}
/*
@@ -494,13 +494,13 @@ static void
pmclog_schedule_io(struct pmc_owner *po)
{
KASSERT(po->po_curbuf != NULL,
- ("[pmc,%d] schedule_io with null buffer po=%p", __LINE__, po));
+ ("[pmclog,%d] schedule_io with null buffer po=%p", __LINE__, po));
KASSERT(po->po_curbuf->plb_ptr >= po->po_curbuf->plb_base,
- ("[pmc,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__,
+ ("[pmclog,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__,
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_base));
KASSERT(po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence,
- ("[pmc,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__,
+ ("[pmclog,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__,
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_fence));
PMCDBG(LOG,SIO, 1, "po=%p", po);
@@ -558,13 +558,13 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
/* return EBUSY if a log file was already present */
if (po->po_flags & PMC_PO_OWNS_LOGFILE)
- return EBUSY;
+ return (EBUSY);
KASSERT(po->po_kthread == NULL,
- ("[pmc,%d] po=%p kthread (%p) already present", __LINE__, po,
+ ("[pmclog,%d] po=%p kthread (%p) already present", __LINE__, po,
po->po_kthread));
KASSERT(po->po_file == NULL,
- ("[pmc,%d] po=%p file (%p) already present", __LINE__, po,
+ ("[pmclog,%d] po=%p file (%p) already present", __LINE__, po,
po->po_file));
/* get a reference to the file state */
@@ -591,7 +591,7 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
PMCLOG_EMIT32(md->pmd_cputype);
PMCLOG_DESPATCH(po);
- return 0;
+ return (0);
error:
/* shutdown the thread */
@@ -600,15 +600,15 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
pmclog_stop_kthread(po);
mtx_unlock(&pmc_kthread_mtx);
- KASSERT(po->po_kthread == NULL, ("[pmc,%d] po=%p kthread not stopped",
- __LINE__, po));
+ KASSERT(po->po_kthread == NULL, ("[pmclog,%d] po=%p kthread not "
+ "stopped", __LINE__, po));
if (po->po_file)
(void) fdrop(po->po_file, curthread);
po->po_file = NULL; /* clear file and error state */
po->po_error = 0;
- return error;
+ return (error);
}
@@ -626,12 +626,12 @@ pmclog_deconfigure_log(struct pmc_owner *po)
PMCDBG(LOG,CFG,1, "de-config po=%p", po);
if ((po->po_flags & PMC_PO_OWNS_LOGFILE) == 0)
- return EINVAL;
+ return (EINVAL);
KASSERT(po->po_sscount == 0,
- ("[pmc,%d] po=%p still owning SS PMCs", __LINE__, po));
+ ("[pmclog,%d] po=%p still owning SS PMCs", __LINE__, po));
KASSERT(po->po_file != NULL,
- ("[pmc,%d] po=%p no log file", __LINE__, po));
+ ("[pmclog,%d] po=%p no log file", __LINE__, po));
/* stop the kthread, this will reset the 'OWNS_LOGFILE' flag */
mtx_lock(&pmc_kthread_mtx);
@@ -640,7 +640,7 @@ pmclog_deconfigure_log(struct pmc_owner *po)
mtx_unlock(&pmc_kthread_mtx);
KASSERT(po->po_kthread == NULL,
- ("[pmc,%d] po=%p kthread not stopped", __LINE__, po));
+ ("[pmclog,%d] po=%p kthread not stopped", __LINE__, po));
/* return all queued log buffers to the global pool */
while ((lb = TAILQ_FIRST(&po->po_logbuffers)) != NULL) {
@@ -664,7 +664,7 @@ pmclog_deconfigure_log(struct pmc_owner *po)
po->po_file = NULL;
po->po_error = 0;
- return error;
+ return (error);
}
/*
@@ -683,7 +683,7 @@ pmclog_flush(struct pmc_owner *po)
* return that.
*/
if (po->po_error)
- return po->po_error;
+ return (po->po_error);
error = 0;
@@ -709,12 +709,14 @@ pmclog_flush(struct pmc_owner *po)
po->po_flags |= PMC_PO_IN_FLUSH; /* ask for a wakeup */
error = msleep(po->po_kthread, &pmc_kthread_mtx, PWAIT,
"pmcflush", 0);
+ if (error == 0)
+ error = po->po_error;
}
error:
mtx_unlock(&pmc_kthread_mtx);
- return error;
+ return (error);
}
@@ -948,7 +950,7 @@ pmclog_process_userlog(struct pmc_owner *po, struct pmc_op_writelog *wl)
PMCLOG_DESPATCH(po);
error:
- return error;
+ return (error);
}
/*
@@ -964,8 +966,8 @@ pmclog_initialize()
struct pmclog_buffer *plb;
if (pmclog_buffer_size <= 0) {
- (void) printf("hwpmc: tunable logbuffersize=%d must be greater "
- "than zero.\n", pmclog_buffer_size);
+ (void) printf("hwpmc: tunable logbuffersize=%d must be "
+ "greater than zero.\n", pmclog_buffer_size);
pmclog_buffer_size = PMC_LOG_BUFFER_SIZE;
}
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index a38921f..c239a69 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -1863,8 +1863,11 @@ pmc_hook_handler(struct thread *td, int function, void *arg)
/*
* Record a call chain.
*/
+ KASSERT(td == curthread, ("[pmc,%d] td != curthread",
+ __LINE__));
pmc_capture_user_callchain(PCPU_GET(cpuid),
(struct trapframe *) arg);
+ td->td_pflags &= ~TDP_CALLCHAIN;
break;
default:
@@ -3794,30 +3797,28 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
*/
static void
-pmc_post_callchain_ast(void)
+pmc_post_callchain_callback(void)
{
struct thread *td;
td = curthread;
+ KASSERT((td->td_pflags & TDP_CALLCHAIN) == 0,
+ ("[pmc,%d] thread %p already marked for callchain capture",
+ __LINE__, (void *) td));
+
/*
- * Mark this thread as needing processing in ast().
- * td->td_pflags will be safe to touch as the process was in
- * user space when it was interrupted.
+ * Mark this thread as needing callchain capture.
+ * `td->td_pflags' will be safe to touch because this thread
+ * was in user space when it was interrupted.
*/
td->td_pflags |= TDP_CALLCHAIN;
/*
- * Again, since we've entered this function directly from
- * userland, `td' is guaranteed to be not locked by this CPU,
- * so its safe to try acquire the thread lock even though we
- * are executing in an NMI context. We need to acquire this
- * lock before touching `td_flags' because other CPUs may be
- * in the process of touching this field.
+ * Don't let this thread migrate between CPUs until callchain
+ * capture completes.
*/
- thread_lock(td);
- td->td_flags |= TDF_ASTPENDING;
- thread_unlock(td);
+ sched_pin();
return;
}
@@ -3869,6 +3870,10 @@ pmc_process_interrupt(int cpu, struct pmc *pm, struct trapframe *tf,
(int) (psb->ps_write - psb->ps_samples),
(int) (psb->ps_read - psb->ps_samples));
+ KASSERT(pm->pm_runcount >= 0,
+ ("[pmc,%d] pm=%p runcount %d", __LINE__, (void *) pm,
+ pm->pm_runcount));
+
atomic_add_rel_32(&pm->pm_runcount, 1); /* hold onto PMC */
ps->ps_pmc = pm;
if ((td = curthread) && td->td_proc)
@@ -3876,6 +3881,7 @@ pmc_process_interrupt(int cpu, struct pmc *pm, struct trapframe *tf,
else
ps->ps_pid = -1;
ps->ps_cpu = cpu;
+ ps->ps_td = td;
ps->ps_flags = inuserspace ? PMC_CC_F_USERSPACE : 0;
callchaindepth = (pm->pm_flags & PMC_F_CALLCHAIN) ?
@@ -3893,7 +3899,7 @@ pmc_process_interrupt(int cpu, struct pmc *pm, struct trapframe *tf,
pmc_save_kernel_callchain(ps->ps_pc,
callchaindepth, tf);
else {
- pmc_post_callchain_ast();
+ pmc_post_callchain_callback();
callchaindepth = PMC_SAMPLE_INUSE;
}
}
@@ -3925,20 +3931,41 @@ pmc_capture_user_callchain(int cpu, struct trapframe *tf)
{
int i;
struct pmc *pm;
+ struct thread *td;
struct pmc_sample *ps;
struct pmc_samplebuffer *psb;
+#ifdef INVARIANTS
+ int ncallchains;
+#endif
+
+ sched_unpin(); /* Can migrate safely now. */
psb = pmc_pcpu[cpu]->pc_sb;
+ td = curthread;
+
+ KASSERT(td->td_pflags & TDP_CALLCHAIN,
+ ("[pmc,%d] Retrieving callchain for thread that doesn't want it",
+ __LINE__));
+
+#ifdef INVARIANTS
+ ncallchains = 0;
+#endif
/*
* Iterate through all deferred callchain requests.
*/
- for (i = 0; i < pmc_nsamples; i++) {
+ ps = psb->ps_samples;
+ for (i = 0; i < pmc_nsamples; i++, ps++) {
- ps = &psb->ps_samples[i];
if (ps->ps_nsamples != PMC_SAMPLE_INUSE)
continue;
+ if (ps->ps_td != td)
+ continue;
+
+ KASSERT(ps->ps_cpu == cpu,
+ ("[pmc,%d] cpu mismatch ps_cpu=%d pcpu=%d", __LINE__,
+ ps->ps_cpu, PCPU_GET(cpuid)));
pm = ps->ps_pmc;
@@ -3946,14 +3973,26 @@ pmc_capture_user_callchain(int cpu, struct trapframe *tf)
("[pmc,%d] Retrieving callchain for PMC that doesn't "
"want it", __LINE__));
+ KASSERT(pm->pm_runcount > 0,
+ ("[pmc,%d] runcount %d", __LINE__, pm->pm_runcount));
+
/*
* Retrieve the callchain and mark the sample buffer
* as 'processable' by the timer tick sweep code.
*/
ps->ps_nsamples = pmc_save_user_callchain(ps->ps_pc,
pmc_callchaindepth, tf);
+
+#ifdef INVARIANTS
+ ncallchains++;
+#endif
+
}
+ KASSERT(ncallchains > 0,
+ ("[pmc,%d] cpu %d didn't find a sample to collect", __LINE__,
+ cpu));
+
return;
}
@@ -3991,6 +4030,11 @@ pmc_process_samples(int cpu)
}
pm = ps->ps_pmc;
+
+ KASSERT(pm->pm_runcount > 0,
+ ("[pmc,%d] pm=%p runcount %d", __LINE__, (void *) pm,
+ pm->pm_runcount));
+
po = pm->pm_owner;
KASSERT(PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)),
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index e22b7bf..1ad4e91 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -335,6 +335,23 @@ isp_reset(ispsoftc_t *isp)
/*
* XXX: Should probably do some bus sensing.
*/
+ } else if (IS_ULTRA3(isp)) {
+ sdparam *sdp = isp->isp_param;
+
+ isp->isp_clock = 100;
+
+ if (IS_10160(isp))
+ btype = "10160";
+ else if (IS_12160(isp))
+ btype = "12160";
+ else
+ btype = "<UNKLVD>";
+ sdp->isp_lvdmode = 1;
+
+ if (IS_DUALBUS(isp)) {
+ sdp++;
+ sdp->isp_lvdmode = 1;
+ }
} else if (IS_ULTRA2(isp)) {
static const char m[] = "bus %d is in %s Mode";
uint16_t l;
@@ -346,10 +363,6 @@ isp_reset(ispsoftc_t *isp)
btype = "1280";
else if (IS_1080(isp))
btype = "1080";
- else if (IS_10160(isp))
- btype = "10160";
- else if (IS_12160(isp))
- btype = "12160";
else
btype = "<UNKLVD>";
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c
index f4230a2..bb9e64b 100644
--- a/sys/dev/md/md.c
+++ b/sys/dev/md/md.c
@@ -374,8 +374,11 @@ g_md_access(struct g_provider *pp, int r, int w, int e)
struct md_s *sc;
sc = pp->geom->softc;
- if (sc == NULL)
+ if (sc == NULL) {
+ if (r <= 0 && w <= 0 && e <= 0)
+ return (0);
return (ENXIO);
+ }
r += pp->acr;
w += pp->acw;
e += pp->ace;
diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c
index a2af0ba..7cdb304 100644
--- a/sys/dev/mfi/mfi.c
+++ b/sys/dev/mfi/mfi.c
@@ -296,7 +296,8 @@ mfi_attach(struct mfi_softc *sc)
uint32_t status;
int error, commsz, framessz, sensesz;
int frames, unit, max_fw_sge;
- device_printf(sc->mfi_dev, "Megaraid SAS driver Ver 2.00 \n");
+
+ device_printf(sc->mfi_dev, "Megaraid SAS driver Ver 3.00 \n");
mtx_init(&sc->mfi_io_lock, "MFI I/O lock", NULL, MTX_DEF);
sx_init(&sc->mfi_config_lock, "MFI config");
diff --git a/sys/dev/mfi/mfi_pci.c b/sys/dev/mfi/mfi_pci.c
index 902dce5..5f0b341 100644
--- a/sys/dev/mfi/mfi_pci.c
+++ b/sys/dev/mfi/mfi_pci.c
@@ -123,7 +123,7 @@ struct mfi_ident {
{0x1000, 0x0079, 0x1028, 0x1f18, MFI_FLAGS_GEN2, "Dell PERC H700 Modular"},
{0x1000, 0x0079, 0x1028, 0x1f19, MFI_FLAGS_GEN2, "Dell PERC H700"},
{0x1000, 0x0079, 0x1028, 0x1f1b, MFI_FLAGS_GEN2, "Dell PERC H800"},
- {0x1000, 0x0079, 0x1028, 0xffff, MFI_FLAGS_GEN2, "Dell PERC H700/H800"},
+ {0x1000, 0x0079, 0x1028, 0xffff, MFI_FLAGS_GEN2, "Dell PERC Gen2"},
{0x1000, 0x0079, 0xffff, 0xffff, MFI_FLAGS_GEN2, "LSI MegaSAS Gen2"},
{0x1000, 0x007c, 0xffff, 0xffff, MFI_FLAGS_1078, "LSI MegaSAS 1078"},
{0x1000, 0x0411, 0xffff, 0xffff, MFI_FLAGS_1064R, "LSI MegaSAS 1064R"}, /* Brocton IOP */
diff --git a/sys/dev/nfe/if_nfe.c b/sys/dev/nfe/if_nfe.c
index 7a36a2e..e5a5294 100644
--- a/sys/dev/nfe/if_nfe.c
+++ b/sys/dev/nfe/if_nfe.c
@@ -3080,7 +3080,7 @@ nfe_sysctl_node(struct nfe_softc *sc)
&stats->rx_unicast, "Unicast Frames");
NFE_SYSCTL_STAT_ADD32(ctx, child, "multicast",
&stats->rx_multicast, "Multicast Frames");
- NFE_SYSCTL_STAT_ADD32(ctx, child, "brocadcast",
+ NFE_SYSCTL_STAT_ADD32(ctx, child, "broadcast",
&stats->rx_broadcast, "Broadcast Frames");
if ((sc->nfe_flags & NFE_MIB_V2) != 0) {
NFE_SYSCTL_STAT_ADD64(ctx, child, "octets",
diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c
index 7a394c1..19de2b97 100644
--- a/sys/dev/ofw/ofw_bus_subr.c
+++ b/sys/dev/ofw/ofw_bus_subr.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>.
* Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org>
* All rights reserved.
*
@@ -33,7 +34,9 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/errno.h>
+#include <sys/libkern.h>
+#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/openfirm.h>
@@ -71,6 +74,22 @@ ofw_bus_gen_destroy_devinfo(struct ofw_bus_devinfo *obd)
free(obd->obd_type, M_OFWPROP);
}
+int
+ofw_bus_gen_child_pnpinfo_str(device_t cbdev, device_t child, char *buf,
+ size_t buflen)
+{
+ if (ofw_bus_get_name(child) != NULL) {
+ strlcat(buf, "name=", buflen);
+ strlcat(buf, ofw_bus_get_name(child), buflen);
+ }
+
+ if (ofw_bus_get_compat(child) != NULL) {
+ strlcat(buf, " compat=", buflen);
+ strlcat(buf, ofw_bus_get_compat(child), buflen);
+ }
+
+ return (0);
+};
const char *
ofw_bus_gen_get_compat(device_t bus, device_t dev)
@@ -126,3 +145,135 @@ ofw_bus_gen_get_type(device_t bus, device_t dev)
return (NULL);
return (obd->obd_type);
}
+
+static int
+ofw_bus_searchprop(phandle_t node, char *propname, void *buf, int buflen)
+{
+ int rv;
+
+ for (; node != 0; node = OF_parent(node)) {
+ if ((rv = OF_getprop(node, propname, buf, buflen)) != -1)
+ return (rv);
+ }
+ return (-1);
+}
+
+void
+ofw_bus_setup_iinfo(phandle_t node, struct ofw_bus_iinfo *ii, int intrsz)
+{
+ pcell_t addrc;
+ int msksz;
+
+ if (OF_getprop(node, "#address-cells", &addrc, sizeof(addrc)) == -1)
+ addrc = 2;
+ ii->opi_addrc = addrc * sizeof(pcell_t);
+
+ ii->opi_imapsz = OF_getprop_alloc(node, "interrupt-map", 1,
+ (void **)&ii->opi_imap);
+ if (ii->opi_imapsz > 0) {
+ msksz = OF_getprop_alloc(node, "interrupt-map-mask", 1,
+ (void **)&ii->opi_imapmsk);
+ /*
+ * Failure to get the mask is ignored; a full mask is used then.
+ * Barf on bad mask sizes, however.
+ */
+ if (msksz != -1 && msksz != ii->opi_addrc + intrsz) {
+ panic("ofw_bus_setup_iinfo: bad interrupt-map-mask "
+ "property!");
+ }
+ }
+
+}
+
+int
+ofw_bus_lookup_imap(phandle_t node, struct ofw_bus_iinfo *ii, void *reg,
+ int regsz, void *pintr, int pintrsz, void *mintr, int mintrsz,
+ void *maskbuf)
+{
+ int rv;
+
+ if (ii->opi_imapsz <= 0)
+ return (0);
+ KASSERT(regsz >= ii->opi_addrc,
+ ("ofw_bus_lookup_imap: register size too small: %d < %d",
+ regsz, ii->opi_addrc));
+ rv = OF_getprop(node, "reg", reg, regsz);
+ if (rv < regsz)
+ panic("ofw_bus_lookup_imap: could not get reg property");
+ return (ofw_bus_search_intrmap(pintr, pintrsz, reg, ii->opi_addrc,
+ ii->opi_imap, ii->opi_imapsz, ii->opi_imapmsk, maskbuf, mintr,
+ mintrsz));
+}
+
+/*
+ * Map an interrupt using the firmware reg, interrupt-map and
+ * interrupt-map-mask properties.
+ * The interrupt property to be mapped must be of size intrsz, and pointed to
+ * by intr. The regs property of the node for which the mapping is done must
+ * be passed as regs. This property is an array of register specifications;
+ * the size of the address part of such a specification must be passed as
+ * physsz. Only the first element of the property is used.
+ * imap and imapsz hold the interrupt mask and it's size.
+ * imapmsk is a pointer to the interrupt-map-mask property, which must have
+ * a size of physsz + intrsz; it may be NULL, in which case a full mask is
+ * assumed.
+ * maskbuf must point to a buffer of length physsz + intrsz.
+ * The interrupt is returned in result, which must point to a buffer of length
+ * rintrsz (which gives the expected size of the mapped interrupt).
+ * Returns 1 if a mapping was found, 0 otherwise.
+ */
+int
+ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz,
+ void *imap, int imapsz, void *imapmsk, void *maskbuf, void *result,
+ int rintrsz)
+{
+ phandle_t parent;
+ u_int8_t *ref = maskbuf;
+ u_int8_t *uiintr = intr;
+ u_int8_t *uiregs = regs;
+ u_int8_t *uiimapmsk = imapmsk;
+ u_int8_t *mptr;
+ pcell_t pintrsz;
+ int i, rsz, tsz;
+
+ rsz = -1;
+ if (imapmsk != NULL) {
+ for (i = 0; i < physsz; i++)
+ ref[i] = uiregs[i] & uiimapmsk[i];
+ for (i = 0; i < intrsz; i++)
+ ref[physsz + i] = uiintr[i] & uiimapmsk[physsz + i];
+ } else {
+ bcopy(regs, ref, physsz);
+ bcopy(intr, ref + physsz, intrsz);
+ }
+
+ mptr = imap;
+ i = imapsz;
+ tsz = physsz + intrsz + sizeof(phandle_t) + rintrsz;
+ while (i > 0) {
+ KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map"));
+ bcopy(mptr + physsz + intrsz, &parent, sizeof(parent));
+ if (ofw_bus_searchprop(parent, "#interrupt-cells",
+ &pintrsz, sizeof(pintrsz)) == -1)
+ pintrsz = 1; /* default */
+ pintrsz *= sizeof(pcell_t);
+ if (pintrsz != rintrsz)
+ panic("ofw_bus_search_intrmap: expected interrupt cell "
+ "size incorrect: %d > %d", rintrsz, pintrsz);
+
+ /*
+ * XXX: Apple hardware uses a second cell to set information
+ * on the interrupt trigger type. This information should
+ * be used somewhere to program the PIC.
+ */
+
+ if (bcmp(ref, mptr, physsz + intrsz) == 0) {
+ bcopy(mptr + physsz + intrsz + sizeof(parent),
+ result, rintrsz);
+ return (1);
+ }
+ mptr += tsz;
+ i -= tsz;
+ }
+ return (0);
+}
diff --git a/sys/dev/ofw/ofw_bus_subr.h b/sys/dev/ofw/ofw_bus_subr.h
index 6096b3e..58dd587 100644
--- a/sys/dev/ofw/ofw_bus_subr.h
+++ b/sys/dev/ofw/ofw_bus_subr.h
@@ -37,9 +37,30 @@
#include "ofw_bus_if.h"
+#define ORIP_NOINT -1
+#define ORIR_NOTFOUND 0xffffffff
+
+struct ofw_bus_iinfo {
+ u_int8_t *opi_imap;
+ u_int8_t *opi_imapmsk;
+ int opi_imapsz;
+ pcell_t opi_addrc;
+};
+
int ofw_bus_gen_setup_devinfo(struct ofw_bus_devinfo *, phandle_t);
void ofw_bus_gen_destroy_devinfo(struct ofw_bus_devinfo *);
+/* Helper method to report interesting OF properties in pnpinfo */
+int ofw_bus_gen_child_pnpinfo_str(device_t, device_t, char *, size_t);
+
+/* Routines for processing firmware interrupt maps */
+
+void ofw_bus_setup_iinfo(phandle_t, struct ofw_bus_iinfo *, int);
+int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int,
+ void *, int, void *, int, void *);
+int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *,
+ void *, void *, int);
+
ofw_bus_get_compat_t ofw_bus_gen_get_compat;
ofw_bus_get_model_t ofw_bus_gen_get_model;
ofw_bus_get_name_t ofw_bus_gen_get_name;
diff --git a/sys/dev/ofw/ofw_if.m b/sys/dev/ofw/ofw_if.m
new file mode 100644
index 0000000..431ac91
--- /dev/null
+++ b/sys/dev/ofw/ofw_if.m
@@ -0,0 +1,357 @@
+#-
+# Copyright (c) 2008 Nathan Whitehorn
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofwvar.h>
+
+/**
+ * @defgroup OFW ofw - KObj methods for Open Firmware RTAS implementations
+ * @brief A set of methods to implement the Open Firmware client side interface.
+ *@{
+ */
+
+INTERFACE ofw;
+
+/**
+ * @brief Initialize OFW client interface
+ *
+ * @param _cookie A handle to the client interface, generally the OF
+ * callback routine.
+ */
+METHOD void init {
+ ofw_t _ofw;
+ void *_cookie;
+};
+
+/**
+ * @brief Return next sibling of node
+ *
+ * @param _node Selected node
+ */
+METHOD phandle_t peer {
+ ofw_t _ofw;
+ phandle_t _node;
+};
+
+/**
+ * @brief Return parent of node
+ *
+ * @param _node Selected node
+ */
+METHOD phandle_t parent {
+ ofw_t _ofw;
+ phandle_t _node;
+};
+
+/**
+ * @brief Return first child of node
+ *
+ * @param _node Selected node
+ */
+METHOD phandle_t child {
+ ofw_t _ofw;
+ phandle_t _node;
+};
+
+/**
+ * @brief Return package corresponding to instance
+ *
+ * @param _handle Selected instance
+ */
+METHOD phandle_t instance_to_package {
+ ofw_t _ofw;
+ ihandle_t _handle;
+};
+
+/**
+ * @brief Return length of node property
+ *
+ * @param _node Selected node
+ * @param _prop Property name
+ */
+METHOD ssize_t getproplen {
+ ofw_t _ofw;
+ phandle_t _node;
+ const char *_prop;
+};
+
+/**
+ * @brief Read node property
+ *
+ * @param _node Selected node
+ * @param _prop Property name
+ * @param _buf Pointer to buffer
+ * @param _size Size of buffer
+ */
+METHOD ssize_t getprop {
+ ofw_t _ofw;
+ phandle_t _node;
+ const char *_prop;
+ void *_buf;
+ size_t _size;
+};
+
+/**
+ * @brief Get next property name
+ *
+ * @param _node Selected node
+ * @param _prop Current property name
+ * @param _buf Buffer for next property name
+ * @param _size Size of buffer
+ */
+METHOD int nextprop {
+ ofw_t _ofw;
+ phandle_t _node;
+ const char *_prop;
+ char *_buf;
+ size_t _size;
+};
+
+/**
+ * @brief Set property
+ *
+ * @param _node Selected node
+ * @param _prop Property name
+ * @param _buf Value to set
+ * @param _size Size of buffer
+ */
+METHOD int setprop {
+ ofw_t _ofw;
+ phandle_t _node;
+ const char *_prop;
+ const void *_buf;
+ size_t _size;
+};
+
+/**
+ * @brief Canonicalize path
+ *
+ * @param _path Path to canonicalize
+ * @param _buf Buffer for canonicalized path
+ * @param _size Size of buffer
+ */
+METHOD ssize_t canon {
+ ofw_t _ofw;
+ const char *_path;
+ char *_buf;
+ size_t _size;
+};
+
+/**
+ * @brief Return phandle for named device
+ *
+ * @param _path Device path
+ */
+METHOD phandle_t finddevice {
+ ofw_t _ofw;
+ const char *_path;
+};
+
+/**
+ * @brief Return path for node instance
+ *
+ * @param _handle Instance handle
+ * @param _path Buffer for path
+ * @param _size Size of buffer
+ */
+METHOD ssize_t instance_to_path {
+ ofw_t _ofw;
+ ihandle_t _handle;
+ char *_path;
+ size_t _size;
+};
+
+/**
+ * @brief Return path for node
+ *
+ * @param _node Package node
+ * @param _path Buffer for path
+ * @param _size Size of buffer
+ */
+METHOD ssize_t package_to_path {
+ ofw_t _ofw;
+ phandle_t _node;
+ char *_path;
+ size_t _size;
+};
+
+
+# Methods for OF method calls (optional)
+
+/**
+ * @brief Test to see if a service exists.
+ *
+ * @param _name name of the service
+ */
+METHOD int test {
+ ofw_t _ofw;
+ const char *_name;
+};
+
+/**
+ * @brief Call method belonging to an instance handle
+ *
+ * @param _instance Instance handle
+ * @param _method Method name
+ * @param _nargs Number of arguments
+ * @param _nreturns Number of return values
+ * @param _args_and_returns Values for arguments, followed by returns
+ */
+
+METHOD int call_method {
+ ofw_t _ofw;
+ ihandle_t _instance;
+ const char *_method;
+ int _nargs;
+ int _nreturns;
+
+ unsigned long *_args_and_returns;
+};
+
+/**
+ * @brief Interpret a forth command
+ *
+ * @param _cmd Command
+ * @param _nreturns Number of return values
+ * @param _returns Values for returns
+ */
+
+METHOD int interpret {
+ ofw_t _ofw;
+ const char *_cmd;
+ int _nreturns;
+ unsigned long *_returns;
+};
+
+# Device I/O Functions (optional)
+
+/**
+ * @brief Open node, returning instance handle
+ *
+ * @param _path Path to node
+ */
+METHOD ihandle_t open {
+ ofw_t _ofw;
+ const char *_path;
+}
+
+/**
+ * @brief Close node instance
+ *
+ * @param _instance Instance to close
+ */
+METHOD void close {
+ ofw_t _ofw;
+ ihandle_t _instance;
+}
+
+/**
+ * @brief Read from device
+ *
+ * @param _instance Device instance
+ * @param _buf Buffer to read to
+ * @param _size Size of buffer
+ */
+METHOD ssize_t read {
+ ofw_t _ofw;
+ ihandle_t _instance;
+ void *_buf;
+ size_t size;
+}
+
+/**
+ * @brief Write to device
+ *
+ * @param _instance Device instance
+ * @param _buf Buffer to write from
+ * @param _size Size of buffer
+ */
+METHOD ssize_t write {
+ ofw_t _ofw;
+ ihandle_t _instance;
+ const void *_buf;
+ size_t size;
+}
+
+/**
+ * @brief Seek device
+ *
+ * @param _instance Device instance
+ * @param _off Offset to which to seek
+ */
+METHOD int seek {
+ ofw_t _ofw;
+ ihandle_t _instance;
+ uint64_t _off;
+}
+
+# Open Firmware memory management
+
+/**
+ * @brief Claim virtual memory
+ *
+ * @param _addr Requested memory location (NULL for first available)
+ * @param _size Requested size in bytes
+ * @param _align Requested alignment
+ */
+METHOD caddr_t claim {
+ ofw_t _ofw;
+ void *_addr;
+ size_t _size;
+ u_int _align;
+}
+
+/**
+ * @brief Release virtual memory
+ *
+ * @param _addr Memory location
+ * @param _size Size in bytes
+ */
+METHOD void release {
+ ofw_t _ofw;
+ void *_addr;
+ size_t _size;
+};
+
+# Commands for returning control to the firmware
+
+/**
+ * @brief Temporarily return control to firmware
+ */
+METHOD void enter {
+ ofw_t _ofw;
+};
+
+/**
+ * @brief Halt and return control to firmware
+ */
+METHOD void exit {
+ ofw_t _ofw;
+};
+
+
diff --git a/sys/dev/ofw/ofw_standard.c b/sys/dev/ofw/ofw_standard.c
new file mode 100644
index 0000000..e097145
--- /dev/null
+++ b/sys/dev/ofw/ofw_standard.c
@@ -0,0 +1,763 @@
+/* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */
+
+/*-
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
+ */
+/*-
+ * Copyright (C) 2000 Benno Rice.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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 TOOLS GMBH 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/kernel.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+
+#include <machine/stdarg.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofwvar.h>
+#include "ofw_if.h"
+
+static void ofw_std_init(ofw_t ofw, void *openfirm);
+static int ofw_std_test(ofw_t ofw, const char *name);
+static int ofw_std_interpret(ofw_t ofw, const char *cmd, int nreturns,
+ unsigned long *returns);
+static phandle_t ofw_std_peer(ofw_t ofw, phandle_t node);
+static phandle_t ofw_std_child(ofw_t ofw, phandle_t node);
+static phandle_t ofw_std_parent(ofw_t ofw, phandle_t node);
+static phandle_t ofw_std_instance_to_package(ofw_t ofw, ihandle_t instance);
+static ssize_t ofw_std_getproplen(ofw_t ofw, phandle_t package,
+ const char *propname);
+static ssize_t ofw_std_getprop(ofw_t ofw, phandle_t package,
+ const char *propname, void *buf, size_t buflen);
+static int ofw_std_nextprop(ofw_t ofw, phandle_t package, const char *previous,
+ char *buf, size_t);
+static int ofw_std_setprop(ofw_t ofw, phandle_t package, char *propname,
+ void *buf, size_t len);
+static ssize_t ofw_std_canon(ofw_t ofw, const char *device, char *buf,
+ size_t len);
+static phandle_t ofw_std_finddevice(ofw_t ofw, const char *device);
+static ssize_t ofw_std_instance_to_path(ofw_t ofw, ihandle_t instance,
+ char *buf, size_t len);
+static ssize_t ofw_std_package_to_path(ofw_t ofw, phandle_t package, char *buf,
+ size_t len);
+static int ofw_std_call_method(ofw_t ofw, ihandle_t instance,
+ const char *method, int nargs, int nreturns,
+ unsigned long *args_and_returns);
+static ihandle_t ofw_std_open(ofw_t ofw, const char *device);
+static void ofw_std_close(ofw_t ofw, ihandle_t instance);
+static ssize_t ofw_std_read(ofw_t ofw, ihandle_t instance, void *addr,
+ size_t len);
+static ssize_t ofw_std_write(ofw_t ofw, ihandle_t instance, const void *addr,
+ size_t len);
+static int ofw_std_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos);
+static caddr_t ofw_std_claim(ofw_t ofw, void *virt, size_t size, u_int align);
+static void ofw_std_release(ofw_t ofw, void *virt, size_t size);
+static void ofw_std_enter(ofw_t ofw);
+static void ofw_std_exit(ofw_t ofw);
+
+static ofw_method_t ofw_std_methods[] = {
+ OFWMETHOD(ofw_init, ofw_std_init),
+ OFWMETHOD(ofw_peer, ofw_std_peer),
+ OFWMETHOD(ofw_child, ofw_std_child),
+ OFWMETHOD(ofw_parent, ofw_std_parent),
+ OFWMETHOD(ofw_instance_to_package, ofw_std_instance_to_package),
+ OFWMETHOD(ofw_getproplen, ofw_std_getproplen),
+ OFWMETHOD(ofw_getprop, ofw_std_getprop),
+ OFWMETHOD(ofw_nextprop, ofw_std_nextprop),
+ OFWMETHOD(ofw_setprop, ofw_std_setprop),
+ OFWMETHOD(ofw_canon, ofw_std_canon),
+ OFWMETHOD(ofw_finddevice, ofw_std_finddevice),
+ OFWMETHOD(ofw_instance_to_path, ofw_std_instance_to_path),
+ OFWMETHOD(ofw_package_to_path, ofw_std_package_to_path),
+
+ OFWMETHOD(ofw_test, ofw_std_test),
+ OFWMETHOD(ofw_call_method, ofw_std_call_method),
+ OFWMETHOD(ofw_interpret, ofw_std_interpret),
+ OFWMETHOD(ofw_open, ofw_std_open),
+ OFWMETHOD(ofw_close, ofw_std_close),
+ OFWMETHOD(ofw_read, ofw_std_read),
+ OFWMETHOD(ofw_write, ofw_std_write),
+ OFWMETHOD(ofw_seek, ofw_std_seek),
+ OFWMETHOD(ofw_claim, ofw_std_claim),
+ OFWMETHOD(ofw_release, ofw_std_release),
+ OFWMETHOD(ofw_enter, ofw_std_enter),
+ OFWMETHOD(ofw_exit, ofw_std_exit),
+
+ { 0, 0 }
+};
+
+static ofw_def_t ofw_std = {
+ OFW_STD_DIRECT,
+ ofw_std_methods,
+ 0
+};
+OFW_DEF(ofw_std);
+
+static int (*openfirmware)(void *);
+
+/* Initialiser */
+
+static void
+ofw_std_init(ofw_t ofw, void *openfirm)
+{
+ openfirmware = (int (*)(void *))openfirm;
+}
+
+/*
+ * Generic functions
+ */
+
+/* Test to see if a service exists. */
+static int
+ofw_std_test(ofw_t ofw, const char *name)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t service;
+ cell_t missing;
+ } args = {
+ (cell_t)"test",
+ 1,
+ 1,
+ };
+
+ args.service = (cell_t)name;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.missing);
+}
+
+static int
+ofw_std_interpret(ofw_t ofw, const char *cmd, int nreturns,
+ unsigned long *returns)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t slot[16];
+ } args = {
+ (cell_t)"interpret",
+ 1,
+ };
+ cell_t status;
+ int i = 0, j = 0;
+
+ args.nreturns = ++nreturns;
+ args.slot[i++] = (cell_t)cmd;
+ if (openfirmware(&args) == -1) {
+ return (-1);
+ }
+ status = args.slot[i++];
+ while (i < 1 + nreturns)
+ returns[j] = args.slot[i++];
+ return (status);
+}
+
+/*
+ * Device tree functions
+ */
+
+/* Return the next sibling of this node or 0. */
+static phandle_t
+ofw_std_peer(ofw_t ofw, phandle_t node)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t node;
+ cell_t next;
+ } args = {
+ (cell_t)"peer",
+ 1,
+ 1,
+ };
+
+ args.node = node;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.next);
+}
+
+/* Return the first child of this node or 0. */
+static phandle_t
+ofw_std_child(ofw_t ofw, phandle_t node)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t node;
+ cell_t child;
+ } args = {
+ (cell_t)"child",
+ 1,
+ 1,
+ };
+
+ args.node = node;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.child);
+}
+
+/* Return the parent of this node or 0. */
+static phandle_t
+ofw_std_parent(ofw_t ofw, phandle_t node)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t node;
+ cell_t parent;
+ } args = {
+ (cell_t)"parent",
+ 1,
+ 1,
+ };
+
+ args.node = node;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.parent);
+}
+
+/* Return the package handle that corresponds to an instance handle. */
+static phandle_t
+ofw_std_instance_to_package(ofw_t ofw, ihandle_t instance)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t package;
+ } args = {
+ (cell_t)"instance-to-package",
+ 1,
+ 1,
+ };
+
+ args.instance = instance;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.package);
+}
+
+/* Get the length of a property of a package. */
+static ssize_t
+ofw_std_getproplen(ofw_t ofw, phandle_t package, const char *propname)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t propname;
+ cell_t proplen;
+ } args = {
+ (cell_t)"getproplen",
+ 2,
+ 1,
+ };
+
+ args.package = package;
+ args.propname = (cell_t)propname;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.proplen);
+}
+
+/* Get the value of a property of a package. */
+static ssize_t
+ofw_std_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
+ size_t buflen)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t propname;
+ cell_t buf;
+ cell_t buflen;
+ cell_t size;
+ } args = {
+ (cell_t)"getprop",
+ 4,
+ 1,
+ };
+
+ args.package = package;
+ args.propname = (cell_t)propname;
+ args.buf = (cell_t)buf;
+ args.buflen = buflen;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.size);
+}
+
+/* Get the next property of a package. */
+static int
+ofw_std_nextprop(ofw_t ofw, phandle_t package, const char *previous, char *buf,
+ size_t size)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t previous;
+ cell_t buf;
+ cell_t flag;
+ } args = {
+ (cell_t)"nextprop",
+ 3,
+ 1,
+ };
+
+ args.package = package;
+ args.previous = (cell_t)previous;
+ args.buf = (cell_t)buf;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.flag);
+}
+
+/* Set the value of a property of a package. */
+/* XXX Has a bug on FirePower */
+static int
+ofw_std_setprop(ofw_t ofw, phandle_t package, char *propname, void *buf,
+ size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t propname;
+ cell_t buf;
+ cell_t len;
+ cell_t size;
+ } args = {
+ (cell_t)"setprop",
+ 4,
+ 1,
+ };
+
+ args.package = package;
+ args.propname = (cell_t)propname;
+ args.buf = (cell_t)buf;
+ args.len = len;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.size);
+}
+
+/* Convert a device specifier to a fully qualified pathname. */
+static ssize_t
+ofw_std_canon(ofw_t ofw, const char *device, char *buf, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t device;
+ cell_t buf;
+ cell_t len;
+ cell_t size;
+ } args = {
+ (cell_t)"canon",
+ 3,
+ 1,
+ };
+
+ args.device = (cell_t)device;
+ args.buf = (cell_t)buf;
+ args.len = len;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.size);
+}
+
+/* Return a package handle for the specified device. */
+static phandle_t
+ofw_std_finddevice(ofw_t ofw, const char *device)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t device;
+ cell_t package;
+ } args = {
+ (cell_t)"finddevice",
+ 1,
+ 1,
+ };
+
+ args.device = (cell_t)device;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.package);
+}
+
+/* Return the fully qualified pathname corresponding to an instance. */
+static ssize_t
+ofw_std_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t buf;
+ cell_t len;
+ cell_t size;
+ } args = {
+ (cell_t)"instance-to-path",
+ 3,
+ 1,
+ };
+
+ args.instance = instance;
+ args.buf = (cell_t)buf;
+ args.len = len;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.size);
+}
+
+/* Return the fully qualified pathname corresponding to a package. */
+static ssize_t
+ofw_std_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t buf;
+ cell_t len;
+ cell_t size;
+ } args = {
+ (cell_t)"package-to-path",
+ 3,
+ 1,
+ };
+
+ args.package = package;
+ args.buf = (cell_t)buf;
+ args.len = len;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.size);
+}
+
+/* Call the method in the scope of a given instance. */
+static int
+ofw_std_call_method(ofw_t ofw, ihandle_t instance, const char *method,
+ int nargs, int nreturns, unsigned long *args_and_returns)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t method;
+ cell_t instance;
+ cell_t args_n_results[12];
+ } args = {
+ (cell_t)"call-method",
+ 2,
+ 1,
+ };
+ cell_t *cp;
+ unsigned long *ap;
+ int n;
+
+ if (nargs > 6)
+ return (-1);
+ args.nargs = nargs + 2;
+ args.nreturns = nreturns + 1;
+ args.method = (cell_t)method;
+ args.instance = instance;
+
+ ap = args_and_returns;
+ for (cp = args.args_n_results + (n = nargs); --n >= 0;)
+ *--cp = *(ap++);
+ if (openfirmware(&args) == -1)
+ return (-1);
+ if (args.args_n_results[nargs])
+ return (args.args_n_results[nargs]);
+ for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
+ *(ap++) = *--cp;
+ return (0);
+}
+
+/*
+ * Device I/O functions
+ */
+
+/* Open an instance for a device. */
+static ihandle_t
+ofw_std_open(ofw_t ofw, const char *device)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t device;
+ cell_t instance;
+ } args = {
+ (cell_t)"open",
+ 1,
+ 1,
+ };
+
+ args.device = (cell_t)device;
+ if (openfirmware(&args) == -1 || args.instance == 0) {
+ return (-1);
+ }
+ return (args.instance);
+}
+
+/* Close an instance. */
+static void
+ofw_std_close(ofw_t ofw, ihandle_t instance)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ } args = {
+ (cell_t)"close",
+ 1,
+ };
+
+ args.instance = instance;
+ openfirmware(&args);
+}
+
+/* Read from an instance. */
+static ssize_t
+ofw_std_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t addr;
+ cell_t len;
+ cell_t actual;
+ } args = {
+ (cell_t)"read",
+ 3,
+ 1,
+ };
+
+ args.instance = instance;
+ args.addr = (cell_t)addr;
+ args.len = len;
+ if (openfirmware(&args) == -1)
+ return (-1);
+
+ return (args.actual);
+}
+
+/* Write to an instance. */
+static ssize_t
+ofw_std_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t addr;
+ cell_t len;
+ cell_t actual;
+ } args = {
+ (cell_t)"write",
+ 3,
+ 1,
+ };
+
+ args.instance = instance;
+ args.addr = (cell_t)addr;
+ args.len = len;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.actual);
+}
+
+/* Seek to a position. */
+static int
+ofw_std_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t poshi;
+ cell_t poslo;
+ cell_t status;
+ } args = {
+ (cell_t)"seek",
+ 3,
+ 1,
+ };
+
+ args.instance = instance;
+ args.poshi = pos >> 32;
+ args.poslo = pos;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.status);
+}
+
+/*
+ * Memory functions
+ */
+
+/* Claim an area of memory. */
+static caddr_t
+ofw_std_claim(ofw_t ofw, void *virt, size_t size, u_int align)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t virt;
+ cell_t size;
+ cell_t align;
+ cell_t baseaddr;
+ } args = {
+ (cell_t)"claim",
+ 3,
+ 1,
+ };
+
+ args.virt = (cell_t)virt;
+ args.size = size;
+ args.align = align;
+ if (openfirmware(&args) == -1)
+ return ((void *)-1);
+ return ((void *)args.baseaddr);
+}
+
+/* Release an area of memory. */
+static void
+ofw_std_release(ofw_t ofw, void *virt, size_t size)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t virt;
+ cell_t size;
+ } args = {
+ (cell_t)"release",
+ 2,
+ };
+
+ args.virt = (cell_t)virt;
+ args.size = size;
+ openfirmware(&args);
+}
+
+/*
+ * Control transfer functions
+ */
+
+/* Suspend and drop back to the Open Firmware interface. */
+static void
+ofw_std_enter(ofw_t ofw)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ } args = {
+ (cell_t)"enter",
+ };
+
+ openfirmware(&args);
+ /* We may come back. */
+}
+
+/* Shut down and drop back to the Open Firmware interface. */
+static void
+ofw_std_exit(ofw_t ofw)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ } args = {
+ (cell_t)"exit",
+ };
+
+ openfirmware(&args);
+ for (;;) /* just in case */
+ ;
+}
+
diff --git a/sys/dev/ofw/ofwvar.h b/sys/dev/ofw/ofwvar.h
new file mode 100644
index 0000000..950dded
--- /dev/null
+++ b/sys/dev/ofw/ofwvar.h
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 2005 Peter Grehan
+ * Copyright (c) 2008 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _OFW_OFWVAR_H_
+#define _OFW_OFWVAR_H_
+
+/*
+ * An Open Firmware client implementation is declared with a kernel object and
+ * an associated method table, similar to a device driver.
+ *
+ * e.g.
+ *
+ * static ofw_method_t fdt_methods[] = {
+ * OFWMETHOD(ofw_init, fdt_init),
+ * OFWMETHOD(ofw_finddevice, fdt_finddevice),
+ * ...
+ * OFWMETHOD(ofw_nextprop, fdt_nextprop),
+ * { 0, 0 }
+ * };
+ *
+ * static ofw_def_t ofw_fdt = {
+ * "ofw_fdt",
+ * fdt_methods,
+ * sizeof(fdt_softc), // or 0 if no softc
+ * };
+ *
+ * OFW_DEF(ofw_fdt);
+ */
+
+#include <sys/kobj.h>
+
+struct ofw_kobj {
+ /*
+ * An OFW instance is a kernel object.
+ */
+ KOBJ_FIELDS;
+
+ /*
+ * Utility elements that an instance may use
+ */
+ struct mtx ofw_mtx; /* available for instance use */
+ void *ofw_iptr; /* instance data pointer */
+
+ /*
+ * Opaque data that can be overlaid with an instance-private
+ * structure. OFW code can test that this is large enough at
+ * compile time with a sizeof() test againt it's softc. There
+ * is also a run-time test when the MMU kernel object is
+ * registered.
+ */
+#define OFW_OPAQUESZ 64
+ u_int ofw_opaque[OFW_OPAQUESZ];
+};
+
+typedef struct ofw_kobj *ofw_t;
+typedef struct kobj_class ofw_def_t;
+
+#define ofw_method_t kobj_method_t
+#define OFWMETHOD KOBJMETHOD
+
+#define OFW_DEF(name) DATA_SET(ofw_set, name)
+
+#endif /* _OFW_OFWVAR_H_ */
diff --git a/sys/dev/ofw/openfirm.c b/sys/dev/ofw/openfirm.c
index ff889e5..c7b2203 100644
--- a/sys/dev/ofw/openfirm.c
+++ b/sys/dev/ofw/openfirm.c
@@ -66,23 +66,70 @@ __FBSDID("$FreeBSD$");
#include <machine/stdarg.h>
#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofwvar.h>
+
+#include "ofw_if.h"
MALLOC_DEFINE(M_OFWPROP, "openfirm", "Open Firmware properties");
static ihandle_t stdout;
+static ofw_def_t *ofw_def_impl;
+static ofw_t ofw_obj;
+static struct ofw_kobj ofw_kernel_obj;
+static struct kobj_ops ofw_kernel_kops;
+
+/*
+ * OFW install routines. Highest priority wins, equal priority also
+ * overrides allowing last-set to win.
+ */
+SET_DECLARE(ofw_set, ofw_def_t);
+
+boolean_t
+OF_install(char *name, int prio)
+{
+ ofw_def_t **ofwpp, *ofwp;
+ static int curr_prio = 0;
+
+ /*
+ * Try and locate the OFW kobj corresponding to the name
+ */
+ SET_FOREACH(ofwpp, ofw_set) {
+ ofwp = *ofwpp;
+
+ if (ofwp->name &&
+ !strcmp(ofwp->name, name) &&
+ prio >= curr_prio) {
+ curr_prio = prio;
+ ofw_def_impl = ofwp;
+ return (TRUE);
+ }
+ }
+
+ return (FALSE);
+}
+
/* Initialiser */
void
-OF_init(int (*openfirm)(void *))
+OF_init(void *cookie)
{
phandle_t chosen;
- set_openfirm_callback(openfirm);
+ ofw_obj = &ofw_kernel_obj;
+ /*
+ * Take care of compiling the selected class, and
+ * then statically initialize the OFW object
+ */
+ kobj_class_compile_static(ofw_def_impl, &ofw_kernel_kops);
+ kobj_init((kobj_t)ofw_obj, ofw_def_impl);
+
+ OFW_INIT(ofw_obj, cookie);
+
if ((chosen = OF_finddevice("/chosen")) == -1)
OF_exit();
if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1)
- OF_exit();
+ stdout = -1;
}
void
@@ -103,75 +150,27 @@ OF_printf(const char *fmt, ...)
/* Test to see if a service exists. */
int
-OF_test(char *name)
+OF_test(const char *name)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t service;
- cell_t missing;
- } args = {
- (cell_t)"test",
- 1,
- 1,
- };
-
- args.service = (cell_t)name;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.missing);
+ return (OFW_TEST(ofw_obj, name));
}
int
-OF_interpret(char *cmd, int nreturns, ...)
+OF_interpret(const char *cmd, int nreturns, ...)
{
va_list ap;
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t slot[16];
- } args = {
- (cell_t)"interpret",
- 1,
- };
- cell_t status;
+ unsigned long slots[16];
int i = 0;
+ int status;
+
+ status = OFW_INTERPRET(ofw_obj, cmd, nreturns, slots);
va_start(ap, nreturns);
- args.nreturns = ++nreturns;
- args.slot[i++] = (cell_t)cmd;
- while (i < 1)
- args.slot[i++] = va_arg(ap, cell_t);
- if (openfirmware(&args) == -1) {
- va_end(ap);
- return (-1);
- }
- status = args.slot[i++];
while (i < 1 + nreturns)
- *va_arg(ap, cell_t *) = args.slot[i++];
+ *va_arg(ap, cell_t *) = slots[i++];
va_end(ap);
- return (status);
-}
-/* Return firmware millisecond count. */
-int
-OF_milliseconds()
-{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t ms;
- } args = {
- (cell_t)"milliseconds",
- 0,
- 1,
- };
-
- openfirmware(&args);
- return (args.ms);
+ return (status);
}
/*
@@ -182,140 +181,42 @@ OF_milliseconds()
phandle_t
OF_peer(phandle_t node)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t node;
- cell_t next;
- } args = {
- (cell_t)"peer",
- 1,
- 1,
- };
-
- args.node = node;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.next);
+ return (OFW_PEER(ofw_obj, node));
}
/* Return the first child of this node or 0. */
phandle_t
OF_child(phandle_t node)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t node;
- cell_t child;
- } args = {
- (cell_t)"child",
- 1,
- 1,
- };
-
- args.node = node;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.child);
+ return (OFW_CHILD(ofw_obj, node));
}
/* Return the parent of this node or 0. */
phandle_t
OF_parent(phandle_t node)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t node;
- cell_t parent;
- } args = {
- (cell_t)"parent",
- 1,
- 1,
- };
-
- args.node = node;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.parent);
+ return (OFW_PARENT(ofw_obj, node));
}
/* Return the package handle that corresponds to an instance handle. */
phandle_t
OF_instance_to_package(ihandle_t instance)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t instance;
- cell_t package;
- } args = {
- (cell_t)"instance-to-package",
- 1,
- 1,
- };
-
- args.instance = instance;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.package);
+ return (OFW_INSTANCE_TO_PACKAGE(ofw_obj, instance));
}
/* Get the length of a property of a package. */
-int
-OF_getproplen(phandle_t package, char *propname)
+ssize_t
+OF_getproplen(phandle_t package, const char *propname)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t package;
- cell_t propname;
- cell_t proplen;
- } args = {
- (cell_t)"getproplen",
- 2,
- 1,
- };
-
- args.package = package;
- args.propname = (cell_t)propname;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.proplen);
+ return (OFW_GETPROPLEN(ofw_obj, package, propname));
}
/* Get the value of a property of a package. */
-int
-OF_getprop(phandle_t package, char *propname, void *buf, int buflen)
+ssize_t
+OF_getprop(phandle_t package, const char *propname, void *buf, size_t buflen)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t package;
- cell_t propname;
- cell_t buf;
- cell_t buflen;
- cell_t size;
- } args = {
- (cell_t)"getprop",
- 4,
- 1,
- };
-
- args.package = package;
- args.propname = (cell_t)propname;
- args.buf = (cell_t)buf;
- args.buflen = buflen;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.size);
+ return (OFW_GETPROP(ofw_obj, package, propname, buf, buflen));
}
/*
@@ -323,8 +224,8 @@ OF_getprop(phandle_t package, char *propname, void *buf, int buflen)
* (using the M_OFWPROP malloc pool and M_WAITOK). elsz is the size of a
* single element, the number of elements is return in number.
*/
-int
-OF_getprop_alloc(phandle_t package, char *propname, int elsz, void **buf)
+ssize_t
+OF_getprop_alloc(phandle_t package, const char *propname, int elsz, void **buf)
{
int len;
@@ -344,194 +245,69 @@ OF_getprop_alloc(phandle_t package, char *propname, int elsz, void **buf)
/* Get the next property of a package. */
int
-OF_nextprop(phandle_t package, char *previous, char *buf)
+OF_nextprop(phandle_t package, const char *previous, char *buf, size_t size)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t package;
- cell_t previous;
- cell_t buf;
- cell_t flag;
- } args = {
- (cell_t)"nextprop",
- 3,
- 1,
- };
-
- args.package = package;
- args.previous = (cell_t)previous;
- args.buf = (cell_t)buf;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.flag);
+ return (OFW_NEXTPROP(ofw_obj, package, previous, buf, size));
}
/* Set the value of a property of a package. */
-/* XXX Has a bug on FirePower */
int
-OF_setprop(phandle_t package, char *propname, void *buf, int len)
+OF_setprop(phandle_t package, const char *propname, const void *buf, size_t len)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t package;
- cell_t propname;
- cell_t buf;
- cell_t len;
- cell_t size;
- } args = {
- (cell_t)"setprop",
- 4,
- 1,
- };
-
- args.package = package;
- args.propname = (cell_t)propname;
- args.buf = (cell_t)buf;
- args.len = len;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.size);
+ return (OFW_SETPROP(ofw_obj, package, propname, buf,len));
}
/* Convert a device specifier to a fully qualified pathname. */
-int
-OF_canon(const char *device, char *buf, int len)
+ssize_t
+OF_canon(const char *device, char *buf, size_t len)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t device;
- cell_t buf;
- cell_t len;
- cell_t size;
- } args = {
- (cell_t)"canon",
- 3,
- 1,
- };
-
- args.device = (cell_t)device;
- args.buf = (cell_t)buf;
- args.len = len;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.size);
+ return (OFW_CANON(ofw_obj, device, buf, len));
}
/* Return a package handle for the specified device. */
phandle_t
OF_finddevice(const char *device)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t device;
- cell_t package;
- } args = {
- (cell_t)"finddevice",
- 1,
- 1,
- };
-
- args.device = (cell_t)device;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.package);
+ return (OFW_FINDDEVICE(ofw_obj, device));
}
/* Return the fully qualified pathname corresponding to an instance. */
-int
-OF_instance_to_path(ihandle_t instance, char *buf, int len)
+ssize_t
+OF_instance_to_path(ihandle_t instance, char *buf, size_t len)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t instance;
- cell_t buf;
- cell_t len;
- cell_t size;
- } args = {
- (cell_t)"instance-to-path",
- 3,
- 1,
- };
-
- args.instance = instance;
- args.buf = (cell_t)buf;
- args.len = len;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.size);
+ return (OFW_INSTANCE_TO_PATH(ofw_obj, instance, buf, len));
}
/* Return the fully qualified pathname corresponding to a package. */
-int
-OF_package_to_path(phandle_t package, char *buf, int len)
+ssize_t
+OF_package_to_path(phandle_t package, char *buf, size_t len)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t package;
- cell_t buf;
- cell_t len;
- cell_t size;
- } args = {
- (cell_t)"package-to-path",
- 3,
- 1,
- };
-
- args.package = package;
- args.buf = (cell_t)buf;
- args.len = len;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.size);
+ return (OFW_PACKAGE_TO_PATH(ofw_obj, package, buf, len));
}
/* Call the method in the scope of a given instance. */
int
-OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
+OF_call_method(const char *method, ihandle_t instance, int nargs, int nreturns,
+ ...)
{
va_list ap;
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t method;
- cell_t instance;
- cell_t args_n_results[12];
- } args = {
- (cell_t)"call-method",
- 2,
- 1,
- };
- cell_t *cp;
- int n;
+ unsigned long args_n_results[12];
+ int n, status;
if (nargs > 6)
return (-1);
- args.nargs = nargs + 2;
- args.nreturns = nreturns + 1;
- args.method = (cell_t)method;
- args.instance = instance;
va_start(ap, nreturns);
- for (cp = args.args_n_results + (n = nargs); --n >= 0;)
- *--cp = va_arg(ap, cell_t);
- if (openfirmware(&args) == -1)
- return (-1);
- if (args.args_n_results[nargs])
- return (args.args_n_results[nargs]);
- for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
- *va_arg(ap, cell_t *) = *--cp;
+ for (n = 0; n < nargs; n++)
+ args_n_results[n] = va_arg(ap, unsigned long);
+
+ status = OFW_CALL_METHOD(ofw_obj, instance, method, nargs, nreturns,
+ args_n_results);
+
+ if (status != 0)
+ return (status);
+
+ for (; n < nargs + nreturns; n++)
+ *va_arg(ap, unsigned long *) = args_n_results[n];
va_end(ap);
return (0);
}
@@ -542,122 +318,37 @@ OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
/* Open an instance for a device. */
ihandle_t
-OF_open(char *device)
+OF_open(const char *device)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t device;
- cell_t instance;
- } args = {
- (cell_t)"open",
- 1,
- 1,
- };
-
- args.device = (cell_t)device;
- if (openfirmware(&args) == -1 || args.instance == 0) {
- return (-1);
- }
- return (args.instance);
+ return (OFW_OPEN(ofw_obj, device));
}
/* Close an instance. */
void
OF_close(ihandle_t instance)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t instance;
- } args = {
- (cell_t)"close",
- 1,
- };
-
- args.instance = instance;
- openfirmware(&args);
+ OFW_CLOSE(ofw_obj, instance);
}
/* Read from an instance. */
-int
-OF_read(ihandle_t instance, void *addr, int len)
+ssize_t
+OF_read(ihandle_t instance, void *addr, size_t len)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t instance;
- cell_t addr;
- cell_t len;
- cell_t actual;
- } args = {
- (cell_t)"read",
- 3,
- 1,
- };
-
- args.instance = instance;
- args.addr = (cell_t)addr;
- args.len = len;
- if (openfirmware(&args) == -1)
- return (-1);
-
- return (args.actual);
+ return (OFW_READ(ofw_obj, instance, addr, len));
}
/* Write to an instance. */
-int
-OF_write(ihandle_t instance, void *addr, int len)
+ssize_t
+OF_write(ihandle_t instance, const void *addr, size_t len)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t instance;
- cell_t addr;
- cell_t len;
- cell_t actual;
- } args = {
- (cell_t)"write",
- 3,
- 1,
- };
-
- args.instance = instance;
- args.addr = (cell_t)addr;
- args.len = len;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.actual);
+ return (OFW_WRITE(ofw_obj, instance, addr, len));
}
/* Seek to a position. */
int
-OF_seek(ihandle_t instance, u_int64_t pos)
+OF_seek(ihandle_t instance, uint64_t pos)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t instance;
- cell_t poshi;
- cell_t poslo;
- cell_t status;
- } args = {
- (cell_t)"seek",
- 3,
- 1,
- };
-
- args.instance = instance;
- args.poshi = pos >> 32;
- args.poslo = pos;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.status);
+ return (OFW_SEEK(ofw_obj, instance, pos));
}
/*
@@ -666,145 +357,37 @@ OF_seek(ihandle_t instance, u_int64_t pos)
/* Claim an area of memory. */
void *
-OF_claim(void *virt, u_int size, u_int align)
+OF_claim(void *virt, size_t size, u_int align)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t virt;
- cell_t size;
- cell_t align;
- cell_t baseaddr;
- } args = {
- (cell_t)"claim",
- 3,
- 1,
- };
-
- args.virt = (cell_t)virt;
- args.size = size;
- args.align = align;
- if (openfirmware(&args) == -1)
- return ((void *)-1);
- return ((void *)args.baseaddr);
+ return (OFW_CLAIM(ofw_obj, virt, size, align));
}
/* Release an area of memory. */
void
-OF_release(void *virt, u_int size)
+OF_release(void *virt, size_t size)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t virt;
- cell_t size;
- } args = {
- (cell_t)"release",
- 2,
- };
-
- args.virt = (cell_t)virt;
- args.size = size;
- openfirmware(&args);
+ OFW_RELEASE(ofw_obj, virt, size);
}
/*
* Control transfer functions
*/
-/* Reset the system and call "boot <bootspec>". */
-void
-OF_boot(char *bootspec)
-{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t bootspec;
- } args = {
- (cell_t)"boot",
- 1,
- };
-
- args.bootspec = (cell_t)bootspec;
- openfirmware(&args);
- for (;;) /* just in case */
- ;
-}
-
/* Suspend and drop back to the Open Firmware interface. */
void
OF_enter()
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- } args = {
- (cell_t)"enter",
- };
-
- openfirmware(&args);
- /* We may come back. */
+ OFW_ENTER(ofw_obj);
}
/* Shut down and drop back to the Open Firmware interface. */
void
OF_exit()
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- } args = {
- (cell_t)"exit",
- };
-
- openfirmware(&args);
+ /* Should not return */
+ OFW_EXIT(ofw_obj);
+
for (;;) /* just in case */
;
}
-/* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
-#if 0
-void
-OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
-{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t virt;
- cell_t size;
- cell_t entry;
- cell_t arg;
- cell_t len;
- } args = {
- (cell_t)"chain",
- 5,
- };
-
- args.virt = (cell_t)virt;
- args.size = size;
- args.entry = (cell_t)entry;
- args.arg = (cell_t)arg;
- args.len = len;
- openfirmware(&args);
-}
-#else
-void
-OF_chain(void *virt, u_int size,
- void (*entry)(void *, u_int, void *, void *, u_int), void *arg, u_int len)
-{
- /*
- * This is a REALLY dirty hack till the firmware gets this going
- */
-#if 0
- if (size > 0)
- OF_release(virt, size);
-#endif
- entry(0, 0, openfirmware, arg, len);
-}
-#endif
diff --git a/sys/dev/ofw/openfirm.h b/sys/dev/ofw/openfirm.h
index a8c0633..08a0544 100644
--- a/sys/dev/ofw/openfirm.h
+++ b/sys/dev/ofw/openfirm.h
@@ -60,78 +60,82 @@
#ifndef _OPENFIRM_H_
#define _OPENFIRM_H_
+#include <sys/types.h>
+
/*
* Prototypes for Open Firmware Interface Routines
*/
-typedef unsigned long cell_t;
-
-typedef unsigned int ihandle_t;
-typedef unsigned int phandle_t;
+typedef uint32_t ihandle_t;
+typedef uint32_t phandle_t;
+typedef uint32_t pcell_t;
#ifdef _KERNEL
-#include <sys/cdefs.h>
-#include <sys/types.h>
#include <sys/malloc.h>
+#include <machine/ofw_machdep.h>
+
MALLOC_DECLARE(M_OFWPROP);
/*
- * Stuff that is used by the Open Firmware code.
+ * Open Firmware interface initialization. OF_install installs the named
+ * interface as the Open Firmware access mechanism, OF_init initializes it.
*/
-void set_openfirm_callback(int (*)(void *));
-int openfirmware(void *);
+
+boolean_t OF_install(char *name, int prio);
+void OF_init(void *cookie);
/*
- * This isn't actually an Open Firmware function, but it seemed like the right
- * place for it to go.
+ * Known Open Firmware interface names
*/
-void OF_init(int (*openfirm)(void *));
+
+#define OFW_STD_DIRECT "ofw_std" /* Standard OF interface */
+#define OFW_STD_REAL "ofw_real" /* Real-mode OF interface */
+#define OFW_FDT "ofw_fdt" /* Flattened Device Tree */
/* Generic functions */
-int OF_test(char *);
+int OF_test(const char *);
void OF_printf(const char *, ...);
/* Device tree functions */
-phandle_t OF_peer(phandle_t);
-phandle_t OF_child(phandle_t);
-phandle_t OF_parent(phandle_t);
-phandle_t OF_instance_to_package(ihandle_t);
-int OF_getproplen(phandle_t, char *);
-int OF_getprop(phandle_t, char *, void *, int);
-int OF_getprop_alloc(phandle_t package, char *propname, int elsz,
- void **buf);
-int OF_nextprop(phandle_t, char *, char *);
-int OF_setprop(phandle_t, char *, void *, int);
-int OF_canon(const char *, char *, int);
-phandle_t OF_finddevice(const char *);
-int OF_instance_to_path(ihandle_t, char *, int);
-int OF_package_to_path(phandle_t, char *, int);
-int OF_call_method(char *, ihandle_t, int, int, ...);
+phandle_t OF_peer(phandle_t node);
+phandle_t OF_child(phandle_t node);
+phandle_t OF_parent(phandle_t node);
+ssize_t OF_getproplen(phandle_t node, const char *propname);
+ssize_t OF_getprop(phandle_t node, const char *propname, void *buf,
+ size_t len);
+ssize_t OF_getprop_alloc(phandle_t node, const char *propname,
+ int elsz, void **buf);
+int OF_nextprop(phandle_t node, const char *propname, char *buf,
+ size_t len);
+int OF_setprop(phandle_t node, const char *name, const void *buf,
+ size_t len);
+ssize_t OF_canon(const char *path, char *buf, size_t len);
+phandle_t OF_finddevice(const char *path);
+ssize_t OF_package_to_path(phandle_t node, char *buf, size_t len);
/* Device I/O functions */
-ihandle_t OF_open(char *);
-void OF_close(ihandle_t);
-int OF_read(ihandle_t, void *, int);
-int OF_write(ihandle_t, void *, int);
-int OF_seek(ihandle_t, u_quad_t);
+ihandle_t OF_open(const char *path);
+void OF_close(ihandle_t instance);
+ssize_t OF_read(ihandle_t instance, void *buf, size_t len);
+ssize_t OF_write(ihandle_t instance, const void *buf, size_t len);
+int OF_seek(ihandle_t instance, uint64_t where);
+
+phandle_t OF_instance_to_package(ihandle_t instance);
+ssize_t OF_instance_to_path(ihandle_t instance, char *buf, size_t len);
+int OF_call_method(const char *method, ihandle_t instance,
+ int nargs, int nreturns, ...);
/* Memory functions */
-void *OF_claim(void *, u_int, u_int);
-void OF_release(void *, u_int);
+void *OF_claim(void *virtrequest, size_t size, u_int align);
+void OF_release(void *virt, size_t size);
/* Control transfer functions */
-void OF_boot(char *);
void OF_enter(void);
void OF_exit(void) __attribute__((noreturn));
-void OF_chain(void *, u_int,
- void (*)(void *, u_int, void *, void *, u_int), void *, u_int);
/* User interface functions */
-int OF_interpret(char *, int, ...);
-
-/* Time function */
-int OF_milliseconds(void);
+int OF_interpret(const char *cmd, int nreturns, ...);
#endif /* _KERNEL */
#endif /* _OPENFIRM_H_ */
diff --git a/sys/dev/ofw/openfirmio.c b/sys/dev/ofw/openfirmio.c
index 47f2517..d042f02 100644
--- a/sys/dev/ofw/openfirmio.c
+++ b/sys/dev/ofw/openfirmio.c
@@ -221,7 +221,7 @@ openfirm_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
if (error)
break;
}
- ok = OF_nextprop(node, name, newname);
+ ok = OF_nextprop(node, name, newname, sizeof(newname));
if (ok == 0) {
error = ENOENT;
break;
diff --git a/sys/dev/ofw/openpromio.c b/sys/dev/ofw/openpromio.c
index cb7343f..8ba6d3a 100644
--- a/sys/dev/ofw/openpromio.c
+++ b/sys/dev/ofw/openpromio.c
@@ -174,7 +174,7 @@ openprom_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
error = OF_getprop(node, prop, buf, proplen);
break;
case OPROMNXTPROP:
- error = OF_nextprop(node, prop, buf);
+ error = OF_nextprop(node, prop, buf, OPROMMAXPARAM);
proplen = strlen(buf);
break;
}
diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c
index 6709d6d..2ad55fd 100644
--- a/sys/dev/re/if_re.c
+++ b/sys/dev/re/if_re.c
@@ -1157,6 +1157,7 @@ re_attach(device_t dev)
msic = 0;
if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
+ sc->rl_flags |= RL_FLAG_PCIE;
msic = pci_msi_count(dev);
if (bootverbose)
device_printf(dev, "MSI count : %d\n", msic);
@@ -1262,8 +1263,13 @@ re_attach(device_t dev)
sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE |
RL_FLAG_MACSTAT;
break;
- case RL_HWREV_8168C:
case RL_HWREV_8168C_SPIN2:
+ sc->rl_flags |= RL_FLAG_MACSLEEP;
+ /* FALLTHROUGH */
+ case RL_HWREV_8168C:
+ if ((hwrev & 0x00700000) == 0x00200000)
+ sc->rl_flags |= RL_FLAG_MACSLEEP;
+ /* FALLTHROUGH */
case RL_HWREV_8168CP:
case RL_HWREV_8168D:
sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE |
@@ -1351,6 +1357,16 @@ re_attach(device_t dev)
goto fail;
}
+ /* Take controller out of deep sleep mode. */
+ if ((sc->rl_flags & RL_FLAG_MACSLEEP) != 0) {
+ if ((CSR_READ_1(sc, RL_MACDBG) & 0x80) == 0x80)
+ CSR_WRITE_1(sc, RL_GPIO,
+ CSR_READ_1(sc, RL_GPIO) | 0x01);
+ else
+ CSR_WRITE_1(sc, RL_GPIO,
+ CSR_READ_1(sc, RL_GPIO) & ~0x01);
+ }
+
/* Take PHY out of power down mode. */
if ((sc->rl_flags & RL_FLAG_PHYWAKE) != 0) {
re_gmii_writereg(dev, 1, 0x1f, 0);
@@ -2027,16 +2043,6 @@ re_txeof(struct rl_softc *sc)
/* No changes made to the TX ring, so no flush needed */
if (sc->rl_ldata.rl_tx_free != sc->rl_ldata.rl_tx_desc_cnt) {
- /*
- * Some chips will ignore a second TX request issued
- * while an existing transmission is in progress. If
- * the transmitter goes idle but there are still
- * packets waiting to be sent, we need to restart the
- * channel here to flush them out. This only seems to
- * be required with the PCIe devices.
- */
- CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START);
-
#ifdef RE_TX_MODERATION
/*
* If not all descriptors have been reaped yet, reload
@@ -2100,6 +2106,9 @@ re_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
return;
if (status)
CSR_WRITE_2(sc, RL_ISR, status);
+ if ((status & (RL_ISR_TX_OK | RL_ISR_TX_DESC_UNAVAIL)) &&
+ (sc->rl_flags & RL_FLAG_PCIE))
+ CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START);
/*
* XXX check behaviour on receiver stalls.
@@ -2161,6 +2170,17 @@ re_int_task(void *arg, int npending)
if (status & (RL_ISR_RX_OK|RL_ISR_RX_ERR|RL_ISR_FIFO_OFLOW))
rval = re_rxeof(sc);
+ /*
+ * Some chips will ignore a second TX request issued
+ * while an existing transmission is in progress. If
+ * the transmitter goes idle but there are still
+ * packets waiting to be sent, we need to restart the
+ * channel here to flush them out. This only seems to
+ * be required with the PCIe devices.
+ */
+ if ((status & (RL_ISR_TX_OK | RL_ISR_TX_DESC_UNAVAIL)) &&
+ (sc->rl_flags & RL_FLAG_PCIE))
+ CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START);
if (status & (
#ifdef RE_TX_MODERATION
RL_ISR_TIMEOUT_EXPIRED|
@@ -2963,6 +2983,12 @@ re_resume(device_t dev)
RL_LOCK(sc);
ifp = sc->rl_ifp;
+ /* Take controller out of sleep mode. */
+ if ((sc->rl_flags & RL_FLAG_MACSLEEP) != 0) {
+ if ((CSR_READ_1(sc, RL_MACDBG) & 0x80) == 0x80)
+ CSR_WRITE_1(sc, RL_GPIO,
+ CSR_READ_1(sc, RL_GPIO) | 0x01);
+ }
/* reinitialize interface if necessary */
if (ifp->if_flags & IFF_UP)
@@ -3018,6 +3044,12 @@ re_setwol(struct rl_softc *sc)
return;
ifp = sc->rl_ifp;
+ /* Put controller into sleep mode. */
+ if ((sc->rl_flags & RL_FLAG_MACSLEEP) != 0) {
+ if ((CSR_READ_1(sc, RL_MACDBG) & 0x80) == 0x80)
+ CSR_WRITE_1(sc, RL_GPIO,
+ CSR_READ_1(sc, RL_GPIO) & ~0x01);
+ }
if ((ifp->if_capenable & IFCAP_WOL) != 0 &&
(sc->rl_flags & RL_FLAG_WOLRXENB) != 0)
CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_RX_ENB);
diff --git a/sys/dev/snp/snp.c b/sys/dev/snp/snp.c
index f2dcc1b..8d6485c 100644
--- a/sys/dev/snp/snp.c
+++ b/sys/dev/snp/snp.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/poll.h>
+#include <sys/proc.h>
#include <sys/snoop.h>
#include <sys/sx.h>
#include <sys/systm.h>
@@ -246,7 +247,7 @@ snp_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
sx_xunlock(&snp_register_lock);
return (EBUSY);
}
- error = ttyhook_register(&ss->snp_tty, td, *(int *)data,
+ error = ttyhook_register(&ss->snp_tty, td->td_proc, *(int *)data,
&snp_hook, ss);
sx_xunlock(&snp_register_lock);
if (error != 0)
diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c
index 4be21fb1..a185f51 100644
--- a/sys/dev/sound/pci/hda/hdac.c
+++ b/sys/dev/sound/pci/hda/hdac.c
@@ -83,7 +83,7 @@
#include "mixer_if.h"
-#define HDA_DRV_TEST_REV "20081123_0118"
+#define HDA_DRV_TEST_REV "20081219_0119"
SND_DECLARE_FILE("$FreeBSD$");
@@ -180,6 +180,11 @@ SND_DECLARE_FILE("$FreeBSD$");
#define HDA_SIS_966 HDA_MODEL_CONSTRUCT(SIS, 0x7502)
#define HDA_SIS_ALL HDA_MODEL_CONSTRUCT(SIS, 0xffff)
+/* ULI */
+#define ULI_VENDORID 0x10b9
+#define HDA_ULI_M5461 HDA_MODEL_CONSTRUCT(ULI, 0x5461)
+#define HDA_ULI_ALL HDA_MODEL_CONSTRUCT(ULI, 0xffff)
+
/* OEM/subvendors */
/* Intel */
@@ -467,12 +472,14 @@ static const struct {
{ HDA_ATI_SB600, "ATI SB600" },
{ HDA_VIA_VT82XX, "VIA VT8251/8237A" },
{ HDA_SIS_966, "SiS 966" },
+ { HDA_ULI_M5461, "ULI M5461" },
/* Unknown */
{ HDA_INTEL_ALL, "Intel (Unknown)" },
{ HDA_NVIDIA_ALL, "NVidia (Unknown)" },
{ HDA_ATI_ALL, "ATI (Unknown)" },
{ HDA_VIA_ALL, "VIA (Unknown)" },
{ HDA_SIS_ALL, "SiS (Unknown)" },
+ { HDA_ULI_ALL, "ULI (Unknown)" },
};
#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0]))
@@ -635,6 +642,7 @@ static const struct {
/* Silicon Image */
#define SII_VENDORID 0x1095
+#define HDA_CODEC_SII1392 HDA_CODEC_CONSTRUCT(SII, 0x1392)
#define HDA_CODEC_SIIXXXX HDA_CODEC_CONSTRUCT(SII, 0xffff)
/* Lucent/Agere */
@@ -669,9 +677,21 @@ static const struct {
#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715)
#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716)
#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717)
+#define HDA_CODEC_VT1708B_0 HDA_CODEC_CONSTRUCT(VIA, 0xe720)
+#define HDA_CODEC_VT1708B_1 HDA_CODEC_CONSTRUCT(VIA, 0xe721)
+#define HDA_CODEC_VT1708B_2 HDA_CODEC_CONSTRUCT(VIA, 0xe722)
+#define HDA_CODEC_VT1708B_3 HDA_CODEC_CONSTRUCT(VIA, 0xe723)
+#define HDA_CODEC_VT1708B_4 HDA_CODEC_CONSTRUCT(VIA, 0xe724)
+#define HDA_CODEC_VT1708B_5 HDA_CODEC_CONSTRUCT(VIA, 0xe725)
+#define HDA_CODEC_VT1708B_6 HDA_CODEC_CONSTRUCT(VIA, 0xe726)
+#define HDA_CODEC_VT1708B_7 HDA_CODEC_CONSTRUCT(VIA, 0xe727)
#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff)
/* ATI */
+#define HDA_CODEC_ATIRS600_1 HDA_CODEC_CONSTRUCT(ATI, 0x793c)
+#define HDA_CODEC_ATIRS600_2 HDA_CODEC_CONSTRUCT(ATI, 0x7919)
+#define HDA_CODEC_ATIRS690 HDA_CODEC_CONSTRUCT(ATI, 0x791a)
+#define HDA_CODEC_ATIR6XX HDA_CODEC_CONSTRUCT(ATI, 0xaa01)
#define HDA_CODEC_ATIXXXX HDA_CODEC_CONSTRUCT(ATI, 0xffff)
/* NVIDIA */
@@ -774,6 +794,19 @@ static const struct {
{ HDA_CODEC_VT1709_5, "VIA VT1709_5" },
{ HDA_CODEC_VT1709_6, "VIA VT1709_6" },
{ HDA_CODEC_VT1709_7, "VIA VT1709_7" },
+ { HDA_CODEC_VT1708B_0, "VIA VT1708B_0" },
+ { HDA_CODEC_VT1708B_1, "VIA VT1708B_1" },
+ { HDA_CODEC_VT1708B_2, "VIA VT1708B_2" },
+ { HDA_CODEC_VT1708B_3, "VIA VT1708B_3" },
+ { HDA_CODEC_VT1708B_4, "VIA VT1708B_4" },
+ { HDA_CODEC_VT1708B_5, "VIA VT1708B_5" },
+ { HDA_CODEC_VT1708B_6, "VIA VT1708B_6" },
+ { HDA_CODEC_VT1708B_7, "VIA VT1708B_7" },
+ { HDA_CODEC_ATIRS600_1,"ATI RS600 HDMI" },
+ { HDA_CODEC_ATIRS600_2,"ATI RS600 HDMI" },
+ { HDA_CODEC_ATIRS690, "ATI RS690/780 HDMI" },
+ { HDA_CODEC_ATIR6XX, "ATI R6xx HDMI" },
+ { HDA_CODEC_SII1392, "Silicon Image SiI1392 HDMI" },
/* Unknown codec */
{ HDA_CODEC_ALCXXXX, "Realtek (Unknown)" },
{ HDA_CODEC_ADXXXX, "Analog Devices (Unknown)" },
diff --git a/sys/dev/usb/ucom.c b/sys/dev/usb/ucom.c
index 7496d40..ae263a0 100644
--- a/sys/dev/usb/ucom.c
+++ b/sys/dev/usb/ucom.c
@@ -700,6 +700,29 @@ ucomstartread(struct ucom_softc *sc)
return (USBD_NORMAL_COMPLETION);
}
+void
+ucomrxchars(struct ucom_softc *sc, u_char *cp, u_int32_t cc)
+{
+ struct tty *tp = sc->sc_tty;
+
+ /* Give characters to tty layer. */
+ if (ttydisc_can_bypass(tp)) {
+ DPRINTFN(7, ("ucomreadcb: buf = %*D\n", cc, cp, ""));
+ cc -= ttydisc_rint_bypass(tp, cp, cc);
+ } else {
+ while (cc > 0) {
+ DPRINTFN(7, ("ucomreadcb: char = 0x%02x\n", *cp));
+ if (ttydisc_rint(tp, *cp, 0) == -1)
+ break;
+ cc--;
+ cp++;
+ }
+ }
+ if (cc > 0)
+ device_printf(sc->sc_dev, "lost %d chars\n", cc);
+ ttydisc_rint_done(tp);
+}
+
static void
ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
{
@@ -709,6 +732,7 @@ ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
u_int32_t cc;
u_char *cp;
+ (void)tp; /* Used for debugging */
DPRINTF(("ucomreadcb: status = %d\n", status));
if (status != USBD_NORMAL_COMPLETION) {
@@ -737,22 +761,8 @@ ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
device_get_nameunit(sc->sc_dev), cc);
goto resubmit;
}
- if (cc < 1)
- goto resubmit;
-
- /* Give characters to tty layer. */
- while (cc > 0) {
- DPRINTFN(7, ("ucomreadcb: char = 0x%02x\n", *cp));
- if (ttydisc_rint(tp, *cp, 0) == -1) {
- /* XXX what should we do? */
- printf("%s: lost %d chars\n",
- device_get_nameunit(sc->sc_dev), cc);
- break;
- }
- cc--;
- cp++;
- }
- ttydisc_rint_done(tp);
+ if (cc > 0)
+ ucomrxchars(sc, cp, cc);
resubmit:
err = ucomstartread(sc);
diff --git a/sys/dev/usb/ucomvar.h b/sys/dev/usb/ucomvar.h
index 0fcd7f3..4433a1a 100644
--- a/sys/dev/usb/ucomvar.h
+++ b/sys/dev/usb/ucomvar.h
@@ -166,3 +166,4 @@ void ucom_attach_tty(struct ucom_softc *, char*, int);
int ucom_attach(struct ucom_softc *);
int ucom_detach(struct ucom_softc *);
void ucom_status_change(struct ucom_softc *);
+void ucomrxchars(struct ucom_softc *sc, u_char *cp, u_int32_t cc);
diff --git a/sys/dev/usb/uftdi.c b/sys/dev/usb/uftdi.c
index 5a9921b..c32bfa6 100644
--- a/sys/dev/usb/uftdi.c
+++ b/sys/dev/usb/uftdi.c
@@ -100,7 +100,7 @@ SYSCTL_INT(_hw_usb_uftdi, OID_AUTO, debug, CTLFLAG_RW,
* These are the maximum number of bytes transferred per frame.
* The output buffer size cannot be increased due to the size encoding.
*/
-#define UFTDIIBUFSIZE 64
+#define UFTDIIBUFSIZE 256
#define UFTDIOBUFSIZE 64
struct uftdi_softc {
@@ -458,32 +458,33 @@ uftdi_read(void *vsc, int portno, u_char **ptr, u_int32_t *count)
{
struct uftdi_softc *sc = vsc;
u_char msr, lsr;
+ unsigned l;
+
+ DPRINTFN(15,("uftdi_read: sc=%p, port=%d count=%d\n",
+ sc, portno, *count));
+ while (*count > 0) {
+ l = *count;
+ if (l > 64)
+ l = 64;
+
+ msr = FTDI_GET_MSR(*ptr);
+ lsr = FTDI_GET_LSR(*ptr);
+
+ if (sc->sc_msr != msr ||
+ (sc->sc_lsr & FTDI_LSR_MASK) != (lsr & FTDI_LSR_MASK)) {
+ DPRINTF(("uftdi_read: status change msr=0x%02x(0x%02x) "
+ "lsr=0x%02x(0x%02x)\n", msr, sc->sc_msr,
+ lsr, sc->sc_lsr));
+ sc->sc_msr = msr;
+ sc->sc_lsr = lsr;
+ ucom_status_change(&sc->sc_ucom);
+ }
- DPRINTFN(15,("uftdi_read: sc=%p, port=%d count=%d\n", sc, portno,
- *count));
-
- msr = FTDI_GET_MSR(*ptr);
- lsr = FTDI_GET_LSR(*ptr);
-
-#ifdef USB_DEBUG
- if (*count != 2)
- DPRINTFN(10,("uftdi_read: sc=%p, port=%d count=%d data[0]="
- "0x%02x\n", sc, portno, *count, (*ptr)[2]));
-#endif
-
- if (sc->sc_msr != msr ||
- (sc->sc_lsr & FTDI_LSR_MASK) != (lsr & FTDI_LSR_MASK)) {
- DPRINTF(("uftdi_read: status change msr=0x%02x(0x%02x) "
- "lsr=0x%02x(0x%02x)\n", msr, sc->sc_msr,
- lsr, sc->sc_lsr));
- sc->sc_msr = msr;
- sc->sc_lsr = lsr;
- ucom_status_change(&sc->sc_ucom);
+ if (l > 2)
+ ucomrxchars(&sc->sc_ucom, (*ptr) + 2, l - 2);
+ *ptr += l;
+ *count -= l;
}
-
- /* Pick up status and adjust data part. */
- *ptr += 2;
- *count -= 2;
}
static size_t
diff --git a/sys/fs/hpfs/hpfs_vnops.c b/sys/fs/hpfs/hpfs_vnops.c
index c5a2a06..4ec6b1e 100644
--- a/sys/fs/hpfs/hpfs_vnops.c
+++ b/sys/fs/hpfs/hpfs_vnops.c
@@ -661,7 +661,7 @@ hpfs_strategy(ap)
bp->b_error = error;
bp->b_ioflags |= BIO_ERROR;
bufdone(bp);
- return (error);
+ return (0);
}
if ((long)bp->b_blkno == -1)
vfs_bio_clrbuf(bp);
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index ccbd0b1..9dc547f 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -1880,7 +1880,7 @@ msdosfs_strategy(ap)
bp->b_error = error;
bp->b_ioflags |= BIO_ERROR;
bufdone(bp);
- return (error);
+ return (0);
}
if ((long)bp->b_blkno == -1)
vfs_bio_clrbuf(bp);
diff --git a/sys/fs/ntfs/ntfs_vnops.c b/sys/fs/ntfs/ntfs_vnops.c
index 76c3c64..ee62a5c 100644
--- a/sys/fs/ntfs/ntfs_vnops.c
+++ b/sys/fs/ntfs/ntfs_vnops.c
@@ -339,7 +339,7 @@ ntfs_strategy(ap)
}
}
bufdone(bp);
- return (error);
+ return (0);
}
static int
diff --git a/sys/fs/nwfs/nwfs_vnops.c b/sys/fs/nwfs/nwfs_vnops.c
index 9dcd9aa..ca0a887 100644
--- a/sys/fs/nwfs/nwfs_vnops.c
+++ b/sys/fs/nwfs/nwfs_vnops.c
@@ -804,7 +804,7 @@ static int nwfs_strategy (ap)
*/
if ((bp->b_flags & B_ASYNC) == 0 )
error = nwfs_doio(ap->a_vp, bp, cr, td);
- return (error);
+ return (0);
}
diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c
index e34ebe2..9b1e76d 100644
--- a/sys/fs/smbfs/smbfs_vnops.c
+++ b/sys/fs/smbfs/smbfs_vnops.c
@@ -864,7 +864,7 @@ smbfs_strategy (ap)
if ((bp->b_flags & B_ASYNC) == 0 )
error = smbfs_doio(ap->a_vp, bp, cr, td);
- return error;
+ return (0);
}
int
diff --git a/sys/geom/geom_vfs.c b/sys/geom/geom_vfs.c
index 0621eff..86c909d 100644
--- a/sys/geom/geom_vfs.c
+++ b/sys/geom/geom_vfs.c
@@ -93,10 +93,23 @@ g_vfs_strategy(struct bufobj *bo, struct buf *bp)
{
struct g_consumer *cp;
struct bio *bip;
+ int vfslocked;
cp = bo->bo_private;
G_VALID_CONSUMER(cp);
+ /*
+ * If the the provider has orphaned us, just return EXIO.
+ */
+ if (cp->provider == NULL) {
+ bp->b_error = ENXIO;
+ bp->b_ioflags |= BIO_ERROR;
+ vfslocked = VFS_LOCK_GIANT(((struct mount *)NULL));
+ bufdone(bp);
+ VFS_UNLOCK_GIANT(vfslocked);
+ return;
+ }
+
bip = g_alloc_bio();
bip->bio_cmd = bp->b_iocmd;
bip->bio_offset = bp->b_iooffset;
@@ -110,18 +123,20 @@ g_vfs_strategy(struct bufobj *bo, struct buf *bp)
static void
g_vfs_orphan(struct g_consumer *cp)
{
+ struct g_geom *gp;
+ struct bufobj *bo;
+
+ g_topology_assert();
+
+ gp = cp->geom;
+ bo = gp->softc;
+ g_trace(G_T_TOPOLOGY, "g_vfs_orphan(%p(%s))", cp, gp->name);
+ if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
+ g_access(cp, -cp->acr, -cp->acw, -cp->ace);
+ g_detach(cp);
/*
- * Don't do anything here yet.
- *
- * Ideally we should detach the consumer already now, but that
- * leads to a locking requirement in the I/O path to see if we have
- * a consumer or not. Considering how ugly things are going to get
- * anyway as none of our filesystems are graceful about i/o errors,
- * this is not important right now.
- *
- * Down the road, this is the place where we could give the user
- * a "Abort, Retry or Ignore" option to replace the media again.
+ * Do not destroy the geom. Filesystem will do this during unmount.
*/
}
diff --git a/sys/gnu/fs/ext2fs/ext2_vnops.c b/sys/gnu/fs/ext2fs/ext2_vnops.c
index f81d509..1b5023c 100644
--- a/sys/gnu/fs/ext2fs/ext2_vnops.c
+++ b/sys/gnu/fs/ext2fs/ext2_vnops.c
@@ -1399,7 +1399,7 @@ ext2_strategy(ap)
bp->b_error = error;
bp->b_ioflags |= BIO_ERROR;
bufdone(bp);
- return (error);
+ return (0);
}
if ((long)bp->b_blkno == -1)
vfs_bio_clrbuf(bp);
diff --git a/sys/gnu/fs/reiserfs/reiserfs_vnops.c b/sys/gnu/fs/reiserfs/reiserfs_vnops.c
index e6323ea..12fe409 100644
--- a/sys/gnu/fs/reiserfs/reiserfs_vnops.c
+++ b/sys/gnu/fs/reiserfs/reiserfs_vnops.c
@@ -350,8 +350,13 @@ reiserfs_strategy(struct vop_strategy_args /* {
bp->b_ioflags |= BIO_ERROR;
}
+ if (error) {
+ bp->b_ioflags |= BIO_ERROR;
+ bp->b_error = error;
+ }
+
bufdone(bp);
- return (error);
+ return (0);
}
/*
diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c b/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c
index d0efcf2..6d8d4eb 100644
--- a/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c
+++ b/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c
@@ -1136,7 +1136,7 @@ _xfs_strategy(
bp->b_error = error;
bp->b_ioflags |= BIO_ERROR;
bufdone(bp);
- return (error);
+ return (0);
}
if ((long)bp->b_blkno == -1)
vfs_bio_clrbuf(bp);
diff --git a/sys/i386/conf/DEFAULTS b/sys/i386/conf/DEFAULTS
index 2450f82..1411f09 100644
--- a/sys/i386/conf/DEFAULTS
+++ b/sys/i386/conf/DEFAULTS
@@ -20,8 +20,8 @@ device io # I/O device
device uart_ns8250
# Default partitioning schemes
-options GEOM_BSD
-options GEOM_MBR
+options GEOM_PART_BSD
+options GEOM_PART_MBR
# enable support for native hardware
options NATIVE
diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s
index 0ad2597..1451fa8 100644
--- a/sys/i386/i386/exception.s
+++ b/sys/i386/i386/exception.s
@@ -438,9 +438,18 @@ doreti_nmi:
iret
outofnmi:
/*
- * Clear interrupts and jump to AST handling code.
+ * Call the callchain capture hook after turning interrupts back on.
*/
+ movl pmc_hook,%ecx
+ orl %ecx,%ecx
+ jz doreti_exit
+ pushl %esp /* frame pointer */
+ pushl $PMC_FN_USER_CALLCHAIN /* command */
+ movl PCPU(CURTHREAD),%eax
+ pushl %eax /* curthread */
sti
+ call *%ecx
+ addl $12,%esp
jmp doreti_ast
ENTRY(end_exceptions)
#endif
diff --git a/sys/i386/i386/identcpu.c b/sys/i386/i386/identcpu.c
index 67ff943..cf70af7 100644
--- a/sys/i386/i386/identcpu.c
+++ b/sys/i386/i386/identcpu.c
@@ -826,15 +826,15 @@ printcpuinfo(void)
"\003SVM" /* Secure Virtual Mode */
"\004ExtAPIC" /* Extended APIC register */
"\005CR8" /* CR8 in legacy mode */
- "\006<b5>"
- "\007<b6>"
- "\010<b7>"
+ "\006ABM" /* LZCNT instruction */
+ "\007SSE4A" /* SSE4A */
+ "\010MAS" /* Misaligned SSE mode */
"\011Prefetch" /* 3DNow! Prefetch/PrefetchW */
- "\012<b9>"
- "\013<b10>"
- "\014<b11>"
- "\015<b12>"
- "\016<b13>"
+ "\012OSVW" /* OS visible workaround */
+ "\013IBS" /* Instruction based sampling */
+ "\014SSE5" /* SSE5 */
+ "\015SKINIT" /* SKINIT/STGI */
+ "\016WDT" /* Watchdog timer */
"\017<b14>"
"\020<b15>"
"\021<b16>"
diff --git a/sys/i386/include/elf.h b/sys/i386/include/elf.h
index cf2a2d2..1470173 100644
--- a/sys/i386/include/elf.h
+++ b/sys/i386/include/elf.h
@@ -84,18 +84,6 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused for i386). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-
-/*
- * The following non-standard values are used for passing information
- * from John Polstra's testbed program to the dynamic linker. These
- * are expected to go away soon.
- *
- * Unfortunately, these overlap the Linux non-standard values, so they
- * must not be used in the same context.
- */
-#define AT_BRK 10 /* Starting point for sbrk and brk. */
-#define AT_DEBUG 11 /* Debugging level. */
-
/*
* The following non-standard values are used in Linux ELF binaries.
*/
diff --git a/sys/i386/include/specialreg.h b/sys/i386/include/specialreg.h
index b4842e9..c3cbec7 100644
--- a/sys/i386/include/specialreg.h
+++ b/sys/i386/include/specialreg.h
@@ -147,7 +147,15 @@
#define AMDID2_SVM 0x00000004
#define AMDID2_EXT_APIC 0x00000008
#define AMDID2_CR8 0x00000010
+#define AMDID2_ABM 0x00000020
+#define AMDID2_SSE4A 0x00000040
+#define AMDID2_MAS 0x00000080
#define AMDID2_PREFETCH 0x00000100
+#define AMDID2_OSVW 0x00000200
+#define AMDID2_IBS 0x00000400
+#define AMDID2_SSE5 0x00000800
+#define AMDID2_SKINIT 0x00001000
+#define AMDID2_WDT 0x00002000
/*
* CPUID instruction 1 eax info
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index 7444901..42365fb 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -245,8 +245,6 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
args = (Elf32_Auxargs *)imgp->auxargs;
pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2);
- if (args->trace)
- AUXARGS_ENTRY(pos, AT_DEBUG, 1);
if (args->execfd != -1)
AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
diff --git a/sys/ia64/include/elf.h b/sys/ia64/include/elf.h
index ec22512..faab8d1 100644
--- a/sys/ia64/include/elf.h
+++ b/sys/ia64/include/elf.h
@@ -82,18 +82,6 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused for i386). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-
-/*
- * The following non-standard values are used for passing information
- * from John Polstra's testbed program to the dynamic linker. These
- * are expected to go away soon.
- *
- * Unfortunately, these overlap the Linux non-standard values, so they
- * must not be used in the same context.
- */
-#define AT_BRK 10 /* Starting point for sbrk and brk. */
-#define AT_DEBUG 11 /* Debugging level. */
-
/*
* The following non-standard values are used in Linux ELF binaries.
*/
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index af78e55..431ee38 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -97,9 +97,6 @@ SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO,
TUNABLE_INT("kern.elf" __XSTRING(__ELF_WORD_SIZE) ".fallback_brand",
&__elfN(fallback_brand));
-static int elf_trace = 0;
-SYSCTL_INT(_debug, OID_AUTO, __elfN(trace), CTLFLAG_RW, &elf_trace, 0, "");
-
static int elf_legacy_coredump = 0;
SYSCTL_INT(_debug, OID_AUTO, __elfN(legacy_coredump), CTLFLAG_RW,
&elf_legacy_coredump, 0, "");
@@ -839,7 +836,6 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
elf_auxargs->base = addr;
elf_auxargs->flags = 0;
elf_auxargs->entry = entry;
- elf_auxargs->trace = elf_trace;
imgp->auxargs = elf_auxargs;
imgp->interpreted = 0;
@@ -894,12 +890,8 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp)
base = (Elf_Addr *)*stack_base;
pos = base + (imgp->args->argc + imgp->args->envc + 2);
- if (args->trace) {
- AUXARGS_ENTRY(pos, AT_DEBUG, 1);
- }
- if (args->execfd != -1) {
+ if (args->execfd != -1)
AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
- }
AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
diff --git a/sys/kern/kern_cpu.c b/sys/kern/kern_cpu.c
index 50fff53..7b0b588 100644
--- a/sys/kern/kern_cpu.c
+++ b/sys/kern/kern_cpu.c
@@ -144,7 +144,9 @@ static int
cpufreq_attach(device_t dev)
{
struct cpufreq_softc *sc;
+ struct pcpu *pc;
device_t parent;
+ uint64_t rate;
int numdevs;
CF_DEBUG("initializing %s\n", device_get_nameunit(dev));
@@ -156,7 +158,12 @@ cpufreq_attach(device_t dev)
CF_MTX_INIT(&sc->lock);
sc->curr_level.total_set.freq = CPUFREQ_VAL_UNKNOWN;
SLIST_INIT(&sc->saved_freq);
- sc->max_mhz = CPUFREQ_VAL_UNKNOWN;
+ /* Try to get current CPU freq to use it as maximum later if needed */
+ pc = cpu_get_pcpu(dev);
+ if (cpu_est_clockrate(pc->pc_cpuid, &rate) == 0)
+ sc->max_mhz = rate / 1000000;
+ else
+ sc->max_mhz = CPUFREQ_VAL_UNKNOWN;
/*
* Only initialize one set of sysctls for all CPUs. In the future,
diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c
index 03581a4..a7810ef 100644
--- a/sys/kern/kern_mbuf.c
+++ b/sys/kern/kern_mbuf.c
@@ -120,7 +120,6 @@ tunable_mbinit(void *dummy)
}
SYSINIT(tunable_mbinit, SI_SUB_TUNABLES, SI_ORDER_MIDDLE, tunable_mbinit, NULL);
-/* XXX: These should be tuneables. Can't change UMA limits on the fly. */
static int
sysctl_nmbclusters(SYSCTL_HANDLER_ARGS)
{
diff --git a/sys/kern/subr_kobj.c b/sys/kern/subr_kobj.c
index 4e2f096..bc36667 100644
--- a/sys/kern/subr_kobj.c
+++ b/sys/kern/subr_kobj.c
@@ -60,6 +60,19 @@ static struct mtx kobj_mtx;
static int kobj_mutex_inited;
static int kobj_next_id = 1;
+/*
+ * In the event that kobj_mtx has not been initialized yet,
+ * we will ignore it, and run without locks in order to support
+ * use of KOBJ before mutexes are available. This early in the boot
+ * process, everything is single threaded and so races should not
+ * happen. This is used to provide the PMAP layer on PowerPC, as well
+ * as board support.
+ */
+
+#define KOBJ_LOCK() if (kobj_mutex_inited) mtx_lock(&kobj_mtx);
+#define KOBJ_UNLOCK() if (kobj_mutex_inited) mtx_unlock(&kobj_mtx);
+#define KOBJ_ASSERT(what) if (kobj_mutex_inited) mtx_assert(&kobj_mtx,what);
+
SYSCTL_UINT(_kern, OID_AUTO, kobj_methodcount, CTLFLAG_RD,
&kobj_next_id, 0, "");
@@ -74,12 +87,6 @@ kobj_init_mutex(void *arg)
SYSINIT(kobj, SI_SUB_LOCK, SI_ORDER_ANY, kobj_init_mutex, NULL);
-void
-kobj_machdep_init(void)
-{
- kobj_init_mutex(NULL);
-}
-
/*
* This method structure is used to initialise new caches. Since the
* desc pointer is NULL, it is guaranteed never to match any read
@@ -99,8 +106,8 @@ kobj_error_method(void)
static void
kobj_register_method(struct kobjop_desc *desc)
{
+ KOBJ_ASSERT(MA_OWNED);
- mtx_assert(&kobj_mtx, MA_OWNED);
if (desc->id == 0) {
desc->id = kobj_next_id++;
}
@@ -117,7 +124,7 @@ kobj_class_compile_common(kobj_class_t cls, kobj_ops_t ops)
kobj_method_t *m;
int i;
- mtx_assert(&kobj_mtx, MA_OWNED);
+ KOBJ_ASSERT(MA_OWNED);
/*
* Don't do anything if we are already compiled.
@@ -145,7 +152,7 @@ kobj_class_compile(kobj_class_t cls)
{
kobj_ops_t ops;
- mtx_assert(&kobj_mtx, MA_NOTOWNED);
+ KOBJ_ASSERT(MA_NOTOWNED);
/*
* Allocate space for the compiled ops table.
@@ -154,7 +161,7 @@ kobj_class_compile(kobj_class_t cls)
if (!ops)
panic("kobj_compile_methods: out of memory");
- mtx_lock(&kobj_mtx);
+ KOBJ_LOCK();
/*
* We may have lost a race for kobj_class_compile here - check
@@ -162,28 +169,30 @@ kobj_class_compile(kobj_class_t cls)
* class.
*/
if (cls->ops) {
- mtx_unlock(&kobj_mtx);
+ KOBJ_UNLOCK();
free(ops, M_KOBJ);
return;
}
kobj_class_compile_common(cls, ops);
- mtx_unlock(&kobj_mtx);
+ KOBJ_UNLOCK();
}
void
kobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops)
{
- mtx_assert(&kobj_mtx, MA_NOTOWNED);
+ KOBJ_ASSERT(MA_NOTOWNED);
/*
* Increment refs to make sure that the ops table is not freed.
*/
- mtx_lock(&kobj_mtx);
+ KOBJ_LOCK();
+
cls->refs++;
kobj_class_compile_common(cls, ops);
- mtx_unlock(&kobj_mtx);
+
+ KOBJ_UNLOCK();
}
static kobj_method_t*
@@ -254,8 +263,8 @@ kobj_class_free(kobj_class_t cls)
kobj_method_t *m;
void* ops = 0;
- mtx_assert(&kobj_mtx, MA_NOTOWNED);
- mtx_lock(&kobj_mtx);
+ KOBJ_ASSERT(MA_NOTOWNED);
+ KOBJ_LOCK();
/*
* Protect against a race between kobj_create and
@@ -275,7 +284,7 @@ kobj_class_free(kobj_class_t cls)
cls->ops = 0;
}
- mtx_unlock(&kobj_mtx);
+ KOBJ_UNLOCK();
if (ops)
free(ops, M_KOBJ);
@@ -302,9 +311,9 @@ kobj_create(kobj_class_t cls,
void
kobj_init(kobj_t obj, kobj_class_t cls)
{
- mtx_assert(&kobj_mtx, MA_NOTOWNED);
+ KOBJ_ASSERT(MA_NOTOWNED);
retry:
- mtx_lock(&kobj_mtx);
+ KOBJ_LOCK();
/*
* Consider compiling the class' method table.
@@ -315,7 +324,7 @@ kobj_init(kobj_t obj, kobj_class_t cls)
* because of the call to malloc - we drop the lock
* and re-try.
*/
- mtx_unlock(&kobj_mtx);
+ KOBJ_UNLOCK();
kobj_class_compile(cls);
goto retry;
}
@@ -323,7 +332,7 @@ kobj_init(kobj_t obj, kobj_class_t cls)
obj->ops = cls->ops;
cls->refs++;
- mtx_unlock(&kobj_mtx);
+ KOBJ_UNLOCK();
}
void
@@ -337,11 +346,11 @@ kobj_delete(kobj_t obj, struct malloc_type *mtype)
* after its last instance is deleted. As an optimisation, we
* should defer this for a short while to avoid thrashing.
*/
- mtx_assert(&kobj_mtx, MA_NOTOWNED);
- mtx_lock(&kobj_mtx);
+ KOBJ_ASSERT(MA_NOTOWNED);
+ KOBJ_LOCK();
cls->refs--;
refs = cls->refs;
- mtx_unlock(&kobj_mtx);
+ KOBJ_UNLOCK();
if (!refs)
kobj_class_free(cls);
diff --git a/sys/kern/subr_param.c b/sys/kern/subr_param.c
index 3701fda..6a0745f 100644
--- a/sys/kern/subr_param.c
+++ b/sys/kern/subr_param.c
@@ -73,6 +73,10 @@ __FBSDID("$FreeBSD$");
#define MAXFILES (maxproc * 2)
#endif
+enum VM_GUEST { VM_GUEST_NO, VM_GUEST_VM, VM_GUEST_XEN };
+
+static int sysctl_kern_vm_guest(SYSCTL_HANDLER_ARGS);
+
int hz;
int tick;
int maxusers; /* base tunable */
@@ -86,6 +90,7 @@ int nswbuf;
int maxswzone; /* max swmeta KVA storage */
int maxbcache; /* max buffer cache KVA storage */
int maxpipekva; /* Limit on pipe KVA */
+int vm_guest; /* Running as virtual machine guest? */
u_long maxtsiz; /* max text size */
u_long dfldsiz; /* initial data size limit */
u_long maxdsiz; /* max data size */
@@ -110,6 +115,9 @@ SYSCTL_ULONG(_kern, OID_AUTO, maxssiz, CTLFLAG_RDTUN, &maxssiz, 0,
"max stack size");
SYSCTL_ULONG(_kern, OID_AUTO, sgrowsiz, CTLFLAG_RDTUN, &sgrowsiz, 0,
"amount to grow stack");
+SYSCTL_PROC(_kern, OID_AUTO, vm_guest, CTLFLAG_RD | CTLTYPE_STRING,
+ NULL, 0, sysctl_kern_vm_guest, "A",
+ "Virtual machine detected? (none|generic|xen)");
/*
* These have to be allocated somewhere; allocating
@@ -133,7 +141,18 @@ static const char *const vm_pnames[] = {
NULL
};
-static int
+static const char *const vm_guest_sysctl_names[] = {
+ "none",
+ "generic",
+ "xen",
+ NULL
+};
+
+
+/*
+ * Detect known Virtual Machine hosts by inspecting the emulated BIOS.
+ */
+static enum VM_GUEST
detect_virtual(void)
{
char *sysenv;
@@ -144,7 +163,7 @@ detect_virtual(void)
for (i = 0; vm_bnames[i] != NULL; i++)
if (strcmp(sysenv, vm_bnames[i]) == 0) {
freeenv(sysenv);
- return (1);
+ return (VM_GUEST_VM);
}
freeenv(sysenv);
}
@@ -153,11 +172,11 @@ detect_virtual(void)
for (i = 0; vm_pnames[i] != NULL; i++)
if (strcmp(sysenv, vm_pnames[i]) == 0) {
freeenv(sysenv);
- return (1);
+ return (VM_GUEST_VM);
}
freeenv(sysenv);
}
- return (0);
+ return (VM_GUEST_NO);
}
/*
@@ -166,11 +185,15 @@ detect_virtual(void)
void
init_param1(void)
{
-
+#ifndef XEN
+ vm_guest = detect_virtual();
+#else
+ vm_guest = VM_GUEST_XEN;
+#endif
hz = -1;
TUNABLE_INT_FETCH("kern.hz", &hz);
if (hz == -1)
- hz = detect_virtual() ? HZ_VM : HZ;
+ hz = vm_guest > VM_GUEST_NO ? HZ_VM : HZ;
tick = 1000000 / hz;
#ifdef VM_SWZONE_SIZE_MAX
@@ -257,3 +280,13 @@ init_param3(long kmempages)
maxpipekva = 512 * 1024;
TUNABLE_INT_FETCH("kern.ipc.maxpipekva", &maxpipekva);
}
+
+/*
+ * Sysctl stringiying handler for kern.vm_guest.
+ */
+static int
+sysctl_kern_vm_guest(SYSCTL_HANDLER_ARGS)
+{
+ return (SYSCTL_OUT(req, vm_guest_sysctl_names[vm_guest],
+ strlen(vm_guest_sysctl_names[vm_guest])));
+}
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index e7e8120..ba54524 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -44,7 +44,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_hwpmc_hooks.h"
#include "opt_ktrace.h"
#include "opt_mac.h"
#ifdef __i386__
@@ -179,13 +178,6 @@ ast(struct trapframe *framep)
td->td_profil_ticks = 0;
td->td_pflags &= ~TDP_OWEUPC;
}
-#if defined(HWPMC_HOOKS)
- if (td->td_pflags & TDP_CALLCHAIN) {
- PMC_CALL_HOOK_UNLOCKED(td, PMC_FN_USER_CALLCHAIN,
- (void *) framep);
- td->td_pflags &= ~TDP_CALLCHAIN;
- }
-#endif
if (flags & TDF_ALRMPEND) {
PROC_LOCK(p);
psignal(p, SIGVTALRM);
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index e0045ce..d6735fa 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/cons.h>
#include <sys/fcntl.h>
#include <sys/file.h>
+#include <sys/filedesc.h>
#include <sys/filio.h>
#ifdef COMPAT_43TTY
#include <sys/ioctl_compat.h>
@@ -870,10 +871,10 @@ tty_alloc(struct ttydevsw *tsw, void *sc, struct mtx *mutex)
tty_init_termios(tp);
- cv_init(&tp->t_inwait, "tty input");
- cv_init(&tp->t_outwait, "tty output");
- cv_init(&tp->t_bgwait, "tty background");
- cv_init(&tp->t_dcdwait, "tty dcd");
+ cv_init(&tp->t_inwait, "ttyinp");
+ cv_init(&tp->t_outwait, "ttyout");
+ cv_init(&tp->t_bgwait, "ttybgw");
+ cv_init(&tp->t_dcdwait, "ttydcd");
ttyinq_init(&tp->t_inq);
ttyoutq_init(&tp->t_outq);
@@ -883,7 +884,7 @@ tty_alloc(struct ttydevsw *tsw, void *sc, struct mtx *mutex)
tp->t_mtx = mutex;
} else {
tp->t_mtx = &tp->t_mtxobj;
- mtx_init(&tp->t_mtxobj, "tty lock", NULL, MTX_DEF);
+ mtx_init(&tp->t_mtxobj, "ttylck", NULL, MTX_DEF);
}
knlist_init(&tp->t_inpoll.si_note, tp->t_mtx, NULL, NULL, NULL);
@@ -1673,18 +1674,24 @@ ttyhook_defrint(struct tty *tp, char c, int flags)
}
int
-ttyhook_register(struct tty **rtp, struct thread *td, int fd,
+ttyhook_register(struct tty **rtp, struct proc *p, int fd,
struct ttyhook *th, void *softc)
{
struct tty *tp;
struct file *fp;
struct cdev *dev;
struct cdevsw *cdp;
+ struct filedesc *fdp;
int error;
/* Validate the file descriptor. */
- if (fget(td, fd, &fp) != 0)
- return (EINVAL);
+ if ((fdp = p->p_fd) == NULL)
+ return (EBADF);
+ FILEDESC_SLOCK(fdp);
+ if ((fp = fget_locked(fdp, fd)) == NULL || fp->f_ops == &badfileops) {
+ FILEDESC_SUNLOCK(fdp);
+ return (EBADF);
+ }
/* Make sure the vnode is bound to a character device. */
error = EINVAL;
@@ -1723,7 +1730,7 @@ ttyhook_register(struct tty **rtp, struct thread *td, int fd,
done3: tty_unlock(tp);
done2: dev_relthread(dev);
-done1: fdrop(fp, td);
+done1: FILEDESC_SUNLOCK(fdp);
return (error);
}
diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c
index 9e81a6d..c767daa 100644
--- a/sys/kern/tty_pts.c
+++ b/sys/kern/tty_pts.c
@@ -273,6 +273,16 @@ ptsdev_ioctl(struct file *fp, u_long cmd, void *data,
case FIONBIO:
/* This device supports non-blocking operation. */
return (0);
+ case FIONREAD:
+ tty_lock(tp);
+ if (psc->pts_flags & PTS_FINISHED) {
+ /* Force read() to be called. */
+ *(int *)data = 1;
+ } else {
+ *(int *)data = ttydisc_getc_poll(tp);
+ }
+ tty_unlock(tp);
+ return (0);
case FIODGNAME: {
struct fiodgname_arg *fgn;
const char *p;
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index 06682d5..c4840ce 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -814,6 +814,10 @@ success:
if ((cnp->cn_flags & (ISLASTCN | LOCKSHARED | LOCKLEAF)) ==
(ISLASTCN | LOCKLEAF) && VOP_ISLOCKED(dp) != LK_EXCLUSIVE) {
vn_lock(dp, LK_UPGRADE | LK_RETRY);
+ if (dp->v_iflag & VI_DOOMED) {
+ error = ENOENT;
+ goto bad2;
+ }
}
if (vfslocked && dvfslocked)
VFS_UNLOCK_GIANT(dvfslocked); /* Only need one */
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 12368c9..2b870f0 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -507,29 +507,20 @@ vfs_mount_destroy(struct mount *mp)
{
MNT_ILOCK(mp);
+ mp->mnt_kern_flag |= MNTK_REFEXPIRE;
+ if (mp->mnt_kern_flag & MNTK_MWAIT) {
+ mp->mnt_kern_flag &= ~MNTK_MWAIT;
+ wakeup(mp);
+ }
while (mp->mnt_ref)
msleep(mp, MNT_MTX(mp), PVFS, "mntref", 0);
- if (mp->mnt_writeopcount > 0) {
- printf("Waiting for mount point write ops\n");
- while (mp->mnt_writeopcount > 0) {
- mp->mnt_kern_flag |= MNTK_SUSPEND;
- msleep(&mp->mnt_writeopcount,
- MNT_MTX(mp),
- PZERO, "mntdestroy2", 0);
- }
- printf("mount point write ops completed\n");
- }
- if (mp->mnt_secondary_writes > 0) {
- printf("Waiting for mount point secondary write ops\n");
- while (mp->mnt_secondary_writes > 0) {
- mp->mnt_kern_flag |= MNTK_SUSPEND;
- msleep(&mp->mnt_secondary_writes,
- MNT_MTX(mp),
- PZERO, "mntdestroy3", 0);
- }
- printf("mount point secondary write ops completed\n");
- }
- MNT_IUNLOCK(mp);
+ KASSERT(mp->mnt_ref == 0,
+ ("%s: invalid refcount in the drain path @ %s:%d", __func__,
+ __FILE__, __LINE__));
+ if (mp->mnt_writeopcount != 0)
+ panic("vfs_mount_destroy: nonzero writeopcount");
+ if (mp->mnt_secondary_writes != 0)
+ panic("vfs_mount_destroy: nonzero secondary_writes");
mp->mnt_vfc->vfc_refcount--;
if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) {
struct vnode *vp;
@@ -538,18 +529,10 @@ vfs_mount_destroy(struct mount *mp)
vprint("", vp);
panic("unmount: dangling vnode");
}
- MNT_ILOCK(mp);
- if (mp->mnt_kern_flag & MNTK_MWAIT)
- wakeup(mp);
- if (mp->mnt_writeopcount != 0)
- panic("vfs_mount_destroy: nonzero writeopcount");
- if (mp->mnt_secondary_writes != 0)
- panic("vfs_mount_destroy: nonzero secondary_writes");
if (mp->mnt_nvnodelistsize != 0)
panic("vfs_mount_destroy: nonzero nvnodelistsize");
- mp->mnt_writeopcount = -1000;
- mp->mnt_nvnodelistsize = -1000;
- mp->mnt_secondary_writes = -1000;
+ if (mp->mnt_lockref != 0)
+ panic("vfs_mount_destroy: nonzero lock refcount");
MNT_IUNLOCK(mp);
#ifdef MAC
mac_mount_destroy(mp);
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 16373b1..eb02693 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -345,7 +345,7 @@ vfs_busy(struct mount *mp, int flags)
MNT_ILOCK(mp);
MNT_REF(mp);
if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
- if (flags & MBF_NOWAIT) {
+ if (flags & MBF_NOWAIT || mp->mnt_kern_flag & MNTK_REFEXPIRE) {
MNT_REL(mp);
MNT_IUNLOCK(mp);
return (ENOENT);
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index e4f4f8b..198009d 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -200,19 +200,21 @@ quotactl(td, uap)
AUDIT_ARG(uid, uap->uid);
if (jailed(td->td_ucred) && !prison_quotas)
return (EPERM);
- NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1,
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
UIO_USERSPACE, uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
vfslocked = NDHASGIANT(&nd);
NDFREE(&nd, NDF_ONLY_PNBUF);
mp = nd.ni_vp->v_mount;
- if ((error = vfs_busy(mp, 0))) {
- vrele(nd.ni_vp);
+ vfs_ref(mp);
+ vput(nd.ni_vp);
+ error = vfs_busy(mp, 0);
+ vfs_rel(mp);
+ if (error) {
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
- vrele(nd.ni_vp);
error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, td);
vfs_unbusy(mp);
VFS_UNLOCK_GIANT(vfslocked);
@@ -306,6 +308,12 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
vfs_ref(mp);
NDFREE(&nd, NDF_ONLY_PNBUF);
vput(nd.ni_vp);
+ error = vfs_busy(mp, 0);
+ vfs_rel(mp);
+ if (error) {
+ VFS_UNLOCK_GIANT(vfslocked);
+ return (error);
+ }
#ifdef MAC
error = mac_mount_check_stat(td->td_ucred, mp);
if (error)
@@ -329,7 +337,7 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
}
*buf = *sp;
out:
- vfs_rel(mp);
+ vfs_unbusy(mp);
VFS_UNLOCK_GIANT(vfslocked);
if (mtx_owned(&Giant))
printf("statfs(%d): %s: %d\n", vfslocked, path, error);
@@ -391,6 +399,10 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
error = EBADF;
goto out;
}
+ error = vfs_busy(mp, 0);
+ vfs_rel(mp);
+ if (error)
+ goto out;
#ifdef MAC
error = mac_mount_check_stat(td->td_ucred, mp);
if (error)
@@ -415,7 +427,7 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
*buf = *sp;
out:
if (mp)
- vfs_rel(mp);
+ vfs_unbusy(mp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
diff --git a/sys/mips/conf/DEFAULTS b/sys/mips/conf/DEFAULTS
index 18a9a26..dc480ce 100644
--- a/sys/mips/conf/DEFAULTS
+++ b/sys/mips/conf/DEFAULTS
@@ -9,5 +9,5 @@ device mem
device uart_ns8250
-options GEOM_BSD
-options GEOM_MBR
+options GEOM_PART_BSD
+options GEOM_PART_MBR
diff --git a/sys/mips/include/elf.h b/sys/mips/include/elf.h
index fc1035e..6e48ec1 100644
--- a/sys/mips/include/elf.h
+++ b/sys/mips/include/elf.h
@@ -40,9 +40,11 @@
/* Information taken from MIPS ABI supplemental */
-#include <sys/elf32.h> /* Definitions common to all 32 bit architectures. */
-
+#ifndef __ELF_WORD_SIZE
#define __ELF_WORD_SIZE 32 /* Used by <sys/elf_generic.h> */
+#endif
+#include <sys/elf32.h> /* Definitions common to all 32 bit architectures. */
+#include <sys/elf64.h> /* Definitions common to all 64 bit architectures. */
#include <sys/elf_generic.h>
#define ELF_ARCH EM_MIPS
@@ -114,6 +116,16 @@ typedef union {
Elf32_Word gt_bytes; /* This many bytes would be used */
} gt_entry; /* Subsequent entries in section */
} Elf32_gptab;
+typedef union {
+ struct {
+ Elf64_Word gt_current_g_value; /* -G val used in compilation */
+ Elf64_Word gt_unused; /* Not used */
+ } gt_header; /* First entry in section */
+ struct {
+ Elf64_Word gt_g_value; /* If this val were used for -G */
+ Elf64_Word gt_bytes; /* This many bytes would be used */
+ } gt_entry; /* Subsequent entries in section */
+} Elf64_gptab;
/*
* Entry found in sections of type SHT_MIPS_REGINFO.
@@ -123,6 +135,11 @@ typedef struct {
Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */
Elf32_Sword ri_gp_value; /* $gp register value */
} Elf32_RegInfo;
+typedef struct {
+ Elf64_Word ri_gprmask; /* General registers used */
+ Elf64_Word ri_cprmask[4]; /* Coprocessor registers used */
+ Elf64_Sword ri_gp_value; /* $gp register value */
+} Elf64_RegInfo;
/*
@@ -147,10 +164,38 @@ typedef struct {
#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */
#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */
-#define R_TYPE(name) __CONCAT(R_MIPS_,name)
+/*
+ * These are from the 64-bit Irix ELF ABI
+ */
+#define R_MIPS_SHIFT5 16
+#define R_MIPS_SHIFT6 17
+#define R_MIPS_64 18
+#define R_MIPS_GOT_DISP 19
+#define R_MIPS_GOT_PAGE 20
+#define R_MIPS_GOT_OFST 21
+#define R_MIPS_GOT_HI16 22
+#define R_MIPS_GOT_LO16 23
+#define R_MIPS_SUB 24
+#define R_MIPS_INSERT_A 25
+#define R_MIPS_INSERT_B 26
+#define R_MIPS_DELETE 27
+#define R_MIPS_HIGHER 28
+#define R_MIPS_HIGHEST 29
+#define R_MIPS_SCN_DISP 32
+#define R_MIPS_REL16 33
+#define R_MIPS_ADD_IMMEDIATE 34
+#define R_MIPS_PJUMP 35
+#define R_MIPS_ERLGOT 36
+
+#define R_MIPS_max 37
+#define R_TYPE(name) __CONCAT(R_MIPS_,name)
/* Define "machine" characteristics */
+#if __ELF_WORD_SIZE == 32
#define ELF_TARG_CLASS ELFCLASS32
+#else
+#define ELF_TARG_CLASS ELFCLASS64
+#endif
#ifdef __MIPSEB__
#define ELF_TARG_DATA ELFDATA2MSB
#else
@@ -159,23 +204,30 @@ typedef struct {
#define ELF_TARG_MACH EM_MIPS
#define ELF_TARG_VER 1
-
/*
* Auxiliary vector entries for passing information to the interpreter.
*
* The i386 supplement to the SVR4 ABI specification names this "auxv_t",
* but POSIX lays claim to all symbols ending with "_t".
*/
-
typedef struct { /* Auxiliary vector entry on initial stack */
int a_type; /* Entry type. */
union {
- long a_val; /* Integer value. */
+ int a_val; /* Integer value. */
void *a_ptr; /* Address. */
void (*a_fcn)(void); /* Function pointer (not used). */
} a_un;
} Elf32_Auxinfo;
+typedef struct { /* Auxiliary vector entry on initial stack */
+ long a_type; /* Entry type. */
+ union {
+ long a_val; /* Integer value. */
+ void *a_ptr; /* Address. */
+ void (*a_fcn)(void); /* Function pointer (not used). */
+ } a_un;
+} Elf64_Auxinfo;
+
__ElfType(Auxinfo);
/* Values for a_type. */
@@ -189,18 +241,6 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused for i386). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-
-/*
- * The following non-standard values are used for passing information
- * from John Polstra's testbed program to the dynamic linker. These
- * are expected to go away soon.
- *
- * Unfortunately, these overlap the Linux non-standard values, so they
- * must not be used in the same context.
- */
-#define AT_BRK 10 /* Starting point for sbrk and brk. */
-#define AT_DEBUG 11 /* Debugging level. */
-
/*
* The following non-standard values are used in Linux ELF binaries.
*/
diff --git a/sys/mips/mips/elf_machdep.c b/sys/mips/mips/elf_machdep.c
index dc08bc2..163d0ee 100644
--- a/sys/mips/mips/elf_machdep.c
+++ b/sys/mips/mips/elf_machdep.c
@@ -93,22 +93,6 @@ SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&freebsd_brand_info);
-static Elf32_Brandinfo freebsd_brand_oinfo = {
- .brand = ELFOSABI_FREEBSD,
- .machine = EM_MIPS,
- .compat_3_brand = "FreeBSD",
- .emul_path = NULL,
- .interp_path = "/usr/libexec/ld-elf.so.1",
- .sysvec = &elf32_freebsd_sysvec,
- .interp_newpath = NULL,
- .flags = 0
-};
-
-SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
- (sysinit_cfunc_t) elf32_insert_brand_entry,
- &freebsd_brand_oinfo);
-
-
void
elf32_dump_thread(struct thread *td __unused, void *dst __unused,
size_t *off __unused)
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index eee15c1..97d7cf2 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -30,9 +30,6 @@ SUBDIR= ${_3dfx} \
${_asr} \
ata \
ath \
- ath_rate_amrr \
- ath_rate_onoe \
- ath_rate_sample \
aue \
${_auxio} \
axe \
diff --git a/sys/modules/ath/Makefile b/sys/modules/ath/Makefile
index 4f478f6..068d337 100644
--- a/sys/modules/ath/Makefile
+++ b/sys/modules/ath/Makefile
@@ -29,44 +29,80 @@
# $FreeBSD$
#
-.PATH: ${.CURDIR}/../../dev/ath \
- ${.CURDIR}/../../dev/ath/ath_hal \
- ${.CURDIR}/../../dev/ath/ath_hal/ar5210 \
- ${.CURDIR}/../../dev/ath/ath_hal/ar5211 \
- ${.CURDIR}/../../dev/ath/ath_hal/ar5212 \
- ${.CURDIR}/../../dev/ath/ath_hal/ar5416
+ATH_RATE?= sample # tx rate control algorithm
-AR5210_SRCS=ah_eeprom_v1.c \
+.PATH: ${.CURDIR}/../../dev/ath
+.PATH: ${.CURDIR}/../../dev/ath/ath_hal
+
+KMOD= if_ath
+SRCS= if_ath.c if_ath_pci.c
+# NB: v3 eeprom support used by both AR5211 and AR5212; just include it
+SRCS+= ah_osdep.c ah.c ah_regdomain.c ah_eeprom_v3.c
+SRCS+= device_if.h bus_if.h pci_if.h opt_inet.h opt_ath.h opt_ah.h
+
+#
+# AR5210 support; these are first generation 11a-only devices.
+#
+.PATH: ${.CURDIR}/../../dev/ath/ath_hal/ar5210
+SRCS+= ah_eeprom_v1.c \
ar5210_attach.c ar5210_beacon.c ar5210_interrupts.c \
ar5210_keycache.c ar5210_misc.c ar5210_phy.c ar5210_power.c \
ar5210_recv.c ar5210_reset.c ar5210_xmit.c
-AR5211_SRCS=ar5211_attach.c ar5211_beacon.c ar5211_interrupts.c \
+
+#
+# AR5211 support; these are second generation 11b/g/a devices
+# (but 11g was OFDM only and is not supported).
+#
+.PATH: ${.CURDIR}/../../dev/ath/ath_hal/ar5211
+SRCS+= ar5211_attach.c ar5211_beacon.c ar5211_interrupts.c \
ar5211_keycache.c ar5211_misc.c ar5211_phy.c ar5211_power.c \
ar5211_recv.c ar5211_reset.c ar5211_xmit.c
-AR5212_SRCS=ar5212_ani.c ar5212_attach.c ar5212_beacon.c ar5212_eeprom.c \
+
+#
+# AR5212 support; this covers all other pci/cardbus legacy parts.
+#
+.PATH: ${.CURDIR}/../../dev/ath/ath_hal/ar5212
+SRCS+= ar5212_ani.c ar5212_attach.c ar5212_beacon.c ar5212_eeprom.c \
ar5212_gpio.c ar5212_interrupts.c ar5212_keycache.c ar5212_misc.c \
ar5212_phy.c ar5212_power.c ar5212_recv.c ar5212_reset.c \
- ar5212_rfgain.c ar5212_xmit.c \
- ar2413.c ar2425.c ar5111.c ar5112.c ar5413.c
-AR5416_SRCS=ah_eeprom_v14.c \
+ ar5212_rfgain.c ar5212_xmit.c
+# RF backends
+SRCS+= ar5111.c
+SRCS+= ar5112.c
+SRCS+= ar2413.c
+SRCS+= ar2425.c
+SRCS+= ar5413.c
+
+#
+# AR5416, AR9160 support; these are 11n parts but only really
+# supported (right now) operating in legacy mode. Note enabling
+# this support requires defining AH_SUPPORT_AR5416 in opt_ah.h
+# so the 11n tx/rx descriptor format is handled.
+#
+# NB: 9160 depends on 5416 but 5416 does not require 9160
+#
+.PATH: ${.CURDIR}/../../dev/ath/ath_hal/ar5416
+SRCS+= ah_eeprom_v14.c \
ar5416_ani.c ar5416_attach.c ar5416_beacon.c ar5416_cal.c \
ar5416_cal_iq.c ar5416_cal_adcgain.c ar5416_cal_adcdc.c \
ar5416_eeprom.c ar5416_gpio.c ar5416_interrupts.c ar5416_keycache.c \
ar5416_misc.c ar5416_phy.c ar5416_power.c ar5416_recv.c \
- ar5416_reset.c ar5416_xmit.c \
- ar2133.c
-AR9160_SRCS=ar9160_attach.c
+ ar5416_reset.c ar5416_xmit.c
+SRCS+= ar9160_attach.c
+# RF backend for 5416 and 9160
+SRCS+= ar2133.c
-KMOD= if_ath
-SRCS= if_ath.c if_ath_pci.c
-# NB: v3 eeprom support used by both AR5211 and AR5212; just include it
-SRCS+= ah_osdep.c ah.c ah_regdomain.c ah_eeprom_v3.c
-SRCS+= ${AR5210_SRCS}
-SRCS+= ${AR5211_SRCS}
-SRCS+= ${AR5212_SRCS}
-SRCS+= ${AR5416_SRCS}
-SRCS+= ${AR9160_SRCS}
-SRCS+= device_if.h bus_if.h pci_if.h opt_inet.h opt_ath.h opt_ah.h
+# NB: rate control is bound to the driver by symbol names so only pick one
+.if ${ATH_RATE} == "sample"
+.PATH: ${.CURDIR}/../../dev/ath/ath_rate/sample
+SRCS+= sample.c opt_wlan.h
+.elif ${ATH_RATE} == "onoe"
+.PATH: ${.CURDIR}/../../dev/ath/ath_rate/onoe
+SRCS+= onoe.c
+.elif ${ATH_RATE} == "amrr"
+.PATH: ${.CURDIR}/../../dev/ath/ath_rate/amrr
+SRCS+= amrr.c
+.endif
CFLAGS+= -I. -I${.CURDIR}/../../dev/ath -I${.CURDIR}/../../dev/ath/ath_hal
diff --git a/sys/modules/ath_rate_amrr/Makefile b/sys/modules/ath_rate_amrr/Makefile
deleted file mode 100644
index cbeea9c..0000000
--- a/sys/modules/ath_rate_amrr/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Copyright (c) 2004-2008 Sam Leffler, Errno Consulting
-# 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.
-# 2. Redistributions in binary form must reproduce at minimum a disclaimer
-# similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
-# redistribution must be conditioned upon including a substantially
-# similar Disclaimer requirement for further binary redistribution.
-#
-# NO WARRANTY
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
-# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
-# THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
-#
-# $FreeBSD$
-#
-
-.PATH: ${.CURDIR}/../../dev/ath/ath_rate/amrr
-
-KMOD= ath_rate
-SRCS= amrr.c
-SRCS+= device_if.h bus_if.h pci_if.h opt_inet.h opt_ah.h opt_wlan.h
-
-CFLAGS+= -I. -I${.CURDIR}/../../dev/ath -I${.CURDIR}/../../dev/ath/ath_hal
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/ath_rate_onoe/Makefile b/sys/modules/ath_rate_onoe/Makefile
deleted file mode 100644
index fe725e4..0000000
--- a/sys/modules/ath_rate_onoe/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Copyright (c) 2004-2008 Sam Leffler, Errno Consulting
-# 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.
-# 2. Redistributions in binary form must reproduce at minimum a disclaimer
-# similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
-# redistribution must be conditioned upon including a substantially
-# similar Disclaimer requirement for further binary redistribution.
-#
-# NO WARRANTY
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
-# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
-# THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
-#
-# $FreeBSD$
-#
-
-.PATH: ${.CURDIR}/../../dev/ath/ath_rate/onoe
-
-KMOD= ath_rate
-SRCS= onoe.c
-SRCS+= device_if.h bus_if.h pci_if.h opt_inet.h opt_ah.h opt_wlan.h
-
-CFLAGS+= -I. -I${.CURDIR}/../../dev/ath -I${.CURDIR}/../../dev/ath/ath_hal
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/ath_rate_sample/Makefile b/sys/modules/ath_rate_sample/Makefile
deleted file mode 100644
index c179d10..0000000
--- a/sys/modules/ath_rate_sample/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Copyright (c) 2004-2008 Sam Leffler, Errno Consulting
-# 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.
-# 2. Redistributions in binary form must reproduce at minimum a disclaimer
-# similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
-# redistribution must be conditioned upon including a substantially
-# similar Disclaimer requirement for further binary redistribution.
-#
-# NO WARRANTY
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
-# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
-# THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
-#
-# $FreeBSD$
-#
-
-.PATH: ${.CURDIR}/../../dev/ath/ath_rate/sample
-
-KMOD= ath_rate
-SRCS= sample.c
-SRCS+= device_if.h bus_if.h pci_if.h opt_inet.h opt_ah.h opt_wlan.h
-
-CFLAGS+= -I. -I${.CURDIR}/../../dev/ath -I${.CURDIR}/../../dev/ath/ath_hal
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/cxgb/Makefile b/sys/modules/cxgb/Makefile
index 7d56988..71cbb7a 100644
--- a/sys/modules/cxgb/Makefile
+++ b/sys/modules/cxgb/Makefile
@@ -25,7 +25,7 @@ _toe_header = ${_sysdir}/netinet/toedev.h
.if exists(${_toe_header})
_toecore = toecore
-_tom = tom
+#_tom = tom
.endif
.if ${MACHINE_ARCH} == "i386" && exists(${_toe_header})
diff --git a/sys/net/ieee8023ad_lacp.c b/sys/net/ieee8023ad_lacp.c
index 27cf480..bd44e23 100644
--- a/sys/net/ieee8023ad_lacp.c
+++ b/sys/net/ieee8023ad_lacp.c
@@ -901,6 +901,7 @@ lacp_aggregator_bandwidth(struct lacp_aggregator *la)
static void
lacp_select_active_aggregator(struct lacp_softc *lsc)
{
+ struct lagg_softc *sc = lsc->lsc_softc;
struct lacp_aggregator *la;
struct lacp_aggregator *best_la = NULL;
uint64_t best_speed = 0;
@@ -956,6 +957,7 @@ lacp_select_active_aggregator(struct lacp_softc *lsc)
#endif /* defined(LACP_DEBUG) */
if (lsc->lsc_active_aggregator != best_la) {
+ sc->sc_ifp->if_baudrate = best_speed;
lsc->lsc_active_aggregator = best_la;
lacp_update_portmap(lsc);
if (best_la) {
diff --git a/sys/net/if.c b/sys/net/if.c
index 5142a5c..070202c 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -60,6 +60,7 @@
#include <sys/jail.h>
#include <sys/vimage.h>
#include <machine/stdarg.h>
+#include <vm/uma.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -157,7 +158,7 @@ static struct knlist ifklist;
#endif
int ifqmaxlen = IFQ_MAXLEN;
-struct mtx ifnet_lock;
+struct rwlock ifnet_lock;
static if_com_alloc_t *if_com_alloc[256];
static if_com_free_t *if_com_free[256];
@@ -190,14 +191,23 @@ MALLOC_DEFINE(M_IFNET, "ifnet", "interface internals");
MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
+static struct ifnet *
+ifnet_byindex_locked(u_short idx)
+{
+ INIT_VNET_NET(curvnet);
+ struct ifnet *ifp;
+
+ ifp = V_ifindex_table[idx].ife_ifnet;
+ return (ifp);
+}
+
struct ifnet *
ifnet_byindex(u_short idx)
{
- INIT_VNET_NET(curvnet);
struct ifnet *ifp;
IFNET_RLOCK();
- ifp = V_ifindex_table[idx].ife_ifnet;
+ ifp = ifnet_byindex_locked(idx);
IFNET_RUNLOCK();
return (ifp);
}
@@ -218,7 +228,7 @@ ifaddr_byindex(u_short idx)
struct ifaddr *ifa;
IFNET_RLOCK();
- ifa = ifnet_byindex(idx)->if_addr;
+ ifa = ifnet_byindex_locked(idx)->if_addr;
IFNET_RUNLOCK();
return (ifa);
}
@@ -498,7 +508,7 @@ if_free_type(struct ifnet *ifp, u_char type)
ifnet_setbyindex(ifp->if_index, NULL);
/* XXX: should be locked with if_findindex() */
- while (V_if_index > 0 && ifnet_byindex(V_if_index) == NULL)
+ while (V_if_index > 0 && ifnet_byindex_locked(V_if_index) == NULL)
V_if_index--;
IFNET_WUNLOCK();
@@ -1110,7 +1120,7 @@ if_rtdel(struct radix_node *rn, void *arg)
return (0);
err = rtrequest_fib(RTM_DELETE, rt_key(rt), rt->rt_gateway,
- rt_mask(rt), rt->rt_flags,
+ rt_mask(rt), rt->rt_flags|RTF_RNH_LOCKED,
(struct rtentry **) NULL, rt->rt_fibnum);
if (err) {
log(LOG_WARNING, "if_rtdel: error %d\n", err);
@@ -1366,6 +1376,9 @@ done:
return (ifa);
}
+#include <net/route.h>
+#include <net/if_llatbl.h>
+
/*
* Default action when installing a route with a Link Level gateway.
* Lookup an appropriate real ifa to point to.
diff --git a/sys/net/if_arcsubr.c b/sys/net/if_arcsubr.c
index 0f5fef3..0089d13 100644
--- a/sys/net/if_arcsubr.c
+++ b/sys/net/if_arcsubr.c
@@ -64,6 +64,7 @@
#include <net/if_arc.h>
#include <net/if_arp.h>
#include <net/bpf.h>
+#include <net/if_llatbl.h>
#if defined(INET) || defined(INET6)
#include <netinet/in.h>
@@ -108,6 +109,7 @@ arc_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
u_int8_t atype, adst;
int loop_copy = 0;
int isphds;
+ struct llentry *lle;
if (!((ifp->if_flags & IFF_UP) &&
(ifp->if_drv_flags & IFF_DRV_RUNNING)))
@@ -127,7 +129,7 @@ arc_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
else if (ifp->if_flags & IFF_NOARP)
adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF;
else {
- error = arpresolve(ifp, rt0, m, dst, &adst);
+ error = arpresolve(ifp, rt0, m, dst, &adst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
}
@@ -165,7 +167,7 @@ arc_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
#endif
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)&adst);
+ error = nd6_storelladdr(ifp, m, dst, (u_char *)&adst, &lle);
if (error)
return (error);
atype = ARCTYPE_INET6;
diff --git a/sys/net/if_atmsubr.c b/sys/net/if_atmsubr.c
index 9d1a7fa..7e36187 100644
--- a/sys/net/if_atmsubr.c
+++ b/sys/net/if_atmsubr.c
@@ -153,22 +153,11 @@ atm_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
case AF_INET:
case AF_INET6:
{
- struct rtentry *rt = NULL;
- /*
- * check route
- */
- if (rt0 != NULL) {
- error = rt_check(&rt, &rt0, dst);
- if (error)
- goto bad;
- RT_UNLOCK(rt);
- }
-
if (dst->sa_family == AF_INET6)
etype = ETHERTYPE_IPV6;
else
etype = ETHERTYPE_IP;
- if (!atmresolve(rt, m, dst, &atmdst)) {
+ if (!atmresolve(rt0, m, dst, &atmdst)) {
m = NULL;
/* XXX: atmresolve already free'd it */
senderr(EHOSTUNREACH);
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 4524fdd..73a08dd 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -64,6 +64,7 @@
#include <net/ethernet.h>
#include <net/if_bridgevar.h>
#include <net/if_vlan_var.h>
+#include <net/if_llatbl.h>
#include <net/pf_mtag.h>
#include <net/vnet.h>
@@ -87,6 +88,7 @@
#include <netipx/ipx.h>
#include <netipx/ipx_if.h>
#endif
+
int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m);
int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp,
struct sockaddr *dst, short *tp, int *hlen);
@@ -151,6 +153,7 @@ static int ether_ipfw;
#endif
#endif
+
/*
* Ethernet output routine.
* Encapsulate a packet of type family for the local net.
@@ -164,6 +167,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
short type;
int error, hdrcmplt = 0;
u_char esrc[ETHER_ADDR_LEN], edst[ETHER_ADDR_LEN];
+ struct llentry *lle = NULL;
struct ether_header *eh;
struct pf_mtag *t;
int loop_copy = 1;
@@ -186,7 +190,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
- error = arpresolve(ifp, rt0, m, dst, edst);
+ error = arpresolve(ifp, rt0, m, dst, edst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
type = htons(ETHERTYPE_IP);
@@ -221,7 +225,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
#endif
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst);
+ error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle);
if (error)
return error;
type = htons(ETHERTYPE_IPV6);
@@ -289,6 +293,17 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
senderr(EAFNOSUPPORT);
}
+ if (lle != NULL && (lle->la_flags & LLE_IFADDR)) {
+ int csum_flags = 0;
+ if (m->m_pkthdr.csum_flags & CSUM_IP)
+ csum_flags |= (CSUM_IP_CHECKED|CSUM_IP_VALID);
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)
+ csum_flags |= (CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
+ m->m_pkthdr.csum_flags |= csum_flags;
+ m->m_pkthdr.csum_data = 0xffff;
+ return (if_simloop(ifp, m, dst->sa_family, 0));
+ }
+
/*
* Add local net header. If no space in first mbuf,
* allocate another.
diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c
index e37d7ae..438a6e8 100644
--- a/sys/net/if_fddisubr.c
+++ b/sys/net/if_fddisubr.c
@@ -55,6 +55,7 @@
#include <net/if_dl.h>
#include <net/if_llc.h>
#include <net/if_types.h>
+#include <net/if_llatbl.h>
#include <net/ethernet.h>
#include <net/netisr.h>
@@ -120,6 +121,7 @@ fddi_output(ifp, m, dst, rt0)
int loop_copy = 0, error = 0, hdrcmplt = 0;
u_char esrc[FDDI_ADDR_LEN], edst[FDDI_ADDR_LEN];
struct fddi_header *fh;
+ struct llentry *lle;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
@@ -137,7 +139,7 @@ fddi_output(ifp, m, dst, rt0)
switch (dst->sa_family) {
#ifdef INET
case AF_INET: {
- error = arpresolve(ifp, rt0, m, dst, edst);
+ error = arpresolve(ifp, rt0, m, dst, edst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
type = htons(ETHERTYPE_IP);
@@ -173,7 +175,7 @@ fddi_output(ifp, m, dst, rt0)
#endif /* INET */
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst);
+ error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle);
if (error)
return (error); /* Something bad happened */
type = htons(ETHERTYPE_IPV6);
diff --git a/sys/net/if_fwsubr.c b/sys/net/if_fwsubr.c
index 77e7b70..9d7b95b 100644
--- a/sys/net/if_fwsubr.c
+++ b/sys/net/if_fwsubr.c
@@ -51,6 +51,7 @@
#include <net/if_types.h>
#include <net/bpf.h>
#include <net/firewire.h>
+#include <net/if_llatbl.h>
#if defined(INET) || defined(INET6)
#include <netinet/in.h>
@@ -80,7 +81,6 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
{
struct fw_com *fc = IFP2FWC(ifp);
int error, type;
- struct rtentry *rt = NULL;
struct m_tag *mtag;
union fw_encap *enc;
struct fw_hwaddr *destfw;
@@ -89,6 +89,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
struct mbuf *mtail;
int unicast, dgl, foff;
static int next_dgl;
+ struct llentry *lle;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
@@ -102,13 +103,6 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
goto bad;
}
- if (rt0 != NULL) {
- error = rt_check(&rt, &rt0, dst);
- if (error)
- goto bad;
- RT_UNLOCK(rt);
- }
-
/*
* For unicast, we make a tag to store the lladdr of the
* destination. This might not be the first time we have seen
@@ -144,7 +138,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
* doesn't fit into the arp model.
*/
if (unicast) {
- error = arpresolve(ifp, rt, m, dst, (u_char *) destfw);
+ error = arpresolve(ifp, rt0, m, dst, (u_char *) destfw, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
}
@@ -173,8 +167,8 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
#ifdef INET6
case AF_INET6:
if (unicast) {
- error = nd6_storelladdr(fc->fc_ifp, rt, m, dst,
- (u_char *) destfw);
+ error = nd6_storelladdr(fc->fc_ifp, m, dst,
+ (u_char *) destfw, &lle);
if (error)
return (error);
}
diff --git a/sys/net/if_iso88025subr.c b/sys/net/if_iso88025subr.c
index 00e323a..ff82e10 100644
--- a/sys/net/if_iso88025subr.c
+++ b/sys/net/if_iso88025subr.c
@@ -59,6 +59,7 @@
#include <net/if_dl.h>
#include <net/if_llc.h>
#include <net/if_types.h>
+#include <net/if_llatbl.h>
#include <net/ethernet.h>
#include <net/netisr.h>
@@ -243,7 +244,7 @@ iso88025_output(ifp, m, dst, rt0)
struct iso88025_header *th;
struct iso88025_header gen_th;
struct sockaddr_dl *sdl = NULL;
- struct rtentry *rt = NULL;
+ struct llentry *lle;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
@@ -260,14 +261,8 @@ iso88025_output(ifp, m, dst, rt0)
/* Calculate routing info length based on arp table entry */
/* XXX any better way to do this ? */
- if (rt0 != NULL) {
- error = rt_check(&rt, &rt0, dst);
- if (error)
- goto bad;
- RT_UNLOCK(rt);
- }
- if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway))
+ if (rt0 && (sdl = (struct sockaddr_dl *)rt0->rt_gateway))
if (SDL_ISO88025(sdl)->trld_rcf != 0)
rif_len = TR_RCF_RIFLEN(SDL_ISO88025(sdl)->trld_rcf);
@@ -289,7 +284,7 @@ iso88025_output(ifp, m, dst, rt0)
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
- error = arpresolve(ifp, rt0, m, dst, edst);
+ error = arpresolve(ifp, rt0, m, dst, edst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
snap_type = ETHERTYPE_IP;
@@ -324,7 +319,7 @@ iso88025_output(ifp, m, dst, rt0)
#endif /* INET */
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst);
+ error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle);
if (error)
return (error);
snap_type = ETHERTYPE_IPV6;
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index be6e0b8..0ab96b3 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -310,6 +310,7 @@ lagg_capabilities(struct lagg_softc *sc)
{
struct lagg_port *lp;
int cap = ~0, ena = ~0;
+ u_long hwa = ~0UL;
LAGG_WLOCK_ASSERT(sc);
@@ -317,14 +318,18 @@ lagg_capabilities(struct lagg_softc *sc)
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
cap &= lp->lp_ifp->if_capabilities;
ena &= lp->lp_ifp->if_capenable;
+ hwa &= lp->lp_ifp->if_hwassist;
}
cap = (cap == ~0 ? 0 : cap);
ena = (ena == ~0 ? 0 : ena);
+ hwa = (hwa == ~0 ? 0 : hwa);
if (sc->sc_ifp->if_capabilities != cap ||
- sc->sc_ifp->if_capenable != ena) {
+ sc->sc_ifp->if_capenable != ena ||
+ sc->sc_ifp->if_hwassist != hwa) {
sc->sc_ifp->if_capabilities = cap;
sc->sc_ifp->if_capenable = ena;
+ sc->sc_ifp->if_hwassist = hwa;
getmicrotime(&sc->sc_ifp->if_lastchange);
if (sc->sc_ifflags & IFF_DEBUG)
@@ -1206,6 +1211,7 @@ lagg_linkstate(struct lagg_softc *sc)
{
struct lagg_port *lp;
int new_link = LINK_STATE_DOWN;
+ uint64_t speed;
/* Our link is considered up if at least one of our ports is active */
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
@@ -1215,6 +1221,25 @@ lagg_linkstate(struct lagg_softc *sc)
}
}
if_link_state_change(sc->sc_ifp, new_link);
+
+ /* Update if_baudrate to reflect the max possible speed */
+ switch (sc->sc_proto) {
+ case LAGG_PROTO_FAILOVER:
+ sc->sc_ifp->if_baudrate = sc->sc_primary != NULL ?
+ sc->sc_primary->lp_ifp->if_baudrate : 0;
+ break;
+ case LAGG_PROTO_ROUNDROBIN:
+ case LAGG_PROTO_LOADBALANCE:
+ case LAGG_PROTO_ETHERCHANNEL:
+ speed = 0;
+ SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
+ speed += lp->lp_ifp->if_baudrate;
+ sc->sc_ifp->if_baudrate = speed;
+ break;
+ case LAGG_PROTO_LACP:
+ /* LACP updates if_baudrate itself */
+ break;
+ }
}
static void
diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
new file mode 100644
index 0000000..a3d1b05
--- /dev/null
+++ b/sys/net/if_llatbl.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
+ * Copyright (c) 2004-2008 Qing Li. All rights reserved.
+ * Copyright (c) 2008 Kip Macy. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 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 "opt_inet.h"
+#include "opt_inet6.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/syslog.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rwlock.h>
+#include <sys/vimage.h>
+
+#include <vm/uma.h>
+
+#include <netinet/in.h>
+#include <net/if_llatbl.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_var.h>
+#include <net/route.h>
+#include <netinet/if_ether.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
+
+MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables");
+
+static SLIST_HEAD(, lltable) lltables = SLIST_HEAD_INITIALIZER(lltables);
+
+extern void arprequest(struct ifnet *, struct in_addr *, struct in_addr *,
+ u_char *);
+
+/*
+ * Dump arp state for a specific address family.
+ */
+int
+lltable_sysctl_dumparp(int af, struct sysctl_req *wr)
+{
+ struct lltable *llt;
+ int error = 0;
+
+ IFNET_RLOCK();
+ SLIST_FOREACH(llt, &lltables, llt_link) {
+ if (llt->llt_af == af) {
+ error = llt->llt_dump(llt, wr);
+ if (error != 0)
+ goto done;
+ }
+ }
+done:
+ IFNET_RUNLOCK();
+ return (error);
+}
+
+/*
+ * Deletes an address from the address table.
+ * This function is called by the timer functions
+ * such as arptimer() and nd6_llinfo_timer(), and
+ * the caller does the locking.
+ */
+void
+llentry_free(struct llentry *lle)
+{
+
+ LLE_WLOCK_ASSERT(lle);
+ LIST_REMOVE(lle, lle_next);
+
+ if (lle->la_hold != NULL)
+ m_freem(lle->la_hold);
+
+ LLE_FREE_LOCKED(lle);
+}
+
+/*
+ * Free all entries from given table and free itself.
+ * Since lltables collects from all of the intefaces,
+ * the caller of this function must acquire IFNET_WLOCK().
+ */
+void
+lltable_free(struct lltable *llt)
+{
+ struct llentry *lle, *next;
+ int i;
+
+ KASSERT(llt != NULL, ("%s: llt is NULL", __func__));
+
+ IFNET_WLOCK();
+ SLIST_REMOVE(&lltables, llt, lltable, llt_link);
+ IFNET_WUNLOCK();
+
+ for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
+ LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
+
+ callout_drain(&lle->la_timer);
+ LLE_WLOCK(lle);
+ llentry_free(lle);
+ }
+ }
+
+ free(llt, M_LLTABLE);
+}
+
+void
+lltable_drain(int af)
+{
+ struct lltable *llt;
+ struct llentry *lle;
+ register int i;
+
+ IFNET_RLOCK();
+ SLIST_FOREACH(llt, &lltables, llt_link) {
+ if (llt->llt_af != af)
+ continue;
+
+ for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
+ LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
+ if (lle->la_hold) {
+ m_freem(lle->la_hold);
+ lle->la_hold = NULL;
+ }
+ }
+ }
+ }
+ IFNET_RUNLOCK();
+}
+
+/*
+ * Create a new lltable.
+ */
+struct lltable *
+lltable_init(struct ifnet *ifp, int af)
+{
+ struct lltable *llt;
+ register int i;
+
+ llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK);
+ if (llt == NULL)
+ return (NULL);
+
+ llt->llt_af = af;
+ llt->llt_ifp = ifp;
+ for (i = 0; i < LLTBL_HASHTBL_SIZE; i++)
+ LIST_INIT(&llt->lle_head[i]);
+
+ IFNET_WLOCK();
+ SLIST_INSERT_HEAD(&lltables, llt, llt_link);
+ IFNET_WUNLOCK();
+
+ return (llt);
+}
+
+/*
+ * Called in route_output when adding/deleting a route to an interface.
+ */
+int
+lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
+{
+ struct sockaddr_dl *dl =
+ (struct sockaddr_dl *)info->rti_info[RTAX_GATEWAY];
+ struct sockaddr *dst = (struct sockaddr *)info->rti_info[RTAX_DST];
+ struct ifnet *ifp;
+ struct lltable *llt;
+ struct llentry *lle;
+ u_int laflags = 0, flags = 0;
+ int error = 0;
+
+ if (dl == NULL || dl->sdl_family != AF_LINK) {
+ log(LOG_INFO, "%s: invalid dl\n", __func__);
+ return EINVAL;
+ }
+ ifp = ifnet_byindex(dl->sdl_index);
+ if (ifp == NULL) {
+ log(LOG_INFO, "%s: invalid ifp (sdl_index %d)\n",
+ __func__, dl->sdl_index);
+ return EINVAL;
+ }
+
+ switch (rtm->rtm_type) {
+ case RTM_ADD:
+ if (rtm->rtm_flags & RTF_ANNOUNCE) {
+ flags |= LLE_PUB;
+#ifdef INET
+ if (dst->sa_family == AF_INET &&
+ ((struct sockaddr_inarp *)dst)->sin_other != 0) {
+ struct rtentry *rt = rtalloc1(dst, 0, 0);
+ if (rt == NULL || !(rt->rt_flags & RTF_HOST)) {
+ log(LOG_INFO, "%s: RTM_ADD publish "
+ "(proxy only) is invalid\n",
+ __func__);
+ RTFREE(rt);
+ return EINVAL;
+ }
+ RTFREE(rt);
+
+ flags |= LLE_PROXY;
+ }
+#endif
+ }
+ flags |= LLE_CREATE;
+ break;
+
+ case RTM_DELETE:
+ flags |= LLE_DELETE;
+ break;
+
+ case RTM_CHANGE:
+ break;
+
+ default:
+ return EINVAL; /* XXX not implemented yet */
+ }
+
+ /* XXX linked list may be too expensive */
+ IFNET_RLOCK();
+ SLIST_FOREACH(llt, &lltables, llt_link) {
+ if (llt->llt_af == dst->sa_family &&
+ llt->llt_ifp == ifp)
+ break;
+ }
+ IFNET_RUNLOCK();
+ KASSERT(llt != NULL, ("Yep, ugly hacks are bad\n"));
+
+ if (flags && LLE_CREATE)
+ flags |= LLE_EXCLUSIVE;
+
+ IF_AFDATA_LOCK(ifp);
+ lle = lla_lookup(llt, flags, dst);
+ IF_AFDATA_UNLOCK(ifp);
+ if (LLE_IS_VALID(lle)) {
+ if (flags & LLE_CREATE) {
+ /*
+ * If we delay the delete, then a subsequent
+ * "arp add" should look up this entry, reset the
+ * LLE_DELETED flag, and reset the expiration timer
+ */
+ bcopy(LLADDR(dl), &lle->ll_addr, ifp->if_addrlen);
+ lle->la_flags |= LLE_VALID;
+ lle->la_flags &= ~LLE_DELETED;
+#ifdef INET6
+ /*
+ * ND6
+ */
+ if (dst->sa_family == AF_INET6)
+ lle->ln_state = ND6_LLINFO_REACHABLE;
+#endif
+ /*
+ * NB: arp and ndp always set (RTF_STATIC | RTF_HOST)
+ */
+
+ if (rtm->rtm_rmx.rmx_expire == 0) {
+ lle->la_flags |= LLE_STATIC;
+ lle->la_expire = 0;
+ } else
+ lle->la_expire = rtm->rtm_rmx.rmx_expire;
+ laflags = lle->la_flags;
+ LLE_WUNLOCK(lle);
+#ifdef INET
+ /* gratuitous ARP */
+ if ((laflags & LLE_PUB) && dst->sa_family == AF_INET) {
+ arprequest(ifp,
+ &((struct sockaddr_in *)dst)->sin_addr,
+ &((struct sockaddr_in *)dst)->sin_addr,
+ ((laflags & LLE_PROXY) ?
+ (u_char *)IF_LLADDR(ifp) :
+ (u_char *)LLADDR(dl)));
+ }
+#endif
+ } else {
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WUNLOCK(lle);
+ else
+ LLE_RUNLOCK(lle);
+ }
+ } else if ((lle == NULL) && (flags & LLE_DELETE))
+ error = EINVAL;
+
+
+ return (error);
+}
diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h
new file mode 100644
index 0000000..50e617d
--- /dev/null
+++ b/sys/net/if_llatbl.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
+ * Copyright (c) 2004-2008 Qing Li. All rights reserved.
+ * Copyright (c) 2008 Kip Macy. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 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$");
+
+#ifndef _NET_IF_LLATBL_H_
+#define _NET_IF_LLATBL_H_
+
+#include <sys/_rwlock.h>
+#include <netinet/in.h>
+
+struct ifnet;
+struct sysctl_req;
+struct rt_msghdr;
+struct rt_addrinfo;
+
+struct llentry;
+LIST_HEAD(llentries, llentry);
+
+/*
+ * Code referencing llentry must at least hold
+ * a shared lock
+ */
+struct llentry {
+ LIST_ENTRY(llentry) lle_next;
+ struct rwlock lle_lock;
+ struct lltable *lle_tbl;
+ struct llentries *lle_head;
+ struct mbuf *la_hold;
+ time_t la_expire;
+ uint16_t la_flags;
+ uint16_t la_asked;
+ uint16_t la_preempt;
+ uint16_t ln_byhint;
+ int16_t ln_state; /* IPv6 has ND6_LLINFO_NOSTATE == -2 */
+ uint16_t ln_router;
+ time_t ln_ntick;
+ int lle_refcnt;
+
+ union {
+ uint64_t mac_aligned;
+ uint16_t mac16[3];
+ } ll_addr;
+
+ /* XXX af-private? */
+ union {
+ struct callout ln_timer_ch;
+ struct callout la_timer;
+ } lle_timer;
+ /* NB: struct sockaddr must immediately follow */
+};
+
+#define LLE_WLOCK(lle) rw_wlock(&(lle)->lle_lock)
+#define LLE_RLOCK(lle) rw_rlock(&(lle)->lle_lock)
+#define LLE_WUNLOCK(lle) rw_wunlock(&(lle)->lle_lock)
+#define LLE_RUNLOCK(lle) rw_runlock(&(lle)->lle_lock)
+#define LLE_DOWNGRADE(lle) rw_downgrade(&(lle)->lle_lock)
+#define LLE_TRY_UPGRADE(lle) rw_try_upgrade(&(lle)->lle_lock)
+#define LLE_LOCK_INIT(lle) rw_init_flags(&(lle)->lle_lock, "lle", RW_DUPOK)
+#define LLE_LOCK_DESTROY(lle) rw_destroy(&(lle)->lle_lock)
+#define LLE_WLOCK_ASSERT(lle) rw_assert(&(lle)->lle_lock, RA_WLOCKED)
+
+#define LLE_IS_VALID(lle) (((lle) != NULL) && ((lle) != (void *)-1))
+
+#define LLE_ADDREF(lle) do { \
+ LLE_WLOCK_ASSERT(lle); \
+ KASSERT((lle)->lle_refcnt >= 0, \
+ ("negative refcnt %d", (lle)->lle_refcnt)); \
+ (lle)->lle_refcnt++; \
+} while (0)
+
+#define LLE_REMREF(lle) do { \
+ LLE_WLOCK_ASSERT(lle); \
+ KASSERT((lle)->lle_refcnt > 1, \
+ ("bogus refcnt %d", (lle)->lle_refcnt)); \
+ (lle)->lle_refcnt--; \
+} while (0)
+
+#define LLE_FREE_LOCKED(lle) do { \
+ if ((lle)->lle_refcnt <= 1) \
+ (lle)->lle_tbl->llt_free((lle)->lle_tbl, (lle));\
+ else { \
+ (lle)->lle_refcnt--; \
+ LLE_WUNLOCK(lle); \
+ } \
+ /* guard against invalid refs */ \
+ lle = 0; \
+} while (0)
+
+#define LLE_FREE(lle) do { \
+ LLE_WLOCK(lle); \
+ if ((lle)->lle_refcnt <= 1) \
+ (lle)->lle_tbl->llt_free((lle)->lle_tbl, (lle));\
+ else { \
+ (lle)->lle_refcnt--; \
+ LLE_WUNLOCK(lle); \
+ } \
+ /* guard against invalid refs */ \
+ lle = NULL; \
+} while (0)
+
+
+#define ln_timer_ch lle_timer.ln_timer_ch
+#define la_timer lle_timer.la_timer
+
+/* XXX bad name */
+#define L3_ADDR(lle) ((struct sockaddr *)(&lle[1]))
+#define L3_ADDR_LEN(lle) (((struct sockaddr *)(&lle[1]))->sa_len)
+
+#ifndef LLTBL_HASHTBL_SIZE
+#define LLTBL_HASHTBL_SIZE 32 /* default 32 ? */
+#endif
+
+#ifndef LLTBL_HASHMASK
+#define LLTBL_HASHMASK (LLTBL_HASHTBL_SIZE - 1)
+#endif
+
+struct lltable {
+ SLIST_ENTRY(lltable) llt_link;
+ struct llentries lle_head[LLTBL_HASHTBL_SIZE];
+ int llt_af;
+ struct ifnet *llt_ifp;
+
+ struct llentry * (*llt_new)(const struct sockaddr *, u_int);
+ void (*llt_free)(struct lltable *, struct llentry *);
+ struct llentry * (*llt_lookup)(struct lltable *, u_int flags,
+ const struct sockaddr *l3addr);
+ int (*llt_rtcheck)(struct ifnet *,
+ const struct sockaddr *);
+ int (*llt_dump)(struct lltable *,
+ struct sysctl_req *);
+};
+MALLOC_DECLARE(M_LLTABLE);
+
+/*
+ * flags to be passed to arplookup.
+ */
+#define LLE_DELETED 0x0001 /* entry must be deleted */
+#define LLE_STATIC 0x0002 /* entry is static */
+#define LLE_IFADDR 0x0004 /* entry is interface addr */
+#define LLE_VALID 0x0008 /* ll_addr is valid */
+#define LLE_PROXY 0x0010 /* proxy entry ??? */
+#define LLE_PUB 0x0020 /* publish entry ??? */
+#define LLE_DELETE 0x4000 /* delete on a lookup - match LLE_IFADDR */
+#define LLE_CREATE 0x8000 /* create on a lookup miss */
+#define LLE_EXCLUSIVE 0x2000 /* return lle xlocked */
+
+#define LLATBL_HASH(key, mask) \
+ (((((((key >> 8) ^ key) >> 8) ^ key) >> 8) ^ key) & mask)
+
+struct lltable *lltable_init(struct ifnet *, int);
+void lltable_free(struct lltable *);
+void lltable_drain(int);
+int lltable_sysctl_dumparp(int, struct sysctl_req *);
+
+void llentry_free(struct llentry *);
+
+/*
+ * Generic link layer address lookup function.
+ */
+static __inline struct llentry *
+lla_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
+{
+ return llt->llt_lookup(llt, flags, l3addr);
+}
+
+int lla_rt_output(struct rt_msghdr *, struct rt_addrinfo *);
+#endif /* _NET_IF_LLATBL_H_ */
diff --git a/sys/net/if_media.h b/sys/net/if_media.h
index 18726da..f4b3d81 100644
--- a/sys/net/if_media.h
+++ b/sys/net/if_media.h
@@ -145,6 +145,11 @@ uint64_t ifmedia_baudrate(int);
#define IFM_10G_SR 19 /* 10GBase-SR 850nm Multi-mode */
#define IFM_10G_CX4 20 /* 10GBase CX4 copper */
#define IFM_2500_SX 21 /* 2500BaseSX - multi-mode fiber */
+#define IFM_10G_TWINAX 22 /* 10GBase Twinax copper */
+#define IFM_10G_TWINAX_LONG 23 /* 10GBase Twinax Long copper */
+#define IFM_10G_LRM 24 /* 10GBase-LRM 850nm Multi-mode */
+#define IFM_UNKNOWN 25 /* New media types that have not been defined yet */
+
/* note 31 is the max! */
@@ -349,6 +354,10 @@ struct ifmedia_description {
{ IFM_10G_SR, "10Gbase-SR" }, \
{ IFM_10G_CX4, "10Gbase-CX4" }, \
{ IFM_2500_SX, "2500BaseSX" }, \
+ { IFM_10G_LRM, "10Gbase-LRM" }, \
+ { IFM_10G_TWINAX, "10Gbase-Twinax" }, \
+ { IFM_10G_TWINAX_LONG, "10Gbase-Twinax-Long" }, \
+ { IFM_UNKNOWN, "Unknown" }, \
{ 0, NULL }, \
}
@@ -603,6 +612,9 @@ struct ifmedia_baudrate {
{ IFM_ETHER | IFM_10G_SR, IF_Gbps(10ULL) }, \
{ IFM_ETHER | IFM_10G_CX4, IF_Gbps(10ULL) }, \
{ IFM_ETHER | IFM_2500_SX, IF_Mbps(2500ULL) }, \
+ { IFM_ETHER | IFM_10G_TWINAX, IF_Gbps(10ULL) }, \
+ { IFM_ETHER | IFM_10G_TWINAX_LONG, IF_Gbps(10ULL) }, \
+ { IFM_ETHER | IFM_10G_LRM, IF_Gbps(10ULL) }, \
\
{ IFM_TOKEN | IFM_TOK_STP4, IF_Mbps(4) }, \
{ IFM_TOKEN | IFM_TOK_STP16, IF_Mbps(16) }, \
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 0724488..250bed9 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -77,9 +77,11 @@ struct ifvlantrunk;
#ifdef _KERNEL
#include <sys/mbuf.h>
#include <sys/eventhandler.h>
+#include <sys/buf_ring.h>
#endif /* _KERNEL */
#include <sys/lock.h> /* XXX */
#include <sys/mutex.h> /* XXX */
+#include <sys/rwlock.h> /* XXX */
#include <sys/event.h> /* XXX */
#include <sys/_task.h>
@@ -169,25 +171,24 @@ struct ifnet {
void *if_bridge; /* bridge glue */
- struct lltable *lltables; /* list of L3-L2 resolution tables */
-
struct label *if_label; /* interface MAC label */
/* these are only used by IPv6 */
struct ifprefixhead if_prefixhead; /* list of prefixes per if */
void *if_afdata[AF_MAX];
int if_afdata_initialized;
- struct mtx if_afdata_mtx;
+ struct rwlock if_afdata_lock;
struct task if_starttask; /* task for IFF_NEEDSGIANT */
struct task if_linktask; /* task for link change events */
struct mtx if_addr_mtx; /* mutex to protect address lists */
+
LIST_ENTRY(ifnet) if_clones; /* interfaces of a cloner */
TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */
/* protected by if_addr_mtx */
void *if_pf_kif;
void *if_lagg; /* lagg glue */
- void *if_pspare[8]; /* multiq/TOE 3; vimage 3; general use 4 */
- void (*if_qflush) /* flush any queues */
+ void *if_pspare[8]; /* TOE 3; vimage 3; general use 4 */
+ void (*if_qflush) /* flush any queues */
(struct ifnet *);
int (*if_transmit) /* initiate output routine */
(struct ifnet *, struct mbuf *);
@@ -359,11 +360,19 @@ typedef void (*group_change_event_handler_t)(void *, const char *);
EVENTHANDLER_DECLARE(group_change_event, group_change_event_handler_t);
#define IF_AFDATA_LOCK_INIT(ifp) \
- mtx_init(&(ifp)->if_afdata_mtx, "if_afdata", NULL, MTX_DEF)
-#define IF_AFDATA_LOCK(ifp) mtx_lock(&(ifp)->if_afdata_mtx)
-#define IF_AFDATA_TRYLOCK(ifp) mtx_trylock(&(ifp)->if_afdata_mtx)
-#define IF_AFDATA_UNLOCK(ifp) mtx_unlock(&(ifp)->if_afdata_mtx)
-#define IF_AFDATA_DESTROY(ifp) mtx_destroy(&(ifp)->if_afdata_mtx)
+ rw_init(&(ifp)->if_afdata_lock, "if_afdata")
+
+#define IF_AFDATA_WLOCK(ifp) rw_wlock(&(ifp)->if_afdata_lock)
+#define IF_AFDATA_RLOCK(ifp) rw_rlock(&(ifp)->if_afdata_lock)
+#define IF_AFDATA_WUNLOCK(ifp) rw_wunlock(&(ifp)->if_afdata_lock)
+#define IF_AFDATA_RUNLOCK(ifp) rw_runlock(&(ifp)->if_afdata_lock)
+#define IF_AFDATA_LOCK(ifp) IF_AFDATA_WLOCK(ifp)
+#define IF_AFDATA_UNLOCK(ifp) IF_AFDATA_WUNLOCK(ifp)
+#define IF_AFDATA_TRYLOCK(ifp) rw_try_wlock(&(ifp)->if_afdata_lock)
+#define IF_AFDATA_DESTROY(ifp) rw_destroy(&(ifp)->if_afdata_lock)
+
+#define IF_AFDATA_LOCK_ASSERT(ifp) rw_assert(&(ifp)->if_afdata_lock, RA_LOCKED)
+#define IF_AFDATA_UNLOCK_ASSERT(ifp) rw_assert(&(ifp)->if_afdata_lock, RA_UNLOCKED)
#define IFF_LOCKGIANT(ifp) do { \
if ((ifp)->if_flags & IFF_NEEDSGIANT) \
@@ -540,6 +549,45 @@ do { \
IFQ_PURGE(ifq); \
} while (0)
+#ifdef _KERNEL
+static __inline void
+drbr_stats_update(struct ifnet *ifp, int len, int mflags)
+{
+
+ ifp->if_obytes += len;
+ if (mflags & M_MCAST)
+ ifp->if_omcasts++;
+}
+
+static __inline int
+drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m)
+{
+ int error = 0;
+ int len = m->m_pkthdr.len;
+ int mflags = m->m_flags;
+
+ if ((error = buf_ring_enqueue(br, m)) == ENOBUFS) {
+ br->br_drops++;
+ _IF_DROP(&ifp->if_snd);
+ m_freem(m);
+ } else
+ drbr_stats_update(ifp, len, mflags);
+
+ return (error);
+}
+
+static __inline void
+drbr_free(struct buf_ring *br, struct malloc_type *type)
+{
+ struct mbuf *m;
+
+ while ((m = buf_ring_dequeue_sc(br)) != NULL)
+ m_freem(m);
+
+ buf_ring_free(br, type);
+}
+#endif
+
/*
* 72 was chosen below because it is the size of a TCP/IP
* header (40) + the minimum mss (32).
@@ -635,14 +683,14 @@ struct ifmultiaddr {
IFA_UNLOCK(ifa); \
} while (0)
-extern struct mtx ifnet_lock;
+extern struct rwlock ifnet_lock;
#define IFNET_LOCK_INIT() \
- mtx_init(&ifnet_lock, "ifnet", NULL, MTX_DEF | MTX_RECURSE)
-#define IFNET_WLOCK() mtx_lock(&ifnet_lock)
-#define IFNET_WUNLOCK() mtx_unlock(&ifnet_lock)
-#define IFNET_WLOCK_ASSERT() mtx_assert(&ifnet_lock, MA_OWNED)
-#define IFNET_RLOCK() IFNET_WLOCK()
-#define IFNET_RUNLOCK() IFNET_WUNLOCK()
+ rw_init_flags(&ifnet_lock, "ifnet", RW_RECURSE)
+#define IFNET_WLOCK() rw_wlock(&ifnet_lock)
+#define IFNET_WUNLOCK() rw_wunlock(&ifnet_lock)
+#define IFNET_WLOCK_ASSERT() rw_assert(&ifnet_lock, RA_LOCKED)
+#define IFNET_RLOCK() rw_rlock(&ifnet_lock)
+#define IFNET_RUNLOCK() rw_runlock(&ifnet_lock)
struct ifindex_entry {
struct ifnet *ife_ifnet;
@@ -659,10 +707,12 @@ struct ifnet *ifnet_byindex(u_short idx);
struct ifaddr *ifaddr_byindex(u_short idx);
struct cdev *ifdev_byindex(u_short idx);
+#ifdef VIMAGE_GLOBALS
extern struct ifnethead ifnet;
-extern int ifqmaxlen;
extern struct ifnet *loif; /* first loopback interface */
extern int if_index;
+#endif
+extern int ifqmaxlen;
int if_addgroup(struct ifnet *, const char *);
int if_delgroup(struct ifnet *, const char *);
diff --git a/sys/net/pfil.c b/sys/net/pfil.c
index bb82bb3..3018eb9 100644
--- a/sys/net/pfil.c
+++ b/sys/net/pfil.c
@@ -97,33 +97,26 @@ pfil_head_register(struct pfil_head *ph)
struct pfil_head *lph;
PFIL_LIST_LOCK();
- LIST_FOREACH(lph, &pfil_head_list, ph_list)
+ LIST_FOREACH(lph, &pfil_head_list, ph_list) {
if (ph->ph_type == lph->ph_type &&
ph->ph_un.phu_val == lph->ph_un.phu_val) {
PFIL_LIST_UNLOCK();
return EEXIST;
}
- PFIL_LIST_UNLOCK();
-
+ }
PFIL_LOCK_INIT(ph);
- PFIL_WLOCK(ph);
ph->ph_nhooks = 0;
-
TAILQ_INIT(&ph->ph_in);
TAILQ_INIT(&ph->ph_out);
-
- PFIL_LIST_LOCK();
LIST_INSERT_HEAD(&pfil_head_list, ph, ph_list);
PFIL_LIST_UNLOCK();
-
- PFIL_WUNLOCK(ph);
-
return (0);
}
/*
- * pfil_head_unregister() removes a pfil_head from the packet filter
- * hook mechanism.
+ * pfil_head_unregister() removes a pfil_head from the packet filter hook
+ * mechanism. The producer of the hook promises that all outstanding
+ * invocations of the hook have completed before it unregisters the hook.
*/
int
pfil_head_unregister(struct pfil_head *ph)
@@ -131,21 +124,13 @@ pfil_head_unregister(struct pfil_head *ph)
struct packet_filter_hook *pfh, *pfnext;
PFIL_LIST_LOCK();
- /*
- * LIST_REMOVE is safe for unlocked pfil_heads in ph_list.
- * No need to WLOCK all of them.
- */
LIST_REMOVE(ph, ph_list);
PFIL_LIST_UNLOCK();
-
- PFIL_WLOCK(ph);
-
TAILQ_FOREACH_SAFE(pfh, &ph->ph_in, pfil_link, pfnext)
free(pfh, M_IFADDR);
TAILQ_FOREACH_SAFE(pfh, &ph->ph_out, pfil_link, pfnext)
free(pfh, M_IFADDR);
PFIL_LOCK_DESTROY(ph);
-
return (0);
}
@@ -175,14 +160,13 @@ pfil_head_get(int type, u_long val)
* PFIL_WAITOK OK to call malloc with M_WAITOK.
*/
int
-pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *),
- void *arg, int flags, struct pfil_head *ph)
+pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int,
+ struct inpcb *), void *arg, int flags, struct pfil_head *ph)
{
struct packet_filter_hook *pfh1 = NULL;
struct packet_filter_hook *pfh2 = NULL;
int err;
- /* Get memory */
if (flags & PFIL_IN) {
pfh1 = (struct packet_filter_hook *)malloc(sizeof(*pfh1),
M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT);
@@ -199,17 +183,13 @@ pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, struct in
goto error;
}
}
-
- /* Lock */
PFIL_WLOCK(ph);
-
- /* Add */
if (flags & PFIL_IN) {
pfh1->pfil_func = func;
pfh1->pfil_arg = arg;
err = pfil_list_add(&ph->ph_in, pfh1, flags & ~PFIL_OUT);
if (err)
- goto done;
+ goto locked_error;
ph->ph_nhooks++;
}
if (flags & PFIL_OUT) {
@@ -219,15 +199,13 @@ pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, struct in
if (err) {
if (flags & PFIL_IN)
pfil_list_remove(&ph->ph_in, func, arg);
- goto done;
+ goto locked_error;
}
ph->ph_nhooks++;
}
-
PFIL_WUNLOCK(ph);
-
return 0;
-done:
+locked_error:
PFIL_WUNLOCK(ph);
error:
if (pfh1 != NULL)
diff --git a/sys/net/pfil.h b/sys/net/pfil.h
index 22d3d16..5db9e55 100644
--- a/sys/net/pfil.h
+++ b/sys/net/pfil.h
@@ -49,7 +49,8 @@ struct inpcb;
*/
struct packet_filter_hook {
TAILQ_ENTRY(packet_filter_hook) pfil_link;
- int (*pfil_func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *);
+ int (*pfil_func)(void *, struct mbuf **, struct ifnet *, int,
+ struct inpcb *);
void *pfil_arg;
int pfil_flags;
};
diff --git a/sys/net/radix.c b/sys/net/radix.c
index e70d17d..39b198e 100644
--- a/sys/net/radix.c
+++ b/sys/net/radix.c
@@ -1087,6 +1087,7 @@ rn_walktree(h, f, w)
* while applying the function f to it, so we need to calculate
* the successor node in advance.
*/
+
/* First time through node, go left */
while (rn->rn_bit >= 0)
rn = rn->rn_left;
diff --git a/sys/net/radix_mpath.c b/sys/net/radix_mpath.c
index 68233fe..8d94d01 100644
--- a/sys/net/radix_mpath.c
+++ b/sys/net/radix_mpath.c
@@ -266,8 +266,8 @@ rtalloc_mpath_fib(struct route *ro, u_int32_t hash, u_int fibnum)
* be done for sendto(3) case?
*/
if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP))
- return; /* XXX */
- ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, RTF_CLONING, fibnum);
+ return;
+ ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, 0, fibnum);
/* if the route does not exist or it is not multipath, don't care */
if (ro->ro_rt == NULL)
diff --git a/sys/net/route.c b/sys/net/route.c
index be71e13..1f3e096 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -41,6 +41,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/syslog.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
@@ -53,6 +54,7 @@
#include <sys/vimage.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/route.h>
#ifdef RADIX_MPATH
@@ -269,8 +271,7 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
struct radix_node *rn;
struct rtentry *newrt;
struct rt_addrinfo info;
- u_long nflags;
- int needresolve = 0, err = 0, msgtype = RTM_MISS;
+ int err = 0, msgtype = RTM_MISS;
int needlock;
KASSERT((fibnum < rt_numfibs), ("rtalloc1_fib: bad fibnum"));
@@ -283,10 +284,9 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
*/
if (rnh == NULL) {
V_rtstat.rts_unreach++;
- goto miss2;
+ goto miss;
}
needlock = !(ignflags & RTF_RNH_LOCKED);
-retry:
if (needlock)
RADIX_NODE_HEAD_RLOCK(rnh);
#ifdef INVARIANTS
@@ -295,103 +295,33 @@ retry:
#endif
rn = rnh->rnh_matchaddr(dst, rnh);
if (rn && ((rn->rn_flags & RNF_ROOT) == 0)) {
-
newrt = rt = RNTORT(rn);
- nflags = rt->rt_flags & ~ignflags;
- if (report && (nflags & RTF_CLONING)) {
- if (needlock && !RADIX_NODE_HEAD_LOCK_TRY_UPGRADE(rnh)) {
- RADIX_NODE_HEAD_RUNLOCK(rnh);
- RADIX_NODE_HEAD_LOCK(rnh);
- /*
- * lookup again to make sure it wasn't changed
- */
- rn = rnh->rnh_matchaddr(dst, rnh);
- if (!(rn && ((rn->rn_flags & RNF_ROOT) == 0))) {
- RADIX_NODE_HEAD_UNLOCK(rnh);
- needresolve = 0;
- log(LOG_INFO, "retrying route lookup ...\n");
- goto retry;
- }
- }
- needresolve = 1;
- } else {
- RT_LOCK(newrt);
- RT_ADDREF(newrt);
- if (needlock)
- RADIX_NODE_HEAD_RUNLOCK(rnh);
- goto done;
- }
- }
- /*
- * if needresolve is set then we have the exclusive lock
- * and we need to keep it held for the benefit of rtrequest_fib
- */
- if (!needresolve && needlock)
+ RT_LOCK(newrt);
+ RT_ADDREF(newrt);
+ if (needlock)
+ RADIX_NODE_HEAD_RUNLOCK(rnh);
+ goto done;
+
+ } else if (needlock)
RADIX_NODE_HEAD_RUNLOCK(rnh);
- if (needresolve) {
- RADIX_NODE_HEAD_WLOCK_ASSERT(rnh);
+ /*
+ * Either we hit the root or couldn't find any match,
+ * Which basically means
+ * "caint get there frm here"
+ */
+ V_rtstat.rts_unreach++;
+miss:
+ if (report) {
/*
- * We are apparently adding (report = 0 in delete).
- * If it requires that it be cloned, do so.
- * (This implies it wasn't a HOST route.)
+ * If required, report the failure to the supervising
+ * Authorities.
+ * For a delete, this is not an error. (report == 0)
*/
- err = rtrequest_fib(RTM_RESOLVE, dst, NULL,
- NULL, RTF_RNH_LOCKED, &newrt, fibnum);
- if (err) {
- /*
- * If the cloning didn't succeed, maybe
- * what we have will do. Return that.
- */
- newrt = rt; /* existing route */
- RT_LOCK(newrt);
- RT_ADDREF(newrt);
- goto miss;
- }
- KASSERT(newrt, ("no route and no error"));
- RT_LOCK(newrt);
- if (newrt->rt_flags & RTF_XRESOLVE) {
- /*
- * If the new route specifies it be
- * externally resolved, then go do that.
- */
- msgtype = RTM_RESOLVE;
- goto miss;
- }
- /* Inform listeners of the new route. */
bzero(&info, sizeof(info));
- info.rti_info[RTAX_DST] = rt_key(newrt);
- info.rti_info[RTAX_NETMASK] = rt_mask(newrt);
- info.rti_info[RTAX_GATEWAY] = newrt->rt_gateway;
- if (newrt->rt_ifp != NULL) {
- info.rti_info[RTAX_IFP] =
- newrt->rt_ifp->if_addr->ifa_addr;
- info.rti_info[RTAX_IFA] = newrt->rt_ifa->ifa_addr;
- }
- rt_missmsg(RTM_ADD, &info, newrt->rt_flags, 0);
- if (needlock)
- RADIX_NODE_HEAD_UNLOCK(rnh);
- } else {
- /*
- * Either we hit the root or couldn't find any match,
- * Which basically means
- * "caint get there frm here"
- */
- V_rtstat.rts_unreach++;
- miss:
- if (needlock && needresolve)
- RADIX_NODE_HEAD_UNLOCK(rnh);
- miss2: if (report) {
- /*
- * If required, report the failure to the supervising
- * Authorities.
- * For a delete, this is not an error. (report == 0)
- */
- bzero(&info, sizeof(info));
- info.rti_info[RTAX_DST] = dst;
- rt_missmsg(msgtype, &info, 0, err);
- }
- }
+ info.rti_info[RTAX_DST] = dst;
+ rt_missmsg(msgtype, &info, 0, err);
+ }
done:
if (newrt)
RT_LOCK_ASSERT(newrt);
@@ -420,7 +350,7 @@ rtfree(struct rtentry *rt)
*/
RT_REMREF(rt);
if (rt->rt_refcnt > 0) {
- printf("%s: %p has %lu refs\n", __func__, rt, rt->rt_refcnt);
+ log(LOG_DEBUG, "%s: %p has %d refs\t", __func__, rt, rt->rt_refcnt);
goto done;
}
@@ -461,8 +391,6 @@ rtfree(struct rtentry *rt)
*/
if (rt->rt_ifa)
IFAFREE(rt->rt_ifa);
- rt->rt_parent = NULL; /* NB: no refcnt on parent */
-
/*
* The key is separatly alloc'd so free it (see rt_setgate()).
* This also frees the gateway, as they are always malloc'd
@@ -715,14 +643,6 @@ ifa_ifwithroute_fib(int flags, struct sockaddr *dst, struct sockaddr *gateway,
return (ifa);
}
-static walktree_f_t rt_fixdelete;
-static walktree_f_t rt_fixchange;
-
-struct rtfc_arg {
- struct rtentry *rt0;
- struct radix_node_head *rnh;
-};
-
/*
* Do appropriate manipulations of a routing tree given
* all the bits of info needed
@@ -828,8 +748,13 @@ rtexpunge(struct rtentry *rt)
struct ifaddr *ifa;
int error = 0;
+ /*
+ * Find the correct routing tree to use for this Address Family
+ */
rnh = V_rt_tables[rt->rt_fibnum][rt_key(rt)->sa_family];
RT_LOCK_ASSERT(rt);
+ if (rnh == NULL)
+ return (EAFNOSUPPORT);
RADIX_NODE_HEAD_LOCK_ASSERT(rnh);
#if 0
/*
@@ -840,13 +765,6 @@ rtexpunge(struct rtentry *rt)
KASSERT(rt->rt_refcnt <= 1, ("bogus refcnt %ld", rt->rt_refcnt));
#endif
/*
- * Find the correct routing tree to use for this Address Family
- */
- rnh = V_rt_tables[rt->rt_fibnum][rt_key(rt)->sa_family];
- if (rnh == NULL)
- return (EAFNOSUPPORT);
-
- /*
* Remove the item from the tree; it should be there,
* but when callers invoke us blindly it may not (sigh).
*/
@@ -863,24 +781,6 @@ rtexpunge(struct rtentry *rt)
rt->rt_flags &= ~RTF_UP;
/*
- * Now search what's left of the subtree for any cloned
- * routes which might have been formed from this node.
- */
- if ((rt->rt_flags & RTF_CLONING) && rt_mask(rt))
- rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
- rt_fixdelete, rt);
-
- /*
- * Remove any external references we may have.
- * This might result in another rtentry being freed if
- * we held its last reference.
- */
- if (rt->rt_gwroute) {
- RTFREE(rt->rt_gwroute);
- rt->rt_gwroute = NULL;
- }
-
- /*
* Give the protocol a chance to keep things in sync.
*/
if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) {
@@ -904,12 +804,6 @@ bad:
}
int
-rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
-{
- return (rtrequest1_fib(req, info, ret_nrt, 0));
-}
-
-int
rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
u_int fibnum)
{
@@ -941,10 +835,9 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
* If we are adding a host route then we don't want to put
* a netmask in the tree, nor do we want to clone it.
*/
- if (flags & RTF_HOST) {
+ if (flags & RTF_HOST)
netmask = NULL;
- flags &= ~RTF_CLONING;
- }
+
switch (req) {
case RTM_DELETE:
#ifdef RADIX_MPATH
@@ -1023,26 +916,6 @@ normal_rtdel:
rt->rt_flags &= ~RTF_UP;
/*
- * Now search what's left of the subtree for any cloned
- * routes which might have been formed from this node.
- */
- if ((rt->rt_flags & RTF_CLONING) &&
- rt_mask(rt)) {
- rnh->rnh_walktree_from(rnh, dst, rt_mask(rt),
- rt_fixdelete, rt);
- }
-
- /*
- * Remove any external references we may have.
- * This might result in another rtentry being freed if
- * we held its last reference.
- */
- if (rt->rt_gwroute) {
- RTFREE(rt->rt_gwroute);
- rt->rt_gwroute = NULL;
- }
-
- /*
* give the protocol a chance to keep things in sync.
*/
if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
@@ -1069,20 +942,12 @@ deldone:
} else
RTFREE_LOCKED(rt);
break;
-
case RTM_RESOLVE:
- if (ret_nrt == NULL || (rt = *ret_nrt) == NULL)
- senderr(EINVAL);
- ifa = rt->rt_ifa;
- /* XXX locking? */
- flags = rt->rt_flags &
- ~(RTF_CLONING | RTF_STATIC);
- flags |= RTF_WASCLONED;
- gateway = rt->rt_gateway;
- if ((netmask = rt->rt_genmask) == NULL)
- flags |= RTF_HOST;
- goto makeroute;
-
+ /*
+ * resolve was only used for route cloning
+ * here for compat
+ */
+ break;
case RTM_ADD:
if ((flags & RTF_GATEWAY) && !gateway)
senderr(EINVAL);
@@ -1093,8 +958,6 @@ deldone:
if (info->rti_ifa == NULL && (error = rt_getifa_fib(info, fibnum)))
senderr(error);
ifa = info->rti_ifa;
-
- makeroute:
rt = uma_zalloc(rtzone, M_NOWAIT | M_ZERO);
if (rt == NULL)
senderr(ENOBUFS);
@@ -1103,7 +966,7 @@ deldone:
rt->rt_fibnum = fibnum;
/*
* Add the gateway. Possibly re-malloc-ing the storage for it
- * also add the rt_gwroute if possible.
+ *
*/
RT_LOCK(rt);
if ((error = rt_setgate(rt, dst, gateway)) != 0) {
@@ -1138,8 +1001,6 @@ deldone:
/* do not permit exactly the same dst/mask/gw pair */
if (rn_mpath_capable(rnh) &&
rt_mpath_conflict(rnh, rt, netmask)) {
- if (rt->rt_gwroute)
- RTFREE(rt->rt_gwroute);
if (rt->rt_ifa) {
IFAFREE(rt->rt_ifa);
}
@@ -1152,34 +1013,11 @@ deldone:
/* XXX mtu manipulation will be done in rnh_addaddr -- itojun */
rn = rnh->rnh_addaddr(ndst, netmask, rnh, rt->rt_nodes);
- if (rn == NULL) {
- struct rtentry *rt2;
- /*
- * Uh-oh, we already have one of these in the tree.
- * We do a special hack: if the route that's already
- * there was generated by the cloning mechanism
- * then we just blow it away and retry the insertion
- * of the new one.
- */
- rt2 = rtalloc1_fib(dst, 0, RTF_RNH_LOCKED, fibnum);
- if (rt2 && rt2->rt_parent) {
- rtexpunge(rt2);
- RT_UNLOCK(rt2);
- rn = rnh->rnh_addaddr(ndst, netmask,
- rnh, rt->rt_nodes);
- } else if (rt2) {
- /* undo the extra ref we got */
- RTFREE_LOCKED(rt2);
- }
- }
-
/*
* If it still failed to go into the tree,
* then un-make it (this should be a function)
*/
if (rn == NULL) {
- if (rt->rt_gwroute)
- RTFREE(rt->rt_gwroute);
if (rt->rt_ifa)
IFAFREE(rt->rt_ifa);
Free(rt_key(rt));
@@ -1188,33 +1026,6 @@ deldone:
senderr(EEXIST);
}
- rt->rt_parent = NULL;
-
- /*
- * If we got here from RESOLVE, then we are cloning
- * so clone the rest, and note that we
- * are a clone (and increment the parent's references)
- */
- if (req == RTM_RESOLVE) {
- KASSERT(ret_nrt && *ret_nrt,
- ("no route to clone from"));
- rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */
- rt->rt_rmx.rmx_pksent = 0; /* reset packet counter */
- if ((*ret_nrt)->rt_flags & RTF_CLONING) {
- /*
- * NB: We do not bump the refcnt on the parent
- * entry under the assumption that it will
- * remain so long as we do. This is
- * important when deleting the parent route
- * as this operation requires traversing
- * the tree to delete all clones and futzing
- * with refcnts requires us to double-lock
- * parent through this back reference.
- */
- rt->rt_parent = *ret_nrt;
- }
- }
-
/*
* If this protocol has something to add to this then
* allow it to do that as well.
@@ -1223,20 +1034,6 @@ deldone:
ifa->ifa_rtrequest(req, rt, info);
/*
- * We repeat the same procedure from rt_setgate() here because
- * it doesn't fire when we call it there because the node
- * hasn't been added to the tree yet.
- */
- if (req == RTM_ADD &&
- !(rt->rt_flags & RTF_HOST) && rt_mask(rt) != NULL) {
- struct rtfc_arg arg;
- arg.rnh = rnh;
- arg.rt0 = rt;
- rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
- rt_fixchange, &arg);
- }
-
- /*
* actually return a resultant rtentry and
* give the caller a single reference.
*/
@@ -1263,159 +1060,21 @@ bad:
#undef ifpaddr
#undef flags
-/*
- * Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family''
- * (i.e., the routes related to it by the operation of cloning). This
- * routine is iterated over all potential former-child-routes by way of
- * rnh->rnh_walktree_from() above, and those that actually are children of
- * the late parent (passed in as VP here) are themselves deleted.
- */
-static int
-rt_fixdelete(struct radix_node *rn, void *vp)
-{
- struct rtentry *rt = RNTORT(rn);
- struct rtentry *rt0 = vp;
-
- if (rt->rt_parent == rt0 &&
- !(rt->rt_flags & (RTF_PINNED | RTF_CLONING))) {
- return rtrequest_fib(RTM_DELETE, rt_key(rt), NULL, rt_mask(rt),
- rt->rt_flags|RTF_RNH_LOCKED, NULL, rt->rt_fibnum);
- }
- return 0;
-}
-
-/*
- * This routine is called from rt_setgate() to do the analogous thing for
- * adds and changes. There is the added complication in this case of a
- * middle insert; i.e., insertion of a new network route between an older
- * network route and (cloned) host routes. For this reason, a simple check
- * of rt->rt_parent is insufficient; each candidate route must be tested
- * against the (mask, value) of the new route (passed as before in vp)
- * to see if the new route matches it.
- *
- * XXX - it may be possible to do fixdelete() for changes and reserve this
- * routine just for adds. I'm not sure why I thought it was necessary to do
- * changes this way.
- */
-
-static int
-rt_fixchange(struct radix_node *rn, void *vp)
-{
- struct rtentry *rt = RNTORT(rn);
- struct rtfc_arg *ap = vp;
- struct rtentry *rt0 = ap->rt0;
- struct radix_node_head *rnh = ap->rnh;
- u_char *xk1, *xm1, *xk2, *xmp;
- int i, len, mlen;
-
- /* make sure we have a parent, and route is not pinned or cloning */
- if (!rt->rt_parent ||
- (rt->rt_flags & (RTF_PINNED | RTF_CLONING)))
- return 0;
-
- if (rt->rt_parent == rt0) /* parent match */
- goto delete_rt;
- /*
- * There probably is a function somewhere which does this...
- * if not, there should be.
- */
- len = imin(rt_key(rt0)->sa_len, rt_key(rt)->sa_len);
-
- xk1 = (u_char *)rt_key(rt0);
- xm1 = (u_char *)rt_mask(rt0);
- xk2 = (u_char *)rt_key(rt);
-
- /* avoid applying a less specific route */
- xmp = (u_char *)rt_mask(rt->rt_parent);
- mlen = rt_key(rt->rt_parent)->sa_len;
- if (mlen > rt_key(rt0)->sa_len) /* less specific route */
- return 0;
- for (i = rnh->rnh_treetop->rn_offset; i < mlen; i++)
- if ((xmp[i] & ~(xmp[i] ^ xm1[i])) != xmp[i])
- return 0; /* less specific route */
-
- for (i = rnh->rnh_treetop->rn_offset; i < len; i++)
- if ((xk2[i] & xm1[i]) != xk1[i])
- return 0; /* no match */
-
- /*
- * OK, this node is a clone, and matches the node currently being
- * changed/added under the node's mask. So, get rid of it.
- */
-delete_rt:
- return rtrequest_fib(RTM_DELETE, rt_key(rt), NULL,
- rt_mask(rt), rt->rt_flags, NULL, rt->rt_fibnum);
-}
-
int
rt_setgate(struct rtentry *rt, struct sockaddr *dst, struct sockaddr *gate)
{
INIT_VNET_NET(curvnet);
/* XXX dst may be overwritten, can we move this to below */
+ int dlen = SA_SIZE(dst), glen = SA_SIZE(gate);
+#ifdef INVARIANTS
struct radix_node_head *rnh =
V_rt_tables[rt->rt_fibnum][dst->sa_family];
- int dlen = SA_SIZE(dst), glen = SA_SIZE(gate);
+#endif
-again:
RT_LOCK_ASSERT(rt);
RADIX_NODE_HEAD_LOCK_ASSERT(rnh);
/*
- * A host route with the destination equal to the gateway
- * will interfere with keeping LLINFO in the routing
- * table, so disallow it.
- */
- if (((rt->rt_flags & (RTF_HOST|RTF_GATEWAY|RTF_LLINFO)) ==
- (RTF_HOST|RTF_GATEWAY)) &&
- dst->sa_len == gate->sa_len &&
- bcmp(dst, gate, dst->sa_len) == 0) {
- /*
- * The route might already exist if this is an RTM_CHANGE
- * or a routing redirect, so try to delete it.
- */
- if (rt_key(rt))
- rtexpunge(rt);
- return EADDRNOTAVAIL;
- }
-
- /*
- * Cloning loop avoidance in case of bad configuration.
- */
- if (rt->rt_flags & RTF_GATEWAY) {
- struct rtentry *gwrt;
-
- RT_UNLOCK(rt); /* XXX workaround LOR */
- gwrt = rtalloc1_fib(gate, 1, RTF_RNH_LOCKED, rt->rt_fibnum);
- if (gwrt == rt) {
- RT_REMREF(rt);
- return (EADDRINUSE); /* failure */
- }
- /*
- * Try to reacquire the lock on rt, and if it fails,
- * clean state and restart from scratch.
- */
- if (!RT_TRYLOCK(rt)) {
- RTFREE_LOCKED(gwrt);
- RT_LOCK(rt);
- goto again;
- }
- /*
- * If there is already a gwroute, then drop it. If we
- * are asked to replace route with itself, then do
- * not leak its refcounter.
- */
- if (rt->rt_gwroute != NULL) {
- if (rt->rt_gwroute == gwrt) {
- RT_REMREF(rt->rt_gwroute);
- } else
- RTFREE(rt->rt_gwroute);
- }
-
- if ((rt->rt_gwroute = gwrt) != NULL)
- RT_UNLOCK(rt->rt_gwroute);
- }
-
- /*
* Prepare to store the gateway in rt->rt_gateway.
* Both dst and gateway are stored one after the other in the same
* malloc'd chunk. If we have room, we can reuse the old buffer,
@@ -1446,21 +1105,7 @@ again:
*/
bcopy(gate, rt->rt_gateway, glen);
- /*
- * This isn't going to do anything useful for host routes, so
- * don't bother. Also make sure we have a reasonable mask
- * (we don't yet have one during adds).
- */
- if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) {
- struct rtfc_arg arg;
-
- arg.rnh = rnh;
- arg.rt0 = rt;
- rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
- rt_fixchange, &arg);
- }
-
- return 0;
+ return (0);
}
static void
@@ -1500,6 +1145,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
char tempbuf[_SOCKADDR_TMPSIZE];
int didwork = 0;
int a_failure = 0;
+ static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
if (flags & RTF_HOST) {
dst = ifa->ifa_dstaddr;
@@ -1604,7 +1250,14 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
info.rti_ifa = ifa;
info.rti_flags = flags | ifa->ifa_flags;
info.rti_info[RTAX_DST] = dst;
- info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
+ /*
+ * doing this for compatibility reasons
+ */
+ if (cmd == RTM_ADD)
+ info.rti_info[RTAX_GATEWAY] =
+ (struct sockaddr *)&null_sdl;
+ else
+ info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
info.rti_info[RTAX_NETMASK] = netmask;
error = rtrequest1_fib(cmd, &info, &rt, fibnum);
if (error == 0 && rt != NULL) {
@@ -1628,6 +1281,15 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
rt->rt_ifa = ifa;
}
#endif
+ /*
+ * doing this for compatibility reasons
+ */
+ if (cmd == RTM_ADD) {
+ ((struct sockaddr_dl *)rt->rt_gateway)->sdl_type =
+ rt->rt_ifp->if_type;
+ ((struct sockaddr_dl *)rt->rt_gateway)->sdl_index =
+ rt->rt_ifp->if_index;
+ }
rt_newaddrmsg(cmd, ifa, error, rt);
if (cmd == RTM_DELETE) {
/*
@@ -1696,147 +1358,5 @@ rtinit(struct ifaddr *ifa, int cmd, int flags)
return (rtinit1(ifa, cmd, flags, fib));
}
-/*
- * rt_check() is invoked on each layer 2 output path, prior to
- * encapsulating outbound packets.
- *
- * The function is mostly used to find a routing entry for the gateway,
- * which in some protocol families could also point to the link-level
- * address for the gateway itself (the side effect of revalidating the
- * route to the destination is rather pointless at this stage, we did it
- * already a moment before in the pr_output() routine to locate the ifp
- * and gateway to use).
- *
- * When we remove the layer-3 to layer-2 mapping tables from the
- * routing table, this function can be removed.
- *
- * === On input ===
- * *dst is the address of the NEXT HOP (which coincides with the
- * final destination if directly reachable);
- * *lrt0 points to the cached route to the final destination;
- * *lrt is not meaningful;
- * (*lrt0 has no ref held on it by us so REMREF is not needed.
- * Refs only account for major structural references and not usages,
- * which is actually a bit of a problem.)
- *
- * === Operation ===
- * If the route is marked down try to find a new route. If the route
- * to the gateway is gone, try to setup a new route. Otherwise,
- * if the route is marked for packets to be rejected, enforce that.
- * Note that rtalloc returns an rtentry with an extra REF that we may
- * need to lose.
- *
- * === On return ===
- * *dst is unchanged;
- * *lrt0 points to the (possibly new) route to the final destination
- * *lrt points to the route to the next hop [LOCKED]
- *
- * Their values are meaningful ONLY if no error is returned.
- *
- * To follow this you have to remember that:
- * RT_REMREF reduces the reference count by 1 but doesn't check it for 0 (!)
- * RTFREE_LOCKED includes an RT_REMREF (or an rtfree if refs == 1)
- * and an RT_UNLOCK
- * RTFREE does an RT_LOCK and an RTFREE_LOCKED
- * The gwroute pointer counts as a reference on the rtentry to which it points.
- * so when we add it we use the ref that rtalloc gives us and when we lose it
- * we need to remove the reference.
- * RT_TEMP_UNLOCK does an RT_ADDREF before freeing the lock, and
- * RT_RELOCK locks it (it can't have gone away due to the ref) and
- * drops the ref, possibly freeing it and zeroing the pointer if
- * the ref goes to 0 (unlocking in the process).
- */
-int
-rt_check(struct rtentry **lrt, struct rtentry **lrt0, struct sockaddr *dst)
-{
- struct rtentry *rt;
- struct rtentry *rt0;
- u_int fibnum;
-
- KASSERT(*lrt0 != NULL, ("rt_check"));
- rt0 = *lrt0;
- rt = NULL;
- fibnum = rt0->rt_fibnum;
-
- /* NB: the locking here is tortuous... */
- RT_LOCK(rt0);
-retry:
- if (rt0 && (rt0->rt_flags & RTF_UP) == 0) {
- /* Current rt0 is useless, try get a replacement. */
- RT_UNLOCK(rt0);
- rt0 = NULL;
- }
- if (rt0 == NULL) {
- rt0 = rtalloc1_fib(dst, 1, 0UL, fibnum);
- if (rt0 == NULL) {
- return (EHOSTUNREACH);
- }
- RT_REMREF(rt0); /* don't need the reference. */
- }
-
- if (rt0->rt_flags & RTF_GATEWAY) {
- if ((rt = rt0->rt_gwroute) != NULL) {
- RT_LOCK(rt); /* NB: gwroute */
- if ((rt->rt_flags & RTF_UP) == 0) {
- /* gw route is dud. ignore/lose it */
- RTFREE_LOCKED(rt); /* unref (&unlock) gwroute */
- rt = rt0->rt_gwroute = NULL;
- }
- }
-
- if (rt == NULL) { /* NOT AN ELSE CLAUSE */
- RT_TEMP_UNLOCK(rt0); /* MUST return to undo this */
- rt = rtalloc1_fib(rt0->rt_gateway, 1, 0UL, fibnum);
- if ((rt == rt0) || (rt == NULL)) {
- /* the best we can do is not good enough */
- if (rt) {
- RT_REMREF(rt); /* assumes ref > 0 */
- RT_UNLOCK(rt);
- }
- RTFREE(rt0); /* lock, unref, (unlock) */
- return (ENETUNREACH);
- }
- /*
- * Relock it and lose the added reference.
- * All sorts of things could have happenned while we
- * had no lock on it, so check for them.
- */
- RT_RELOCK(rt0);
- if (rt0 == NULL || ((rt0->rt_flags & RTF_UP) == 0))
- /* Ru-roh.. what we had is no longer any good */
- goto retry;
- /*
- * While we were away, someone replaced the gateway.
- * Since a reference count is involved we can't just
- * overwrite it.
- */
- if (rt0->rt_gwroute) {
- if (rt0->rt_gwroute != rt) {
- RTFREE_LOCKED(rt);
- goto retry;
- }
- } else {
- rt0->rt_gwroute = rt;
- }
- }
- RT_LOCK_ASSERT(rt);
- RT_UNLOCK(rt0);
- } else {
- /* think of rt as having the lock from now on.. */
- rt = rt0;
- }
- /* XXX why are we inspecting rmx_expire? */
- if ((rt->rt_flags & RTF_REJECT) &&
- (rt->rt_rmx.rmx_expire == 0 ||
- time_uptime < rt->rt_rmx.rmx_expire)) {
- RT_UNLOCK(rt);
- return (rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
- }
-
- *lrt = rt;
- *lrt0 = rt0;
- return (0);
-}
-
/* This must be before ip6_init2(), which is now SI_ORDER_MIDDLE */
SYSINIT(route, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, 0);
diff --git a/sys/net/route.h b/sys/net/route.h
index fb8df39..5062198 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -135,15 +135,11 @@ struct rtentry {
#define rt_key(r) (*((struct sockaddr **)(&(r)->rt_nodes->rn_key)))
#define rt_mask(r) (*((struct sockaddr **)(&(r)->rt_nodes->rn_mask)))
struct sockaddr *rt_gateway; /* value */
- u_long rt_flags; /* up/down?, host/net */
+ int rt_flags; /* up/down?, host/net */
+ int rt_refcnt; /* # held references */
struct ifnet *rt_ifp; /* the answer: interface to use */
struct ifaddr *rt_ifa; /* the answer: interface address to use */
struct rt_metrics_lite rt_rmx; /* metrics used by rx'ing protocols */
- long rt_refcnt; /* # held references */
- struct sockaddr *rt_genmask; /* for generation of cloned routes */
- caddr_t rt_llinfo; /* pointer to link level info cache */
- struct rtentry *rt_gwroute; /* implied entry for gatewayed routes */
- struct rtentry *rt_parent; /* cloning parent of this route */
u_int rt_fibnum; /* which FIB */
#ifdef _KERNEL
/* XXX ugly, user apps use this definition but don't have a mtx def */
@@ -175,9 +171,9 @@ struct ortentry {
#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */
#define RTF_DONE 0x40 /* message confirmed */
/* 0x80 unused, was RTF_DELCLONE */
-#define RTF_CLONING 0x100 /* generate new routes on use */
+/* 0x100 unused, was RTF_CLONING */
#define RTF_XRESOLVE 0x200 /* external daemon resolves name */
-#define RTF_LLINFO 0x400 /* generated by link layer (e.g. ARP) */
+/* 0x400 unused, was RTF_LLINFO */
#define RTF_STATIC 0x800 /* manually added */
#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */
#define RTF_PROTO2 0x4000 /* protocol specific routing flag */
@@ -188,7 +184,7 @@ struct ortentry {
#define RTF_PRCLONING 0x10000 /* unused, for compatibility */
#endif
-#define RTF_WASCLONED 0x20000 /* route generated through cloning */
+/* 0x20000 unused, was RTF_WASCLONED */
#define RTF_PROTO3 0x40000 /* protocol specific routing flag */
/* 0x80000 unused */
#define RTF_PINNED 0x100000 /* future use */
@@ -326,14 +322,14 @@ struct rt_addrinfo {
#define RT_ADDREF(_rt) do { \
RT_LOCK_ASSERT(_rt); \
KASSERT((_rt)->rt_refcnt >= 0, \
- ("negative refcnt %ld", (_rt)->rt_refcnt)); \
+ ("negative refcnt %d", (_rt)->rt_refcnt)); \
(_rt)->rt_refcnt++; \
} while (0)
#define RT_REMREF(_rt) do { \
RT_LOCK_ASSERT(_rt); \
KASSERT((_rt)->rt_refcnt > 0, \
- ("bogus refcnt %ld", (_rt)->rt_refcnt)); \
+ ("bogus refcnt %d", (_rt)->rt_refcnt)); \
(_rt)->rt_refcnt--; \
} while (0)
@@ -409,7 +405,6 @@ void rtredirect(struct sockaddr *, struct sockaddr *,
struct sockaddr *, int, struct sockaddr *);
int rtrequest(int, struct sockaddr *,
struct sockaddr *, struct sockaddr *, int, struct rtentry **);
-int rtrequest1(int, struct rt_addrinfo *, struct rtentry **);
/* defaults to "all" FIBs */
int rtinit_fib(struct ifaddr *, int, int);
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index e8cc021..30591c7 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -53,6 +53,7 @@
#include <sys/vimage.h>
#include <net/if.h>
+#include <net/if_llatbl.h>
#include <net/netisr.h>
#include <net/raw_cb.h>
#include <net/route.h>
@@ -496,19 +497,6 @@ route_output(struct mbuf *m, struct socket *so)
(info.rti_info[RTAX_GATEWAY] != NULL &&
info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX))
senderr(EINVAL);
- if (info.rti_info[RTAX_GENMASK]) {
- struct radix_node *t;
- t = rn_addmask((caddr_t) info.rti_info[RTAX_GENMASK], 0, 1);
- if (t != NULL &&
- bcmp((char *)(void *)info.rti_info[RTAX_GENMASK] + 1,
- (char *)(void *)t->rn_key + 1,
- ((struct sockaddr *)t->rn_key)->sa_len - 1) == 0)
- info.rti_info[RTAX_GENMASK] =
- (struct sockaddr *)t->rn_key;
- else
- senderr(ENOBUFS);
- }
-
/*
* Verify that the caller has the appropriate privilege; RTM_GET
* is the only operation the non-superuser is allowed.
@@ -526,6 +514,11 @@ route_output(struct mbuf *m, struct socket *so)
if (info.rti_info[RTAX_GATEWAY] == NULL)
senderr(EINVAL);
saved_nrt = NULL;
+ /* support for new ARP code */
+ if (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) {
+ error = lla_rt_output(rtm, &info);
+ break;
+ }
error = rtrequest1_fib(RTM_ADD, &info, &saved_nrt,
so->so_fibnum);
if (error == 0 && saved_nrt) {
@@ -534,13 +527,18 @@ route_output(struct mbuf *m, struct socket *so)
&rtm->rtm_rmx, &saved_nrt->rt_rmx);
rtm->rtm_index = saved_nrt->rt_ifp->if_index;
RT_REMREF(saved_nrt);
- saved_nrt->rt_genmask = info.rti_info[RTAX_GENMASK];
RT_UNLOCK(saved_nrt);
}
break;
case RTM_DELETE:
saved_nrt = NULL;
+ /* support for new ARP code */
+ if (info.rti_info[RTAX_GATEWAY] &&
+ (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK)) {
+ error = lla_rt_output(rtm, &info);
+ break;
+ }
error = rtrequest1_fib(RTM_DELETE, &info, &saved_nrt,
so->so_fibnum);
if (error == 0) {
@@ -612,7 +610,7 @@ route_output(struct mbuf *m, struct socket *so)
info.rti_info[RTAX_DST] = rt_key(rt);
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
info.rti_info[RTAX_NETMASK] = rt_mask(rt);
- info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
+ info.rti_info[RTAX_GENMASK] = 0;
if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
ifp = rt->rt_ifp;
if (ifp) {
@@ -673,10 +671,10 @@ route_output(struct mbuf *m, struct socket *so)
rt->rt_ifa->ifa_addr))) {
RT_UNLOCK(rt);
RADIX_NODE_HEAD_LOCK(rnh);
- if ((error = rt_getifa_fib(&info,
- rt->rt_fibnum)) != 0)
- senderr(error);
+ error = rt_getifa_fib(&info, rt->rt_fibnum);
RADIX_NODE_HEAD_UNLOCK(rnh);
+ if (error != 0)
+ senderr(error);
RT_LOCK(rt);
}
if (info.rti_ifa != NULL &&
@@ -699,8 +697,7 @@ route_output(struct mbuf *m, struct socket *so)
RT_UNLOCK(rt);
senderr(error);
}
- if (!(rt->rt_flags & RTF_LLINFO))
- rt->rt_flags |= RTF_GATEWAY;
+ rt->rt_flags |= RTF_GATEWAY;
}
if (info.rti_ifa != NULL &&
info.rti_ifa != rt->rt_ifa) {
@@ -718,8 +715,6 @@ route_output(struct mbuf *m, struct socket *so)
rtm->rtm_index = rt->rt_ifp->if_index;
if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info);
- if (info.rti_info[RTAX_GENMASK])
- rt->rt_genmask = info.rti_info[RTAX_GENMASK];
/* FALLTHROUGH */
case RTM_LOCK:
/* We don't support locks anymore */
@@ -1261,7 +1256,7 @@ sysctl_dumpentry(struct radix_node *rn, void *vw)
info.rti_info[RTAX_DST] = rt_key(rt);
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
info.rti_info[RTAX_NETMASK] = rt_mask(rt);
- info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
+ info.rti_info[RTAX_GENMASK] = 0;
if (rt->rt_ifp) {
info.rti_info[RTAX_IFP] = rt->rt_ifp->if_addr->ifa_addr;
info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
@@ -1440,6 +1435,11 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS)
RADIX_NODE_HEAD_UNLOCK(rnh);
} else if (af != 0)
error = EAFNOSUPPORT;
+ /*
+ * take care of llinfo entries
+ */
+ if (w.w_op == NET_RT_FLAGS)
+ error = lltable_sysctl_dumparp(af, w.w_req);
break;
case NET_RT_IFLIST:
diff --git a/sys/net80211/_ieee80211.h b/sys/net80211/_ieee80211.h
index b735b5c..f5858fe 100644
--- a/sys/net80211/_ieee80211.h
+++ b/sys/net80211/_ieee80211.h
@@ -137,7 +137,7 @@ struct ieee80211_channel {
uint8_t ic_extieee; /* HT40 extension channel number */
};
-#define IEEE80211_CHAN_MAX 255
+#define IEEE80211_CHAN_MAX 256
#define IEEE80211_CHAN_BYTES 32 /* howmany(IEEE80211_CHAN_MAX, NBBY) */
#define IEEE80211_CHAN_ANY 0xffff /* token for ``any channel'' */
#define IEEE80211_CHAN_ANYC \
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c
index cce1312..e0a9432 100644
--- a/sys/net80211/ieee80211.c
+++ b/sys/net80211/ieee80211.c
@@ -118,7 +118,7 @@ ieee80211_chan_init(struct ieee80211com *ic)
struct ieee80211_channel *c;
int i;
- KASSERT(0 < ic->ic_nchans && ic->ic_nchans < IEEE80211_CHAN_MAX,
+ KASSERT(0 < ic->ic_nchans && ic->ic_nchans <= IEEE80211_CHAN_MAX,
("invalid number of channels specified: %u", ic->ic_nchans));
memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail));
memset(ic->ic_modecaps, 0, sizeof(ic->ic_modecaps));
@@ -126,8 +126,6 @@ ieee80211_chan_init(struct ieee80211com *ic)
for (i = 0; i < ic->ic_nchans; i++) {
c = &ic->ic_channels[i];
KASSERT(c->ic_flags != 0, ("channel with no flags"));
- KASSERT(c->ic_ieee < IEEE80211_CHAN_MAX,
- ("channel with bogus ieee number %u", c->ic_ieee));
setbit(ic->ic_chan_avail, c->ic_ieee);
/*
* Identify mode capabilities.
diff --git a/sys/net80211/ieee80211_acl.c b/sys/net80211/ieee80211_acl.c
index 13407a4..cb20b87 100644
--- a/sys/net80211/ieee80211_acl.c
+++ b/sys/net80211/ieee80211_acl.c
@@ -99,7 +99,7 @@ acl_attach(struct ieee80211vap *vap)
{
struct aclstate *as;
- MALLOC(as, struct aclstate *, sizeof(struct aclstate),
+ as = (struct aclstate *) malloc(sizeof(struct aclstate),
M_80211_ACL, M_NOWAIT | M_ZERO);
if (as == NULL)
return 0;
@@ -123,7 +123,7 @@ acl_detach(struct ieee80211vap *vap)
acl_free_all(vap);
vap->iv_as = NULL;
ACL_LOCK_DESTROY(as);
- FREE(as, M_80211_ACL);
+ free(as, M_80211_ACL);
}
static __inline struct acl *
@@ -147,7 +147,7 @@ _acl_free(struct aclstate *as, struct acl *acl)
TAILQ_REMOVE(&as->as_list, acl, acl_list);
LIST_REMOVE(acl, acl_hash);
- FREE(acl, M_80211_ACL);
+ free(acl, M_80211_ACL);
as->as_nacls--;
}
@@ -175,7 +175,7 @@ acl_add(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
struct acl *acl, *new;
int hash;
- MALLOC(new, struct acl *, sizeof(struct acl), M_80211_ACL, M_NOWAIT | M_ZERO);
+ new = (struct acl *) malloc(sizeof(struct acl), M_80211_ACL, M_NOWAIT | M_ZERO);
if (new == NULL) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
"ACL: add %s failed, no memory\n", ether_sprintf(mac));
@@ -188,7 +188,7 @@ acl_add(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
LIST_FOREACH(acl, &as->as_hash[hash], acl_hash) {
if (IEEE80211_ADDR_EQ(acl->acl_macaddr, mac)) {
ACL_UNLOCK(as);
- FREE(new, M_80211_ACL);
+ free(new, M_80211_ACL);
IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
"ACL: add %s failed, already present\n",
ether_sprintf(mac));
@@ -301,7 +301,7 @@ acl_getioctl(struct ieee80211vap *vap, struct ieee80211req *ireq)
ireq->i_len = space; /* return required space */
return 0; /* NB: must not error */
}
- MALLOC(ap, struct ieee80211req_maclist *, space,
+ ap = (struct ieee80211req_maclist *) malloc(space,
M_TEMP, M_NOWAIT);
if (ap == NULL)
return ENOMEM;
@@ -317,7 +317,7 @@ acl_getioctl(struct ieee80211vap *vap, struct ieee80211req *ireq)
ireq->i_len = space;
} else
error = copyout(ap, ireq->i_data, ireq->i_len);
- FREE(ap, M_TEMP);
+ free(ap, M_TEMP);
return error;
}
return EINVAL;
diff --git a/sys/net80211/ieee80211_crypto.h b/sys/net80211/ieee80211_crypto.h
index 63a9583..40a6b03 100644
--- a/sys/net80211/ieee80211_crypto.h
+++ b/sys/net80211/ieee80211_crypto.h
@@ -218,7 +218,7 @@ static __inline void
ieee80211_crypto_resetkey(struct ieee80211vap *vap,
struct ieee80211_key *k, ieee80211_keyix ix)
{
- k->wk_cipher = &ieee80211_cipher_none;;
+ k->wk_cipher = &ieee80211_cipher_none;
k->wk_private = k->wk_cipher->ic_attach(vap, k);
k->wk_keyix = k->wk_rxkeyix = ix;
k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV;
diff --git a/sys/net80211/ieee80211_crypto_ccmp.c b/sys/net80211/ieee80211_crypto_ccmp.c
index bdaf7e3..c2e9486 100644
--- a/sys/net80211/ieee80211_crypto_ccmp.c
+++ b/sys/net80211/ieee80211_crypto_ccmp.c
@@ -96,7 +96,7 @@ ccmp_attach(struct ieee80211vap *vap, struct ieee80211_key *k)
{
struct ccmp_ctx *ctx;
- MALLOC(ctx, struct ccmp_ctx *, sizeof(struct ccmp_ctx),
+ ctx = (struct ccmp_ctx *) malloc(sizeof(struct ccmp_ctx),
M_80211_CRYPTO, M_NOWAIT | M_ZERO);
if (ctx == NULL) {
vap->iv_stats.is_crypto_nomem++;
@@ -113,7 +113,7 @@ ccmp_detach(struct ieee80211_key *k)
{
struct ccmp_ctx *ctx = k->wk_private;
- FREE(ctx, M_80211_CRYPTO);
+ free(ctx, M_80211_CRYPTO);
KASSERT(nrefs > 0, ("imbalanced attach/detach"));
nrefs--; /* NB: we assume caller locking */
}
diff --git a/sys/net80211/ieee80211_crypto_tkip.c b/sys/net80211/ieee80211_crypto_tkip.c
index f509856..b20946a 100644
--- a/sys/net80211/ieee80211_crypto_tkip.c
+++ b/sys/net80211/ieee80211_crypto_tkip.c
@@ -109,7 +109,7 @@ tkip_attach(struct ieee80211vap *vap, struct ieee80211_key *k)
{
struct tkip_ctx *ctx;
- MALLOC(ctx, struct tkip_ctx *, sizeof(struct tkip_ctx),
+ ctx = (struct tkip_ctx *) malloc(sizeof(struct tkip_ctx),
M_80211_CRYPTO, M_NOWAIT | M_ZERO);
if (ctx == NULL) {
vap->iv_stats.is_crypto_nomem++;
@@ -126,7 +126,7 @@ tkip_detach(struct ieee80211_key *k)
{
struct tkip_ctx *ctx = k->wk_private;
- FREE(ctx, M_80211_CRYPTO);
+ free(ctx, M_80211_CRYPTO);
KASSERT(nrefs > 0, ("imbalanced attach/detach"));
nrefs--; /* NB: we assume caller locking */
}
diff --git a/sys/net80211/ieee80211_crypto_wep.c b/sys/net80211/ieee80211_crypto_wep.c
index 7eade59..07c1797 100644
--- a/sys/net80211/ieee80211_crypto_wep.c
+++ b/sys/net80211/ieee80211_crypto_wep.c
@@ -87,7 +87,7 @@ wep_attach(struct ieee80211vap *vap, struct ieee80211_key *k)
{
struct wep_ctx *ctx;
- MALLOC(ctx, struct wep_ctx *, sizeof(struct wep_ctx),
+ ctx = (struct wep_ctx *) malloc(sizeof(struct wep_ctx),
M_80211_CRYPTO, M_NOWAIT | M_ZERO);
if (ctx == NULL) {
vap->iv_stats.is_crypto_nomem++;
@@ -106,7 +106,7 @@ wep_detach(struct ieee80211_key *k)
{
struct wep_ctx *ctx = k->wk_private;
- FREE(ctx, M_80211_CRYPTO);
+ free(ctx, M_80211_CRYPTO);
KASSERT(nrefs > 0, ("imbalanced attach/detach"));
nrefs--; /* NB: we assume caller locking */
}
diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c
index b3dd4d4..59c6a46 100644
--- a/sys/net80211/ieee80211_ddb.c
+++ b/sys/net80211/ieee80211_ddb.c
@@ -92,7 +92,8 @@ __FBSDID("$FreeBSD$");
#define IEEE80211_NODE_BITS \
"\20\1AUTH\2QOS\3ERP\5PWR_MGT\6AREF\7HT\10HTCOMPAT\11WPS\12TSN" \
- "\13AMPDU_RX\14AMPDU_TX\15MIMO_PS\16MIMO_RTS\17RIFS\20SGI20\21SGI40"
+ "\13AMPDU_RX\14AMPDU_TX\15MIMO_PS\16MIMO_RTS\17RIFS\20SGI20\21SGI40" \
+ "\22ASSOCID"
#define IEEE80211_ERP_BITS \
"\20\1NON_ERP_PRESENT\2USE_PROTECTION\3LONG_PREAMBLE"
@@ -541,7 +542,7 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta, int showp
*/
db_printf("\tnchans %d", ic->ic_nchans);
#if 0
- struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX+1];
+ struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX];
uint8_t ic_chan_avail[IEEE80211_CHAN_BYTES];
uint8_t ic_chan_active[IEEE80211_CHAN_BYTES];
uint8_t ic_chan_scan[IEEE80211_CHAN_BYTES];
diff --git a/sys/net80211/ieee80211_dfs.h b/sys/net80211/ieee80211_dfs.h
index 36d14aa..9076077 100644
--- a/sys/net80211/ieee80211_dfs.h
+++ b/sys/net80211/ieee80211_dfs.h
@@ -32,7 +32,7 @@
*/
struct ieee80211_dfs_state {
- int nol_event[IEEE80211_CHAN_MAX+1];
+ int nol_event[IEEE80211_CHAN_MAX];
struct callout nol_timer; /* NOL list processing */
struct callout cac_timer; /* CAC timer */
struct timeval lastevent; /* time of last radar event */
diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c
index 71174b7..60de0f4 100644
--- a/sys/net80211/ieee80211_freebsd.c
+++ b/sys/net80211/ieee80211_freebsd.c
@@ -234,7 +234,7 @@ ieee80211_sysctl_vattach(struct ieee80211vap *vap)
struct sysctl_oid *oid;
char num[14]; /* sufficient for 32 bits */
- MALLOC(ctx, struct sysctl_ctx_list *, sizeof(struct sysctl_ctx_list),
+ ctx = (struct sysctl_ctx_list *) malloc(sizeof(struct sysctl_ctx_list),
M_DEVBUF, M_NOWAIT | M_ZERO);
if (ctx == NULL) {
if_printf(ifp, "%s: cannot allocate sysctl context!\n",
@@ -310,7 +310,7 @@ ieee80211_sysctl_vdetach(struct ieee80211vap *vap)
if (vap->iv_sysctl != NULL) {
sysctl_ctx_free(vap->iv_sysctl);
- FREE(vap->iv_sysctl, M_DEVBUF);
+ free(vap->iv_sysctl, M_DEVBUF);
vap->iv_sysctl = NULL;
}
}
diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c
index 60cbe4b..c333954 100644
--- a/sys/net80211/ieee80211_hostap.c
+++ b/sys/net80211/ieee80211_hostap.c
@@ -902,7 +902,7 @@ hostap_auth_open(struct ieee80211_node *ni, struct ieee80211_frame *wh,
* open auth is attempted.
*/
if (ni->ni_challenge != NULL) {
- FREE(ni->ni_challenge, M_80211_NODE);
+ free(ni->ni_challenge, M_80211_NODE);
ni->ni_challenge = NULL;
}
/* XXX hack to workaround calling convention */
@@ -928,6 +928,11 @@ hostap_auth_open(struct ieee80211_node *ni, struct ieee80211_frame *wh,
* after the transaction completes.
*/
ni->ni_flags |= IEEE80211_NODE_AREF;
+ /*
+ * Mark the node as requiring a valid association id
+ * before outbound traffic is permitted.
+ */
+ ni->ni_flags |= IEEE80211_NODE_ASSOCID;
if (vap->iv_acl != NULL &&
vap->iv_acl->iac_getpolicy(vap) == IEEE80211_MACCMD_POLICY_RADIUS) {
@@ -1054,6 +1059,11 @@ hostap_auth_shared(struct ieee80211_node *ni, struct ieee80211_frame *wh,
* after the transaction completes.
*/
ni->ni_flags |= IEEE80211_NODE_AREF;
+ /*
+ * Mark the node as requiring a valid associatio id
+ * before outbound traffic is permitted.
+ */
+ ni->ni_flags |= IEEE80211_NODE_ASSOCID;
IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
ni->ni_noise = noise;
ni->ni_rstamp = rstamp;
@@ -1986,7 +1996,7 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
return;
/* discard challenge after association */
if (ni->ni_challenge != NULL) {
- FREE(ni->ni_challenge, M_80211_NODE);
+ free(ni->ni_challenge, M_80211_NODE);
ni->ni_challenge = NULL;
}
/* NB: 802.11 spec says to ignore station's privacy bit */
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index e72a2a2..e68bb6c 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -499,7 +499,7 @@ int
ieee80211_alloc_challenge(struct ieee80211_node *ni)
{
if (ni->ni_challenge == NULL)
- MALLOC(ni->ni_challenge, uint32_t*, IEEE80211_CHALLENGE_LEN,
+ ni->ni_challenge = (uint32_t *) malloc(IEEE80211_CHALLENGE_LEN,
M_80211_NODE, M_NOWAIT);
if (ni->ni_challenge == NULL) {
IEEE80211_NOTE(ni->ni_vap,
@@ -673,14 +673,6 @@ ieee80211_parse_beacon(struct ieee80211_node *ni, struct mbuf *m,
}
IEEE80211_VERIFY_ELEMENT(scan->ssid, IEEE80211_NWID_LEN,
scan->status |= IEEE80211_BPARSE_SSID_INVALID);
-#if IEEE80211_CHAN_MAX < 255
- if (scan->chan > IEEE80211_CHAN_MAX) {
- IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,
- wh, NULL, "invalid channel %u", scan->chan);
- vap->iv_stats.is_rx_badchan++;
- scan->status |= IEEE80211_BPARSE_CHAN_INVALID;
- }
-#endif
if (scan->chan != scan->bchan && ic->ic_phytype != IEEE80211_T_FH) {
/*
* Frame was received on a channel different from the
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index ae39fd6..b967e47 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -320,14 +320,14 @@ ieee80211_ioctl_getscanresults(struct ieee80211vap *vap,
space = req.space;
/* XXX M_WAITOK after driver lock released */
- MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO);
+ p = malloc(space, M_TEMP, M_NOWAIT | M_ZERO);
if (p == NULL)
return ENOMEM;
req.sr = p;
ieee80211_scan_iterate(vap, get_scan_result, &req);
ireq->i_len = space - req.space;
error = copyout(p, ireq->i_data, ireq->i_len);
- FREE(p, M_TEMP);
+ free(p, M_TEMP);
} else
ireq->i_len = 0;
@@ -467,7 +467,7 @@ getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq,
if (req.space > 0) {
space = req.space;
/* XXX M_WAITOK after driver lock released */
- MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO);
+ p = malloc(space, M_TEMP, M_NOWAIT | M_ZERO);
if (p == NULL) {
error = ENOMEM;
goto bad;
@@ -479,7 +479,7 @@ getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq,
get_sta_info(&req, ni);
ireq->i_len = space - req.space;
error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len);
- FREE(p, M_TEMP);
+ free(p, M_TEMP);
} else
ireq->i_len = 0;
bad:
@@ -696,7 +696,7 @@ ieee80211_ioctl_getdevcaps(struct ieee80211com *ic,
if (ireq->i_len != sizeof(struct ieee80211_devcaps_req))
return EINVAL;
- MALLOC(dc, struct ieee80211_devcaps_req *,
+ dc = (struct ieee80211_devcaps_req *) malloc(
sizeof(struct ieee80211_devcaps_req), M_TEMP, M_NOWAIT | M_ZERO);
if (dc == NULL)
return ENOMEM;
@@ -707,7 +707,7 @@ ieee80211_ioctl_getdevcaps(struct ieee80211com *ic,
ic->ic_getradiocaps(ic, &ci->ic_nchans, ci->ic_chans);
ieee80211_sort_channels(ci->ic_chans, ci->ic_nchans);
error = copyout(dc, ireq->i_data, sizeof(*dc));
- FREE(dc, M_TEMP);
+ free(dc, M_TEMP);
return error;
}
@@ -1556,7 +1556,7 @@ ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211req_chanlist list;
u_char chanlist[IEEE80211_CHAN_BYTES];
- int i, j, nchan, error;
+ int i, nchan, error;
if (ireq->i_len != sizeof(list))
return EINVAL;
@@ -1564,22 +1564,16 @@ ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
if (error)
return error;
memset(chanlist, 0, sizeof(chanlist));
- /*
- * Since channel 0 is not available for DS, channel 1
- * is assigned to LSB on WaveLAN.
- */
- if (ic->ic_phytype == IEEE80211_T_DS)
- i = 1;
- else
- i = 0;
nchan = 0;
- for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
+ for (i = 0; i < ic->ic_nchans; i++) {
+ const struct ieee80211_channel *c = &ic->ic_channels[i];
/*
- * NB: silently discard unavailable channels so users
- * can specify 1-255 to get all available channels.
+ * Calculate the intersection of the user list and the
+ * available channels so users can do things like specify
+ * 1-255 to get all available channels.
*/
- if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i)) {
- setbit(chanlist, i);
+ if (isset(list.ic_channels, c->ic_ieee)) {
+ setbit(chanlist, c->ic_ieee);
nchan++;
}
}
@@ -1890,8 +1884,6 @@ ieee80211_ioctl_setchannel(struct ieee80211vap *vap,
if (ireq->i_val == 0 ||
ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) {
c = IEEE80211_CHAN_ANYC;
- } else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX) {
- return EINVAL;
} else {
struct ieee80211_channel *c2;
@@ -1993,14 +1985,14 @@ ieee80211_ioctl_setregdomain(struct ieee80211vap *vap,
if (ireq->i_len != sizeof(struct ieee80211_regdomain_req))
return EINVAL;
- MALLOC(reg, struct ieee80211_regdomain_req *,
+ reg = (struct ieee80211_regdomain_req *) malloc(
sizeof(struct ieee80211_regdomain_req), M_TEMP, M_NOWAIT);
if (reg == NULL)
return ENOMEM;
error = copyin(ireq->i_data, reg, sizeof(*reg));
if (error == 0)
error = ieee80211_setregdomain(vap, reg);
- FREE(reg, M_TEMP);
+ free(reg, M_TEMP);
return (error == 0 ? ENETRESET : error);
}
@@ -2139,7 +2131,7 @@ setappie(struct ieee80211_appie **aie, const struct ieee80211req *ireq)
if (ireq->i_len == 0) { /* delete any existing ie */
if (app != NULL) {
*aie = NULL; /* XXX racey */
- FREE(app, M_80211_NODE_IE);
+ free(app, M_80211_NODE_IE);
}
return 0;
}
@@ -2153,20 +2145,20 @@ setappie(struct ieee80211_appie **aie, const struct ieee80211req *ireq)
*
* XXX bad bad bad
*/
- MALLOC(napp, struct ieee80211_appie *,
+ napp = (struct ieee80211_appie *) malloc(
sizeof(struct ieee80211_appie) + ireq->i_len, M_80211_NODE_IE, M_NOWAIT);
if (napp == NULL)
return ENOMEM;
/* XXX holding ic lock */
error = copyin(ireq->i_data, napp->ie_data, ireq->i_len);
if (error) {
- FREE(napp, M_80211_NODE_IE);
+ free(napp, M_80211_NODE_IE);
return error;
}
napp->ie_len = ireq->i_len;
*aie = napp;
if (app != NULL)
- FREE(app, M_80211_NODE_IE);
+ free(app, M_80211_NODE_IE);
return 0;
}
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index 8e9d91f..e3028d9 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -153,7 +153,7 @@ ieee80211_node_latevattach(struct ieee80211vap *vap)
"WARNING: max aid too small, changed to %d\n",
vap->iv_max_aid);
}
- MALLOC(vap->iv_aid_bitmap, uint32_t *,
+ vap->iv_aid_bitmap = (uint32_t *) malloc(
howmany(vap->iv_max_aid, 32) * sizeof(uint32_t),
M_80211_NODE, M_NOWAIT | M_ZERO);
if (vap->iv_aid_bitmap == NULL) {
@@ -180,7 +180,7 @@ ieee80211_node_vdetach(struct ieee80211vap *vap)
vap->iv_bss = NULL;
}
if (vap->iv_aid_bitmap != NULL) {
- FREE(vap->iv_aid_bitmap, M_80211_NODE);
+ free(vap->iv_aid_bitmap, M_80211_NODE);
vap->iv_aid_bitmap = NULL;
}
}
@@ -732,6 +732,7 @@ ieee80211_sta_join(struct ieee80211vap *vap, struct ieee80211_channel *chan,
ni->ni_erp = se->se_erp;
IEEE80211_RSSI_LPF(ni->ni_avgrssi, se->se_rssi);
ni->ni_noise = se->se_noise;
+ ni->ni_flags |= IEEE80211_NODE_ASSOCID;
if (ieee80211_ies_init(&ni->ni_ies, se->se_ies.data, se->se_ies.len)) {
ieee80211_ies_expand(&ni->ni_ies);
@@ -788,7 +789,7 @@ node_alloc(struct ieee80211vap *vap, const uint8_t macaddr[IEEE80211_ADDR_LEN])
{
struct ieee80211_node *ni;
- MALLOC(ni, struct ieee80211_node *, sizeof(struct ieee80211_node),
+ ni = (struct ieee80211_node *) malloc(sizeof(struct ieee80211_node),
M_80211_NODE, M_NOWAIT | M_ZERO);
return ni;
}
@@ -806,11 +807,11 @@ ieee80211_ies_init(struct ieee80211_ies *ies, const uint8_t *data, int len)
memset(ies, 0, offsetof(struct ieee80211_ies, data));
if (ies->data != NULL && ies->len != len) {
/* data size changed */
- FREE(ies->data, M_80211_NODE_IE);
+ free(ies->data, M_80211_NODE_IE);
ies->data = NULL;
}
if (ies->data == NULL) {
- MALLOC(ies->data, uint8_t *, len, M_80211_NODE_IE, M_NOWAIT);
+ ies->data = (uint8_t *) malloc(len, M_80211_NODE_IE, M_NOWAIT);
if (ies->data == NULL) {
ies->len = 0;
/* NB: pointers have already been zero'd above */
@@ -829,7 +830,7 @@ void
ieee80211_ies_cleanup(struct ieee80211_ies *ies)
{
if (ies->data != NULL)
- FREE(ies->data, M_80211_NODE_IE);
+ free(ies->data, M_80211_NODE_IE);
}
/*
@@ -898,8 +899,10 @@ node_cleanup(struct ieee80211_node *ni)
* has happened. This is probably not needed as the node
* should always be removed from the table so not found but
* do it just in case.
+ * Likewise clear the ASSOCID flag as these flags are intended
+ * to be managed in tandem.
*/
- ni->ni_flags &= ~IEEE80211_NODE_AREF;
+ ni->ni_flags &= ~(IEEE80211_NODE_AREF | IEEE80211_NODE_ASSOCID);
/*
* Drain power save queue and, if needed, clear TIM.
@@ -909,7 +912,7 @@ node_cleanup(struct ieee80211_node *ni)
ni->ni_associd = 0;
if (ni->ni_challenge != NULL) {
- FREE(ni->ni_challenge, M_80211_NODE);
+ free(ni->ni_challenge, M_80211_NODE);
ni->ni_challenge = NULL;
}
/*
@@ -945,7 +948,7 @@ node_free(struct ieee80211_node *ni)
ieee80211_ies_cleanup(&ni->ni_ies);
ieee80211_psq_cleanup(&ni->ni_psq);
IEEE80211_NODE_WDSQ_DESTROY(ni);
- FREE(ni, M_80211_NODE);
+ free(ni, M_80211_NODE);
}
static void
@@ -1511,19 +1514,8 @@ ieee80211_find_txnode(struct ieee80211vap *vap,
vap->iv_opmode == IEEE80211_M_WDS ||
IEEE80211_IS_MULTICAST(macaddr))
ni = ieee80211_ref_node(vap->iv_bss);
- else {
+ else
ni = ieee80211_find_node_locked(nt, macaddr);
- if (vap->iv_opmode == IEEE80211_M_HOSTAP &&
- (ni != NULL && ni->ni_associd == 0)) {
- /*
- * Station is not associated; don't permit the
- * data frame to be sent by returning NULL. This
- * is kinda a kludge but the least intrusive way
- * to add this check into all drivers.
- */
- ieee80211_unref_node(&ni); /* NB: null's ni */
- }
- }
IEEE80211_NODE_UNLOCK(nt);
if (ni == NULL) {
@@ -1651,7 +1643,7 @@ ieee80211_node_delucastkey(struct ieee80211_node *ni)
IEEE80211_NODE_LOCK(nt);
nikey = NULL;
status = 1; /* NB: success */
- if (!IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey)) {
+ if (ni->ni_ucastkey.wk_keyix != IEEE80211_KEYIX_NONE) {
keyix = ni->ni_ucastkey.wk_rxkeyix;
status = ieee80211_crypto_delkey(ni->ni_vap, &ni->ni_ucastkey);
if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax) {
@@ -1799,7 +1791,7 @@ ieee80211_node_table_init(struct ieee80211com *ic,
nt->nt_inact_init = inact;
nt->nt_keyixmax = keyixmax;
if (nt->nt_keyixmax > 0) {
- MALLOC(nt->nt_keyixmap, struct ieee80211_node **,
+ nt->nt_keyixmap = (struct ieee80211_node **) malloc(
keyixmax * sizeof(struct ieee80211_node *),
M_80211_NODE, M_NOWAIT | M_ZERO);
if (nt->nt_keyixmap == NULL)
@@ -1860,7 +1852,7 @@ ieee80211_node_table_cleanup(struct ieee80211_node_table *nt)
printf("%s: %s[%u] still active\n", __func__,
nt->nt_name, i);
#endif
- FREE(nt->nt_keyixmap, M_80211_NODE);
+ free(nt->nt_keyixmap, M_80211_NODE);
nt->nt_keyixmap = NULL;
}
IEEE80211_NODE_ITERATE_LOCK_DESTROY(nt);
diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h
index b8a30ad..bd304d5 100644
--- a/sys/net80211/ieee80211_node.h
+++ b/sys/net80211/ieee80211_node.h
@@ -117,6 +117,7 @@ struct ieee80211_node {
#define IEEE80211_NODE_RIFS 0x004000 /* RIFS enabled */
#define IEEE80211_NODE_SGI20 0x008000 /* Short GI in HT20 enabled */
#define IEEE80211_NODE_SGI40 0x010000 /* Short GI in HT40 enabled */
+#define IEEE80211_NODE_ASSOCID 0x020000 /* xmit requires associd */
uint16_t ni_associd; /* association ID */
uint16_t ni_vlan; /* vlan tag */
uint16_t ni_txpower; /* current transmit power */
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index e5c6889..050d892 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -203,10 +203,8 @@ ieee80211_start(struct ifnet *ifp)
continue;
}
/* XXX AUTH'd */
- /* XXX mark vap to identify if associd is required */
if (ni->ni_associd == 0 &&
- (vap->iv_opmode == IEEE80211_M_STA ||
- vap->iv_opmode == IEEE80211_M_HOSTAP || IS_DWDS(vap))) {
+ (ni->ni_flags & IEEE80211_NODE_ASSOCID)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_OUTPUT,
eh->ether_dhost, NULL,
"sta not associated (type 0x%04x)",
diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c
index b2ace4a..aad82ba 100644
--- a/sys/net80211/ieee80211_power.c
+++ b/sys/net80211/ieee80211_power.c
@@ -80,7 +80,7 @@ ieee80211_power_latevattach(struct ieee80211vap *vap)
*/
if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
vap->iv_tim_len = howmany(vap->iv_max_aid,8) * sizeof(uint8_t);
- MALLOC(vap->iv_tim_bitmap, uint8_t *, vap->iv_tim_len,
+ vap->iv_tim_bitmap = (uint8_t *) malloc(vap->iv_tim_len,
M_80211_POWER, M_NOWAIT | M_ZERO);
if (vap->iv_tim_bitmap == NULL) {
printf("%s: no memory for TIM bitmap!\n", __func__);
@@ -94,7 +94,7 @@ void
ieee80211_power_vdetach(struct ieee80211vap *vap)
{
if (vap->iv_tim_bitmap != NULL) {
- FREE(vap->iv_tim_bitmap, M_80211_POWER);
+ free(vap->iv_tim_bitmap, M_80211_POWER);
vap->iv_tim_bitmap = NULL;
}
}
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index 452bd3f..31b68fd 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -214,7 +214,7 @@ ieee80211_proto_vdetach(struct ieee80211vap *vap)
{
#define FREEAPPIE(ie) do { \
if (ie != NULL) \
- FREE(ie, M_80211_NODE_IE); \
+ free(ie, M_80211_NODE_IE); \
} while (0)
/*
* Detach operating mode module.
diff --git a/sys/net80211/ieee80211_regdomain.c b/sys/net80211/ieee80211_regdomain.c
index 0e41355..724d00b 100644
--- a/sys/net80211/ieee80211_regdomain.c
+++ b/sys/net80211/ieee80211_regdomain.c
@@ -338,7 +338,7 @@ ieee80211_setregdomain(struct ieee80211vap *vap,
reg->rd.isocc[0], reg->rd.isocc[1]);
return EINVAL;
}
- if (reg->chaninfo.ic_nchans >= IEEE80211_CHAN_MAX) {
+ if (reg->chaninfo.ic_nchans > IEEE80211_CHAN_MAX) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
"%s: too many channels %u, max %u\n", __func__,
reg->chaninfo.ic_nchans, IEEE80211_CHAN_MAX);
diff --git a/sys/net80211/ieee80211_scan.c b/sys/net80211/ieee80211_scan.c
index dabb404..f56617a0 100644
--- a/sys/net80211/ieee80211_scan.c
+++ b/sys/net80211/ieee80211_scan.c
@@ -96,7 +96,7 @@ ieee80211_scan_attach(struct ieee80211com *ic)
{
struct scan_state *ss;
- MALLOC(ss, struct scan_state *, sizeof(struct scan_state),
+ ss = (struct scan_state *) malloc(sizeof(struct scan_state),
M_80211_SCAN, M_NOWAIT | M_ZERO);
if (ss == NULL) {
ic->ic_scan = NULL;
@@ -122,7 +122,7 @@ ieee80211_scan_detach(struct ieee80211com *ic)
}
ic->ic_flags &= ~IEEE80211_F_SCAN;
ic->ic_scan = NULL;
- FREE(SCAN_PRIVATE(ss), M_80211_SCAN);
+ free(SCAN_PRIVATE(ss), M_80211_SCAN);
}
}
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c
index e3a4bda..15e4ff6 100644
--- a/sys/net80211/ieee80211_scan_sta.c
+++ b/sys/net80211/ieee80211_scan_sta.c
@@ -87,6 +87,9 @@ struct sta_entry {
#define STA_HASH(addr) \
(((const uint8_t *)(addr))[IEEE80211_ADDR_LEN - 1] % STA_HASHSIZE)
+#define MAX_IEEE_CHAN 256 /* max acceptable IEEE chan # */
+CTASSERT(MAX_IEEE_CHAN >= 256);
+
struct sta_table {
struct mtx st_lock; /* on scan table */
TAILQ_HEAD(, sta_entry) st_entry; /* all entries */
@@ -96,7 +99,7 @@ struct sta_table {
u_int st_scangen; /* scan generation # */
int st_newscan;
/* ap-related state */
- int st_maxrssi[IEEE80211_CHAN_MAX];
+ int st_maxrssi[MAX_IEEE_CHAN];
};
static void sta_flush_table(struct sta_table *);
@@ -137,7 +140,7 @@ sta_attach(struct ieee80211_scan_state *ss)
{
struct sta_table *st;
- MALLOC(st, struct sta_table *, sizeof(struct sta_table),
+ st = (struct sta_table *) malloc(sizeof(struct sta_table),
M_80211_SCAN, M_NOWAIT | M_ZERO);
if (st == NULL)
return 0;
@@ -161,7 +164,7 @@ sta_detach(struct ieee80211_scan_state *ss)
sta_flush_table(st);
mtx_destroy(&st->st_lock);
mtx_destroy(&st->st_scanlock);
- FREE(st, M_80211_SCAN);
+ free(st, M_80211_SCAN);
KASSERT(nrefs > 0, ("imbalanced attach/detach"));
nrefs--; /* NB: we assume caller locking */
}
@@ -195,7 +198,7 @@ sta_flush_table(struct sta_table *st)
TAILQ_REMOVE(&st->st_entry, se, se_list);
LIST_REMOVE(se, se_hash);
ieee80211_ies_cleanup(&se->base.se_ies);
- FREE(se, M_80211_SCAN);
+ free(se, M_80211_SCAN);
}
memset(st->st_maxrssi, 0, sizeof(st->st_maxrssi));
}
@@ -228,7 +231,7 @@ sta_add(struct ieee80211_scan_state *ss,
LIST_FOREACH(se, &st->st_hash[hash], se_hash)
if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr))
goto found;
- MALLOC(se, struct sta_entry *, sizeof(struct sta_entry),
+ se = (struct sta_entry *) malloc(sizeof(struct sta_entry),
M_80211_SCAN, M_NOWAIT | M_ZERO);
if (se == NULL) {
mtx_unlock(&st->st_lock);
@@ -343,6 +346,7 @@ found:
se->se_seen = 1;
se->se_notseen = 0;
+ KASSERT(sizeof(sp->bchan) == 1, ("bchan size"));
if (rssi > st->st_maxrssi[sp->bchan])
st->st_maxrssi[sp->bchan] = rssi;
@@ -1505,7 +1509,7 @@ adhoc_age(struct ieee80211_scan_state *ss)
TAILQ_REMOVE(&st->st_entry, se, se_list);
LIST_REMOVE(se, se_hash);
ieee80211_ies_cleanup(&se->base.se_ies);
- FREE(se, M_80211_SCAN);
+ free(se, M_80211_SCAN);
}
}
mtx_unlock(&st->st_lock);
@@ -1604,6 +1608,7 @@ ap_pick_channel(struct ieee80211_scan_state *ss, int flags)
/* check channel attributes for band compatibility */
if (flags != 0 && (chan->ic_flags & flags) != flags)
continue;
+ KASSERT(sizeof(chan->ic_ieee) == 1, ("ic_chan size"));
/* XXX channel have interference */
if (st->st_maxrssi[chan->ic_ieee] == 0) {
/* XXX use other considerations */
diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c
index 35fcead..54733c9 100644
--- a/sys/net80211/ieee80211_sta.c
+++ b/sys/net80211/ieee80211_sta.c
@@ -1018,7 +1018,7 @@ sta_auth_shared(struct ieee80211_node *ni, struct ieee80211_frame *wh,
switch (seq) {
case IEEE80211_AUTH_SHARED_PASS:
if (ni->ni_challenge != NULL) {
- FREE(ni->ni_challenge, M_80211_NODE);
+ free(ni->ni_challenge, M_80211_NODE);
ni->ni_challenge = NULL;
}
if (status != 0) {
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index 3e90201..ccd95d0 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -156,7 +156,7 @@ struct ieee80211com {
* (e.g. for dynamic turbo)
*/
int ic_nchans; /* # entries in ic_channels */
- struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX+1];
+ struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX];
uint8_t ic_chan_avail[IEEE80211_CHAN_BYTES];
uint8_t ic_chan_active[IEEE80211_CHAN_BYTES];
uint8_t ic_chan_scan[IEEE80211_CHAN_BYTES];
diff --git a/sys/netgraph/netflow/netflow.c b/sys/netgraph/netflow/netflow.c
index 5443629..411730a 100644
--- a/sys/netgraph/netflow/netflow.c
+++ b/sys/netgraph/netflow/netflow.c
@@ -270,7 +270,7 @@ hash_insert(priv_p priv, struct flow_hash_entry *hsh, struct flow_rec *r,
sin.sin_family = AF_INET;
sin.sin_addr = fle->f.r.r_dst;
/* XXX MRT 0 as a default.. need the m here to get fib */
- rt = rtalloc1_fib((struct sockaddr *)&sin, 0, RTF_CLONING, 0);
+ rt = rtalloc1_fib((struct sockaddr *)&sin, 0, 0, 0);
if (rt != NULL) {
fle->f.fle_o_ifx = rt->rt_ifp->if_index;
@@ -295,7 +295,7 @@ hash_insert(priv_p priv, struct flow_hash_entry *hsh, struct flow_rec *r,
sin.sin_family = AF_INET;
sin.sin_addr = fle->f.r.r_src;
/* XXX MRT 0 as a default revisit. need the mbuf for fib*/
- rt = rtalloc1_fib((struct sockaddr *)&sin, 0, RTF_CLONING, 0);
+ rt = rtalloc1_fib((struct sockaddr *)&sin, 0, 0, 0);
if (rt != NULL) {
if (rt_mask(rt))
fle->f.src_mask = bitcount32(((struct sockaddr_in *)
diff --git a/sys/netgraph/netgraph.h b/sys/netgraph/netgraph.h
index 4072f76..859af71 100644
--- a/sys/netgraph/netgraph.h
+++ b/sys/netgraph/netgraph.h
@@ -1130,7 +1130,6 @@ item_p ng_package_msg(struct ng_mesg *msg, int flags);
item_p ng_package_msg_self(node_p here, hook_p hook, struct ng_mesg *msg);
void ng_replace_retaddr(node_p here, item_p item, ng_ID_t retaddr);
int ng_rmhook_self(hook_p hook); /* if a node wants to kill a hook */
-int ng_rmnode_flags(node_p here, int flags);
int ng_rmnode_self(node_p here); /* if a node wants to suicide */
int ng_rmtype(struct ng_type *tp);
int ng_snd_item(item_p item, int queue);
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c
index 0406da1..0e9f96c 100644
--- a/sys/netgraph/ng_base.c
+++ b/sys/netgraph/ng_base.c
@@ -62,6 +62,9 @@
#include <sys/refcount.h>
#include <sys/proc.h>
#include <sys/vimage.h>
+#include <sys/unistd.h>
+#include <sys/kthread.h>
+#include <sys/smp.h>
#include <machine/cpu.h>
#include <net/netisr.h>
@@ -211,7 +214,7 @@ static int ng_generic_msg(node_p here, item_p item, hook_p lasthook);
static ng_ID_t ng_decodeidname(const char *name);
static int ngb_mod_event(module_t mod, int event, void *data);
static void ng_worklist_add(node_p node);
-static void ngintr(void);
+static void ngthread(void *);
static int ng_apply_item(node_p node, item_p item, int rw);
static void ng_flush_input_queue(node_p node);
static node_p ng_ID2noderef(ng_ID_t ID);
@@ -259,6 +262,10 @@ MALLOC_DEFINE(M_NETGRAPH_MSG, "netgraph_msg", "netgraph name storage");
mtx_lock(&ng_worklist_mtx)
#define NG_WORKLIST_UNLOCK() \
mtx_unlock(&ng_worklist_mtx)
+#define NG_WORKLIST_SLEEP() \
+ mtx_sleep(&ng_worklist, &ng_worklist_mtx, PI_NET, "sleep", 0)
+#define NG_WORKLIST_WAKEUP() \
+ wakeup_one(&ng_worklist)
#ifdef NETGRAPH_DEBUG /*----------------------------------------------*/
/*
@@ -1521,7 +1528,7 @@ ng_mkpeer(node_p node, const char *name, const char *name2, char *type)
/* Shut this node down as soon as everyone is clear of it */
/* Should add arg "immediately" to jump the queue */
int
-ng_rmnode_flags(node_p node, int flags)
+ng_rmnode_self(node_p node)
{
int error;
@@ -1531,16 +1538,10 @@ ng_rmnode_flags(node_p node, int flags)
if (node->nd_flags & NGF_CLOSING)
return (0);
- error = ng_send_fn1(node, NULL, &ng_rmnode, NULL, 0, flags);
+ error = ng_send_fn(node, NULL, &ng_rmnode, NULL, 0);
return (error);
}
-int
-ng_rmnode_self(node_p node)
-{
- return (ng_rmnode_flags(node, NG_NOFLAGS));
-}
-
static void
ng_rmhook_part2(node_p node, hook_p hook, void *arg1, int arg2)
{
@@ -2874,9 +2875,13 @@ out:
uma_zone_t ng_qzone;
uma_zone_t ng_qdzone;
+static int numthreads = 0; /* number of queue threads */
static int maxalloc = 4096;/* limit the damage of a leak */
static int maxdata = 512; /* limit the damage of a DoS */
+TUNABLE_INT("net.graph.threads", &numthreads);
+SYSCTL_INT(_net_graph, OID_AUTO, threads, CTLFLAG_RDTUN, &numthreads,
+ 0, "Number of queue processing threads");
TUNABLE_INT("net.graph.maxalloc", &maxalloc);
SYSCTL_INT(_net_graph, OID_AUTO, maxalloc, CTLFLAG_RDTUN, &maxalloc,
0, "Maximum number of non-data queue items to allocate");
@@ -3070,7 +3075,9 @@ ng_mod_event(module_t mod, int event, void *data)
static int
ngb_mod_event(module_t mod, int event, void *data)
{
- int error = 0;
+ struct proc *p;
+ struct thread *td;
+ int i, error = 0;
switch (event) {
case MOD_LOAD:
@@ -3097,7 +3104,18 @@ ngb_mod_event(module_t mod, int event, void *data)
ng_qdzone = uma_zcreate("NetGraph data items", sizeof(struct ng_item),
NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, 0);
uma_zone_set_max(ng_qdzone, maxdata);
- netisr_register(NETISR_NETGRAPH, (netisr_t *)ngintr, NULL, 0);
+ /* Autoconfigure number of threads. */
+ if (numthreads <= 0)
+ numthreads = mp_ncpus;
+ /* Create threads. */
+ p = NULL; /* start with no process */
+ for (i = 0; i < numthreads; i++) {
+ if (kproc_kthread_add(ngthread, NULL, &p, &td,
+ RFHIGHPID, 0, "ng_queue", "ng_queue%d", i)) {
+ numthreads = i;
+ break;
+ }
+ }
break;
case MOD_UNLOAD:
/* You can't unload it because an interface may be using it. */
@@ -3252,25 +3270,20 @@ SYSCTL_PROC(_debug, OID_AUTO, ng_dump_items, CTLTYPE_INT | CTLFLAG_RW,
/***********************************************************************
* Worklist routines
**********************************************************************/
-/* NETISR thread enters here */
/*
* Pick a node off the list of nodes with work,
- * try get an item to process off it.
- * If there are no more, remove the node from the list.
+ * try get an item to process off it. Remove the node from the list.
*/
static void
-ngintr(void)
+ngthread(void *arg)
{
for (;;) {
node_p node;
/* Get node from the worklist. */
NG_WORKLIST_LOCK();
- node = STAILQ_FIRST(&ng_worklist);
- if (!node) {
- NG_WORKLIST_UNLOCK();
- break;
- }
+ while ((node = STAILQ_FIRST(&ng_worklist)) == NULL)
+ NG_WORKLIST_SLEEP();
STAILQ_REMOVE_HEAD(&ng_worklist, nd_input_queue.q_work);
NG_WORKLIST_UNLOCK();
CTR3(KTR_NET, "%20s: node [%x] (%p) taken off worklist",
@@ -3326,9 +3339,9 @@ ng_worklist_add(node_p node)
NG_WORKLIST_LOCK();
STAILQ_INSERT_TAIL(&ng_worklist, node, nd_input_queue.q_work);
NG_WORKLIST_UNLOCK();
- schednetisr(NETISR_NETGRAPH);
CTR3(KTR_NET, "%20s: node [%x] (%p) put on worklist", __func__,
node->nd_ID, node);
+ NG_WORKLIST_WAKEUP();
} else {
CTR3(KTR_NET, "%20s: node [%x] (%p) already on worklist",
__func__, node->nd_ID, node);
diff --git a/sys/netgraph/ng_mppc.c b/sys/netgraph/ng_mppc.c
index 472968f..5a6c302 100644
--- a/sys/netgraph/ng_mppc.c
+++ b/sys/netgraph/ng_mppc.c
@@ -824,21 +824,24 @@ ng_mppc_reset_req(node_p node)
static void
ng_mppc_getkey(const u_char *h, u_char *h2, int len)
{
- static const u_char pad1[10] =
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
- static const u_char pad2[10] =
- { 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, };
+ static const u_char pad1[40] =
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const u_char pad2[40] =
+ { 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2 };
u_char hash[20];
SHA1_CTX c;
- int k;
SHA1Init(&c);
SHA1Update(&c, h, len);
- for (k = 0; k < 4; k++)
- SHA1Update(&c, pad1, sizeof(pad1));
+ SHA1Update(&c, pad1, sizeof(pad1));
SHA1Update(&c, h2, len);
- for (k = 0; k < 4; k++)
- SHA1Update(&c, pad2, sizeof(pad2));
+ SHA1Update(&c, pad2, sizeof(pad2));
SHA1Final(hash, &c);
bcopy(hash, h2, len);
}
diff --git a/sys/netgraph/ng_tty.c b/sys/netgraph/ng_tty.c
index c504b84..2fa33fc 100644
--- a/sys/netgraph/ng_tty.c
+++ b/sys/netgraph/ng_tty.c
@@ -114,7 +114,6 @@ static th_getc_poll_t ngt_getc_poll;
static th_rint_t ngt_rint;
static th_rint_bypass_t ngt_rint_bypass;
static th_rint_poll_t ngt_rint_poll;
-static th_close_t ngt_close;
static struct ttyhook ngt_hook = {
.th_getc_inject = ngt_getc_inject,
@@ -122,7 +121,6 @@ static struct ttyhook ngt_hook = {
.th_rint = ngt_rint,
.th_rint_bypass = ngt_rint_bypass,
.th_rint_poll = ngt_rint_poll,
- .th_close = ngt_close,
};
/* Netgraph node type descriptor */
@@ -252,7 +250,6 @@ static int
ngt_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
struct proc *p;
- struct thread *td;
const sc_p sc = NG_NODE_PRIVATE(node);
struct ng_mesg *msg, *resp = NULL;
int error = 0;
@@ -266,12 +263,13 @@ ngt_rcvmsg(node_p node, item_p item, hook_p lasthook)
return (EBUSY);
p = pfind(((int *)msg->data)[0]);
- if (p == NULL)
+ if (p == NULL || (p->p_flag & P_WEXIT))
return (ESRCH);
- td = FIRST_THREAD_IN_PROC(p);
- error = ttyhook_register(&sc->tp, td, ((int *)msg->data)[1],
- &ngt_hook, sc);
+ _PHOLD(p);
PROC_UNLOCK(p);
+ error = ttyhook_register(&sc->tp, p, ((int *)msg->data)[1],
+ &ngt_hook, sc);
+ PRELE(p);
if (error != 0)
return (error);
break;
@@ -515,12 +513,3 @@ ngt_rint_poll(struct tty *tp)
return (1);
}
-static void
-ngt_close(struct tty *tp)
-{
- sc_p sc = ttyhook_softc(tp);
-
- /* Must be queued to drop the tty lock */
- ng_rmnode_flags(sc->node, NG_QUEUE);
-}
-
diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h
index 91b1658..fcdc9ce 100644
--- a/sys/netinet/icmp6.h
+++ b/sys/netinet/icmp6.h
@@ -707,8 +707,10 @@ do { \
} \
} while (/*CONSTCOND*/ 0)
+#ifdef VIMAGE_GLOBALS
extern int icmp6_rediraccept; /* accept/process redirects */
extern int icmp6_redirtimeout; /* cache time for redirect routes */
+#endif
#define ICMP6_NODEINFO_FQDNOK 0x1
#define ICMP6_NODEINFO_NODEADDROK 0x2
diff --git a/sys/netinet/icmp_var.h b/sys/netinet/icmp_var.h
index dda84f2..cd9ee00 100644
--- a/sys/netinet/icmp_var.h
+++ b/sys/netinet/icmp_var.h
@@ -74,7 +74,9 @@ struct icmpstat {
#ifdef _KERNEL
SYSCTL_DECL(_net_inet_icmp);
+#ifdef VIMAGE_GLOBALS
extern struct icmpstat icmpstat; /* icmp statistics */
+#endif
extern int badport_bandlim(int);
#define BANDLIM_UNLIMITED -1
#define BANDLIM_ICMP_UNREACH 0
diff --git a/sys/netinet/if_atm.c b/sys/netinet/if_atm.c
index 065f0c4..d534a18 100644
--- a/sys/netinet/if_atm.c
+++ b/sys/netinet/if_atm.c
@@ -127,10 +127,6 @@ atm_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
break;
}
- if ((rt->rt_flags & RTF_CLONING) != 0) {
- printf("atm_rtrequest: cloning route detected?\n");
- break;
- }
if (gate->sa_family != AF_LINK ||
gate->sa_len < sizeof(null_sdl)) {
log(LOG_DEBUG, "atm_rtrequest: bad gateway value");
@@ -332,8 +328,6 @@ atmresolve(struct rtentry *rt, struct mbuf *m, struct sockaddr *dst,
goto bad; /* failed */
RT_REMREF(rt); /* don't keep LL references */
if ((rt->rt_flags & RTF_GATEWAY) != 0 ||
- (rt->rt_flags & RTF_LLINFO) == 0 ||
- /* XXX: are we using LLINFO? */
rt->rt_gateway->sa_family != AF_LINK) {
RT_UNLOCK(rt);
goto bad;
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index da7946d..1b03fb3 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_var.h>
+#include <net/if_llatbl.h>
#include <netinet/if_ether.h>
#include <netinet/vinet.h>
@@ -79,6 +80,7 @@ __FBSDID("$FreeBSD$");
#define SIN(s) ((struct sockaddr_in *)s)
#define SDL(s) ((struct sockaddr_dl *)s)
+#define LLTABLE(ifp) ((struct lltable *)(ifp)->if_afdata[AF_INET])
SYSCTL_DECL(_net_link_ether);
SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, "");
@@ -87,23 +89,13 @@ SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, "");
#ifdef VIMAGE_GLOBALS
static int arpt_keep; /* once resolved, good for 20 more minutes */
static int arp_maxtries;
-static int useloopback; /* use loopback interface for local traffic */
+int useloopback; /* use loopback interface for local traffic */
static int arp_proxyall;
#endif
SYSCTL_V_INT(V_NET, vnet_inet, _net_link_ether_inet, OID_AUTO, max_age,
CTLFLAG_RW, arpt_keep, 0, "ARP entry lifetime in seconds");
-#define rt_expire rt_rmx.rmx_expire
-
-struct llinfo_arp {
- struct callout la_timer;
- struct rtentry *la_rt;
- struct mbuf *la_hold; /* last packet until resolved/timeout */
- u_short la_preempt; /* countdown for pre-expiry arps */
- u_short la_asked; /* # requests sent */
-};
-
static struct ifqueue arpintrq;
SYSCTL_V_INT(V_NET, vnet_inet, _net_link_ether_inet, OID_AUTO, maxtries,
@@ -117,196 +109,65 @@ SYSCTL_V_INT(V_NET, vnet_inet, _net_link_ether_inet, OID_AUTO, proxyall,
"Enable proxy ARP for all suitable requests");
static void arp_init(void);
-static void arp_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
-static void arprequest(struct ifnet *,
+void arprequest(struct ifnet *,
struct in_addr *, struct in_addr *, u_char *);
static void arpintr(struct mbuf *);
static void arptimer(void *);
-static struct rtentry
- *arplookup(u_long, int, int, int);
#ifdef INET
static void in_arpinput(struct mbuf *);
#endif
+#ifdef AF_INET
+void arp_ifscrub(struct ifnet *ifp, uint32_t addr);
+
/*
- * Timeout routine.
+ * called by in_ifscrub to remove entry from the table when
+ * the interface goes away
*/
-static void
-arptimer(void *arg)
+void
+arp_ifscrub(struct ifnet *ifp, uint32_t addr)
{
- struct rtentry *rt = (struct rtentry *)arg;
-
- RT_LOCK_ASSERT(rt);
- /*
- * The lock is needed to close a theoretical race
- * between spontaneous expiry and intentional removal.
- * We still got an extra reference on rtentry, so can
- * safely pass pointers to its contents.
- */
- RT_UNLOCK(rt);
-
- in_rtrequest(RTM_DELETE, rt_key(rt), NULL, rt_mask(rt), 0, NULL,
- rt->rt_fibnum);
+ struct sockaddr_in addr4;
+
+ bzero((void *)&addr4, sizeof(addr4));
+ addr4.sin_len = sizeof(addr4);
+ addr4.sin_family = AF_INET;
+ addr4.sin_addr.s_addr = addr;
+ IF_AFDATA_LOCK(ifp);
+ lla_lookup(LLTABLE(ifp), (LLE_DELETE | LLE_IFADDR),
+ (struct sockaddr *)&addr4);
+ IF_AFDATA_UNLOCK(ifp);
}
+#endif
/*
- * Parallel to llc_rtrequest.
+ * Timeout routine. Age arp_tab entries periodically.
*/
static void
-arp_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
+arptimer(void *arg)
{
- INIT_VNET_NET(curvnet);
- INIT_VNET_INET(curvnet);
- struct sockaddr *gate;
- struct llinfo_arp *la;
- static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
- struct in_ifaddr *ia;
- struct ifaddr *ifa;
+ struct ifnet *ifp;
+ struct llentry *lle = (struct llentry *)arg;
- RT_LOCK_ASSERT(rt);
-
- if (rt->rt_flags & RTF_GATEWAY)
+ if (lle == NULL) {
+ panic("%s: NULL entry!\n", __func__);
return;
- gate = rt->rt_gateway;
- la = (struct llinfo_arp *)rt->rt_llinfo;
- switch (req) {
-
- case RTM_ADD:
- /*
- * XXX: If this is a manually added route to interface
- * such as older version of routed or gated might provide,
- * restore cloning bit.
- */
- if ((rt->rt_flags & RTF_HOST) == 0 &&
- rt_mask(rt) != NULL &&
- SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
- rt->rt_flags |= RTF_CLONING;
- if (rt->rt_flags & RTF_CLONING) {
- /*
- * Case 1: This route should come from a route to iface.
- */
- rt_setgate(rt, rt_key(rt),
- (struct sockaddr *)&null_sdl);
- gate = rt->rt_gateway;
- SDL(gate)->sdl_type = rt->rt_ifp->if_type;
- SDL(gate)->sdl_index = rt->rt_ifp->if_index;
- rt->rt_expire = time_uptime;
- break;
- }
- /* Announce a new entry if requested. */
- if (rt->rt_flags & RTF_ANNOUNCE)
- arprequest(rt->rt_ifp,
- &SIN(rt_key(rt))->sin_addr,
- &SIN(rt_key(rt))->sin_addr,
- (u_char *)LLADDR(SDL(gate)));
- /*FALLTHROUGH*/
- case RTM_RESOLVE:
- if (gate->sa_family != AF_LINK ||
- gate->sa_len < sizeof(null_sdl)) {
- log(LOG_DEBUG, "%s: bad gateway %s%s\n", __func__,
- inet_ntoa(SIN(rt_key(rt))->sin_addr),
- (gate->sa_family != AF_LINK) ?
- " (!AF_LINK)": "");
- break;
- }
- SDL(gate)->sdl_type = rt->rt_ifp->if_type;
- SDL(gate)->sdl_index = rt->rt_ifp->if_index;
- if (la != 0)
- break; /* This happens on a route change */
- /*
- * Case 2: This route may come from cloning, or a manual route
- * add with a LL address.
- */
- R_Zalloc(la, struct llinfo_arp *, sizeof(*la));
- rt->rt_llinfo = (caddr_t)la;
- if (la == 0) {
- log(LOG_DEBUG, "%s: malloc failed\n", __func__);
- break;
- }
- /*
- * We are storing a route entry outside of radix tree. So,
- * it can be found and accessed by other means than radix
- * lookup. The routing code assumes that any rtentry detached
- * from radix can be destroyed safely. To prevent this, we
- * add an additional reference.
- */
- RT_ADDREF(rt);
- la->la_rt = rt;
- rt->rt_flags |= RTF_LLINFO;
- callout_init_mtx(&la->la_timer, &rt->rt_mtx,
- CALLOUT_RETURNUNLOCKED);
-
-#ifdef INET
+ }
+ ifp = lle->lle_tbl->llt_ifp;
+ IF_AFDATA_LOCK(ifp);
+ LLE_WLOCK(lle);
+ if ((lle->la_flags & LLE_DELETED) ||
+ (time_second >= lle->la_expire)) {
+ if (!callout_pending(&lle->la_timer) &&
+ callout_active(&lle->la_timer))
+ (void) llentry_free(lle);
+ } else {
/*
- * This keeps the multicast addresses from showing up
- * in `arp -a' listings as unresolved. It's not actually
- * functional. Then the same for broadcast.
+ * Still valid, just drop our reference
*/
- if (IN_MULTICAST(ntohl(SIN(rt_key(rt))->sin_addr.s_addr)) &&
- rt->rt_ifp->if_type != IFT_ARCNET) {
- ETHER_MAP_IP_MULTICAST(&SIN(rt_key(rt))->sin_addr,
- LLADDR(SDL(gate)));
- SDL(gate)->sdl_alen = 6;
- rt->rt_expire = 0;
- }
- if (in_broadcast(SIN(rt_key(rt))->sin_addr, rt->rt_ifp)) {
- memcpy(LLADDR(SDL(gate)), rt->rt_ifp->if_broadcastaddr,
- rt->rt_ifp->if_addrlen);
- SDL(gate)->sdl_alen = rt->rt_ifp->if_addrlen;
- rt->rt_expire = 0;
- }
-#endif
-
- TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
- if (ia->ia_ifp == rt->rt_ifp &&
- SIN(rt_key(rt))->sin_addr.s_addr ==
- (IA_SIN(ia))->sin_addr.s_addr)
- break;
- }
- if (ia) {
- /*
- * This test used to be
- * if (loif.if_flags & IFF_UP)
- * It allowed local traffic to be forced
- * through the hardware by configuring the loopback down.
- * However, it causes problems during network configuration
- * for boards that can't receive packets they send.
- * It is now necessary to clear "useloopback" and remove
- * the route to force traffic out to the hardware.
- */
- rt->rt_expire = 0;
- bcopy(IF_LLADDR(rt->rt_ifp), LLADDR(SDL(gate)),
- SDL(gate)->sdl_alen = rt->rt_ifp->if_addrlen);
- if (V_useloopback) {
- rt->rt_ifp = V_loif;
- rt->rt_rmx.rmx_mtu = V_loif->if_mtu;
- }
-
- /*
- * make sure to set rt->rt_ifa to the interface
- * address we are using, otherwise we will have trouble
- * with source address selection.
- */
- ifa = &ia->ia_ifa;
- if (ifa != rt->rt_ifa) {
- IFAFREE(rt->rt_ifa);
- IFAREF(ifa);
- rt->rt_ifa = ifa;
- }
- }
- break;
-
- case RTM_DELETE:
- if (la == NULL) /* XXX: at least CARP does this. */
- break;
- callout_stop(&la->la_timer);
- rt->rt_llinfo = NULL;
- rt->rt_flags &= ~RTF_LLINFO;
- RT_REMREF(rt);
- if (la->la_hold)
- m_freem(la->la_hold);
- Free((caddr_t)la);
+ LLE_FREE_LOCKED(lle);
}
+ IF_AFDATA_UNLOCK(ifp);
}
/*
@@ -315,14 +176,37 @@ arp_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
* - arp header target ip address
* - arp header source ethernet address
*/
-static void
-arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip,
+void
+arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip,
u_char *enaddr)
{
struct mbuf *m;
struct arphdr *ah;
struct sockaddr sa;
+ if (sip == NULL) {
+ /* XXX don't believe this can happen (or explain why) */
+ /*
+ * The caller did not supply a source address, try to find
+ * a compatible one among those assigned to this interface.
+ */
+ struct ifaddr *ifa;
+
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ if (!ifa->ifa_addr ||
+ ifa->ifa_addr->sa_family != AF_INET)
+ continue;
+ sip = &SIN(ifa->ifa_addr)->sin_addr;
+ if (0 == ((sip->s_addr ^ tip->s_addr) &
+ SIN(ifa->ifa_netmask)->sin_addr.s_addr) )
+ break; /* found it. */
+ }
+ if (sip == NULL) {
+ printf("%s: cannot find matching address\n", __func__);
+ return;
+ }
+ }
+
if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
return;
m->m_len = sizeof(*ah) + 2*sizeof(struct in_addr) +
@@ -345,8 +229,6 @@ arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip,
sa.sa_len = 2;
m->m_flags |= M_BCAST;
(*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0);
-
- return;
}
/*
@@ -365,16 +247,15 @@ arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip,
*/
int
arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
- struct sockaddr *dst, u_char *desten)
+ struct sockaddr *dst, u_char *desten, struct llentry **lle)
{
INIT_VNET_INET(ifp->if_vnet);
- struct llinfo_arp *la = NULL;
- struct rtentry *rt = NULL;
- struct sockaddr_dl *sdl;
- int error;
- int fibnum = -1;
+ struct llentry *la = 0;
+ u_int flags = 0;
+ int error, renew;
- if (m) {
+ *lle = NULL;
+ if (m != NULL) {
if (m->m_flags & M_BCAST) {
/* broadcast */
(void)memcpy(desten,
@@ -386,110 +267,79 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
return (0);
}
- fibnum = M_GETFIB(m);
}
-
- if (rt0 != NULL) {
- /* Look for a cached arp (ll) entry. */
- if (m == NULL)
- fibnum = rt0->rt_fibnum;
- error = rt_check(&rt, &rt0, dst);
- if (error) {
- m_freem(m);
- return error;
- }
- la = (struct llinfo_arp *)rt->rt_llinfo;
- if (la == NULL)
- RT_UNLOCK(rt);
- }
-
- /*
- * If we had no mbuf and no route, then hope the caller
- * has a fib in mind because we are running out of ideas.
- * I think this should not happen in current code.
- * (kmacy would know).
+ /* XXXXX
*/
- if (fibnum == -1)
- fibnum = curthread->td_proc->p_fibnum; /* last gasp */
-
+retry:
+ IF_AFDATA_RLOCK(ifp);
+ la = lla_lookup(LLTABLE(ifp), flags, dst);
+ IF_AFDATA_RUNLOCK(ifp);
+ if ((la == NULL) && ((flags & LLE_EXCLUSIVE) == 0)
+ && ((ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0)) {
+ flags |= (LLE_CREATE | LLE_EXCLUSIVE);
+ IF_AFDATA_WLOCK(ifp);
+ la = lla_lookup(LLTABLE(ifp), flags, dst);
+ IF_AFDATA_WUNLOCK(ifp);
+ }
if (la == NULL) {
- /*
- * We enter this block if rt0 was NULL,
- * or if rt found by rt_check() didn't have llinfo.
- * we should get a cloned route, which since it should
- * come from the local interface should have a ll entry.
- * It may be incomplete but that's ok.
- */
- rt = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0, fibnum);
- if (rt == NULL) {
- log(LOG_DEBUG,
- "arpresolve: can't allocate route for %s\n",
- inet_ntoa(SIN(dst)->sin_addr));
- m_freem(m);
- return (EINVAL); /* XXX */
- }
- la = (struct llinfo_arp *)rt->rt_llinfo;
- if (la == NULL) {
- RT_UNLOCK(rt);
+ if (flags & LLE_CREATE)
log(LOG_DEBUG,
"arpresolve: can't allocate llinfo for %s\n",
inet_ntoa(SIN(dst)->sin_addr));
- m_freem(m);
- return (EINVAL); /* XXX */
- }
- }
- sdl = SDL(rt->rt_gateway);
- /*
- * Check the address family and length is valid, the address
- * is resolved; otherwise, try to resolve.
- */
- if ((rt->rt_expire == 0 || rt->rt_expire > time_uptime) &&
- sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
-
- bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
+ m_freem(m);
+ return (EINVAL);
+ }
+ if ((la->la_flags & LLE_VALID) &&
+ ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) {
+ bcopy(&la->ll_addr, desten, ifp->if_addrlen);
/*
* If entry has an expiry time and it is approaching,
- * send an ARP request.
+ * see if we need to send an ARP request within this
+ * arpt_down interval.
*/
- if ((rt->rt_expire != 0) &&
- (time_uptime + la->la_preempt > rt->rt_expire)) {
- struct in_addr sin =
- SIN(rt->rt_ifa->ifa_addr)->sin_addr;
+ if (!(la->la_flags & LLE_STATIC) &&
+ time_uptime + la->la_preempt > la->la_expire) {
+ arprequest(ifp, NULL,
+ &SIN(dst)->sin_addr, IF_LLADDR(ifp));
la->la_preempt--;
- RT_UNLOCK(rt);
- arprequest(ifp, &sin, &SIN(dst)->sin_addr,
- IF_LLADDR(ifp));
- return (0);
- }
-
- RT_UNLOCK(rt);
- return (0);
- }
- /*
- * If ARP is disabled or static on this interface, stop.
- * XXX
- * Probably should not allocate empty llinfo struct if we are
- * not going to be sending out an arp request.
- */
- if (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) {
- RT_UNLOCK(rt);
+ }
+
+ *lle = la;
+ error = 0;
+ goto done;
+ }
+
+ if (la->la_flags & LLE_STATIC) { /* should not happen! */
+ log(LOG_DEBUG, "arpresolve: ouch, empty static llinfo for %s\n",
+ inet_ntoa(SIN(dst)->sin_addr));
m_freem(m);
- return (EINVAL);
+ error = EINVAL;
+ goto done;
+ }
+
+ renew = (la->la_asked == 0 || la->la_expire != time_uptime);
+ if ((renew || m != NULL) && (flags & LLE_EXCLUSIVE) == 0) {
+ flags |= LLE_EXCLUSIVE;
+ LLE_RUNLOCK(la);
+ goto retry;
}
/*
* There is an arptab entry, but no ethernet address
* response yet. Replace the held mbuf with this
* latest one.
*/
- if (m) {
- if (la->la_hold)
+ if (m != NULL) {
+ if (la->la_hold != NULL)
m_freem(la->la_hold);
la->la_hold = m;
+ if (renew == 0 && (flags & LLE_EXCLUSIVE)) {
+ flags &= ~LLE_EXCLUSIVE;
+ LLE_DOWNGRADE(la);
+ }
+
}
- KASSERT(rt->rt_expire > 0, ("sending ARP request for static entry"));
-
/*
* Return EWOULDBLOCK if we have tried less than arp_maxtries. It
* will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH
@@ -499,22 +349,24 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
if (la->la_asked < V_arp_maxtries)
error = EWOULDBLOCK; /* First request. */
else
- error = (rt == rt0) ? EHOSTDOWN : EHOSTUNREACH;
-
- if (la->la_asked == 0 || rt->rt_expire != time_uptime) {
- struct in_addr sin =
- SIN(rt->rt_ifa->ifa_addr)->sin_addr;
+ error =
+ (rt0->rt_flags & RTF_GATEWAY) ? EHOSTDOWN : EHOSTUNREACH;
- rt->rt_expire = time_uptime;
- callout_reset(&la->la_timer, hz, arptimer, rt);
+ if (renew) {
+ LLE_ADDREF(la);
+ la->la_expire = time_uptime;
+ callout_reset(&la->la_timer, hz, arptimer, la);
la->la_asked++;
- RT_UNLOCK(rt);
-
- arprequest(ifp, &sin, &SIN(dst)->sin_addr,
+ LLE_WUNLOCK(la);
+ arprequest(ifp, NULL, &SIN(dst)->sin_addr,
IF_LLADDR(ifp));
- } else
- RT_UNLOCK(rt);
-
+ return (error);
+ }
+done:
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WUNLOCK(la);
+ else
+ LLE_RUNLOCK(la);
return (error);
}
@@ -598,21 +450,17 @@ in_arpinput(struct mbuf *m)
{
struct arphdr *ah;
struct ifnet *ifp = m->m_pkthdr.rcvif;
- struct llinfo_arp *la;
+ struct llentry *la = NULL;
struct rtentry *rt;
struct ifaddr *ifa;
struct in_ifaddr *ia;
- struct sockaddr_dl *sdl;
struct sockaddr sa;
struct in_addr isaddr, itaddr, myaddr;
- struct mbuf *hold;
u_int8_t *enaddr = NULL;
- int op, rif_len;
+ int op, flags;
+ struct mbuf *m0;
int req_len;
int bridged = 0, is_bridge = 0;
- u_int fibnum;
- u_int goodfib = 0;
- int firstpass = 1;
#ifdef DEV_CARP
int carp_match = 0;
#endif
@@ -649,7 +497,7 @@ in_arpinput(struct mbuf *m)
*/
LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) {
if (((bridged && ia->ia_ifp->if_bridge != NULL) ||
- (ia->ia_ifp == ifp)) &&
+ ia->ia_ifp == ifp) &&
itaddr.s_addr == ia->ia_addr.sin_addr.s_addr)
goto match;
#ifdef DEV_CARP
@@ -663,7 +511,7 @@ in_arpinput(struct mbuf *m)
}
LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash)
if (((bridged && ia->ia_ifp->if_bridge != NULL) ||
- (ia->ia_ifp == ifp)) &&
+ ia->ia_ifp == ifp) &&
isaddr.s_addr == ia->ia_addr.sin_addr.s_addr)
goto match;
@@ -729,254 +577,151 @@ match:
}
if (ifp->if_flags & IFF_STATICARP)
goto reply;
- /*
- * We look for any FIB that has this address to find
- * the interface etc.
- * For sanity checks that are FIB independent we abort the loop.
- */
- for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
- rt = arplookup(isaddr.s_addr,
- itaddr.s_addr == myaddr.s_addr, 0, fibnum);
- if (rt == NULL)
- continue;
-
- sdl = SDL(rt->rt_gateway);
- /* Only call this once */
- if (firstpass) {
- sin.sin_addr.s_addr = isaddr.s_addr;
- EVENTHANDLER_INVOKE(route_arp_update_event, rt,
- ar_sha(ah), (struct sockaddr *)&sin);
- }
-
- la = (struct llinfo_arp *)rt->rt_llinfo;
- if (la == NULL) {
- RT_UNLOCK(rt);
- continue;
- }
- if (firstpass) {
- /* The following is not an error when doing bridging. */
- if (!bridged && rt->rt_ifp != ifp
+ bzero(&sin, sizeof(sin));
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_family = AF_INET;
+ sin.sin_addr = isaddr;
+ flags = (itaddr.s_addr == myaddr.s_addr) ? LLE_CREATE : 0;
+ flags |= LLE_EXCLUSIVE;
+ IF_AFDATA_LOCK(ifp);
+ la = lla_lookup(LLTABLE(ifp), flags, (struct sockaddr *)&sin);
+ IF_AFDATA_UNLOCK(ifp);
+ if (la != NULL) {
+ /* the following is not an error when doing bridging */
+ if (!bridged && la->lle_tbl->llt_ifp != ifp
#ifdef DEV_CARP
- && (ifp->if_type != IFT_CARP || !carp_match)
+ && (ifp->if_type != IFT_CARP || !carp_match)
#endif
- ) {
- if (log_arp_wrong_iface)
- log(LOG_ERR, "arp: %s is on %s "
- "but got reply from %*D "
- "on %s\n",
- inet_ntoa(isaddr),
- rt->rt_ifp->if_xname,
- ifp->if_addrlen,
- (u_char *)ar_sha(ah), ":",
- ifp->if_xname);
- RT_UNLOCK(rt);
- break;
- }
- if (sdl->sdl_alen &&
- bcmp(ar_sha(ah), LLADDR(sdl), sdl->sdl_alen)) {
- if (rt->rt_expire) {
- if (log_arp_movements)
- log(LOG_INFO,
- "arp: %s moved from %*D to %*D "
- "on %s\n",
- inet_ntoa(isaddr),
- ifp->if_addrlen,
- (u_char *)LLADDR(sdl), ":",
- ifp->if_addrlen,
- (u_char *)ar_sha(ah), ":",
- ifp->if_xname);
- } else {
- RT_UNLOCK(rt);
- if (log_arp_permanent_modify)
- log(LOG_ERR,
- "arp: %*D attempts to "
- "modify permanent entry "
- "for %s on %s\n",
- ifp->if_addrlen,
- (u_char *)ar_sha(ah), ":",
- inet_ntoa(isaddr),
- ifp->if_xname);
- break;
- }
- }
- /*
- * sanity check for the address length.
- * XXX this does not work for protocols
- * with variable address length. -is
- */
- if (sdl->sdl_alen &&
- sdl->sdl_alen != ah->ar_hln) {
- log(LOG_WARNING,
- "arp from %*D: new addr len %d, was %d",
- ifp->if_addrlen, (u_char *) ar_sha(ah),
- ":", ah->ar_hln, sdl->sdl_alen);
+ ) {
+ if (log_arp_wrong_iface)
+ log(LOG_ERR, "arp: %s is on %s "
+ "but got reply from %*D on %s\n",
+ inet_ntoa(isaddr),
+ la->lle_tbl->llt_ifp->if_xname,
+ ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
+ ifp->if_xname);
+ goto reply;
+ }
+ if ((la->la_flags & LLE_VALID) &&
+ bcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) {
+ if (la->la_flags & LLE_STATIC) {
+ log(LOG_ERR,
+ "arp: %*D attempts to modify permanent "
+ "entry for %s on %s\n",
+ ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
+ inet_ntoa(isaddr), ifp->if_xname);
+ goto reply;
}
- if (ifp->if_addrlen != ah->ar_hln) {
- log(LOG_WARNING,
- "arp from %*D: addr len: "
- "new %d, i/f %d (ignored)",
- ifp->if_addrlen, (u_char *) ar_sha(ah),
- ":", ah->ar_hln, ifp->if_addrlen);
- RT_UNLOCK(rt);
- break;
+ if (log_arp_movements) {
+ log(LOG_INFO, "arp: %s moved from %*D "
+ "to %*D on %s\n",
+ inet_ntoa(isaddr),
+ ifp->if_addrlen,
+ (u_char *)&la->ll_addr, ":",
+ ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
+ ifp->if_xname);
}
- firstpass = 0;
- goodfib = fibnum;
}
-
- /* Copy in the information received. */
- (void)memcpy(LLADDR(sdl), ar_sha(ah),
- sdl->sdl_alen = ah->ar_hln);
- /*
- * If we receive an arp from a token-ring station over
- * a token-ring nic then try to save the source routing info.
- * XXXMRT Only minimal Token Ring support for MRT.
- * Only do this on the first pass as if modifies the mbuf.
- */
- if (ifp->if_type == IFT_ISO88025) {
- struct iso88025_header *th = NULL;
- struct iso88025_sockaddr_dl_data *trld;
-
- /* force the fib loop to end after this pass */
- fibnum = rt_numfibs - 1;
-
- th = (struct iso88025_header *)m->m_pkthdr.header;
- trld = SDL_ISO88025(sdl);
- rif_len = TR_RCF_RIFLEN(th->rcf);
- if ((th->iso88025_shost[0] & TR_RII) &&
- (rif_len > 2)) {
- trld->trld_rcf = th->rcf;
- trld->trld_rcf ^= htons(TR_RCF_DIR);
- memcpy(trld->trld_route, th->rd, rif_len - 2);
- trld->trld_rcf &= ~htons(TR_RCF_BCST_MASK);
- /*
- * Set up source routing information for
- * reply packet (XXX)
- */
- m->m_data -= rif_len;
- m->m_len += rif_len;
- m->m_pkthdr.len += rif_len;
- } else {
- th->iso88025_shost[0] &= ~TR_RII;
- trld->trld_rcf = 0;
- }
- m->m_data -= 8;
- m->m_len += 8;
- m->m_pkthdr.len += 8;
- th->rcf = trld->trld_rcf;
+
+ if (ifp->if_addrlen != ah->ar_hln) {
+ log(LOG_WARNING,
+ "arp from %*D: addr len: new %d, i/f %d (ignored)",
+ ifp->if_addrlen, (u_char *) ar_sha(ah), ":",
+ ah->ar_hln, ifp->if_addrlen);
+ goto reply;
}
+ (void)memcpy(&la->ll_addr, ar_sha(ah), ifp->if_addrlen);
+ la->la_flags |= LLE_VALID;
- if (rt->rt_expire) {
- rt->rt_expire = time_uptime + V_arpt_keep;
+ if (!(la->la_flags & LLE_STATIC)) {
+ la->la_expire = time_uptime + V_arpt_keep;
callout_reset(&la->la_timer, hz * V_arpt_keep,
- arptimer, rt);
+ arptimer, la);
}
la->la_asked = 0;
la->la_preempt = V_arp_maxtries;
- hold = la->la_hold;
- la->la_hold = NULL;
- RT_UNLOCK(rt);
- if (hold != NULL)
- (*ifp->if_output)(ifp, hold, rt_key(rt), rt);
- } /* end of FIB loop */
+ if (la->la_hold != NULL) {
+ m0 = la->la_hold;
+ la->la_hold = 0;
+ memcpy(&sa, L3_ADDR(la), sizeof(sa));
+ LLE_WUNLOCK(la);
+
+ (*ifp->if_output)(ifp, m0, &sa, NULL);
+ return;
+ }
+ }
reply:
-
- /*
- * Decide if we have to respond to something.
- */
if (op != ARPOP_REQUEST)
goto drop;
+
if (itaddr.s_addr == myaddr.s_addr) {
/* Shortcut.. the receiving interface is the target. */
(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
(void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
} else {
- /* It's not asking for our address. But it still may
- * be something we should answer.
- *
- * XXX MRT
- * We assume that link level info is independent of
- * the table used and so we use whichever we can and don't
- * have a better option.
+ struct llentry *lle = NULL;
+
+ if (!V_arp_proxyall)
+ goto drop;
+
+ sin.sin_addr = itaddr;
+ /* XXX MRT use table 0 for arp reply */
+ rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0);
+ if (!rt)
+ goto drop;
+
+ /*
+ * Don't send proxies for nodes on the same interface
+ * as this one came out of, or we'll get into a fight
+ * over who claims what Ether address.
*/
- /* Have we been asked to proxy for the target. */
- rt = arplookup(itaddr.s_addr, 0, SIN_PROXY, goodfib);
- if (rt == NULL) {
- /* Nope, only intersted now if proxying everything. */
- struct sockaddr_in sin;
-
- if (!V_arp_proxyall)
- goto drop;
-
- bzero(&sin, sizeof sin);
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof sin;
- sin.sin_addr = itaddr;
-
- /* XXX MRT use table 0 for arp reply */
- rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0);
- if (!rt)
- goto drop;
- /*
- * Don't send proxies for nodes on the same interface
- * as this one came out of, or we'll get into a fight
- * over who claims what Ether address.
- */
- if (rt->rt_ifp == ifp) {
- RTFREE_LOCKED(rt);
- goto drop;
- }
- (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
- (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
+ if (!rt->rt_ifp || rt->rt_ifp == ifp) {
RTFREE_LOCKED(rt);
+ goto drop;
+ }
+ IF_AFDATA_LOCK(rt->rt_ifp);
+ lle = lla_lookup(LLTABLE(rt->rt_ifp), 0, (struct sockaddr *)&sin);
+ IF_AFDATA_UNLOCK(rt->rt_ifp);
+ RTFREE_LOCKED(rt);
- /*
- * Also check that the node which sent the ARP packet
- * is on the the interface we expect it to be on. This
- * avoids ARP chaos if an interface is connected to the
- * wrong network.
- */
- sin.sin_addr = isaddr;
-
- /* XXX MRT use table 0 for arp checks */
- rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0);
- if (!rt)
- goto drop;
- if (rt->rt_ifp != ifp) {
- log(LOG_INFO, "arp_proxy: ignoring request"
- " from %s via %s, expecting %s\n",
- inet_ntoa(isaddr), ifp->if_xname,
- rt->rt_ifp->if_xname);
- RTFREE_LOCKED(rt);
- goto drop;
- }
+ if (lle != NULL) {
+ (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
+ (void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln);
+ LLE_RUNLOCK(lle);
+ } else
+ goto drop;
+
+ /*
+ * Also check that the node which sent the ARP packet
+ * is on the the interface we expect it to be on. This
+ * avoids ARP chaos if an interface is connected to the
+ * wrong network.
+ */
+ sin.sin_addr = isaddr;
+
+ /* XXX MRT use table 0 for arp checks */
+ rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0);
+ if (!rt)
+ goto drop;
+ if (rt->rt_ifp != ifp) {
+ log(LOG_INFO, "arp_proxy: ignoring request"
+ " from %s via %s, expecting %s\n",
+ inet_ntoa(isaddr), ifp->if_xname,
+ rt->rt_ifp->if_xname);
RTFREE_LOCKED(rt);
+ goto drop;
+ }
+ RTFREE_LOCKED(rt);
#ifdef DEBUG_PROXY
- printf("arp: proxying for %s\n",
- inet_ntoa(itaddr));
+ printf("arp: proxying for %s\n",
+ inet_ntoa(itaddr));
#endif
- } else {
- /*
- * Return proxied ARP replies only on the interface
- * or bridge cluster where this network resides.
- * Otherwise we may conflict with the host we are
- * proxying for.
- */
- if (rt->rt_ifp != ifp &&
- (rt->rt_ifp->if_bridge != ifp->if_bridge ||
- ifp->if_bridge == NULL)) {
- RT_UNLOCK(rt);
- goto drop;
- }
- sdl = SDL(rt->rt_gateway);
- (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
- (void)memcpy(ar_sha(ah), LLADDR(sdl), ah->ar_hln);
- RT_UNLOCK(rt);
- }
}
+ if (la != NULL)
+ LLE_WUNLOCK(la);
if (itaddr.s_addr == myaddr.s_addr &&
IN_LINKLOCAL(ntohl(itaddr.s_addr))) {
/* RFC 3927 link-local IPv4; always reply by broadcast. */
@@ -1002,68 +747,35 @@ reply:
return;
drop:
+ if (la != NULL)
+ LLE_WUNLOCK(la);
m_freem(m);
}
#endif
-/*
- * Lookup or enter a new address in arptab.
- */
-static struct rtentry *
-arplookup(u_long addr, int create, int proxy, int fibnum)
-{
- struct rtentry *rt;
- struct sockaddr_inarp sin;
- const char *why = 0;
-
- bzero(&sin, sizeof(sin));
- sin.sin_len = sizeof(sin);
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = addr;
- if (proxy)
- sin.sin_other = SIN_PROXY;
- rt = in_rtalloc1((struct sockaddr *)&sin, create, 0UL, fibnum);
- if (rt == 0)
- return (0);
-
- if (rt->rt_flags & RTF_GATEWAY)
- why = "host is not on local network";
- else if ((rt->rt_flags & RTF_LLINFO) == 0)
- why = "could not allocate llinfo";
- else if (rt->rt_gateway->sa_family != AF_LINK)
- why = "gateway route is not ours";
-
- if (why) {
-#define ISDYNCLONE(_rt) \
- (((_rt)->rt_flags & (RTF_STATIC | RTF_WASCLONED)) == RTF_WASCLONED)
- if (create)
- log(LOG_DEBUG, "arplookup %s failed: %s\n",
- inet_ntoa(sin.sin_addr), why);
- /*
- * If there are no references to this Layer 2 route,
- * and it is a cloned route, and not static, and
- * arplookup() is creating the route, then purge
- * it from the routing table as it is probably bogus.
- */
- if (rt->rt_refcnt == 1 && ISDYNCLONE(rt))
- rtexpunge(rt);
- RTFREE_LOCKED(rt);
- return (0);
-#undef ISDYNCLONE
- } else {
- RT_REMREF(rt);
- return (rt);
- }
-}
-
void
arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa)
{
+ struct llentry *lle;
+
if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY)
arprequest(ifp, &IA_SIN(ifa)->sin_addr,
&IA_SIN(ifa)->sin_addr, IF_LLADDR(ifp));
- ifa->ifa_rtrequest = arp_rtrequest;
- ifa->ifa_flags |= RTF_CLONING;
+ /*
+ * interface address is considered static entry
+ * because the output of the arp utility shows
+ * that L2 entry as permanent
+ */
+ IF_AFDATA_LOCK(ifp);
+ lle = lla_lookup(LLTABLE(ifp), (LLE_CREATE | LLE_IFADDR | LLE_STATIC),
+ (struct sockaddr *)IA_SIN(ifa));
+ IF_AFDATA_UNLOCK(ifp);
+ if (lle == NULL)
+ log(LOG_INFO, "arp_ifinit: cannot create arp "
+ "entry for interface address\n");
+ else
+ LLE_RUNLOCK(lle);
+ ifa->ifa_rtrequest = NULL;
}
void
@@ -1072,8 +784,7 @@ arp_ifinit2(struct ifnet *ifp, struct ifaddr *ifa, u_char *enaddr)
if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY)
arprequest(ifp, &IA_SIN(ifa)->sin_addr,
&IA_SIN(ifa)->sin_addr, enaddr);
- ifa->ifa_rtrequest = arp_rtrequest;
- ifa->ifa_flags |= RTF_CLONING;
+ ifa->ifa_rtrequest = NULL;
}
static void
diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h
index 14df15f..ba4e2f6 100644
--- a/sys/netinet/if_ether.h
+++ b/sys/netinet/if_ether.h
@@ -109,8 +109,11 @@ struct sockaddr_inarp {
extern u_char ether_ipmulticast_min[ETHER_ADDR_LEN];
extern u_char ether_ipmulticast_max[ETHER_ADDR_LEN];
+struct llentry;
+
int arpresolve(struct ifnet *ifp, struct rtentry *rt,
- struct mbuf *m, struct sockaddr *dst, u_char *desten);
+ struct mbuf *m, struct sockaddr *dst, u_char *desten,
+ struct llentry **lle);
void arp_ifinit(struct ifnet *, struct ifaddr *);
void arp_ifinit2(struct ifnet *, struct ifaddr *, u_char *);
#endif
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 9b6dd48..94535b1 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/vimage.h>
#include <net/if.h>
+#include <net/if_llatbl.h>
#include <net/if_types.h>
#include <net/route.h>
@@ -871,6 +872,8 @@ in_addprefix(struct in_ifaddr *target, int flags)
return (error);
}
+extern void arp_ifscrub(struct ifnet *ifp, uint32_t addr);
+
/*
* If there is no other address in the system that can serve a route to the
* same prefix, remove the route. Hand over the route to the new address
@@ -893,6 +896,8 @@ in_scrubprefix(struct in_ifaddr *target)
prefix = target->ia_addr.sin_addr;
mask = target->ia_sockmask.sin_addr;
prefix.s_addr &= mask.s_addr;
+ /* remove arp cache */
+ arp_ifscrub(target->ia_ifp, IA_SIN(target)->sin_addr.s_addr);
}
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
@@ -1015,3 +1020,240 @@ in_ifdetach(struct ifnet *ifp)
in_pcbpurgeif0(&V_udbinfo, ifp);
in_purgemaddrs(ifp);
}
+
+#include <sys/syslog.h>
+#include <net/if_dl.h>
+#include <netinet/if_ether.h>
+
+struct in_llentry {
+ struct llentry base;
+ struct sockaddr_in l3_addr4;
+};
+
+static struct llentry *
+in_lltable_new(const struct sockaddr *l3addr, u_int flags)
+{
+ struct in_llentry *lle;
+
+ lle = malloc(sizeof(struct in_llentry), M_LLTABLE, M_DONTWAIT | M_ZERO);
+ if (lle == NULL) /* NB: caller generates msg */
+ return NULL;
+
+ callout_init(&lle->base.la_timer, CALLOUT_MPSAFE);
+ /*
+ * For IPv4 this will trigger "arpresolve" to generate
+ * an ARP request.
+ */
+ lle->base.la_expire = time_second; /* mark expired */
+ lle->l3_addr4 = *(const struct sockaddr_in *)l3addr;
+ lle->base.lle_refcnt = 1;
+ LLE_LOCK_INIT(&lle->base);
+ return &lle->base;
+}
+
+/*
+ * Deletes an address from the address table.
+ * This function is called by the timer functions
+ * such as arptimer() and nd6_llinfo_timer(), and
+ * the caller does the locking.
+ */
+static void
+in_lltable_free(struct lltable *llt, struct llentry *lle)
+{
+ LLE_WUNLOCK(lle);
+ LLE_LOCK_DESTROY(lle);
+ free(lle, M_LLTABLE);
+}
+
+static int
+in_lltable_rtcheck(struct ifnet *ifp, const struct sockaddr *l3addr)
+{
+ struct rtentry *rt;
+
+ KASSERT(l3addr->sa_family == AF_INET,
+ ("sin_family %d", l3addr->sa_family));
+
+ /* XXX rtalloc1 should take a const param */
+ rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
+ if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
+ log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
+ inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
+ if (rt != NULL)
+ RTFREE_LOCKED(rt);
+ return (EINVAL);
+ }
+ RTFREE_LOCKED(rt);
+ return 0;
+}
+
+/*
+ * Return NULL if not found or marked for deletion.
+ * If found return lle read locked.
+ */
+static struct llentry *
+in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
+{
+ const struct sockaddr_in *sin = (const struct sockaddr_in *)l3addr;
+ struct ifnet *ifp = llt->llt_ifp;
+ struct llentry *lle;
+ struct llentries *lleh;
+ u_int hashkey;
+
+ IF_AFDATA_LOCK_ASSERT(ifp);
+ KASSERT(l3addr->sa_family == AF_INET,
+ ("sin_family %d", l3addr->sa_family));
+
+ hashkey = sin->sin_addr.s_addr;
+ lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
+ LIST_FOREACH(lle, lleh, lle_next) {
+ if (lle->la_flags & LLE_DELETED)
+ continue;
+ if (bcmp(L3_ADDR(lle), l3addr, sizeof(struct sockaddr_in)) == 0)
+ break;
+ }
+ if (lle == NULL) {
+#ifdef DIAGNOSTICS
+ if (flags & LLE_DELETE)
+ log(LOG_INFO, "interface address is missing from cache = %p in delete\n", lle);
+#endif
+ if (!(flags & LLE_CREATE))
+ return (NULL);
+ /*
+ * A route that covers the given address must have
+ * been installed 1st because we are doing a resolution,
+ * verify this.
+ */
+ if (!(flags & LLE_IFADDR) &&
+ in_lltable_rtcheck(ifp, l3addr) != 0)
+ goto done;
+
+ lle = in_lltable_new(l3addr, flags);
+ if (lle == NULL) {
+ log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
+ goto done;
+ }
+ lle->la_flags = flags & ~LLE_CREATE;
+ if ((flags & (LLE_CREATE | LLE_IFADDR)) == (LLE_CREATE | LLE_IFADDR)) {
+ bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
+ lle->la_flags |= (LLE_VALID | LLE_STATIC);
+ }
+
+ lle->lle_tbl = llt;
+ lle->lle_head = lleh;
+ LIST_INSERT_HEAD(lleh, lle, lle_next);
+ } else if (flags & LLE_DELETE) {
+ if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) {
+ LLE_WLOCK(lle);
+ lle->la_flags = LLE_DELETED;
+ LLE_WUNLOCK(lle);
+#ifdef DIAGNOSTICS
+ log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
+#endif
+ }
+ lle = (void *)-1;
+
+ }
+ if (lle != NULL && lle != (void *)-1) {
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WLOCK(lle);
+ else
+ LLE_RLOCK(lle);
+ }
+done:
+ return (lle);
+}
+
+static int
+in_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
+{
+#define SIN(lle) ((struct sockaddr_in *) L3_ADDR(lle))
+ struct ifnet *ifp = llt->llt_ifp;
+ struct llentry *lle;
+ /* XXX stack use */
+ struct {
+ struct rt_msghdr rtm;
+ struct sockaddr_inarp sin;
+ struct sockaddr_dl sdl;
+ } arpc;
+ int error, i;
+
+ /* XXXXX
+ * current IFNET_RLOCK() is mapped to IFNET_WLOCK()
+ * so it is okay to use this ASSERT, change it when
+ * IFNET lock is finalized
+ */
+ IFNET_WLOCK_ASSERT();
+
+ error = 0;
+ for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
+ LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
+ struct sockaddr_dl *sdl;
+
+ /* skip deleted entries */
+ if ((lle->la_flags & (LLE_DELETED|LLE_VALID)) != LLE_VALID)
+ continue;
+ /*
+ * produce a msg made of:
+ * struct rt_msghdr;
+ * struct sockaddr_inarp; (IPv4)
+ * struct sockaddr_dl;
+ */
+ bzero(&arpc, sizeof(arpc));
+ arpc.rtm.rtm_msglen = sizeof(arpc);
+ arpc.sin.sin_family = AF_INET;
+ arpc.sin.sin_len = sizeof(arpc.sin);
+ arpc.sin.sin_addr.s_addr = SIN(lle)->sin_addr.s_addr;
+
+ /* publish */
+ if (lle->la_flags & LLE_PUB) {
+ arpc.rtm.rtm_flags |= RTF_ANNOUNCE;
+ /* proxy only */
+ if (lle->la_flags & LLE_PROXY)
+ arpc.sin.sin_other = SIN_PROXY;
+ }
+
+ sdl = &arpc.sdl;
+ sdl->sdl_family = AF_LINK;
+ sdl->sdl_len = sizeof(*sdl);
+ sdl->sdl_alen = ifp->if_addrlen;
+ sdl->sdl_index = ifp->if_index;
+ sdl->sdl_type = ifp->if_type;
+ bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
+
+ arpc.rtm.rtm_rmx.rmx_expire =
+ lle->la_flags & LLE_STATIC ? 0 : lle->la_expire;
+ arpc.rtm.rtm_flags |= RTF_HOST;
+ if (lle->la_flags & LLE_STATIC)
+ arpc.rtm.rtm_flags |= RTF_STATIC;
+ arpc.rtm.rtm_index = ifp->if_index;
+ error = SYSCTL_OUT(wr, &arpc, sizeof(arpc));
+ if (error)
+ break;
+ }
+ }
+ return error;
+#undef SIN
+}
+
+void *
+in_domifattach(struct ifnet *ifp)
+{
+ struct lltable *llt = lltable_init(ifp, AF_INET);
+
+ if (llt != NULL) {
+ llt->llt_new = in_lltable_new;
+ llt->llt_free = in_lltable_free;
+ llt->llt_rtcheck = in_lltable_rtcheck;
+ llt->llt_lookup = in_lltable_lookup;
+ llt->llt_dump = in_lltable_dump;
+ }
+ return (llt);
+}
+
+void
+in_domifdetach(struct ifnet *ifp __unused, void *aux)
+{
+ struct lltable *llt = (struct lltable *)aux;
+
+ lltable_free(llt);
+}
diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c
index e7916dd..6f5dfe1 100644
--- a/sys/netinet/in_mcast.c
+++ b/sys/netinet/in_mcast.c
@@ -1036,7 +1036,7 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
ro.ro_rt = NULL;
*(struct sockaddr_in *)&ro.ro_dst = gsa->sin;
- in_rtalloc_ign(&ro, RTF_CLONING,
+ in_rtalloc_ign(&ro, 0,
inp->inp_inc.inc_fibnum);
if (ro.ro_rt != NULL) {
ifp = ro.ro_rt->rt_ifp;
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 70f217a..6d1c2aa 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -570,7 +570,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
* Find out route to destination.
*/
if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0)
- in_rtalloc_ign(&sro, RTF_CLONING, inp->inp_inc.inc_fibnum);
+ in_rtalloc_ign(&sro, 0, inp->inp_inc.inc_fibnum);
/*
* If we found a route, use the address corresponding to
@@ -695,6 +695,10 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
ia = ifatoia(ifa_ifwithnet(sintosa(&sain)));
if (cred == NULL || !jailed(cred)) {
+#if __FreeBSD_version < 800000
+ if (ia == NULL)
+ ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa;
+#endif
if (ia == NULL) {
error = ENETUNREACH;
goto done;
@@ -1696,7 +1700,7 @@ db_print_inconninfo(struct in_conninfo *inc, const char *name, int indent)
indent += 2;
#ifdef INET6
- if (inc->inc_flags == 1) {
+ if (inc->inc_flags & INC_ISIPV6) {
/* IPv6. */
ip6_sprintf(laddr_str, &inc->inc6_laddr);
ip6_sprintf(faddr_str, &inc->inc6_faddr);
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index f0275bd..01636fe 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -106,6 +106,12 @@ struct in_conninfo {
/* protocol dependent part */
struct in_endpoints inc_ie;
};
+
+/*
+ * Flags for inc_flags.
+ */
+#define INC_ISIPV6 0x01
+
#define inc_isipv6 inc_flags /* temp compatability */
#define inc_fport inc_ie.ie_fport
#define inc_lport inc_ie.ie_lport
@@ -435,7 +441,7 @@ void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
#define IN6P_RECVIF INP_RECVIF
#define IN6P_MTUDISC INP_MTUDISC
#define IN6P_FAITH INP_FAITH
-#define IN6P_CONTROLOPTS INP_CONTROLOPTS
+#define IN6P_CONTROLOPTS INP_CONTROLOPTS
/*
* socket AF version is {newer than,or include}
* actual datagram AF version
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index a93f1f2..f3fbe0c 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
@@ -364,7 +365,9 @@ struct domain inetdomain = {
.dom_rtattach = in_inithead,
#endif
.dom_rtoffset = 32,
- .dom_maxrtkey = sizeof(struct sockaddr_in)
+ .dom_maxrtkey = sizeof(struct sockaddr_in),
+ .dom_ifattach = in_domifattach,
+ .dom_ifdetach = in_domifdetach
};
DOMAIN_SET(inet);
diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c
index aa4ca0d..f9e9d98 100644
--- a/sys/netinet/in_rmx.c
+++ b/sys/netinet/in_rmx.c
@@ -75,8 +75,8 @@ in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
{
struct rtentry *rt = (struct rtentry *)treenodes;
struct sockaddr_in *sin = (struct sockaddr_in *)rt_key(rt);
- struct radix_node *ret;
+ RADIX_NODE_HEAD_WLOCK_ASSERT(head);
/*
* A little bit of help for both IP output and input:
* For host routes, we make sure that RTF_BROADCAST
@@ -106,31 +106,7 @@ in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
if (!rt->rt_rmx.rmx_mtu && rt->rt_ifp)
rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
- ret = rn_addroute(v_arg, n_arg, head, treenodes);
- if (ret == NULL && rt->rt_flags & RTF_HOST) {
- struct rtentry *rt2;
- /*
- * We are trying to add a host route, but can't.
- * Find out if it is because of an
- * ARP entry and delete it if so.
- */
- rt2 = in_rtalloc1((struct sockaddr *)sin, 0,
- RTF_CLONING, rt->rt_fibnum);
- if (rt2) {
- if (rt2->rt_flags & RTF_LLINFO &&
- rt2->rt_flags & RTF_HOST &&
- rt2->rt_gateway &&
- rt2->rt_gateway->sa_family == AF_LINK) {
- rtexpunge(rt2);
- RTFREE_LOCKED(rt2);
- ret = rn_addroute(v_arg, n_arg, head,
- treenodes);
- } else
- RTFREE_LOCKED(rt2);
- }
- }
-
- return ret;
+ return (rn_addroute(v_arg, n_arg, head, treenodes));
}
/*
@@ -187,13 +163,10 @@ in_clsroute(struct radix_node *rn, struct radix_node_head *head)
if (!(rt->rt_flags & RTF_UP))
return; /* prophylactic measures */
- if ((rt->rt_flags & (RTF_LLINFO | RTF_HOST)) != RTF_HOST)
- return;
-
if (rt->rt_flags & RTPRF_OURS)
return;
- if (!(rt->rt_flags & (RTF_WASCLONED | RTF_DYNAMIC)))
+ if (!(rt->rt_flags & RTF_DYNAMIC))
return;
/*
@@ -434,7 +407,6 @@ in_ifadownkill(struct radix_node *rn, void *xap)
* the routes that rtrequest() would have in any case,
* so that behavior is not needed there.
*/
- rt->rt_flags &= ~RTF_CLONING;
rtexpunge(rt);
}
RT_UNLOCK(rt);
diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h
index 1190826..73868ad 100644
--- a/sys/netinet/in_var.h
+++ b/sys/netinet/in_var.h
@@ -84,9 +84,13 @@ extern u_char inetctlerrmap[];
/*
* Hash table for IP addresses.
*/
-extern LIST_HEAD(in_ifaddrhashhead, in_ifaddr) *in_ifaddrhashtbl;
-extern TAILQ_HEAD(in_ifaddrhead, in_ifaddr) in_ifaddrhead;
+TAILQ_HEAD(in_ifaddrhead, in_ifaddr);
+LIST_HEAD(in_ifaddrhashhead, in_ifaddr);
+#ifdef VIMAGE_GLOBALS
+extern struct in_ifaddrhashhead *in_ifaddrhashtbl;
+extern struct in_ifaddrhead in_ifaddrhead;
extern u_long in_ifaddrhmask; /* mask for hash table */
+#endif
#define INADDR_NHASH_LOG2 9
#define INADDR_NHASH (1 << INADDR_NHASH_LOG2)
@@ -227,7 +231,10 @@ SYSCTL_DECL(_net_inet_ip);
SYSCTL_DECL(_net_inet_raw);
#endif
-extern LIST_HEAD(in_multihead, in_multi) in_multihead;
+LIST_HEAD(in_multihead, in_multi);
+#ifdef VIMAGE_GLOBALS
+extern struct in_multihead in_multihead;
+#endif
/*
* Lock macros for IPv4 layer multicast address lists. IPv4 lock goes
@@ -314,6 +321,9 @@ void ip_input(struct mbuf *);
int in_ifadown(struct ifaddr *ifa, int);
void in_ifscrub(struct ifnet *, struct in_ifaddr *);
struct mbuf *ip_fastforward(struct mbuf *);
+void *in_domifattach(struct ifnet *);
+void in_domifdetach(struct ifnet *, void *);
+
/* XXX */
void in_rtalloc_ign(struct route *ro, u_long ignflags, u_int fibnum);
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index 9f6bc31..6d96163 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -371,14 +371,6 @@ carp_setroute(struct carp_softc *sc, int cmd)
(cmd == RTM_DELETE && count == 0))
rtinit(ifa, cmd, RTF_UP | RTF_HOST);
}
-#ifdef INET6
- if (ifa->ifa_addr->sa_family == AF_INET6) {
- if (cmd == RTM_ADD)
- in6_ifaddloop(ifa);
- else
- in6_ifremloop(ifa);
- }
-#endif /* INET6 */
}
splx(s);
}
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c
index 407b08c..ea106df 100644
--- a/sys/netinet/ip_fastfwd.c
+++ b/sys/netinet/ip_fastfwd.c
@@ -128,7 +128,7 @@ ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m)
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr.s_addr = dest.s_addr;
- in_rtalloc_ign(ro, RTF_CLONING, M_GETFIB(m));
+ in_rtalloc_ign(ro, 0, M_GETFIB(m));
/*
* Route there and interface still up?
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index 6e7db99..831686d 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -637,7 +637,7 @@ void ipfw_nat_destroy(void);
typedef int ip_fw_ctl_t(struct sockopt *);
extern ip_fw_ctl_t *ip_fw_ctl_ptr;
-#ifndef VIMAGE
+#ifdef VIMAGE_GLOBALS
extern int fw_one_pass;
extern int fw_enable;
#ifdef INET6
diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c
index 5c3ac59..1f2e67d 100644
--- a/sys/netinet/ip_fw2.c
+++ b/sys/netinet/ip_fw2.c
@@ -128,8 +128,8 @@ struct vnet_ipfw vnet_ipfw_0;
static u_int32_t set_disable;
static int fw_verbose;
static struct callout ipfw_timeout;
-#endif
static int verbose_limit;
+#endif
static uma_zone_t ipfw_dyn_rule_zone;
@@ -190,8 +190,9 @@ SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, debug, CTLFLAG_RW,
SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, verbose,
CTLFLAG_RW | CTLFLAG_SECURE3,
fw_verbose, 0, "Log matches to ipfw rules");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW,
- &verbose_limit, 0, "Set upper limit of matches of ipfw rules logged");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, verbose_limit,
+ CTLFLAG_RW, verbose_limit, 0,
+ "Set upper limit of matches of ipfw rules logged");
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD,
NULL, IPFW_DEFAULT_RULE, "The default/max possible rule number.");
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, tables_max, CTLFLAG_RD,
@@ -527,7 +528,7 @@ verify_path(struct in_addr src, struct ifnet *ifp, u_int fib)
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr = src;
- in_rtalloc_ign(&ro, RTF_CLONING, fib);
+ in_rtalloc_ign(&ro, 0, fib);
if (ro.ro_rt == NULL)
return 0;
@@ -619,7 +620,7 @@ verify_path6(struct in6_addr *src, struct ifnet *ifp)
dst->sin6_len = sizeof(*dst);
dst->sin6_addr = *src;
/* XXX MRT 0 for ipv6 at this time */
- rtalloc_ign((struct route *)&ro, RTF_CLONING);
+ rtalloc_ign((struct route *)&ro, 0);
if (ro.ro_rt == NULL)
return 0;
@@ -1813,6 +1814,7 @@ add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
INIT_VNET_IPFW(curvnet);
struct radix_node_head *rnh;
struct table_entry *ent;
+ struct radix_node *rn;
if (tbl >= IPFW_TABLES_MAX)
return (EINVAL);
@@ -1825,8 +1827,8 @@ add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
ent->mask.sin_addr.s_addr = htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0);
ent->addr.sin_addr.s_addr = addr & ent->mask.sin_addr.s_addr;
IPFW_WLOCK(ch);
- if (rnh->rnh_addaddr(&ent->addr, &ent->mask, rnh, (void *)ent) ==
- NULL) {
+ rn = rnh->rnh_addaddr(&ent->addr, &ent->mask, rnh, (void *)ent);
+ if (rn == NULL) {
IPFW_WUNLOCK(ch);
free(ent, M_IPFW_TBL);
return (EEXIST);
diff --git a/sys/netinet/ip_fw_pfil.c b/sys/netinet/ip_fw_pfil.c
index 952574d..694f8ab 100644
--- a/sys/netinet/ip_fw_pfil.c
+++ b/sys/netinet/ip_fw_pfil.c
@@ -435,8 +435,10 @@ ipfw_hook(void)
if (pfh_inet == NULL)
return ENOENT;
- pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
- pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
+ (void)pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+ pfh_inet);
+ (void)pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+ pfh_inet);
return 0;
}
@@ -450,8 +452,10 @@ ipfw_unhook(void)
if (pfh_inet == NULL)
return ENOENT;
- pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
- pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
+ (void)pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+ pfh_inet);
+ (void)pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+ pfh_inet);
return 0;
}
@@ -466,8 +470,10 @@ ipfw6_hook(void)
if (pfh_inet6 == NULL)
return ENOENT;
- pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6);
- pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6);
+ (void)pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+ pfh_inet6);
+ (void)pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+ pfh_inet6);
return 0;
}
@@ -481,8 +487,10 @@ ipfw6_unhook(void)
if (pfh_inet6 == NULL)
return ENOENT;
- pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6);
- pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6);
+ (void)pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+ pfh_inet6);
+ (void)pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+ pfh_inet6);
return 0;
}
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index c99c53e..4a169ff 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1286,7 +1286,7 @@ ip_rtaddr(struct in_addr dst, u_int fibnum)
sin->sin_family = AF_INET;
sin->sin_len = sizeof(*sin);
sin->sin_addr = dst;
- in_rtalloc_ign(&sro, RTF_CLONING, fibnum);
+ in_rtalloc_ign(&sro, 0, fibnum);
if (sro.ro_rt == NULL)
return (NULL);
@@ -1412,7 +1412,7 @@ ip_forward(struct mbuf *m, int srcrt)
sin->sin_family = AF_INET;
sin->sin_len = sizeof(*sin);
sin->sin_addr = ip->ip_dst;
- in_rtalloc_ign(&ro, RTF_CLONING, M_GETFIB(m));
+ in_rtalloc_ign(&ro, 0, M_GETFIB(m));
rt = ro.ro_rt;
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 03cf56f..6cda8aa 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -567,7 +567,6 @@ passout:
* to avoid confusing lower layers.
*/
m->m_flags &= ~(M_PROTOFLAGS);
-
error = (*ifp->if_output)(ifp, m,
(struct sockaddr *)dst, ro->ro_rt);
goto done;
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 9b5a3f3..9fe0eca 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -280,7 +280,7 @@ rip_input(struct mbuf *m, int off)
if (!prison_check_ip4(inp->inp_cred, &ip->ip_dst))
continue;
}
- if (last) {
+ if (last != NULL) {
struct mbuf *n;
n = m_copy(m, 0, (int)M_COPYALL);
@@ -310,7 +310,7 @@ rip_input(struct mbuf *m, int off)
if (!prison_check_ip4(inp->inp_cred, &ip->ip_dst))
continue;
}
- if (last) {
+ if (last != NULL) {
struct mbuf *n;
n = m_copy(m, 0, (int)M_COPYALL);
@@ -964,6 +964,7 @@ rip_pcblist(SYSCTL_HANDLER_ARGS)
INP_RLOCK(inp);
if (inp->inp_gencnt <= gencnt) {
struct xinpcb xi;
+
bzero(&xi, sizeof(xi));
xi.xi_len = sizeof xi;
/* XXX should avoid extra copy */
diff --git a/sys/netinet/tcp_hostcache.c b/sys/netinet/tcp_hostcache.c
index 7c76160..c9b5b8c 100644
--- a/sys/netinet/tcp_hostcache.c
+++ b/sys/netinet/tcp_hostcache.c
@@ -249,7 +249,7 @@ tcp_hc_lookup(struct in_conninfo *inc)
/*
* Hash the foreign ip address.
*/
- if (inc->inc_isipv6)
+ if (inc->inc_flags & INC_ISIPV6)
hash = HOSTCACHE_HASH6(&inc->inc6_faddr);
else
hash = HOSTCACHE_HASH(&inc->inc_faddr);
@@ -267,7 +267,7 @@ tcp_hc_lookup(struct in_conninfo *inc)
* Iterate through entries in bucket row looking for a match.
*/
TAILQ_FOREACH(hc_entry, &hc_head->hch_bucket, rmx_q) {
- if (inc->inc_isipv6) {
+ if (inc->inc_flags & INC_ISIPV6) {
if (memcmp(&inc->inc6_faddr, &hc_entry->ip6,
sizeof(inc->inc6_faddr)) == 0)
return hc_entry;
@@ -305,7 +305,7 @@ tcp_hc_insert(struct in_conninfo *inc)
/*
* Hash the foreign ip address.
*/
- if (inc->inc_isipv6)
+ if (inc->inc_flags & INC_ISIPV6)
hash = HOSTCACHE_HASH6(&inc->inc6_faddr);
else
hash = HOSTCACHE_HASH(&inc->inc_faddr);
@@ -360,7 +360,7 @@ tcp_hc_insert(struct in_conninfo *inc)
* Initialize basic information of hostcache entry.
*/
bzero(hc_entry, sizeof(*hc_entry));
- if (inc->inc_isipv6)
+ if (inc->inc_flags & INC_ISIPV6)
bcopy(&inc->inc6_faddr, &hc_entry->ip6, sizeof(hc_entry->ip6));
else
hc_entry->ip4 = inc->inc_faddr;
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index dfb2aff..30b3fde 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -737,9 +737,9 @@ findpcb:
"tp not listening", __func__));
bzero(&inc, sizeof(inc));
- inc.inc_isipv6 = isipv6;
#ifdef INET6
if (isipv6) {
+ inc.inc_flags |= INC_ISIPV6;
inc.inc6_faddr = ip6->ip6_src;
inc.inc6_laddr = ip6->ip6_dst;
} else
@@ -3338,14 +3338,11 @@ tcp_mssopt(struct in_conninfo *inc)
u_long maxmtu = 0;
u_long thcmtu = 0;
size_t min_protoh;
-#ifdef INET6
- int isipv6 = inc->inc_isipv6 ? 1 : 0;
-#endif
KASSERT(inc != NULL, ("tcp_mssopt with NULL in_conninfo pointer"));
#ifdef INET6
- if (isipv6) {
+ if (inc->inc_flags & INC_ISIPV6) {
mss = V_tcp_v6mssdflt;
maxmtu = tcp_maxmtu6(inc, NULL);
thcmtu = tcp_hc_getmtu(inc); /* IPv4 and IPv6 */
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 207d37a..9cb941a 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -434,7 +434,7 @@ tcpip_fillheaders(struct inpcb *inp, void *ip_ptr, void *tcp_ptr)
ip6 = (struct ip6_hdr *)ip_ptr;
ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
- (inp->in6p_flowinfo & IPV6_FLOWINFO_MASK);
+ (inp->inp_flow & IPV6_FLOWINFO_MASK);
ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
(IPV6_VERSION & IPV6_VERSION_MASK);
ip6->ip6_nxt = IPPROTO_TCP;
@@ -1306,7 +1306,6 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
* value (if given) and then notify.
*/
bzero(&inc, sizeof(inc));
- inc.inc_flags = 0; /* IPv4 */
inc.inc_faddr = faddr;
inc.inc_fibnum =
inp->inp_inc.inc_fibnum;
@@ -1343,13 +1342,11 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
if (inp != NULL)
INP_WUNLOCK(inp);
} else {
+ bzero(&inc, sizeof(inc));
inc.inc_fport = th->th_dport;
inc.inc_lport = th->th_sport;
inc.inc_faddr = faddr;
inc.inc_laddr = ip->ip_src;
-#ifdef INET6
- inc.inc_isipv6 = 0;
-#endif
syncache_unreach(&inc, th);
}
INP_INFO_WUNLOCK(&V_tcbinfo);
@@ -1419,11 +1416,12 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
(struct sockaddr *)ip6cp->ip6c_src,
th.th_sport, cmd, NULL, notify);
+ bzero(&inc, sizeof(inc));
inc.inc_fport = th.th_dport;
inc.inc_lport = th.th_sport;
inc.inc6_faddr = ((struct sockaddr_in6 *)sa)->sin6_addr;
inc.inc6_laddr = ip6cp->ip6c_src->sin6_addr;
- inc.inc_isipv6 = 1;
+ inc.inc_flags |= INC_ISIPV6;
INP_INFO_WLOCK(&V_tcbinfo);
syncache_unreach(&inc, &th);
INP_INFO_WUNLOCK(&V_tcbinfo);
@@ -1486,13 +1484,13 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
static u_char isn_secret[32];
static int isn_last_reseed;
static u_int32_t isn_offset, isn_offset_old;
-static MD5_CTX isn_ctx;
#endif
tcp_seq
tcp_new_isn(struct tcpcb *tp)
{
INIT_VNET_INET(tp->t_vnet);
+ MD5_CTX isn_ctx;
u_int32_t md5_buffer[4];
tcp_seq new_isn;
@@ -1508,25 +1506,25 @@ tcp_new_isn(struct tcpcb *tp)
}
/* Compute the md5 hash and return the ISN. */
- MD5Init(&V_isn_ctx);
- MD5Update(&V_isn_ctx, (u_char *) &tp->t_inpcb->inp_fport, sizeof(u_short));
- MD5Update(&V_isn_ctx, (u_char *) &tp->t_inpcb->inp_lport, sizeof(u_short));
+ MD5Init(&isn_ctx);
+ MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_fport, sizeof(u_short));
+ MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_lport, sizeof(u_short));
#ifdef INET6
if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0) {
- MD5Update(&V_isn_ctx, (u_char *) &tp->t_inpcb->in6p_faddr,
+ MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->in6p_faddr,
sizeof(struct in6_addr));
- MD5Update(&V_isn_ctx, (u_char *) &tp->t_inpcb->in6p_laddr,
+ MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->in6p_laddr,
sizeof(struct in6_addr));
} else
#endif
{
- MD5Update(&V_isn_ctx, (u_char *) &tp->t_inpcb->inp_faddr,
+ MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_faddr,
sizeof(struct in_addr));
- MD5Update(&V_isn_ctx, (u_char *) &tp->t_inpcb->inp_laddr,
+ MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_laddr,
sizeof(struct in_addr));
}
- MD5Update(&V_isn_ctx, (u_char *) &V_isn_secret, sizeof(V_isn_secret));
- MD5Final((u_char *) &md5_buffer, &V_isn_ctx);
+ MD5Update(&isn_ctx, (u_char *) &V_isn_secret, sizeof(V_isn_secret));
+ MD5Final((u_char *) &md5_buffer, &isn_ctx);
new_isn = (tcp_seq) md5_buffer[0];
V_isn_offset += ISN_STATIC_INCREMENT +
(arc4random() & ISN_RANDOM_INCREMENT);
@@ -1659,7 +1657,7 @@ tcp_maxmtu(struct in_conninfo *inc, int *flags)
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr = inc->inc_faddr;
- in_rtalloc_ign(&sro, RTF_CLONING, inc->inc_fibnum);
+ in_rtalloc_ign(&sro, 0, inc->inc_fibnum);
}
if (sro.ro_rt != NULL) {
ifp = sro.ro_rt->rt_ifp;
@@ -1694,7 +1692,7 @@ tcp_maxmtu6(struct in_conninfo *inc, int *flags)
sro6.ro_dst.sin6_family = AF_INET6;
sro6.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
sro6.ro_dst.sin6_addr = inc->inc6_faddr;
- rtalloc_ign((struct route *)&sro6, RTF_CLONING);
+ rtalloc_ign((struct route *)&sro6, 0);
}
if (sro6.ro_rt != NULL) {
ifp = sro6.ro_rt->rt_ifp;
@@ -2263,7 +2261,7 @@ tcp_log_addrs(struct in_conninfo *inc, struct tcphdr *th, void *ip4hdr,
strcat(s, "TCP: [");
sp = s + strlen(s);
- if (inc && inc->inc_isipv6 == 0) {
+ if (inc && ((inc->inc_flags & INC_ISIPV6) == 0)) {
inet_ntoa_r(inc->inc_faddr, sp);
sp = s + strlen(s);
sprintf(sp, "]:%i to [", ntohs(inc->inc_fport));
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 838fd52..18fab28 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -430,7 +430,7 @@ syncache_lookup(struct in_conninfo *inc, struct syncache_head **schp)
struct syncache_head *sch;
#ifdef INET6
- if (inc->inc_isipv6) {
+ if (inc->inc_flags & INC_ISIPV6) {
sch = &V_tcp_syncache.hashbase[
SYNCACHE_HASH6(inc, V_tcp_syncache.hashmask)];
*schp = sch;
@@ -454,7 +454,7 @@ syncache_lookup(struct in_conninfo *inc, struct syncache_head **schp)
/* Circle through bucket row to find matching entry. */
TAILQ_FOREACH(sc, &sch->sch_bucket, sc_hash) {
#ifdef INET6
- if (sc->sc_inc.inc_isipv6)
+ if (sc->sc_inc.inc_flags & INC_ISIPV6)
continue;
#endif
if (ENDPTS_EQ(&inc->inc_ie, &sc->sc_inc.inc_ie))
@@ -643,9 +643,9 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
INP_WLOCK(inp);
/* Insert new socket into PCB hash list. */
- inp->inp_inc.inc_isipv6 = sc->sc_inc.inc_isipv6;
+ inp->inp_inc.inc_flags = sc->sc_inc.inc_flags;
#ifdef INET6
- if (sc->sc_inc.inc_isipv6) {
+ if (sc->sc_inc.inc_flags & INC_ISIPV6) {
inp->in6p_laddr = sc->sc_inc.inc6_laddr;
} else {
inp->inp_vflag &= ~INP_IPV6;
@@ -662,7 +662,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
* put the PCB on the hash lists.
*/
#ifdef INET6
- if (sc->sc_inc.inc_isipv6)
+ if (sc->sc_inc.inc_flags & INC_ISIPV6)
inp->in6p_laddr = in6addr_any;
else
#endif
@@ -676,7 +676,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
printf("syncache_socket: could not copy policy\n");
#endif
#ifdef INET6
- if (sc->sc_inc.inc_isipv6) {
+ if (sc->sc_inc.inc_flags & INC_ISIPV6) {
struct inpcb *oinp = sotoinpcb(lso);
struct in6_addr laddr6;
struct sockaddr_in6 sin6;
@@ -708,8 +708,8 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
goto abort;
}
/* Override flowlabel from in6_pcbconnect. */
- inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
- inp->in6p_flowinfo |= sc->sc_flowlabel;
+ inp->inp_flow &= ~IPV6_FLOWLABEL_MASK;
+ inp->inp_flow |= sc->sc_flowlabel;
} else
#endif
{
@@ -993,8 +993,8 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
cred = crhold(so->so_cred);
#ifdef INET6
- if (inc->inc_isipv6 &&
- (inp->in6p_flags & IN6P_AUTOFLOWLABEL))
+ if ((inc->inc_flags & INC_ISIPV6) &&
+ (inp->inp_flags & IN6P_AUTOFLOWLABEL))
autoflowlabel = 1;
#endif
ip_ttl = inp->inp_ip_ttl;
@@ -1022,7 +1022,7 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
* Remember the IP options, if any.
*/
#ifdef INET6
- if (!inc->inc_isipv6)
+ if (!(inc->inc_flags & INC_ISIPV6))
#endif
ipopts = (m) ? ip_srcroute(m) : NULL;
@@ -1123,10 +1123,11 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
sc->sc_cred = cred;
cred = NULL;
sc->sc_ipopts = ipopts;
+ /* XXX-BZ this fib assignment is just useless. */
sc->sc_inc.inc_fibnum = inp->inp_inc.inc_fibnum;
bcopy(inc, &sc->sc_inc, sizeof(struct in_conninfo));
#ifdef INET6
- if (!inc->inc_isipv6)
+ if (!(inc->inc_flags & INC_ISIPV6))
#endif
{
sc->sc_ip_tos = ip_tos;
@@ -1272,7 +1273,7 @@ syncache_respond(struct syncache *sc)
hlen =
#ifdef INET6
- (sc->sc_inc.inc_isipv6) ? sizeof(struct ip6_hdr) :
+ (sc->sc_inc.inc_flags & INC_ISIPV6) ? sizeof(struct ip6_hdr) :
#endif
sizeof(struct ip);
tlen = hlen + sizeof(struct tcphdr);
@@ -1299,7 +1300,7 @@ syncache_respond(struct syncache *sc)
m->m_pkthdr.rcvif = NULL;
#ifdef INET6
- if (sc->sc_inc.inc_isipv6) {
+ if (sc->sc_inc.inc_flags & INC_ISIPV6) {
ip6 = mtod(m, struct ip6_hdr *);
ip6->ip6_vfc = IPV6_VERSION;
ip6->ip6_nxt = IPPROTO_TCP;
@@ -1390,7 +1391,7 @@ syncache_respond(struct syncache *sc)
to.to_signature, IPSEC_DIR_OUTBOUND);
#endif
#ifdef INET6
- if (sc->sc_inc.inc_isipv6)
+ if (sc->sc_inc.inc_flags & INC_ISIPV6)
ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) + optlen);
else
#endif
@@ -1399,7 +1400,7 @@ syncache_respond(struct syncache *sc)
optlen = 0;
#ifdef INET6
- if (sc->sc_inc.inc_isipv6) {
+ if (sc->sc_inc.inc_flags & INC_ISIPV6) {
th->th_sum = 0;
th->th_sum = in6_cksum(m, IPPROTO_TCP, hlen,
tlen + optlen - hlen);
@@ -1653,8 +1654,8 @@ syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch,
sc->sc_iss = ack;
#ifdef INET6
- if (inc->inc_isipv6) {
- if (sotoinpcb(so)->in6p_flags & IN6P_AUTOFLOWLABEL)
+ if (inc->inc_flags & INC_ISIPV6) {
+ if (sotoinpcb(so)->inp_flags & IN6P_AUTOFLOWLABEL)
sc->sc_flowlabel = md5_buffer[1] & IPV6_FLOWLABEL_MASK;
} else
#endif
@@ -1743,7 +1744,7 @@ syncache_pcblist(struct sysctl_req *req, int max_pcbs, int *pcbs_exported)
continue;
bzero(&xt, sizeof(xt));
xt.xt_len = sizeof(xt);
- if (sc->sc_inc.inc_isipv6)
+ if (sc->sc_inc.inc_flags & INC_ISIPV6)
xt.xt_inp.inp_vflag = INP_IPV6;
else
xt.xt_inp.inp_vflag = INP_IPV4;
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index 37fafa0..3138547 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -538,7 +538,7 @@ tcp_twrespond(struct tcptw *tw, int flags)
struct tcpopt to;
#ifdef INET6
struct ip6_hdr *ip6 = NULL;
- int isipv6 = inp->inp_inc.inc_isipv6;
+ int isipv6 = inp->inp_inc.inc_flags & INC_ISIPV6;
#endif
INP_WLOCK_ASSERT(inp);
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 2011dff..f6dcae1 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -519,7 +519,7 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
}
inp->inp_vflag &= ~INP_IPV4;
inp->inp_vflag |= INP_IPV6;
- inp->inp_inc.inc_isipv6 = 1;
+ inp->inp_inc.inc_flags |= INC_ISIPV6;
if (prison_remote_ip6(td->td_ucred, &sin6p->sin6_addr) != 0) {
error = EINVAL;
goto out;
@@ -1167,9 +1167,9 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
inp->in6p_faddr = sin6->sin6_addr;
inp->inp_fport = sin6->sin6_port;
/* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
- inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
- if (inp->in6p_flags & IN6P_AUTOFLOWLABEL)
- inp->in6p_flowinfo |=
+ inp->inp_flow &= ~IPV6_FLOWLABEL_MASK;
+ if (inp->inp_flags & IN6P_AUTOFLOWLABEL)
+ inp->inp_flow |=
(htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
in_pcbrehash(inp);
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index ed872b9..a4392cb 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -38,7 +38,9 @@
/*
* Kernel variables for tcp.
*/
+#ifdef VIMAGE_GLOBALS
extern int tcp_do_rfc1323;
+#endif
/* TCP segment queue entry */
struct tseg_qent {
@@ -48,7 +50,9 @@ struct tseg_qent {
struct mbuf *tqe_m; /* mbuf contains packet */
};
LIST_HEAD(tsegqe_head, tseg_qent);
+#ifdef VIMAGE_GLOBALS
extern int tcp_reass_qsize;
+#endif
extern struct uma_zone *tcp_reass_zone;
struct sackblk {
diff --git a/sys/netinet/vinet.h b/sys/netinet/vinet.h
index 65ccfa4..449334e 100644
--- a/sys/netinet/vinet.h
+++ b/sys/netinet/vinet.h
@@ -142,7 +142,6 @@ struct vnet_inet {
int _isn_last_reseed;
u_int32_t _isn_offset;
u_int32_t _isn_offset_old;
- MD5_CTX _isn_ctx;
struct inpcbhead _udb;
struct inpcbinfo _udbinfo;
@@ -265,7 +264,6 @@ extern struct vnet_inet vnet_inet_0;
#define V_ipsendredirects VNET_INET(ipsendredirects)
#define V_ipstat VNET_INET(ipstat)
#define V_ipstealth VNET_INET(ipstealth)
-#define V_isn_ctx VNET_INET(isn_ctx)
#define V_isn_last_reseed VNET_INET(isn_last_reseed)
#define V_isn_offset VNET_INET(isn_offset)
#define V_isn_offset_old VNET_INET(isn_offset_old)
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 59bc95a..7bdd8a8 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -85,6 +85,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_dl.h>
+#include <net/if_llatbl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <net/vnet.h>
@@ -1147,7 +1148,7 @@ icmp6_mtudisc_update(struct ip6ctlparam *ip6cp, int validated)
mtu = IPV6_MMTU - 8;
bzero(&inc, sizeof(inc));
- inc.inc_flags = 1; /* IPv6 */
+ inc.inc_flags |= INC_ISIPV6;
inc.inc6_faddr = *dst;
if (in6_setscope(&inc.inc6_faddr, m->m_pkthdr.rcvif, NULL))
return;
@@ -1898,8 +1899,8 @@ icmp6_rip6_input(struct mbuf **mp, int off)
INIT_VNET_INET6(curvnet);
struct mbuf *m = *mp;
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
- struct in6pcb *in6p;
- struct in6pcb *last = NULL;
+ struct inpcb *in6p;
+ struct inpcb *last = NULL;
struct sockaddr_in6 fromsa;
struct icmp6_hdr *icmp6;
struct mbuf *opts = NULL;
@@ -1932,7 +1933,7 @@ icmp6_rip6_input(struct mbuf **mp, int off)
LIST_FOREACH(in6p, &V_ripcb, inp_list) {
if ((in6p->inp_vflag & INP_IPV6) == 0)
continue;
- if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6)
+ if (in6p->inp_ip_p != IPPROTO_ICMPV6)
continue;
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
@@ -1946,7 +1947,7 @@ icmp6_rip6_input(struct mbuf **mp, int off)
INP_RUNLOCK(in6p);
continue;
}
- if (last) {
+ if (last != NULL) {
struct mbuf *n = NULL;
/*
@@ -1982,13 +1983,13 @@ icmp6_rip6_input(struct mbuf **mp, int off)
}
if (n != NULL ||
(n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
- if (last->in6p_flags & IN6P_CONTROLOPTS)
+ if (last->inp_flags & INP_CONTROLOPTS)
ip6_savecontrol(last, n, &opts);
/* strip intermediate headers */
m_adj(n, off);
- SOCKBUF_LOCK(&last->in6p_socket->so_rcv);
+ SOCKBUF_LOCK(&last->inp_socket->so_rcv);
if (sbappendaddr_locked(
- &last->in6p_socket->so_rcv,
+ &last->inp_socket->so_rcv,
(struct sockaddr *)&fromsa, n, opts)
== 0) {
/* should notify about lost packet */
@@ -1997,9 +1998,9 @@ icmp6_rip6_input(struct mbuf **mp, int off)
m_freem(opts);
}
SOCKBUF_UNLOCK(
- &last->in6p_socket->so_rcv);
+ &last->inp_socket->so_rcv);
} else
- sorwakeup_locked(last->in6p_socket);
+ sorwakeup_locked(last->inp_socket);
opts = NULL;
}
INP_RUNLOCK(last);
@@ -2007,8 +2008,8 @@ icmp6_rip6_input(struct mbuf **mp, int off)
last = in6p;
}
INP_INFO_RUNLOCK(&V_ripcbinfo);
- if (last) {
- if (last->in6p_flags & IN6P_CONTROLOPTS)
+ if (last != NULL) {
+ if (last->inp_flags & INP_CONTROLOPTS)
ip6_savecontrol(last, m, &opts);
/* strip intermediate headers */
m_adj(m, off);
@@ -2032,15 +2033,15 @@ icmp6_rip6_input(struct mbuf **mp, int off)
}
}
}
- SOCKBUF_LOCK(&last->in6p_socket->so_rcv);
- if (sbappendaddr_locked(&last->in6p_socket->so_rcv,
+ SOCKBUF_LOCK(&last->inp_socket->so_rcv);
+ if (sbappendaddr_locked(&last->inp_socket->so_rcv,
(struct sockaddr *)&fromsa, m, opts) == 0) {
m_freem(m);
if (opts)
m_freem(opts);
- SOCKBUF_UNLOCK(&last->in6p_socket->so_rcv);
+ SOCKBUF_UNLOCK(&last->inp_socket->so_rcv);
} else
- sorwakeup_locked(last->in6p_socket);
+ sorwakeup_locked(last->inp_socket);
INP_RUNLOCK(last);
} else {
m_freem(m);
@@ -2452,6 +2453,7 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
struct mbuf *m = NULL; /* newly allocated one */
struct ip6_hdr *ip6; /* m as struct ip6_hdr */
struct nd_redirect *nd_rd;
+ struct llentry *ln = NULL;
size_t maxlen;
u_char *p;
struct ifnet *outif = NULL;
@@ -2573,35 +2575,35 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
{
/* target lladdr option */
- struct rtentry *rt_router = NULL;
int len;
- struct sockaddr_dl *sdl;
struct nd_opt_hdr *nd_opt;
char *lladdr;
- rt_router = nd6_lookup(router_ll6, 0, ifp);
- if (!rt_router)
+ IF_AFDATA_LOCK(ifp);
+ ln = nd6_lookup(router_ll6, 0, ifp);
+ IF_AFDATA_UNLOCK(ifp);
+ if (ln == NULL)
goto nolladdropt;
+
len = sizeof(*nd_opt) + ifp->if_addrlen;
len = (len + 7) & ~7; /* round by 8 */
/* safety check */
- if (len + (p - (u_char *)ip6) > maxlen)
+ if (len + (p - (u_char *)ip6) > maxlen)
goto nolladdropt;
- if (!(rt_router->rt_flags & RTF_GATEWAY) &&
- (rt_router->rt_flags & RTF_LLINFO) &&
- (rt_router->rt_gateway->sa_family == AF_LINK) &&
- (sdl = (struct sockaddr_dl *)rt_router->rt_gateway) &&
- sdl->sdl_alen) {
+
+ if (ln->la_flags & LLE_VALID) {
nd_opt = (struct nd_opt_hdr *)p;
nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
nd_opt->nd_opt_len = len >> 3;
lladdr = (char *)(nd_opt + 1);
- bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen);
+ bcopy(&ln->ll_addr, lladdr, ifp->if_addrlen);
p += len;
}
}
-nolladdropt:;
-
+nolladdropt:
+ if (ln != NULL)
+ LLE_RUNLOCK(ln);
+
m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
/* just to be safe */
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index c784845..6ba852c 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -88,6 +88,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_var.h>
+#include <net/if_llatbl.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
@@ -135,152 +136,7 @@ static void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
struct in6_multihead in6_multihead; /* XXX BSS initialization */
int (*faithprefix_p)(struct in6_addr *);
-/*
- * Subroutine for in6_ifaddloop() and in6_ifremloop().
- * This routine does actual work.
- */
-static void
-in6_ifloop_request(int cmd, struct ifaddr *ifa)
-{
- struct sockaddr_in6 all1_sa;
- struct rtentry *nrt = NULL;
- int e;
- char ip6buf[INET6_ADDRSTRLEN];
-
- bzero(&all1_sa, sizeof(all1_sa));
- all1_sa.sin6_family = AF_INET6;
- all1_sa.sin6_len = sizeof(struct sockaddr_in6);
- all1_sa.sin6_addr = in6mask128;
-
- /*
- * We specify the address itself as the gateway, and set the
- * RTF_LLINFO flag, so that the corresponding host route would have
- * the flag, and thus applications that assume traditional behavior
- * would be happy. Note that we assume the caller of the function
- * (probably implicitly) set nd6_rtrequest() to ifa->ifa_rtrequest,
- * which changes the outgoing interface to the loopback interface.
- */
- e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr,
- (struct sockaddr *)&all1_sa, RTF_UP|RTF_HOST|RTF_LLINFO, &nrt);
- if (e != 0) {
- /* XXX need more descriptive message */
-
- log(LOG_ERR, "in6_ifloop_request: "
- "%s operation failed for %s (errno=%d)\n",
- cmd == RTM_ADD ? "ADD" : "DELETE",
- ip6_sprintf(ip6buf,
- &((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr), e);
- }
-
- /*
- * Report the addition/removal of the address to the routing socket.
- * XXX: since we called rtinit for a p2p interface with a destination,
- * we end up reporting twice in such a case. Should we rather
- * omit the second report?
- */
- if (nrt) {
- RT_LOCK(nrt);
- /*
- * Make sure rt_ifa be equal to IFA, the second argument of
- * the function. We need this because when we refer to
- * rt_ifa->ia6_flags in ip6_input, we assume that the rt_ifa
- * points to the address instead of the loopback address.
- */
- if (cmd == RTM_ADD && ifa != nrt->rt_ifa) {
- IFAFREE(nrt->rt_ifa);
- IFAREF(ifa);
- nrt->rt_ifa = ifa;
- }
-
- rt_newaddrmsg(cmd, ifa, e, nrt);
- if (cmd == RTM_DELETE)
- RTFREE_LOCKED(nrt);
- else {
- /* the cmd must be RTM_ADD here */
- RT_REMREF(nrt);
- RT_UNLOCK(nrt);
- }
- }
-}
-
-/*
- * Add ownaddr as loopback rtentry. We previously add the route only if
- * necessary (ex. on a p2p link). However, since we now manage addresses
- * separately from prefixes, we should always add the route. We can't
- * rely on the cloning mechanism from the corresponding interface route
- * any more.
- */
-void
-in6_ifaddloop(struct ifaddr *ifa)
-{
- struct rtentry *rt;
- int need_loop;
-
- /* If there is no loopback entry, allocate one. */
- rt = rtalloc1(ifa->ifa_addr, 0, 0);
- need_loop = (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
- (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0);
- if (rt)
- RTFREE_LOCKED(rt);
- if (need_loop)
- in6_ifloop_request(RTM_ADD, ifa);
-}
-
-/*
- * Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
- * if it exists.
- */
-void
-in6_ifremloop(struct ifaddr *ifa)
-{
- INIT_VNET_INET6(curvnet);
- struct in6_ifaddr *ia;
- struct rtentry *rt;
- int ia_count = 0;
-
- /*
- * Some of BSD variants do not remove cloned routes
- * from an interface direct route, when removing the direct route
- * (see comments in net/net_osdep.h). Even for variants that do remove
- * cloned routes, they could fail to remove the cloned routes when
- * we handle multple addresses that share a common prefix.
- * So, we should remove the route corresponding to the deleted address.
- */
- /*
- * Delete the entry only if exact one ifa exists. More than one ifa
- * can exist if we assign a same single address to multiple
- * (probably p2p) interfaces.
- * XXX: we should avoid such a configuration in IPv6...
- */
- for (ia = V_in6_ifaddr; ia; ia = ia->ia_next) {
- if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ia->ia_addr.sin6_addr)) {
- ia_count++;
- if (ia_count > 1)
- break;
- }
- }
-
- if (ia_count == 1) {
- /*
- * Before deleting, check if a corresponding loopbacked host
- * route surely exists. With this check, we can avoid to
- * delete an interface direct route whose destination is same
- * as the address being removed. This can happen when removing
- * a subnet-router anycast address on an interface attahced
- * to a shared medium.
- */
- rt = rtalloc1(ifa->ifa_addr, 0, 0);
- if (rt != NULL) {
- if ((rt->rt_flags & RTF_HOST) != 0 &&
- (rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
- RTFREE_LOCKED(rt);
- in6_ifloop_request(RTM_DELETE, ifa);
- } else
- RT_UNLOCK(rt);
- }
- }
-}
int
in6_mask2len(struct in6_addr *mask, u_char *lim0)
@@ -1131,10 +987,9 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
}
}
if (!rt) {
- /* XXX: we need RTF_CLONING to fake nd6_rtrequest */
error = rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
(struct sockaddr *)&ia->ia_addr,
- (struct sockaddr *)&mltmask, RTF_UP | RTF_CLONING,
+ (struct sockaddr *)&mltmask, RTF_UP,
(struct rtentry **)0);
if (error)
goto cleanup;
@@ -1208,7 +1063,7 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
if (!rt) {
error = rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
(struct sockaddr *)&ia->ia_addr,
- (struct sockaddr *)&mltmask, RTF_UP | RTF_CLONING,
+ (struct sockaddr *)&mltmask, RTF_UP,
(struct rtentry **)0);
if (error)
goto cleanup;
@@ -1287,34 +1142,16 @@ in6_purgeaddr(struct ifaddr *ifa)
{
struct ifnet *ifp = ifa->ifa_ifp;
struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
- char ip6buf[INET6_ADDRSTRLEN];
struct in6_multi_mship *imm;
/* stop DAD processing */
nd6_dad_stop(ifa);
- /*
- * delete route to the destination of the address being purged.
- * The interface must be p2p or loopback in this case.
- */
- if ((ia->ia_flags & IFA_ROUTE) != 0 && ia->ia_dstaddr.sin6_len != 0) {
- int e;
-
- if ((e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST))
- != 0) {
- log(LOG_ERR, "in6_purgeaddr: failed to remove "
- "a route to the p2p destination: %s on %s, "
- "errno=%d\n",
- ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
- if_name(ifp), e);
- /* proceed anyway... */
- } else
- ia->ia_flags &= ~IFA_ROUTE;
- }
-
- /* Remove ownaddr's loopback rtentry, if it exists. */
- in6_ifremloop(&(ia->ia_ifa));
-
+ IF_AFDATA_LOCK(ifp);
+ lla_lookup(LLTABLE6(ifp), (LLE_DELETE | LLE_IFADDR),
+ (struct sockaddr *)&ia->ia_addr);
+ IF_AFDATA_UNLOCK(ifp);
+
/*
* leave from multicast groups we have joined for the interface
*/
@@ -1688,26 +1525,15 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
/* we could do in(6)_socktrim here, but just omit it at this moment. */
- if (newhost) {
- /*
- * set the rtrequest function to create llinfo. It also
- * adjust outgoing interface of the route for the local
- * address when called via in6_ifaddloop() below.
- */
- ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
- }
-
/*
* Special case:
* If a new destination address is specified for a point-to-point
* interface, install a route to the destination as an interface
- * direct route. In addition, if the link is expected to have neighbor
- * cache entries, specify RTF_LLINFO so that a cache entry for the
- * destination address will be created.
- * created
+ * direct route.
* XXX: the logic below rejects assigning multiple addresses on a p2p
* interface that share the same destination.
*/
+#if 0 /* QL - verify */
plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
ia->ia_dstaddr.sin6_family == AF_INET6) {
@@ -1715,7 +1541,6 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
struct rtentry *rt = NULL, **rtp = NULL;
if (nd6_need_cache(ifp) != 0) {
- rtflags |= RTF_LLINFO;
rtp = &rt;
}
@@ -1744,16 +1569,36 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
}
ia->ia_flags |= IFA_ROUTE;
}
- if (plen < 128) {
- /*
- * The RTF_CLONING flag is necessary for in6_is_ifloop_auto().
- */
- ia->ia_ifa.ifa_flags |= RTF_CLONING;
+#else
+ plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
+ if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
+ ia->ia_dstaddr.sin6_family == AF_INET6) {
+ if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD,
+ RTF_UP | RTF_HOST)) != 0)
+ return (error);
+ ia->ia_flags |= IFA_ROUTE;
}
+#endif
/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
- if (newhost)
- in6_ifaddloop(&(ia->ia_ifa));
+ if (newhost) {
+ struct llentry *ln;
+
+ IF_AFDATA_LOCK(ifp);
+ ia->ia_ifa.ifa_rtrequest = NULL;
+
+ /* XXX QL
+ * we need to report rt_newaddrmsg
+ */
+ ln = lla_lookup(LLTABLE6(ifp), (LLE_CREATE | LLE_IFADDR | LLE_EXCLUSIVE),
+ (struct sockaddr *)&ia->ia_addr);
+ IF_AFDATA_UNLOCK(ifp);
+ if (ln != NULL) {
+ ln->la_expire = 0; /* for IPv6 this means permanent */
+ ln->ln_state = ND6_LLINFO_REACHABLE;
+ LLE_WUNLOCK(ln);
+ }
+ }
return (error);
}
@@ -2237,6 +2082,216 @@ in6_if2idlen(struct ifnet *ifp)
}
}
+#include <sys/sysctl.h>
+
+struct in6_llentry {
+ struct llentry base;
+ struct sockaddr_in6 l3_addr6;
+};
+
+static struct llentry *
+in6_lltable_new(const struct sockaddr *l3addr, u_int flags)
+{
+ struct in6_llentry *lle;
+
+ lle = malloc(sizeof(struct in6_llentry), M_LLTABLE,
+ M_DONTWAIT | M_ZERO);
+ if (lle == NULL) /* NB: caller generates msg */
+ return NULL;
+
+ callout_init(&lle->base.ln_timer_ch, CALLOUT_MPSAFE);
+ lle->l3_addr6 = *(const struct sockaddr_in6 *)l3addr;
+ lle->base.lle_refcnt = 1;
+ LLE_LOCK_INIT(&lle->base);
+ return &lle->base;
+}
+
+/*
+ * Deletes an address from the address table.
+ * This function is called by the timer functions
+ * such as arptimer() and nd6_llinfo_timer(), and
+ * the caller does the locking.
+ */
+static void
+in6_lltable_free(struct lltable *llt, struct llentry *lle)
+{
+ LLE_WUNLOCK(lle);
+ LLE_LOCK_DESTROY(lle);
+ free(lle, M_LLTABLE);
+}
+
+static int
+in6_lltable_rtcheck(struct ifnet *ifp, const struct sockaddr *l3addr)
+{
+ struct rtentry *rt;
+ char ip6buf[INET6_ADDRSTRLEN];
+
+ KASSERT(l3addr->sa_family == AF_INET6,
+ ("sin_family %d", l3addr->sa_family));
+
+ /* XXX rtalloc1 should take a const param */
+ rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
+ if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
+ struct ifaddr *ifa;
+ /*
+ * Create an ND6 cache for an IPv6 neighbor
+ * that is not covered by our own prefix.
+ */
+ /* XXX ifaof_ifpforaddr should take a const param */
+ ifa = ifaof_ifpforaddr(__DECONST(struct sockaddr *, l3addr), ifp);
+ if (ifa != NULL) {
+ if (rt != NULL)
+ rtfree(rt);
+ return 0;
+ }
+ log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n",
+ ip6_sprintf(ip6buf, &((const struct sockaddr_in6 *)l3addr)->sin6_addr));
+ if (rt != NULL)
+ rtfree(rt);
+ return EINVAL;
+ }
+ rtfree(rt);
+ return 0;
+}
+
+static struct llentry *
+in6_lltable_lookup(struct lltable *llt, u_int flags,
+ const struct sockaddr *l3addr)
+{
+ const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr;
+ struct ifnet *ifp = llt->llt_ifp;
+ struct llentry *lle;
+ struct llentries *lleh;
+ u_int hashkey;
+
+ IF_AFDATA_LOCK_ASSERT(ifp);
+ KASSERT(l3addr->sa_family == AF_INET6,
+ ("sin_family %d", l3addr->sa_family));
+
+ hashkey = sin6->sin6_addr.s6_addr32[3];
+ lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
+ LIST_FOREACH(lle, lleh, lle_next) {
+ if (lle->la_flags & LLE_DELETED)
+ continue;
+ if (bcmp(L3_ADDR(lle), l3addr, l3addr->sa_len) == 0)
+ break;
+ }
+
+ if (lle == NULL) {
+ if (!(flags & LLE_CREATE))
+ return (NULL);
+ /*
+ * A route that covers the given address must have
+ * been installed 1st because we are doing a resolution,
+ * verify this.
+ */
+ if (!(flags & LLE_IFADDR) &&
+ in6_lltable_rtcheck(ifp, l3addr) != 0)
+ return NULL;
+
+ lle = in6_lltable_new(l3addr, flags);
+ if (lle == NULL) {
+ log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
+ return NULL;
+ }
+ lle->la_flags = flags & ~LLE_CREATE;
+ if ((flags & (LLE_CREATE | LLE_IFADDR)) == (LLE_CREATE | LLE_IFADDR)) {
+ bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
+ lle->la_flags |= (LLE_VALID | LLE_STATIC);
+ }
+
+ lle->lle_tbl = llt;
+ lle->lle_head = lleh;
+ LIST_INSERT_HEAD(lleh, lle, lle_next);
+ } else if (flags & LLE_DELETE) {
+ LLE_WLOCK(lle);
+ lle->la_flags = LLE_DELETED;
+ LLE_WUNLOCK(lle);
+#ifdef DIAGNOSTICS
+ log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
+#endif
+ lle = (void *)-1;
+ }
+ if (LLE_IS_VALID(lle)) {
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WLOCK(lle);
+ else
+ LLE_RLOCK(lle);
+ }
+ return (lle);
+}
+
+static int
+in6_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
+{
+ struct ifnet *ifp = llt->llt_ifp;
+ struct llentry *lle;
+ /* XXX stack use */
+ struct {
+ struct rt_msghdr rtm;
+ struct sockaddr_in6 sin6;
+ /*
+ * ndp.c assumes that sdl is word aligned
+ */
+#ifdef __LP64__
+ uint32_t pad;
+#endif
+ struct sockaddr_dl sdl;
+ } ndpc;
+ int i, error;
+
+ /* XXXXX
+ * current IFNET_RLOCK() is mapped to IFNET_WLOCK()
+ * so it is okay to use this ASSERT, change it when
+ * IFNET lock is finalized
+ */
+ IFNET_WLOCK_ASSERT();
+
+ error = 0;
+ for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
+ LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
+ struct sockaddr_dl *sdl;
+
+ /* skip deleted or invalid entries */
+ if ((lle->la_flags & (LLE_DELETED|LLE_VALID)) != LLE_VALID)
+ continue;
+ /*
+ * produce a msg made of:
+ * struct rt_msghdr;
+ * struct sockaddr_in6 (IPv6)
+ * struct sockaddr_dl;
+ */
+ bzero(&ndpc, sizeof(ndpc));
+ ndpc.rtm.rtm_msglen = sizeof(ndpc);
+ ndpc.sin6.sin6_family = AF_INET6;
+ ndpc.sin6.sin6_len = sizeof(ndpc.sin6);
+ bcopy(L3_ADDR(lle), &ndpc.sin6, L3_ADDR_LEN(lle));
+
+ /* publish */
+ if (lle->la_flags & LLE_PUB)
+ ndpc.rtm.rtm_flags |= RTF_ANNOUNCE;
+
+ sdl = &ndpc.sdl;
+ sdl->sdl_family = AF_LINK;
+ sdl->sdl_len = sizeof(*sdl);
+ sdl->sdl_alen = ifp->if_addrlen;
+ sdl->sdl_index = ifp->if_index;
+ sdl->sdl_type = ifp->if_type;
+ bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
+ ndpc.rtm.rtm_rmx.rmx_expire =
+ lle->la_flags & LLE_STATIC ? 0 : lle->la_expire;
+ ndpc.rtm.rtm_flags |= RTF_HOST;
+ if (lle->la_flags & LLE_STATIC)
+ ndpc.rtm.rtm_flags |= RTF_STATIC;
+ ndpc.rtm.rtm_index = ifp->if_index;
+ error = SYSCTL_OUT(wr, &ndpc, sizeof(ndpc));
+ if (error)
+ break;
+ }
+ }
+ return error;
+}
+
void *
in6_domifattach(struct ifnet *ifp)
{
@@ -2256,6 +2311,14 @@ in6_domifattach(struct ifnet *ifp)
ext->nd_ifinfo = nd6_ifattach(ifp);
ext->scope6_id = scope6_ifattach(ifp);
+ ext->lltable = lltable_init(ifp, AF_INET6);
+ if (ext->lltable != NULL) {
+ ext->lltable->llt_new = in6_lltable_new;
+ ext->lltable->llt_free = in6_lltable_free;
+ ext->lltable->llt_rtcheck = in6_lltable_rtcheck;
+ ext->lltable->llt_lookup = in6_lltable_lookup;
+ ext->lltable->llt_dump = in6_lltable_dump;
+ }
return ext;
}
@@ -2266,6 +2329,7 @@ in6_domifdetach(struct ifnet *ifp, void *aux)
scope6_ifdetach(ext->scope6_id);
nd6_ifdetach(ext->nd_ifinfo);
+ lltable_free(ext->lltable);
free(ext->in6_ifstat, M_IFADDR);
free(ext->icmp6_ifstat, M_IFADDR);
free(ext, M_IFADDR);
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index ad19bee..753f45d 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -394,9 +394,9 @@ in6_pcbconnect(register struct inpcb *inp, struct sockaddr *nam,
inp->in6p_faddr = sin6->sin6_addr;
inp->inp_fport = sin6->sin6_port;
/* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
- inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
- if (inp->in6p_flags & IN6P_AUTOFLOWLABEL)
- inp->in6p_flowinfo |=
+ inp->inp_flow &= ~IPV6_FLOWLABEL_MASK;
+ if (inp->inp_flags & IN6P_AUTOFLOWLABEL)
+ inp->inp_flow |=
(htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
in_pcbrehash(inp);
@@ -414,7 +414,7 @@ in6_pcbdisconnect(struct inpcb *inp)
bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
inp->inp_fport = 0;
/* clear flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
- inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
+ inp->inp_flow &= ~IPV6_FLOWLABEL_MASK;
in_pcbrehash(inp);
}
@@ -617,7 +617,7 @@ in6_pcbnotify(struct inpcbinfo *pcbinfo, struct sockaddr *dst,
*/
if (lport == 0 && fport == 0 && flowinfo &&
inp->inp_socket != NULL &&
- flowinfo == (inp->in6p_flowinfo & IPV6_FLOWLABEL_MASK) &&
+ flowinfo == (inp->inp_flow & IPV6_FLOWLABEL_MASK) &&
IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &sa6_src.sin6_addr))
goto do_notify;
else if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr,
@@ -736,7 +736,7 @@ in6_pcblookup_local(struct inpcbinfo *pcbinfo, struct in6_addr *laddr,
void
in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
{
- struct in6pcb *in6p;
+ struct inpcb *in6p;
struct ip6_moptions *im6o;
struct in6_multi_mship *imm, *nimm;
diff --git a/sys/netinet6/in6_rmx.c b/sys/netinet6/in6_rmx.c
index 7e1a262..ade7649 100644
--- a/sys/netinet6/in6_rmx.c
+++ b/sys/netinet6/in6_rmx.c
@@ -124,6 +124,7 @@ in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rt_key(rt);
struct radix_node *ret;
+ RADIX_NODE_HEAD_WLOCK_ASSERT(head);
if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
rt->rt_flags |= RTF_MULTICAST;
@@ -153,27 +154,7 @@ in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
rt->rt_rmx.rmx_mtu = IN6_LINKMTU(rt->rt_ifp);
ret = rn_addroute(v_arg, n_arg, head, treenodes);
- if (ret == NULL && rt->rt_flags & RTF_HOST) {
- struct rtentry *rt2;
- /*
- * We are trying to add a host route, but can't.
- * Find out if it is because of an
- * ARP entry and delete it if so.
- */
- rt2 = rtalloc1((struct sockaddr *)sin6, 0, RTF_CLONING);
- if (rt2) {
- if (rt2->rt_flags & RTF_LLINFO &&
- rt2->rt_flags & RTF_HOST &&
- rt2->rt_gateway &&
- rt2->rt_gateway->sa_family == AF_LINK) {
- rtexpunge(rt2);
- RTFREE_LOCKED(rt2);
- ret = rn_addroute(v_arg, n_arg, head,
- treenodes);
- } else
- RTFREE_LOCKED(rt2);
- }
- } else if (ret == NULL && rt->rt_flags & RTF_CLONING) {
+ if (ret == NULL) {
struct rtentry *rt2;
/*
* We are trying to add a net route, but can't.
@@ -187,10 +168,9 @@ in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
* net route entry, 3ffe:0501:: -> if0.
* This case should not raise an error.
*/
- rt2 = rtalloc1((struct sockaddr *)sin6, 0, RTF_CLONING);
+ rt2 = rtalloc1((struct sockaddr *)sin6, 0, RTF_RNH_LOCKED);
if (rt2) {
- if ((rt2->rt_flags & (RTF_CLONING|RTF_HOST|RTF_GATEWAY))
- == RTF_CLONING
+ if (((rt2->rt_flags & (RTF_HOST|RTF_GATEWAY)) == 0)
&& rt2->rt_gateway
&& rt2->rt_gateway->sa_family == AF_LINK
&& rt2->rt_ifp == rt->rt_ifp) {
@@ -199,7 +179,7 @@ in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
RTFREE_LOCKED(rt2);
}
}
- return ret;
+ return (ret);
}
/*
@@ -240,39 +220,6 @@ SYSCTL_V_INT(V_NET, vnet_inet6, _net_inet6_ip6, IPV6CTL_RTMAXCACHE,
rtmaxcache, CTLFLAG_RW, rtq_toomany6 , 0, "");
-/*
- * On last reference drop, mark the route as belong to us so that it can be
- * timed out.
- */
-static void
-in6_clsroute(struct radix_node *rn, struct radix_node_head *head)
-{
- INIT_VNET_INET6(curvnet);
- struct rtentry *rt = (struct rtentry *)rn;
-
- RT_LOCK_ASSERT(rt);
-
- if (!(rt->rt_flags & RTF_UP))
- return; /* prophylactic measures */
-
- if ((rt->rt_flags & (RTF_LLINFO | RTF_HOST)) != RTF_HOST)
- return;
-
- if ((rt->rt_flags & (RTF_WASCLONED | RTPRF_OURS)) != RTF_WASCLONED)
- return;
-
- /*
- * As requested by David Greenman:
- * If rtq_reallyold6 is 0, just delete the route without
- * waiting for a timeout cycle to kill it.
- */
- if (V_rtq_reallyold6 != 0) {
- rt->rt_flags |= RTPRF_OURS;
- rt->rt_rmx.rmx_expire = time_uptime + V_rtq_reallyold6;
- } else {
- rtexpunge(rt);
- }
-}
struct rtqk_arg {
struct radix_node_head *rnh;
@@ -307,7 +254,7 @@ in6_rtqkill(struct radix_node *rn, void *rock)
err = rtrequest(RTM_DELETE,
(struct sockaddr *)rt_key(rt),
rt->rt_gateway, rt_mask(rt),
- rt->rt_flags, 0);
+ rt->rt_flags|RTF_RNH_LOCKED, 0);
if (err) {
log(LOG_WARNING, "in6_rtqkill: error %d", err);
} else {
@@ -495,7 +442,6 @@ in6_inithead(void **head, int off)
rnh = *head;
rnh->rnh_addaddr = in6_addroute;
rnh->rnh_matchaddr = in6_matroute;
- rnh->rnh_close = in6_clsroute;
callout_init(&V_rtq_timer6, CALLOUT_MPSAFE);
in6_rtqtimo(rnh); /* kick off timeout first time */
callout_init(&V_rtq_mtutimer, CALLOUT_MPSAFE);
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index 4d7723a..ca65bc9 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -87,6 +87,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/route.h>
+#include <net/if_llatbl.h>
#ifdef RADIX_MPATH
#include <net/radix_mpath.h>
#endif
@@ -131,7 +132,7 @@ int ip6_prefer_tempaddr;
static int selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *, struct ifnet **,
- struct rtentry **, int, int));
+ struct rtentry **, int));
static int in6_selectif __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *ro, struct ifnet **));
@@ -479,8 +480,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
static int
selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct ip6_moptions *mopts, struct route_in6 *ro,
- struct ifnet **retifp, struct rtentry **retrt, int clone,
- int norouteok)
+ struct ifnet **retifp, struct rtentry **retrt, int norouteok)
{
INIT_VNET_INET6(curvnet);
int error = 0;
@@ -536,9 +536,10 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
*/
if (opts && opts->ip6po_nexthop) {
struct route_in6 *ron;
-
+ struct llentry *la;
+
sin6_next = satosin6(opts->ip6po_nexthop);
-
+
/* at this moment, we only support AF_INET6 next hops */
if (sin6_next->sin6_family != AF_INET6) {
error = EAFNOSUPPORT; /* or should we proceed? */
@@ -550,6 +551,36 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
* by that address must be a neighbor of the sending host.
*/
ron = &opts->ip6po_nextroute;
+ /*
+ * XXX what do we do here?
+ * PLZ to be fixing
+ */
+
+
+ if (ron->ro_rt == NULL) {
+ rtalloc((struct route *)ron); /* multi path case? */
+ if (ron->ro_rt == NULL) {
+ if (ron->ro_rt) {
+ RTFREE(ron->ro_rt);
+ ron->ro_rt = NULL;
+ }
+ error = EHOSTUNREACH;
+ goto done;
+ }
+ }
+
+ rt = ron->ro_rt;
+ ifp = rt->rt_ifp;
+ IF_AFDATA_LOCK(ifp);
+ la = lla_lookup(LLTABLE6(ifp), 0, (struct sockaddr *)&sin6_next->sin6_addr);
+ IF_AFDATA_UNLOCK(ifp);
+ if (la != NULL)
+ LLE_RUNLOCK(la);
+ else {
+ error = EHOSTUNREACH;
+ goto done;
+ }
+#if 0
if ((ron->ro_rt &&
(ron->ro_rt->rt_flags & (RTF_UP | RTF_LLINFO)) !=
(RTF_UP | RTF_LLINFO)) ||
@@ -573,16 +604,14 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
goto done;
}
}
- rt = ron->ro_rt;
- ifp = rt->rt_ifp;
+#endif
/*
* When cloning is required, try to allocate a route to the
* destination so that the caller can store path MTU
* information.
*/
- if (!clone)
- goto done;
+ goto done;
}
/*
@@ -608,21 +637,17 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
*sa6 = *dstsock;
sa6->sin6_scope_id = 0;
- if (clone) {
#ifdef RADIX_MPATH
rtalloc_mpath((struct route *)ro,
ntohl(sa6->sin6_addr.s6_addr32[3]));
-#else
- rtalloc((struct route *)ro);
-#endif
- } else {
+#else
ro->ro_rt = rtalloc1(&((struct route *)ro)
- ->ro_dst, 0, 0UL);
+ ->ro_dst, 0, 0UL);
if (ro->ro_rt)
RT_UNLOCK(ro->ro_rt);
- }
+#endif
}
-
+
/*
* do not care about the result if we have the nexthop
* explicitly specified.
@@ -693,7 +718,7 @@ in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
}
if ((error = selectroute(dstsock, opts, mopts, ro, retifp,
- &rt, 0, 1)) != 0) {
+ &rt, 1)) != 0) {
if (ro == &sro && rt && rt == sro.ro_rt)
RTFREE(rt);
return (error);
@@ -745,11 +770,11 @@ in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
int
in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct ip6_moptions *mopts, struct route_in6 *ro,
- struct ifnet **retifp, struct rtentry **retrt, int clone)
+ struct ifnet **retifp, struct rtentry **retrt)
{
return (selectroute(dstsock, opts, mopts, ro, retifp,
- retrt, clone, 0));
+ retrt, 0));
}
/*
@@ -760,7 +785,7 @@ in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
* 3. The system default hoplimit.
*/
int
-in6_selecthlim(struct in6pcb *in6p, struct ifnet *ifp)
+in6_selecthlim(struct inpcb *in6p, struct ifnet *ifp)
{
INIT_VNET_INET6(curvnet);
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index e906d7c..b5dba5e 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -88,13 +88,17 @@ struct in6_addrlifetime {
struct nd_ifinfo;
struct scope6_id;
+struct lltable;
struct in6_ifextra {
struct in6_ifstat *in6_ifstat;
struct icmp6_ifstat *icmp6_ifstat;
struct nd_ifinfo *nd_ifinfo;
struct scope6_id *scope6_id;
+ struct lltable *lltable;
};
+#define LLTABLE6(ifp) (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable)
+
struct in6_ifaddr {
struct ifaddr ia_ifa; /* protocol-independent info */
#define ia_ifp ia_ifa.ifa_ifp
@@ -474,6 +478,8 @@ struct in6_rrenumreq {
extern struct in6_ifaddr *in6_ifaddr;
extern struct icmp6stat icmp6stat;
+
+extern unsigned long in6_maxmtu;
#endif /* VIMAGE_GLOBALS */
#define in6_ifstat_inc(ifp, tag) \
do { \
@@ -483,7 +489,6 @@ do { \
extern struct in6_addr zeroin6_addr;
extern u_char inet6ctlerrmap[];
-extern unsigned long in6_maxmtu;
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_IP6MADDR);
#endif /* MALLOC_DECLARE */
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 7edcaa3..228777b 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -92,6 +92,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_systm.h>
+#include <net/if_llatbl.h>
#ifdef INET
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
@@ -130,7 +131,6 @@ struct vnet_inet6 vnet_inet6_0;
static int ip6qmaxlen;
struct in6_ifaddr *in6_ifaddr;
struct ip6stat ip6stat;
-#endif
extern struct callout in6_tmpaddrtimer_ch;
@@ -144,7 +144,8 @@ extern int icmp6_nodeinfo;
extern int udp6_sendspace;
extern int udp6_recvspace;
-#ifdef VIMAGE_GLOBALS
+extern struct route_in6 ip6_forward_rt;
+
int ip6_forward_srcrt; /* XXX */
int ip6_sourcecheck; /* XXX */
int ip6_sourcecheck_interval; /* XXX */
@@ -301,8 +302,6 @@ ip6_init2(void *dummy)
/* This must be after route_init(), which is now SI_ORDER_THIRD */
SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
-extern struct route_in6 ip6_forward_rt;
-
void
ip6_input(struct mbuf *m)
{
@@ -313,9 +312,11 @@ ip6_input(struct mbuf *m)
u_int32_t plen;
u_int32_t rtalert = ~0;
int nxt, ours = 0;
- struct ifnet *deliverifp = NULL;
+ struct ifnet *deliverifp = NULL, *ifp = NULL;
struct in6_addr odst;
int srcrt = 0;
+ struct llentry *lle = NULL;
+ struct sockaddr_in6 dst6;
#ifdef IPSEC
/*
@@ -550,6 +551,25 @@ passin:
/*
* Unicast check
*/
+
+ bzero(&dst6, sizeof(dst6));
+ dst6.sin6_family = AF_INET6;
+ dst6.sin6_len = sizeof(struct sockaddr_in6);
+ dst6.sin6_addr = ip6->ip6_dst;
+ ifp = m->m_pkthdr.rcvif;
+ IF_AFDATA_LOCK(ifp);
+ lle = lla_lookup(LLTABLE6(ifp), 0,
+ (struct sockaddr *)&dst6);
+ IF_AFDATA_UNLOCK(ifp);
+ if ((lle != NULL) && (lle->la_flags & LLE_IFADDR)) {
+ ours = 1;
+ deliverifp = ifp;
+ LLE_RUNLOCK(lle);
+ goto hbhcheck;
+ }
+ if (lle != NULL)
+ LLE_RUNLOCK(lle);
+
if (V_ip6_forward_rt.ro_rt != NULL &&
(V_ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 &&
IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
@@ -1206,7 +1226,7 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
if (v4only)
return;
- if ((in6p->in6p_flags & IN6P_TCLASS) != 0) {
+ if ((in6p->inp_flags & IN6P_TCLASS) != 0) {
u_int32_t flowinfo;
int tclass;
@@ -1227,7 +1247,7 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
* returned to normal user.
* See also RFC 2292 section 6 (or RFC 3542 section 8).
*/
- if ((in6p->in6p_flags & IN6P_HOPOPTS) != 0) {
+ if ((in6p->inp_flags & IN6P_HOPOPTS) != 0) {
/*
* Check if a hop-by-hop options header is contatined in the
* received packet, and if so, store the options as ancillary
@@ -1279,7 +1299,7 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
}
}
- if ((in6p->in6p_flags & (IN6P_RTHDR | IN6P_DSTOPTS)) != 0) {
+ if ((in6p->inp_flags & (IN6P_RTHDR | IN6P_DSTOPTS)) != 0) {
int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);
/*
@@ -1340,7 +1360,7 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
switch (nxt) {
case IPPROTO_DSTOPTS:
- if (!(in6p->in6p_flags & IN6P_DSTOPTS))
+ if (!(in6p->inp_flags & IN6P_DSTOPTS))
break;
*mp = sbcreatecontrol((caddr_t)ip6e, elen,
@@ -1351,7 +1371,7 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
mp = &(*mp)->m_next;
break;
case IPPROTO_ROUTING:
- if (!in6p->in6p_flags & IN6P_RTHDR)
+ if (!in6p->inp_flags & IN6P_RTHDR)
break;
*mp = sbcreatecontrol((caddr_t)ip6e, elen,
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index 6e5d0d0..ba40b68 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -615,7 +615,7 @@ again:
dst_sa.sin6_len = sizeof(dst_sa);
dst_sa.sin6_addr = ip6->ip6_dst;
if ((error = in6_selectroute(&dst_sa, opt, im6o, ro,
- &ifp, &rt, 0)) != 0) {
+ &ifp, &rt)) != 0) {
switch (error) {
case EHOSTUNREACH:
V_ip6stat.ip6s_noroute++;
@@ -1320,7 +1320,7 @@ ip6_getpmtu(struct route_in6 *ro_pmtu, struct route_in6 *ro,
struct in_conninfo inc;
bzero(&inc, sizeof(inc));
- inc.inc_flags = 1; /* IPv6 */
+ inc.inc_flags |= INC_ISIPV6;
inc.inc6_faddr = *dst;
if (ifp == NULL)
@@ -1464,7 +1464,7 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
else {
/* -1 = kernel default */
in6p->in6p_hops = optval;
- if ((in6p->in6p_vflag &
+ if ((in6p->inp_vflag &
INP_IPV4) != 0)
in6p->inp_ip_ttl = optval;
}
@@ -1472,19 +1472,19 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
#define OPTSET(bit) \
do { \
if (optval) \
- in6p->in6p_flags |= (bit); \
+ in6p->inp_flags |= (bit); \
else \
- in6p->in6p_flags &= ~(bit); \
+ in6p->inp_flags &= ~(bit); \
} while (/*CONSTCOND*/ 0)
#define OPTSET2292(bit) \
do { \
- in6p->in6p_flags |= IN6P_RFC2292; \
+ in6p->inp_flags |= IN6P_RFC2292; \
if (optval) \
- in6p->in6p_flags |= (bit); \
+ in6p->inp_flags |= (bit); \
else \
- in6p->in6p_flags &= ~(bit); \
+ in6p->inp_flags &= ~(bit); \
} while (/*CONSTCOND*/ 0)
-#define OPTBIT(bit) (in6p->in6p_flags & (bit) ? 1 : 0)
+#define OPTBIT(bit) (in6p->inp_flags & (bit) ? 1 : 0)
case IPV6_RECVPKTINFO:
/* cannot mix with RFC2292 */
@@ -1558,7 +1558,7 @@ do { \
break;
case IPV6_FAITH:
- OPTSET(IN6P_FAITH);
+ OPTSET(INP_FAITH);
break;
case IPV6_RECVPATHMTU:
@@ -1578,16 +1578,16 @@ do { \
* available only prior to bind(2).
* see ipng mailing list, Jun 22 2001.
*/
- if (in6p->in6p_lport ||
+ if (in6p->inp_lport ||
!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
error = EINVAL;
break;
}
OPTSET(IN6P_IPV6_V6ONLY);
if (optval)
- in6p->in6p_vflag &= ~INP_IPV4;
+ in6p->inp_vflag &= ~INP_IPV4;
else
- in6p->in6p_vflag |= INP_IPV4;
+ in6p->inp_vflag |= INP_IPV4;
break;
case IPV6_RECVTCLASS:
/* cannot mix with RFC2292 XXX */
@@ -1768,18 +1768,18 @@ do { \
switch (optval) {
case IPV6_PORTRANGE_DEFAULT:
- in6p->in6p_flags &= ~(IN6P_LOWPORT);
- in6p->in6p_flags &= ~(IN6P_HIGHPORT);
+ in6p->inp_flags &= ~(INP_LOWPORT);
+ in6p->inp_flags &= ~(INP_HIGHPORT);
break;
case IPV6_PORTRANGE_HIGH:
- in6p->in6p_flags &= ~(IN6P_LOWPORT);
- in6p->in6p_flags |= IN6P_HIGHPORT;
+ in6p->inp_flags &= ~(INP_LOWPORT);
+ in6p->inp_flags |= INP_HIGHPORT;
break;
case IPV6_PORTRANGE_LOW:
- in6p->in6p_flags &= ~(IN6P_HIGHPORT);
- in6p->in6p_flags |= IN6P_LOWPORT;
+ in6p->inp_flags &= ~(INP_HIGHPORT);
+ in6p->inp_flags |= INP_LOWPORT;
break;
default:
@@ -1881,7 +1881,7 @@ do { \
break;
case IPV6_FAITH:
- optval = OPTBIT(IN6P_FAITH);
+ optval = OPTBIT(INP_FAITH);
break;
case IPV6_V6ONLY:
@@ -1891,10 +1891,10 @@ do { \
case IPV6_PORTRANGE:
{
int flags;
- flags = in6p->in6p_flags;
- if (flags & IN6P_HIGHPORT)
+ flags = in6p->inp_flags;
+ if (flags & INP_HIGHPORT)
optval = IPV6_PORTRANGE_HIGH;
- else if (flags & IN6P_LOWPORT)
+ else if (flags & INP_LOWPORT)
optval = IPV6_PORTRANGE_LOW;
else
optval = 0;
@@ -2050,7 +2050,7 @@ ip6_raw_ctloutput(struct socket *so, struct sockopt *sopt)
{
int error = 0, optval, optlen;
const int icmp6off = offsetof(struct icmp6_hdr, icmp6_cksum);
- struct in6pcb *in6p = sotoin6pcb(so);
+ struct inpcb *in6p = sotoinpcb(so);
int level, op, optname;
level = sopt->sopt_level;
@@ -3326,7 +3326,7 @@ ip6_splithdr(struct mbuf *m, struct ip6_exthdrs *exthdrs)
* Compute IPv6 extension header length.
*/
int
-ip6_optlen(struct in6pcb *in6p)
+ip6_optlen(struct inpcb *in6p)
{
int len;
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index e384da1..55bc5db 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -313,15 +313,16 @@ extern int ip6_auto_linklocal;
extern int ip6_use_tempaddr; /* whether to use temporary addresses. */
extern int ip6_prefer_tempaddr; /* whether to prefer temporary addresses
in the source address selection */
-#endif /* VIMAGE_GLOBALS */
+
+#ifdef IPSTEALTH
+extern int ip6stealth;
+#endif
extern int ip6_use_defzone; /* whether to use the default scope zone
when unspecified */
+#endif /* VIMAGE_GLOBALS */
extern struct pfil_head inet6_pfil_hook; /* packet filter hooks */
-#ifdef IPSTEALTH
-extern int ip6stealth;
-#endif
extern struct pr_usrreqs rip6_usrreqs;
struct sockopt;
@@ -397,7 +398,7 @@ struct in6_addr *in6_selectsrc __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ifnet **, int *));
int in6_selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *, struct ifnet **,
- struct rtentry **, int));
+ struct rtentry **));
u_int32_t ip6_randomid __P((void));
u_int32_t ip6_randomflowlabel __P((void));
#endif /* _KERNEL */
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 18e81c3..e2ca9eb 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -48,6 +48,8 @@ __FBSDID("$FreeBSD$");
#include <sys/protosw.h>
#include <sys/errno.h>
#include <sys/syslog.h>
+#include <sys/lock.h>
+#include <sys/rwlock.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
@@ -61,6 +63,8 @@ __FBSDID("$FreeBSD$");
#include <net/vnet.h>
#include <netinet/in.h>
+#include <net/if_llatbl.h>
+#define L3_ADDR_SIN6(le) ((struct sockaddr_in6 *) L3_ADDR(le))
#include <netinet/if_ether.h>
#include <netinet6/in6_var.h>
#include <netinet/ip6.h>
@@ -98,8 +102,9 @@ int nd6_maxqueuelen;
int nd6_debug;
/* for debugging? */
+#if 0
static int nd6_inuse, nd6_allocated;
-struct llinfo_nd6 llinfo_nd6;
+#endif
struct nd_drhead nd_defrouter;
struct nd_prhead nd_prefix;
@@ -114,9 +119,9 @@ static int nd6_is_new_addr_neighbor __P((struct sockaddr_in6 *,
static void nd6_setmtu0(struct ifnet *, struct nd_ifinfo *);
static void nd6_slowtimo(void *);
static int regen_tmpaddr(struct in6_ifaddr *);
-static struct llinfo_nd6 *nd6_free(struct rtentry *, int);
+static struct llentry *nd6_free(struct llentry *, int);
static void nd6_llinfo_timer(void *);
-static void clear_llinfo_pqueue(struct llinfo_nd6 *);
+static void clear_llinfo_pqueue(struct llentry *);
#ifdef VIMAGE_GLOBALS
struct callout nd6_slowtimo_ch;
@@ -162,8 +167,13 @@ nd6_init(void)
V_dad_ignore_ns = 0; /* ignore NS in DAD - specwise incorrect*/
V_dad_maxtry = 15; /* max # of *tries* to transmit DAD packet */
+ /*
+ * XXX just to get this to compile KMM
+ */
+#ifdef notyet
V_llinfo_nd6.ln_next = &V_llinfo_nd6;
V_llinfo_nd6.ln_prev = &V_llinfo_nd6;
+#endif
LIST_INIT(&V_nd_prefix);
V_ip6_use_tempaddr = 0;
@@ -424,14 +434,23 @@ skip1:
* ND6 timer routine to handle ND6 entries
*/
void
-nd6_llinfo_settimer(struct llinfo_nd6 *ln, long tick)
+nd6_llinfo_settimer_locked(struct llentry *ln, long tick)
{
if (tick < 0) {
- ln->ln_expire = 0;
+ ln->la_expire = 0;
ln->ln_ntick = 0;
callout_stop(&ln->ln_timer_ch);
+ /*
+ * XXX - do we know that there is
+ * callout installed? i.e. are we
+ * guaranteed that we're not dropping
+ * a reference that we did not add?
+ * KMM
+ */
+ LLE_REMREF(ln);
} else {
- ln->ln_expire = time_second + tick / hz;
+ ln->la_expire = time_second + tick / hz;
+ LLE_ADDREF(ln);
if (tick > INT_MAX) {
ln->ln_ntick = tick - INT_MAX;
callout_reset(&ln->ln_timer_ch, INT_MAX,
@@ -444,16 +463,34 @@ nd6_llinfo_settimer(struct llinfo_nd6 *ln, long tick)
}
}
+void
+nd6_llinfo_settimer(struct llentry *ln, long tick)
+{
+
+ LLE_WLOCK(ln);
+ nd6_llinfo_settimer_locked(ln, tick);
+ LLE_WUNLOCK(ln);
+}
+
static void
nd6_llinfo_timer(void *arg)
{
- struct llinfo_nd6 *ln;
- struct rtentry *rt;
+ struct llentry *ln;
struct in6_addr *dst;
struct ifnet *ifp;
struct nd_ifinfo *ndi = NULL;
- ln = (struct llinfo_nd6 *)arg;
+ ln = (struct llentry *)arg;
+ if (ln == NULL) {
+ panic("%s: NULL entry!\n", __func__);
+ return;
+ }
+
+ if ((ifp = ((ln->lle_tbl != NULL) ? ln->lle_tbl->llt_ifp : NULL)) == NULL)
+ panic("ln ifp == NULL");
+
+ CURVNET_SET(ifp->if_vnet);
+ INIT_VNET_INET6(curvnet);
if (ln->ln_ntick > 0) {
if (ln->ln_ntick > INT_MAX) {
@@ -463,52 +500,44 @@ nd6_llinfo_timer(void *arg)
ln->ln_ntick = 0;
nd6_llinfo_settimer(ln, ln->ln_ntick);
}
- return;
+ goto done;
}
- if ((rt = ln->ln_rt) == NULL)
- panic("ln->ln_rt == NULL");
- if ((ifp = rt->rt_ifp) == NULL)
- panic("ln->ln_rt->rt_ifp == NULL");
ndi = ND_IFINFO(ifp);
+ dst = &L3_ADDR_SIN6(ln)->sin6_addr;
+ if ((ln->la_flags & LLE_STATIC) || (ln->la_expire > time_second)) {
+ goto done;
+ }
- CURVNET_SET(ifp->if_vnet);
- INIT_VNET_INET6(curvnet);
-
- /* sanity check */
- if (rt->rt_llinfo && (struct llinfo_nd6 *)rt->rt_llinfo != ln)
- panic("rt_llinfo(%p) is not equal to ln(%p)",
- rt->rt_llinfo, ln);
- if (rt_key(rt) == NULL)
- panic("rt key is NULL in nd6_timer(ln=%p)", ln);
-
- dst = &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr;
+ if (ln->la_flags & LLE_DELETED) {
+ (void)nd6_free(ln, 0);
+ goto done;
+ }
switch (ln->ln_state) {
case ND6_LLINFO_INCOMPLETE:
- if (ln->ln_asked < V_nd6_mmaxtries) {
- ln->ln_asked++;
+ if (ln->la_asked < V_nd6_mmaxtries) {
+ ln->la_asked++;
nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
nd6_ns_output(ifp, NULL, dst, ln, 0);
} else {
- struct mbuf *m = ln->ln_hold;
+ struct mbuf *m = ln->la_hold;
if (m) {
struct mbuf *m0;
/*
- * assuming every packet in ln_hold has the
+ * assuming every packet in la_hold has the
* same IP header
*/
m0 = m->m_nextpkt;
m->m_nextpkt = NULL;
icmp6_error2(m, ICMP6_DST_UNREACH,
- ICMP6_DST_UNREACH_ADDR, 0, rt->rt_ifp);
+ ICMP6_DST_UNREACH_ADDR, 0, ifp);
- ln->ln_hold = m0;
+ ln->la_hold = m0;
clear_llinfo_pqueue(ln);
}
- if (rt && rt->rt_llinfo)
- (void)nd6_free(rt, 0);
+ (void)nd6_free(ln, 0);
ln = NULL;
}
break;
@@ -522,8 +551,7 @@ nd6_llinfo_timer(void *arg)
case ND6_LLINFO_STALE:
/* Garbage Collection(RFC 2461 5.3) */
if (!ND6_LLINFO_PERMANENT(ln)) {
- if (rt && rt->rt_llinfo)
- (void)nd6_free(rt, 1);
+ (void)nd6_free(ln, 1);
ln = NULL;
}
break;
@@ -531,7 +559,7 @@ nd6_llinfo_timer(void *arg)
case ND6_LLINFO_DELAY:
if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) {
/* We need NUD */
- ln->ln_asked = 1;
+ ln->la_asked = 1;
ln->ln_state = ND6_LLINFO_PROBE;
nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
nd6_ns_output(ifp, dst, dst, ln, 0);
@@ -541,31 +569,20 @@ nd6_llinfo_timer(void *arg)
}
break;
case ND6_LLINFO_PROBE:
- if (ln->ln_asked < V_nd6_umaxtries) {
- ln->ln_asked++;
+ if (ln->la_asked < V_nd6_umaxtries) {
+ ln->la_asked++;
nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
nd6_ns_output(ifp, dst, dst, ln, 0);
- } else if (rt->rt_ifa != NULL &&
- rt->rt_ifa->ifa_addr->sa_family == AF_INET6 &&
- (((struct in6_ifaddr *)rt->rt_ifa)->ia_flags & IFA_ROUTE)) {
- /*
- * This is an unreachable neighbor whose address is
- * specified as the destination of a p2p interface
- * (see in6_ifinit()). We should not free the entry
- * since this is sort of a "static" entry generated
- * via interface address configuration.
- */
- ln->ln_asked = 0;
- ln->ln_expire = 0; /* make it permanent */
- ln->ln_state = ND6_LLINFO_STALE;
} else {
- if (rt && rt->rt_llinfo)
- (void)nd6_free(rt, 0);
+ (void)nd6_free(ln, 0);
ln = NULL;
}
break;
}
CURVNET_RESTORE();
+done:
+ if (ln != NULL)
+ LLE_FREE(ln);
}
@@ -772,7 +789,6 @@ void
nd6_purge(struct ifnet *ifp)
{
INIT_VNET_INET6(ifp->if_vnet);
- struct llinfo_nd6 *ln, *nln;
struct nd_defrouter *dr, *ndr;
struct nd_prefix *pr, *npr;
@@ -829,132 +845,54 @@ nd6_purge(struct ifnet *ifp)
nd6_setdefaultiface(0);
if (!V_ip6_forwarding && V_ip6_accept_rtadv) { /* XXX: too restrictive? */
- /* refresh default router list */
+ /* refresh default router list
+ *
+ *
+ */
defrouter_select();
+
}
- /*
- * Nuke neighbor cache entries for the ifp.
- * Note that rt->rt_ifp may not be the same as ifp,
- * due to KAME goto ours hack. See RTM_RESOLVE case in
- * nd6_rtrequest(), and ip6_input().
+ /* XXXXX
+ * We do not nuke the neighbor cache entries here any more
+ * because the neighbor cache is kept in if_afdata[AF_INET6].
+ * nd6_purge() is invoked by in6_ifdetach() which is called
+ * from if_detach() where everything gets purged. So let
+ * in6_domifdetach() do the actual L2 table purging work.
*/
- ln = V_llinfo_nd6.ln_next;
- while (ln && ln != &V_llinfo_nd6) {
- struct rtentry *rt;
- struct sockaddr_dl *sdl;
-
- nln = ln->ln_next;
- rt = ln->ln_rt;
- if (rt && rt->rt_gateway &&
- rt->rt_gateway->sa_family == AF_LINK) {
- sdl = (struct sockaddr_dl *)rt->rt_gateway;
- if (sdl->sdl_index == ifp->if_index)
- nln = nd6_free(rt, 0);
- }
- ln = nln;
- }
}
-struct rtentry *
-nd6_lookup(struct in6_addr *addr6, int create, struct ifnet *ifp)
+/*
+ * the caller acquires and releases the lock on the lltbls
+ * Returns the llentry locked
+ */
+struct llentry *
+nd6_lookup(struct in6_addr *addr6, int flags, struct ifnet *ifp)
{
INIT_VNET_INET6(curvnet);
- struct rtentry *rt;
struct sockaddr_in6 sin6;
- char ip6buf[INET6_ADDRSTRLEN];
-
+ struct llentry *ln;
+ int llflags = 0;
+
bzero(&sin6, sizeof(sin6));
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = *addr6;
- rt = rtalloc1((struct sockaddr *)&sin6, create, 0UL);
- if (rt) {
- if ((rt->rt_flags & RTF_LLINFO) == 0 && create) {
- /*
- * This is the case for the default route.
- * If we want to create a neighbor cache for the
- * address, we should free the route for the
- * destination and allocate an interface route.
- */
- RTFREE_LOCKED(rt);
- rt = NULL;
- }
- }
- if (rt == NULL) {
- if (create && ifp) {
- int e;
- /*
- * If no route is available and create is set,
- * we allocate a host route for the destination
- * and treat it like an interface route.
- * This hack is necessary for a neighbor which can't
- * be covered by our own prefix.
- */
- struct ifaddr *ifa =
- ifaof_ifpforaddr((struct sockaddr *)&sin6, ifp);
- if (ifa == NULL)
- return (NULL);
+ IF_AFDATA_LOCK_ASSERT(ifp);
- /*
- * Create a new route. RTF_LLINFO is necessary
- * to create a Neighbor Cache entry for the
- * destination in nd6_rtrequest which will be
- * called in rtrequest via ifa->ifa_rtrequest.
- */
- if ((e = rtrequest(RTM_ADD, (struct sockaddr *)&sin6,
- ifa->ifa_addr, (struct sockaddr *)&all1_sa,
- (ifa->ifa_flags | RTF_HOST | RTF_LLINFO) &
- ~RTF_CLONING, &rt)) != 0) {
- log(LOG_ERR,
- "nd6_lookup: failed to add route for a "
- "neighbor(%s), errno=%d\n",
- ip6_sprintf(ip6buf, addr6), e);
- }
- if (rt == NULL)
- return (NULL);
- RT_LOCK(rt);
- if (rt->rt_llinfo) {
- struct llinfo_nd6 *ln =
- (struct llinfo_nd6 *)rt->rt_llinfo;
- ln->ln_state = ND6_LLINFO_NOSTATE;
- }
- } else
- return (NULL);
- }
- RT_LOCK_ASSERT(rt);
- RT_REMREF(rt);
- /*
- * Validation for the entry.
- * Note that the check for rt_llinfo is necessary because a cloned
- * route from a parent route that has the L flag (e.g. the default
- * route to a p2p interface) may have the flag, too, while the
- * destination is not actually a neighbor.
- * XXX: we can't use rt->rt_ifp to check for the interface, since
- * it might be the loopback interface if the entry is for our
- * own address on a non-loopback interface. Instead, we should
- * use rt->rt_ifa->ifa_ifp, which would specify the REAL
- * interface.
- * Note also that ifa_ifp and ifp may differ when we connect two
- * interfaces to a same link, install a link prefix to an interface,
- * and try to install a neighbor cache on an interface that does not
- * have a route to the prefix.
- */
- if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
- rt->rt_gateway->sa_family != AF_LINK || rt->rt_llinfo == NULL ||
- (ifp && rt->rt_ifa->ifa_ifp != ifp)) {
- if (create) {
- nd6log((LOG_DEBUG,
- "nd6_lookup: failed to lookup %s (if = %s)\n",
- ip6_sprintf(ip6buf, addr6),
- ifp ? if_name(ifp) : "unspec"));
- }
- RT_UNLOCK(rt);
- return (NULL);
+ if (flags & ND6_CREATE)
+ llflags |= LLE_CREATE;
+ if (flags & ND6_EXCLUSIVE)
+ llflags |= LLE_EXCLUSIVE;
+
+ ln = lla_lookup(LLTABLE6(ifp), llflags, (struct sockaddr *)&sin6);
+ if ((ln != NULL) && (flags & LLE_CREATE)) {
+ ln->ln_state = ND6_LLINFO_NOSTATE;
+ callout_init(&ln->ln_timer_ch, 0);
}
- RT_UNLOCK(rt); /* XXX not ready to return rt locked */
- return (rt);
+
+ return (ln);
}
/*
@@ -1040,7 +978,10 @@ nd6_is_new_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
int
nd6_is_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
{
+ struct llentry *lle;
+ int rc = 0;
+ IF_AFDATA_UNLOCK_ASSERT(ifp);
if (nd6_is_new_addr_neighbor(addr, ifp))
return (1);
@@ -1048,10 +989,13 @@ nd6_is_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
* Even if the address matches none of our addresses, it might be
* in the neighbor cache.
*/
- if (nd6_lookup(&addr->sin6_addr, 0, ifp) != NULL)
- return (1);
-
- return (0);
+ IF_AFDATA_LOCK(ifp);
+ if ((lle = nd6_lookup(&addr->sin6_addr, 0, ifp)) != NULL) {
+ LLE_RUNLOCK(lle);
+ rc = 1;
+ }
+ IF_AFDATA_UNLOCK(ifp);
+ return (rc);
}
/*
@@ -1060,13 +1004,13 @@ nd6_is_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
* make it global, unless you have a strong reason for the change, and are sure
* that the change is safe.
*/
-static struct llinfo_nd6 *
-nd6_free(struct rtentry *rt, int gc)
+static struct llentry *
+nd6_free(struct llentry *ln, int gc)
{
INIT_VNET_INET6(curvnet);
- struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo, *next;
- struct in6_addr in6 = ((struct sockaddr_in6 *)rt_key(rt))->sin6_addr;
+ struct llentry *next;
struct nd_defrouter *dr;
+ struct ifnet *ifp=NULL;
/*
* we used to have pfctlinput(PRC_HOSTDEAD) here.
@@ -1079,8 +1023,7 @@ nd6_free(struct rtentry *rt, int gc)
if (!V_ip6_forwarding) {
int s;
s = splnet();
- dr = defrouter_lookup(&((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
- rt->rt_ifp);
+ dr = defrouter_lookup(&L3_ADDR_SIN6(ln)->sin6_addr, ln->lle_tbl->llt_ifp);
if (dr != NULL && dr->expire &&
ln->ln_state == ND6_LLINFO_STALE && gc) {
@@ -1102,7 +1045,7 @@ nd6_free(struct rtentry *rt, int gc)
else
nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz);
splx(s);
- return (ln->ln_next);
+ return (LIST_NEXT(ln, lle_next));
}
if (ln->ln_router || dr) {
@@ -1111,7 +1054,7 @@ nd6_free(struct rtentry *rt, int gc)
* is in the Default Router List.
* See a corresponding comment in nd6_na_input().
*/
- rt6_flush(&in6, rt->rt_ifp);
+ rt6_flush(&L3_ADDR_SIN6(ln)->sin6_addr, ln->lle_tbl->llt_ifp);
}
if (dr) {
@@ -1152,15 +1095,13 @@ nd6_free(struct rtentry *rt, int gc)
* might have freed other entries (particularly the old next entry) as
* a side effect (XXX).
*/
- next = ln->ln_next;
+ next = LIST_NEXT(ln, lle_next);
- /*
- * Detach the route from the routing tree and the list of neighbor
- * caches, and disable the route entry not to be used in already
- * cached routes.
- */
- rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0,
- rt_mask(rt), 0, (struct rtentry **)0);
+ ifp = ln->lle_tbl->llt_ifp;
+ IF_AFDATA_LOCK(ifp);
+ LLE_WLOCK(ln);
+ llentry_free(ln);
+ IF_AFDATA_UNLOCK(ifp);
return (next);
}
@@ -1174,297 +1115,42 @@ void
nd6_nud_hint(struct rtentry *rt, struct in6_addr *dst6, int force)
{
INIT_VNET_INET6(curvnet);
- struct llinfo_nd6 *ln;
+ struct llentry *ln;
+ struct ifnet *ifp;
- /*
- * If the caller specified "rt", use that. Otherwise, resolve the
- * routing table by supplied "dst6".
- */
- if (rt == NULL) {
- if (dst6 == NULL)
- return;
- if ((rt = nd6_lookup(dst6, 0, NULL)) == NULL)
- return;
- }
-
- if ((rt->rt_flags & RTF_GATEWAY) != 0 ||
- (rt->rt_flags & RTF_LLINFO) == 0 ||
- rt->rt_llinfo == NULL || rt->rt_gateway == NULL ||
- rt->rt_gateway->sa_family != AF_LINK) {
- /* This is not a host route. */
+ if ((dst6 == NULL) || (rt == NULL))
return;
- }
- ln = (struct llinfo_nd6 *)rt->rt_llinfo;
- if (ln->ln_state < ND6_LLINFO_REACHABLE)
+ ifp = rt->rt_ifp;
+ IF_AFDATA_LOCK(ifp);
+ ln = nd6_lookup(dst6, ND6_EXCLUSIVE, NULL);
+ IF_AFDATA_UNLOCK(ifp);
+ if (ln == NULL)
return;
+ if (ln->ln_state < ND6_LLINFO_REACHABLE)
+ goto done;
+
/*
* if we get upper-layer reachability confirmation many times,
* it is possible we have false information.
*/
if (!force) {
ln->ln_byhint++;
- if (ln->ln_byhint > V_nd6_maxnudhint)
- return;
+ if (ln->ln_byhint > V_nd6_maxnudhint) {
+ goto done;
+ }
}
- ln->ln_state = ND6_LLINFO_REACHABLE;
+ ln->ln_state = ND6_LLINFO_REACHABLE;
if (!ND6_LLINFO_PERMANENT(ln)) {
nd6_llinfo_settimer(ln,
(long)ND_IFINFO(rt->rt_ifp)->reachable * hz);
}
+done:
+ LLE_WUNLOCK(ln);
}
-/*
- * info - XXX unused
- */
-void
-nd6_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
-{
- struct sockaddr *gate = rt->rt_gateway;
- struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo;
- static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
- struct ifnet *ifp = rt->rt_ifp;
- struct ifaddr *ifa;
- INIT_VNET_NET(ifp->if_vnet);
- INIT_VNET_INET6(ifp->if_vnet);
-
- RT_LOCK_ASSERT(rt);
-
- if ((rt->rt_flags & RTF_GATEWAY) != 0)
- return;
-
- if (nd6_need_cache(ifp) == 0 && (rt->rt_flags & RTF_HOST) == 0) {
- /*
- * This is probably an interface direct route for a link
- * which does not need neighbor caches (e.g. fe80::%lo0/64).
- * We do not need special treatment below for such a route.
- * Moreover, the RTF_LLINFO flag which would be set below
- * would annoy the ndp(8) command.
- */
- return;
- }
-
- if (req == RTM_RESOLVE &&
- (nd6_need_cache(ifp) == 0 || /* stf case */
- !nd6_is_new_addr_neighbor((struct sockaddr_in6 *)rt_key(rt),
- ifp))) {
- /*
- * FreeBSD and BSD/OS often make a cloned host route based
- * on a less-specific route (e.g. the default route).
- * If the less specific route does not have a "gateway"
- * (this is the case when the route just goes to a p2p or an
- * stf interface), we'll mistakenly make a neighbor cache for
- * the host route, and will see strange neighbor solicitation
- * for the corresponding destination. In order to avoid the
- * confusion, we check if the destination of the route is
- * a neighbor in terms of neighbor discovery, and stop the
- * process if not. Additionally, we remove the LLINFO flag
- * so that ndp(8) will not try to get the neighbor information
- * of the destination.
- */
- rt->rt_flags &= ~RTF_LLINFO;
- return;
- }
-
- switch (req) {
- case RTM_ADD:
- /*
- * There is no backward compatibility :)
- *
- * if ((rt->rt_flags & RTF_HOST) == 0 &&
- * SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
- * rt->rt_flags |= RTF_CLONING;
- */
- if ((rt->rt_flags & RTF_CLONING) ||
- ((rt->rt_flags & RTF_LLINFO) && ln == NULL)) {
- /*
- * Case 1: This route should come from a route to
- * interface (RTF_CLONING case) or the route should be
- * treated as on-link but is currently not
- * (RTF_LLINFO && ln == NULL case).
- */
- rt_setgate(rt, rt_key(rt),
- (struct sockaddr *)&null_sdl);
- gate = rt->rt_gateway;
- SDL(gate)->sdl_type = ifp->if_type;
- SDL(gate)->sdl_index = ifp->if_index;
- if (ln)
- nd6_llinfo_settimer(ln, 0);
- if ((rt->rt_flags & RTF_CLONING) != 0)
- break;
- }
- /*
- * In IPv4 code, we try to annonuce new RTF_ANNOUNCE entry here.
- * We don't do that here since llinfo is not ready yet.
- *
- * There are also couple of other things to be discussed:
- * - unsolicited NA code needs improvement beforehand
- * - RFC2461 says we MAY send multicast unsolicited NA
- * (7.2.6 paragraph 4), however, it also says that we
- * SHOULD provide a mechanism to prevent multicast NA storm.
- * we don't have anything like it right now.
- * note that the mechanism needs a mutual agreement
- * between proxies, which means that we need to implement
- * a new protocol, or a new kludge.
- * - from RFC2461 6.2.4, host MUST NOT send an unsolicited NA.
- * we need to check ip6forwarding before sending it.
- * (or should we allow proxy ND configuration only for
- * routers? there's no mention about proxy ND from hosts)
- */
- /* FALLTHROUGH */
- case RTM_RESOLVE:
- if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) {
- /*
- * Address resolution isn't necessary for a point to
- * point link, so we can skip this test for a p2p link.
- */
- if (gate->sa_family != AF_LINK ||
- gate->sa_len < sizeof(null_sdl)) {
- log(LOG_DEBUG,
- "nd6_rtrequest: bad gateway value: %s\n",
- if_name(ifp));
- break;
- }
- SDL(gate)->sdl_type = ifp->if_type;
- SDL(gate)->sdl_index = ifp->if_index;
- }
- if (ln != NULL)
- break; /* This happens on a route change */
- /*
- * Case 2: This route may come from cloning, or a manual route
- * add with a LL address.
- */
- R_Malloc(ln, struct llinfo_nd6 *, sizeof(*ln));
- rt->rt_llinfo = (caddr_t)ln;
- if (ln == NULL) {
- log(LOG_DEBUG, "nd6_rtrequest: malloc failed\n");
- break;
- }
- V_nd6_inuse++;
- V_nd6_allocated++;
- bzero(ln, sizeof(*ln));
- RT_ADDREF(rt);
- ln->ln_rt = rt;
- callout_init(&ln->ln_timer_ch, 0);
-
- /* this is required for "ndp" command. - shin */
- if (req == RTM_ADD) {
- /*
- * gate should have some valid AF_LINK entry,
- * and ln->ln_expire should have some lifetime
- * which is specified by ndp command.
- */
- ln->ln_state = ND6_LLINFO_REACHABLE;
- ln->ln_byhint = 0;
- } else {
- /*
- * When req == RTM_RESOLVE, rt is created and
- * initialized in rtrequest(), so rt_expire is 0.
- */
- ln->ln_state = ND6_LLINFO_NOSTATE;
- nd6_llinfo_settimer(ln, 0);
- }
- rt->rt_flags |= RTF_LLINFO;
- ln->ln_next = V_llinfo_nd6.ln_next;
- V_llinfo_nd6.ln_next = ln;
- ln->ln_prev = &V_llinfo_nd6;
- ln->ln_next->ln_prev = ln;
-
- /*
- * check if rt_key(rt) is one of my address assigned
- * to the interface.
- */
- ifa = (struct ifaddr *)in6ifa_ifpwithaddr(rt->rt_ifp,
- &SIN6(rt_key(rt))->sin6_addr);
- if (ifa) {
- caddr_t macp = nd6_ifptomac(ifp);
- nd6_llinfo_settimer(ln, -1);
- ln->ln_state = ND6_LLINFO_REACHABLE;
- ln->ln_byhint = 0;
- if (macp) {
- bcopy(macp, LLADDR(SDL(gate)), ifp->if_addrlen);
- SDL(gate)->sdl_alen = ifp->if_addrlen;
- }
- if (V_nd6_useloopback) {
- rt->rt_ifp = &V_loif[0]; /* XXX */
- /*
- * Make sure rt_ifa be equal to the ifaddr
- * corresponding to the address.
- * We need this because when we refer
- * rt_ifa->ia6_flags in ip6_input, we assume
- * that the rt_ifa points to the address instead
- * of the loopback address.
- */
- if (ifa != rt->rt_ifa) {
- IFAFREE(rt->rt_ifa);
- IFAREF(ifa);
- rt->rt_ifa = ifa;
- }
- }
- } else if (rt->rt_flags & RTF_ANNOUNCE) {
- nd6_llinfo_settimer(ln, -1);
- ln->ln_state = ND6_LLINFO_REACHABLE;
- ln->ln_byhint = 0;
-
- /* join solicited node multicast for proxy ND */
- if (ifp->if_flags & IFF_MULTICAST) {
- struct in6_addr llsol;
- int error;
-
- llsol = SIN6(rt_key(rt))->sin6_addr;
- llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
- llsol.s6_addr32[1] = 0;
- llsol.s6_addr32[2] = htonl(1);
- llsol.s6_addr8[12] = 0xff;
- if (in6_setscope(&llsol, ifp, NULL))
- break;
- if (in6_addmulti(&llsol, ifp,
- &error, 0) == NULL) {
- char ip6buf[INET6_ADDRSTRLEN];
- nd6log((LOG_ERR, "%s: failed to join "
- "%s (errno=%d)\n", if_name(ifp),
- ip6_sprintf(ip6buf, &llsol),
- error));
- }
- }
- }
- break;
-
- case RTM_DELETE:
- if (ln == NULL)
- break;
- /* leave from solicited node multicast for proxy ND */
- if ((rt->rt_flags & RTF_ANNOUNCE) != 0 &&
- (ifp->if_flags & IFF_MULTICAST) != 0) {
- struct in6_addr llsol;
- struct in6_multi *in6m;
-
- llsol = SIN6(rt_key(rt))->sin6_addr;
- llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
- llsol.s6_addr32[1] = 0;
- llsol.s6_addr32[2] = htonl(1);
- llsol.s6_addr8[12] = 0xff;
- if (in6_setscope(&llsol, ifp, NULL) == 0) {
- IN6_LOOKUP_MULTI(llsol, ifp, in6m);
- if (in6m)
- in6_delmulti(in6m);
- } else
- ; /* XXX: should not happen. bark here? */
- }
- V_nd6_inuse--;
- ln->ln_next->ln_prev = ln->ln_prev;
- ln->ln_prev->ln_next = ln->ln_next;
- ln->ln_prev = NULL;
- nd6_llinfo_settimer(ln, -1);
- RT_REMREF(rt);
- rt->rt_llinfo = 0;
- rt->rt_flags &= ~RTF_LLINFO;
- clear_llinfo_pqueue(ln);
- Free((caddr_t)ln);
- }
-}
int
nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
@@ -1477,7 +1163,6 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
struct in6_ndifreq *ndif = (struct in6_ndifreq *)data;
struct nd_defrouter *dr;
struct nd_prefix *pr;
- struct rtentry *rt;
int i = 0, error = 0;
int s;
@@ -1667,25 +1352,25 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
}
case SIOCGNBRINFO_IN6:
{
- struct llinfo_nd6 *ln;
+ struct llentry *ln;
struct in6_addr nb_addr = nbi->addr; /* make local for safety */
if ((error = in6_setscope(&nb_addr, ifp, NULL)) != 0)
return (error);
- s = splnet();
- if ((rt = nd6_lookup(&nb_addr, 0, ifp)) == NULL) {
+ IF_AFDATA_LOCK(ifp);
+ ln = nd6_lookup(&nb_addr, 0, ifp);
+ IF_AFDATA_UNLOCK(ifp);
+
+ if (ln == NULL) {
error = EINVAL;
- splx(s);
break;
}
- ln = (struct llinfo_nd6 *)rt->rt_llinfo;
nbi->state = ln->ln_state;
- nbi->asked = ln->ln_asked;
+ nbi->asked = ln->la_asked;
nbi->isrouter = ln->ln_router;
- nbi->expire = ln->ln_expire;
- splx(s);
-
+ nbi->expire = ln->la_expire;
+ LLE_RUNLOCK(ln);
break;
}
case SIOCGDEFIFACE_IN6: /* XXX: should be implemented as a sysctl? */
@@ -1703,20 +1388,29 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
*
* type - ICMP6 type
* code - type dependent information
+ *
+ * XXXXX
+ * The caller of this function already acquired the ndp
+ * cache table lock because the cache entry is returned.
*/
-struct rtentry *
+struct llentry *
nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
int lladdrlen, int type, int code)
{
INIT_VNET_INET6(curvnet);
- struct rtentry *rt = NULL;
- struct llinfo_nd6 *ln = NULL;
+ struct llentry *ln = NULL;
int is_newentry;
- struct sockaddr_dl *sdl = NULL;
int do_update;
int olladdr;
int llchange;
+ int flags = 0;
int newstate = 0;
+ uint16_t router = 0;
+ struct sockaddr_in6 sin6;
+ struct mbuf *chain = NULL;
+ int static_route = 0;
+
+ IF_AFDATA_UNLOCK_ASSERT(ifp);
if (ifp == NULL)
panic("ifp == NULL in nd6_cache_lladdr");
@@ -1736,40 +1430,31 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
* Spec says nothing in sections for RA, RS and NA. There's small
* description on it in NS section (RFC 2461 7.2.3).
*/
-
- rt = nd6_lookup(from, 0, ifp);
- if (rt == NULL) {
- rt = nd6_lookup(from, 1, ifp);
+ flags |= lladdr ? ND6_EXCLUSIVE : 0;
+ IF_AFDATA_LOCK(ifp);
+ ln = nd6_lookup(from, flags, ifp);
+
+ if (ln == NULL) {
+ flags |= LLE_EXCLUSIVE;
+ ln = nd6_lookup(from, flags |ND6_CREATE, ifp);
+ IF_AFDATA_UNLOCK(ifp);
is_newentry = 1;
} else {
+ IF_AFDATA_UNLOCK(ifp);
/* do nothing if static ndp is set */
- if (rt->rt_flags & RTF_STATIC)
- return NULL;
+ if (ln->la_flags & LLE_STATIC) {
+ static_route = 1;
+ goto done;
+ }
is_newentry = 0;
}
-
- if (rt == NULL)
- return NULL;
- if ((rt->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) != RTF_LLINFO) {
-fail:
- (void)nd6_free(rt, 0);
- return NULL;
- }
- ln = (struct llinfo_nd6 *)rt->rt_llinfo;
if (ln == NULL)
- goto fail;
- if (rt->rt_gateway == NULL)
- goto fail;
- if (rt->rt_gateway->sa_family != AF_LINK)
- goto fail;
- sdl = SDL(rt->rt_gateway);
-
- olladdr = (sdl->sdl_alen) ? 1 : 0;
+ return (NULL);
+
+ olladdr = (ln->la_flags & LLE_VALID) ? 1 : 0;
if (olladdr && lladdr) {
- if (bcmp(lladdr, LLADDR(sdl), ifp->if_addrlen))
- llchange = 1;
- else
- llchange = 0;
+ llchange = bcmp(lladdr, &ln->ll_addr,
+ ifp->if_addrlen);
} else
llchange = 0;
@@ -1789,8 +1474,8 @@ fail:
* Record source link-layer address
* XXX is it dependent to ifp->if_type?
*/
- sdl->sdl_alen = ifp->if_addrlen;
- bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
+ bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
+ ln->la_flags |= LLE_VALID;
}
if (!is_newentry) {
@@ -1821,17 +1506,17 @@ fail:
* we must set the timer now, although it is actually
* meaningless.
*/
- nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz);
+ nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
- if (ln->ln_hold) {
+ if (ln->la_hold) {
struct mbuf *m_hold, *m_hold_next;
/*
- * reset the ln_hold in advance, to explicitly
- * prevent a ln_hold lookup in nd6_output()
+ * reset the la_hold in advance, to explicitly
+ * prevent a la_hold lookup in nd6_output()
* (wouldn't happen, though...)
*/
- for (m_hold = ln->ln_hold, ln->ln_hold = NULL;
+ for (m_hold = ln->la_hold, ln->la_hold = NULL;
m_hold; m_hold = m_hold_next) {
m_hold_next = m_hold->m_nextpkt;
m_hold->m_nextpkt = NULL;
@@ -1841,14 +1526,19 @@ fail:
* just set the 2nd argument as the
* 1st one.
*/
- nd6_output(ifp, ifp, m_hold,
- (struct sockaddr_in6 *)rt_key(rt),
- rt);
+ nd6_output_lle(ifp, ifp, m_hold, L3_ADDR_SIN6(ln), NULL, ln, &chain);
}
+ /*
+ * If we have mbufs in the chain we need to do
+ * deferred transmit. Copy the address from the
+ * llentry before dropping the lock down below.
+ */
+ if (chain != NULL)
+ memcpy(&sin6, L3_ADDR_SIN6(ln), sizeof(sin6));
}
} else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
/* probe right away */
- nd6_llinfo_settimer((void *)ln, 0);
+ nd6_llinfo_settimer_locked((void *)ln, 0);
}
}
@@ -1917,6 +1607,20 @@ fail:
break;
}
+ if (ln != NULL) {
+ static_route = (ln->la_flags & LLE_STATIC);
+ router = ln->ln_router;
+
+ if (flags & ND6_EXCLUSIVE)
+ LLE_WUNLOCK(ln);
+ else
+ LLE_RUNLOCK(ln);
+ if (static_route)
+ ln = NULL;
+ }
+ if (chain)
+ nd6_output_flush(ifp, ifp, chain, &sin6, NULL);
+
/*
* When the link-layer address of a router changes, select the
* best router again. In particular, when the neighbor entry is newly
@@ -1932,10 +1636,24 @@ fail:
* for those are not autoconfigured hosts, we explicitly avoid such
* cases for safety.
*/
- if (do_update && ln->ln_router && !V_ip6_forwarding && V_ip6_accept_rtadv)
+ if (do_update && router && !V_ip6_forwarding && V_ip6_accept_rtadv) {
+ /*
+ * guaranteed recursion
+ */
defrouter_select();
-
- return rt;
+ }
+
+ return (ln);
+done:
+ if (ln != NULL) {
+ if (flags & ND6_EXCLUSIVE)
+ LLE_WUNLOCK(ln);
+ else
+ LLE_RUNLOCK(ln);
+ if (static_route)
+ ln = NULL;
+ }
+ return (ln);
}
static void
@@ -1969,18 +1687,44 @@ nd6_slowtimo(void *arg)
CURVNET_RESTORE();
}
-#define senderr(e) { error = (e); goto bad;}
int
nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m0,
struct sockaddr_in6 *dst, struct rtentry *rt0)
{
+
+ return (nd6_output_lle(ifp, origifp, m0, dst, rt0, NULL, NULL));
+}
+
+
+/*
+ * Note that I'm not enforcing any global serialization
+ * lle state or asked changes here as the logic is too
+ * complicated to avoid having to always acquire an exclusive
+ * lock
+ * KMM
+ *
+ */
+#define senderr(e) { error = (e); goto bad;}
+
+int
+nd6_output_lle(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m0,
+ struct sockaddr_in6 *dst, struct rtentry *rt0, struct llentry *lle,
+ struct mbuf **chain)
+{
INIT_VNET_INET6(curvnet);
struct mbuf *m = m0;
- struct rtentry *rt = rt0;
- struct sockaddr_in6 *gw6 = NULL;
- struct llinfo_nd6 *ln = NULL;
+ struct llentry *ln = lle;
int error = 0;
+ int flags = 0;
+#ifdef INVARIANTS
+ if (lle != NULL) {
+
+ LLE_WLOCK_ASSERT(lle);
+
+ KASSERT(chain != NULL, (" lle locked but no mbuf chain pointer passed"));
+ }
+#endif
if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
goto sendpkt;
@@ -1990,81 +1734,6 @@ nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m0,
/*
* next hop determination. This routine is derived from ether_output.
*/
- /* NB: the locking here is tortuous... */
- if (rt != NULL)
- RT_LOCK(rt);
-again:
- if (rt != NULL) {
- if ((rt->rt_flags & RTF_UP) == 0) {
- RT_UNLOCK(rt);
- rt0 = rt = rtalloc1((struct sockaddr *)dst, 1, 0UL);
- if (rt != NULL) {
- RT_REMREF(rt);
- if (rt->rt_ifp != ifp)
- /*
- * XXX maybe we should update ifp too,
- * but the original code didn't and I
- * don't know what is correct here.
- */
- goto again;
- } else
- senderr(EHOSTUNREACH);
- }
-
- if (rt->rt_flags & RTF_GATEWAY) {
- gw6 = (struct sockaddr_in6 *)rt->rt_gateway;
-
- /*
- * We skip link-layer address resolution and NUD
- * if the gateway is not a neighbor from ND point
- * of view, regardless of the value of nd_ifinfo.flags.
- * The second condition is a bit tricky; we skip
- * if the gateway is our own address, which is
- * sometimes used to install a route to a p2p link.
- */
- if (!nd6_is_addr_neighbor(gw6, ifp) ||
- in6ifa_ifpwithaddr(ifp, &gw6->sin6_addr)) {
- RT_UNLOCK(rt);
- /*
- * We allow this kind of tricky route only
- * when the outgoing interface is p2p.
- * XXX: we may need a more generic rule here.
- */
- if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
- senderr(EHOSTUNREACH);
-
- goto sendpkt;
- }
-
- if (rt->rt_gwroute == NULL)
- goto lookup;
- rt = rt->rt_gwroute;
- RT_LOCK(rt); /* NB: gwroute */
- if ((rt->rt_flags & RTF_UP) == 0) {
- RTFREE_LOCKED(rt); /* unlock gwroute */
- rt = rt0;
- rt0->rt_gwroute = NULL;
- lookup:
- RT_UNLOCK(rt0);
- rt = rtalloc1(rt->rt_gateway, 1, 0UL);
- if (rt == rt0) {
- RT_REMREF(rt0);
- RT_UNLOCK(rt0);
- senderr(EHOSTUNREACH);
- }
- RT_LOCK(rt0);
- if (rt0->rt_gwroute != NULL)
- RTFREE(rt0->rt_gwroute);
- rt0->rt_gwroute = rt;
- if (rt == NULL) {
- RT_UNLOCK(rt0);
- senderr(EHOSTUNREACH);
- }
- }
- RT_UNLOCK(rt0);
- }
- RT_UNLOCK(rt);
- }
/*
* Address resolution or Neighbor Unreachability Detection
@@ -2073,38 +1742,46 @@ again:
* or an anycast address(i.e. not a multicast).
*/
- /* Look up the neighbor cache for the nexthop */
- if (rt && (rt->rt_flags & RTF_LLINFO) != 0)
- ln = (struct llinfo_nd6 *)rt->rt_llinfo;
- else {
- /*
- * Since nd6_is_addr_neighbor() internally calls nd6_lookup(),
- * the condition below is not very efficient. But we believe
- * it is tolerable, because this should be a rare case.
- */
- if (nd6_is_addr_neighbor(dst, ifp) &&
- (rt = nd6_lookup(&dst->sin6_addr, 1, ifp)) != NULL)
- ln = (struct llinfo_nd6 *)rt->rt_llinfo;
- }
- if (ln == NULL || rt == NULL) {
+ flags = ((m != NULL) || (lle != NULL)) ? LLE_EXCLUSIVE : 0;
+ if (ln == NULL) {
+ retry:
+ IF_AFDATA_LOCK(ifp);
+ ln = lla_lookup(LLTABLE6(ifp), flags, (struct sockaddr *)dst);
+ IF_AFDATA_UNLOCK(ifp);
+ if ((ln == NULL) && nd6_is_addr_neighbor(dst, ifp)) {
+ /*
+ * Since nd6_is_addr_neighbor() internally calls nd6_lookup(),
+ * the condition below is not very efficient. But we believe
+ * it is tolerable, because this should be a rare case.
+ */
+ flags = ND6_CREATE | (m ? ND6_EXCLUSIVE : 0);
+ IF_AFDATA_LOCK(ifp);
+ ln = nd6_lookup(&dst->sin6_addr, flags, ifp);
+ IF_AFDATA_UNLOCK(ifp);
+ }
+ }
+ if (ln == NULL) {
if ((ifp->if_flags & IFF_POINTOPOINT) == 0 &&
!(ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD)) {
char ip6buf[INET6_ADDRSTRLEN];
log(LOG_DEBUG,
"nd6_output: can't allocate llinfo for %s "
- "(ln=%p, rt=%p)\n",
- ip6_sprintf(ip6buf, &dst->sin6_addr), ln, rt);
+ "(ln=%p)\n",
+ ip6_sprintf(ip6buf, &dst->sin6_addr), ln);
senderr(EIO); /* XXX: good error? */
}
-
goto sendpkt; /* send anyway */
}
/* We don't have to do link-layer address resolution on a p2p link. */
if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
ln->ln_state < ND6_LLINFO_REACHABLE) {
+ if ((flags & LLE_EXCLUSIVE) == 0) {
+ flags |= LLE_EXCLUSIVE;
+ goto retry;
+ }
ln->ln_state = ND6_LLINFO_STALE;
- nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz);
+ nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
}
/*
@@ -2115,9 +1792,14 @@ again:
* (RFC 2461 7.3.3)
*/
if (ln->ln_state == ND6_LLINFO_STALE) {
- ln->ln_asked = 0;
+ if ((flags & LLE_EXCLUSIVE) == 0) {
+ flags |= LLE_EXCLUSIVE;
+ LLE_RUNLOCK(ln);
+ goto retry;
+ }
+ ln->la_asked = 0;
ln->ln_state = ND6_LLINFO_DELAY;
- nd6_llinfo_settimer(ln, (long)V_nd6_delay * hz);
+ nd6_llinfo_settimer_locked(ln, (long)V_nd6_delay * hz);
}
/*
@@ -2137,12 +1819,18 @@ again:
*/
if (ln->ln_state == ND6_LLINFO_NOSTATE)
ln->ln_state = ND6_LLINFO_INCOMPLETE;
- if (ln->ln_hold) {
+
+ if ((flags & LLE_EXCLUSIVE) == 0) {
+ flags |= LLE_EXCLUSIVE;
+ LLE_RUNLOCK(ln);
+ goto retry;
+ }
+ if (ln->la_hold) {
struct mbuf *m_hold;
int i;
-
+
i = 0;
- for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold->m_nextpkt) {
+ for (m_hold = ln->la_hold; m_hold; m_hold = m_hold->m_nextpkt) {
i++;
if (m_hold->m_nextpkt == NULL) {
m_hold->m_nextpkt = m;
@@ -2150,21 +1838,32 @@ again:
}
}
while (i >= V_nd6_maxqueuelen) {
- m_hold = ln->ln_hold;
- ln->ln_hold = ln->ln_hold->m_nextpkt;
+ m_hold = ln->la_hold;
+ ln->la_hold = ln->la_hold->m_nextpkt;
m_freem(m_hold);
i--;
}
} else {
- ln->ln_hold = m;
+ ln->la_hold = m;
}
-
+ /*
+ * We did the lookup (no lle arg) so we
+ * need to do the unlock here
+ */
+ if (lle == NULL) {
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WUNLOCK(ln);
+ else
+ LLE_RUNLOCK(ln);
+ }
+
/*
* If there has been no NS for the neighbor after entering the
* INCOMPLETE state, send the first solicitation.
*/
- if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) {
- ln->ln_asked++;
+ if (!ND6_LLINFO_PERMANENT(ln) && ln->la_asked == 0) {
+ ln->la_asked++;
+
nd6_llinfo_settimer(ln,
(long)ND_IFINFO(ifp)->retrans * hz / 1000);
nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
@@ -2177,23 +1876,97 @@ again:
error = ENETDOWN; /* better error? */
goto bad;
}
+ /*
+ * ln is valid and the caller did not pass in
+ * an llentry
+ */
+ if ((ln != NULL) && (lle == NULL)) {
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WUNLOCK(ln);
+ else
+ LLE_RUNLOCK(ln);
+ }
#ifdef MAC
mac_netinet6_nd6_send(ifp, m);
#endif
+ /*
+ * We were passed in a pointer to an lle with the lock held
+ * this means that we can't call if_output as we will
+ * recurse on the lle lock - so what we do is we create
+ * a list of mbufs to send and transmit them in the caller
+ * after the lock is dropped
+ */
+ if (lle != NULL) {
+ if (*chain == NULL)
+ *chain = m;
+ else {
+ struct mbuf *m = *chain;
+
+ /*
+ * append mbuf to end of deferred chain
+ */
+ while (m->m_nextpkt != NULL)
+ m = m->m_nextpkt;
+ m->m_nextpkt = m;
+ }
+ return (error);
+ }
if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
return ((*ifp->if_output)(origifp, m, (struct sockaddr *)dst,
- rt));
+ NULL));
}
- return ((*ifp->if_output)(ifp, m, (struct sockaddr *)dst, rt));
+ error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, NULL);
+ return (error);
bad:
+ /*
+ * ln is valid and the caller did not pass in
+ * an llentry
+ */
+ if ((ln != NULL) && (lle == NULL)) {
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WUNLOCK(ln);
+ else
+ LLE_RUNLOCK(ln);
+ }
if (m)
m_freem(m);
return (error);
}
#undef senderr
+
+int
+nd6_output_flush(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *chain,
+ struct sockaddr_in6 *dst, struct rtentry *rt)
+{
+ struct mbuf *m, *m_head;
+ struct ifnet *outifp;
+ int error = 0;
+
+ m_head = chain;
+ if ((ifp->if_flags & IFF_LOOPBACK) != 0)
+ outifp = origifp;
+ else
+ outifp = ifp;
+
+ while (m_head) {
+ m = m_head;
+ m_head = m_head->m_nextpkt;
+ error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, rt);
+ }
+
+ /*
+ * XXX
+ * note that intermediate errors are blindly ignored - but this is
+ * the same convention as used with nd6_output when called by
+ * nd6_cache_lladdr
+ */
+ return (error);
+}
+
+
int
nd6_need_cache(struct ifnet *ifp)
{
@@ -2229,14 +2002,18 @@ nd6_need_cache(struct ifnet *ifp)
}
}
+/*
+ * the callers of this function need to be re-worked to drop
+ * the lle lock, drop here for now
+ */
int
-nd6_storelladdr(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
- struct sockaddr *dst, u_char *desten)
+nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
+ struct sockaddr *dst, u_char *desten, struct llentry **lle)
{
- struct sockaddr_dl *sdl;
- struct rtentry *rt;
- int error;
+ struct llentry *ln;
+ *lle = NULL;
+ IF_AFDATA_UNLOCK_ASSERT(ifp);
if (m->m_flags & M_MCAST) {
int i;
@@ -2271,48 +2048,42 @@ nd6_storelladdr(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
}
}
- if (rt0 == NULL) {
- /* this could happen, if we could not allocate memory */
- m_freem(m);
- return (ENOMEM);
- }
-
- error = rt_check(&rt, &rt0, dst);
- if (error) {
- m_freem(m);
- return (error);
- }
- RT_UNLOCK(rt);
- if (rt->rt_gateway->sa_family != AF_LINK) {
- printf("nd6_storelladdr: something odd happens\n");
- m_freem(m);
- return (EINVAL);
- }
- sdl = SDL(rt->rt_gateway);
- if (sdl->sdl_alen == 0) {
- /* this should be impossible, but we bark here for debugging */
- printf("nd6_storelladdr: sdl_alen == 0\n");
+ /*
+ * the entry should have been created in nd6_store_lladdr
+ */
+ IF_AFDATA_LOCK(ifp);
+ ln = lla_lookup(LLTABLE6(ifp), 0, dst);
+ IF_AFDATA_UNLOCK(ifp);
+ if ((ln == NULL) || !(ln->la_flags & LLE_VALID)) {
+ if (ln != NULL)
+ LLE_RUNLOCK(ln);
+ /* this could happen, if we could not allocate memory */
m_freem(m);
- return (EINVAL);
+ return (1);
}
- bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
+ bcopy(&ln->ll_addr, desten, ifp->if_addrlen);
+ *lle = ln;
+ LLE_RUNLOCK(ln);
+ /*
+ * A *small* use after free race exists here
+ */
return (0);
}
-static void
-clear_llinfo_pqueue(struct llinfo_nd6 *ln)
+static void
+clear_llinfo_pqueue(struct llentry *ln)
{
struct mbuf *m_hold, *m_hold_next;
- for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold_next) {
+ for (m_hold = ln->la_hold; m_hold; m_hold = m_hold_next) {
m_hold_next = m_hold->m_nextpkt;
m_hold->m_nextpkt = NULL;
m_freem(m_hold);
}
- ln->ln_hold = NULL;
+ ln->la_hold = NULL;
return;
}
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index 4d3c06b..e2007f7 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -41,20 +41,7 @@
#include <sys/queue.h>
#include <sys/callout.h>
-struct llinfo_nd6 {
- struct llinfo_nd6 *ln_next;
- struct llinfo_nd6 *ln_prev;
- struct rtentry *ln_rt;
- struct mbuf *ln_hold; /* last packet until resolved/timeout */
- long ln_asked; /* number of queries already sent for this addr */
- u_long ln_expire; /* lifetime for NDP state transition */
- short ln_state; /* reachability state */
- short ln_router; /* 2^0: ND6 router bit */
- int ln_byhint; /* # of times we made it reachable by UL hint */
-
- long ln_ntick;
- struct callout ln_timer_ch;
-};
+struct llentry;
#define ND6_LLINFO_NOSTATE -2
/*
@@ -72,7 +59,7 @@ struct llinfo_nd6 {
#define ND6_LLINFO_PROBE 4
#define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE)
-#define ND6_LLINFO_PERMANENT(n) (((n)->ln_expire == 0) && ((n)->ln_state > ND6_LLINFO_INCOMPLETE))
+#define ND6_LLINFO_PERMANENT(n) (((n)->la_expire == 0) && ((n)->ln_state > ND6_LLINFO_INCOMPLETE))
struct nd_ifinfo {
u_int32_t linkmtu; /* LinkMTU */
@@ -98,6 +85,9 @@ struct nd_ifinfo {
*/
#define ND6_IFF_DONT_SET_IFROUTE 0x10
+#define ND6_CREATE LLE_CREATE
+#define ND6_EXCLUSIVE LLE_EXCLUSIVE
+
#ifdef _KERNEL
#define ND_IFINFO(ifp) \
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->nd_ifinfo)
@@ -336,7 +326,6 @@ extern int nd6_mmaxtries;
extern int nd6_useloopback;
extern int nd6_maxnudhint;
extern int nd6_gctimer;
-extern struct llinfo_nd6 llinfo_nd6;
extern struct nd_drhead nd_defrouter;
extern struct nd_prhead nd_prefix;
extern int nd6_debug;
@@ -388,23 +377,28 @@ int nd6_is_addr_neighbor __P((struct sockaddr_in6 *, struct ifnet *));
void nd6_option_init __P((void *, int, union nd_opts *));
struct nd_opt_hdr *nd6_option __P((union nd_opts *));
int nd6_options __P((union nd_opts *));
-struct rtentry *nd6_lookup __P((struct in6_addr *, int, struct ifnet *));
+struct llentry *nd6_lookup __P((struct in6_addr *, int, struct ifnet *));
void nd6_setmtu __P((struct ifnet *));
-void nd6_llinfo_settimer __P((struct llinfo_nd6 *, long));
+void nd6_llinfo_settimer __P((struct llentry *, long));
+void nd6_llinfo_settimer_locked __P((struct llentry *, long));
void nd6_timer __P((void *));
void nd6_purge __P((struct ifnet *));
void nd6_nud_hint __P((struct rtentry *, struct in6_addr *, int));
int nd6_resolve __P((struct ifnet *, struct rtentry *, struct mbuf *,
struct sockaddr *, u_char *));
-void nd6_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *));
int nd6_ioctl __P((u_long, caddr_t, struct ifnet *));
-struct rtentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
+struct llentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
char *, int, int, int));
int nd6_output __P((struct ifnet *, struct ifnet *, struct mbuf *,
struct sockaddr_in6 *, struct rtentry *));
+int nd6_output_lle __P((struct ifnet *, struct ifnet *, struct mbuf *,
+ struct sockaddr_in6 *, struct rtentry *, struct llentry *,
+ struct mbuf **));
+int nd6_output_flush __P((struct ifnet *, struct ifnet *, struct mbuf *,
+ struct sockaddr_in6 *, struct rtentry *));
int nd6_need_cache __P((struct ifnet *));
-int nd6_storelladdr __P((struct ifnet *, struct rtentry *, struct mbuf *,
- struct sockaddr *, u_char *));
+int nd6_storelladdr __P((struct ifnet *, struct mbuf *,
+ struct sockaddr *, u_char *, struct llentry **));
/* nd6_nbr.c */
void nd6_na_input __P((struct mbuf *, int, int));
@@ -412,7 +406,7 @@ void nd6_na_output __P((struct ifnet *, const struct in6_addr *,
const struct in6_addr *, u_long, int, struct sockaddr *));
void nd6_ns_input __P((struct mbuf *, int, int));
void nd6_ns_output __P((struct ifnet *, const struct in6_addr *,
- const struct in6_addr *, struct llinfo_nd6 *, int));
+ const struct in6_addr *, struct llentry *, int));
caddr_t nd6_ifptomac __P((struct ifnet *));
void nd6_dad_start __P((struct ifaddr *, int));
void nd6_dad_stop __P((struct ifaddr *));
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index ecfad0e..c1cb423 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/rwlock.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
@@ -63,6 +65,8 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_var.h>
+#include <net/if_llatbl.h>
+#define L3_ADDR_SIN6(le) ((struct sockaddr_in6 *) L3_ADDR(le))
#include <netinet6/in6_var.h>
#include <netinet6/in6_ifattach.h>
#include <netinet/ip6.h>
@@ -167,7 +171,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
src_sa6.sin6_family = AF_INET6;
src_sa6.sin6_len = sizeof(src_sa6);
src_sa6.sin6_addr = saddr6;
- if (!nd6_is_addr_neighbor(&src_sa6, ifp)) {
+ if (nd6_is_addr_neighbor(&src_sa6, ifp) == 0) {
nd6log((LOG_INFO, "nd6_ns_input: "
"NS packet from non-neighbor\n"));
goto bad;
@@ -378,8 +382,8 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
* dad - duplicate address detection
*/
void
-nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
- const struct in6_addr *taddr6, struct llinfo_nd6 *ln, int dad)
+nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
+ const struct in6_addr *taddr6, struct llentry *ln, int dad)
{
INIT_VNET_INET6(ifp->if_vnet);
struct mbuf *m;
@@ -470,14 +474,14 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
struct ip6_hdr *hip6; /* hold ip6 */
struct in6_addr *hsrc = NULL;
- if (ln && ln->ln_hold) {
+ if ((ln != NULL) && ln->la_hold) {
/*
- * assuming every packet in ln_hold has the same IP
+ * assuming every packet in la_hold has the same IP
* header
*/
- hip6 = mtod(ln->ln_hold, struct ip6_hdr *);
+ hip6 = mtod(ln->la_hold, struct ip6_hdr *);
/* XXX pullup? */
- if (sizeof(*hip6) < ln->ln_hold->m_len)
+ if (sizeof(*hip6) < ln->la_hold->m_len)
hsrc = &hip6->ip6_src;
else
hsrc = NULL;
@@ -600,10 +604,10 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
char *lladdr = NULL;
int lladdrlen = 0;
struct ifaddr *ifa;
- struct llinfo_nd6 *ln;
- struct rtentry *rt;
- struct sockaddr_dl *sdl;
+ struct llentry *ln = NULL;
union nd_opts ndopts;
+ struct mbuf *chain = NULL;
+ struct sockaddr_in6 sin6;
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
if (ip6->ip6_hlim != 255) {
@@ -697,35 +701,37 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
* If no neighbor cache entry is found, NA SHOULD silently be
* discarded.
*/
- rt = nd6_lookup(&taddr6, 0, ifp);
- if ((rt == NULL) ||
- ((ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) ||
- ((sdl = SDL(rt->rt_gateway)) == NULL))
+ IF_AFDATA_LOCK(ifp);
+ ln = nd6_lookup(&taddr6, LLE_EXCLUSIVE, ifp);
+ IF_AFDATA_UNLOCK(ifp);
+ if (ln == NULL) {
goto freeit;
+ }
if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
/*
* If the link-layer has address, and no lladdr option came,
* discard the packet.
*/
- if (ifp->if_addrlen && lladdr == NULL)
+ if (ifp->if_addrlen && lladdr == NULL) {
goto freeit;
+ }
/*
* Record link-layer address, and update the state.
*/
- sdl->sdl_alen = ifp->if_addrlen;
- bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
+ bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
+ ln->la_flags |= LLE_VALID;
if (is_solicited) {
ln->ln_state = ND6_LLINFO_REACHABLE;
ln->ln_byhint = 0;
if (!ND6_LLINFO_PERMANENT(ln)) {
- nd6_llinfo_settimer(ln,
- (long)ND_IFINFO(rt->rt_ifp)->reachable * hz);
+ nd6_llinfo_settimer_locked(ln,
+ (long)ND_IFINFO(ln->lle_tbl->llt_ifp)->reachable * hz);
}
} else {
ln->ln_state = ND6_LLINFO_STALE;
- nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz);
+ nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
}
if ((ln->ln_router = is_router) != 0) {
/*
@@ -744,8 +750,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
if (lladdr == NULL)
llchange = 0;
else {
- if (sdl->sdl_alen) {
- if (bcmp(lladdr, LLADDR(sdl), ifp->if_addrlen))
+ if (ln->la_flags & LLE_VALID) {
+ if (bcmp(lladdr, &ln->ll_addr, ifp->if_addrlen))
llchange = 1;
else
llchange = 0;
@@ -779,7 +785,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
*/
if (ln->ln_state == ND6_LLINFO_REACHABLE) {
ln->ln_state = ND6_LLINFO_STALE;
- nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz);
+ nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
}
goto freeit;
} else if (is_override /* (2a) */
@@ -789,8 +795,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
* Update link-local address, if any.
*/
if (lladdr != NULL) {
- sdl->sdl_alen = ifp->if_addrlen;
- bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
+ bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
+ ln->la_flags |= LLE_VALID;
}
/*
@@ -802,13 +808,13 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
ln->ln_state = ND6_LLINFO_REACHABLE;
ln->ln_byhint = 0;
if (!ND6_LLINFO_PERMANENT(ln)) {
- nd6_llinfo_settimer(ln,
+ nd6_llinfo_settimer_locked(ln,
(long)ND_IFINFO(ifp)->reachable * hz);
}
} else {
if (lladdr != NULL && llchange) {
ln->ln_state = ND6_LLINFO_STALE;
- nd6_llinfo_settimer(ln,
+ nd6_llinfo_settimer_locked(ln,
(long)V_nd6_gctimer * hz);
}
}
@@ -822,9 +828,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
*/
struct nd_defrouter *dr;
struct in6_addr *in6;
- int s;
- in6 = &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr;
+ in6 = &L3_ADDR_SIN6(ln)->sin6_addr;
/*
* Lock to protect the default router list.
@@ -832,8 +837,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
* is only called under the network software interrupt
* context. However, we keep it just for safety.
*/
- s = splnet();
- dr = defrouter_lookup(in6, ifp);
+ dr = defrouter_lookup(in6, ln->lle_tbl->llt_ifp);
if (dr)
defrtrlist_del(dr);
else if (!V_ip6_forwarding) {
@@ -846,21 +850,23 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
*/
rt6_flush(&ip6->ip6_src, ifp);
}
- splx(s);
}
ln->ln_router = is_router;
}
- rt->rt_flags &= ~RTF_REJECT;
- ln->ln_asked = 0;
- if (ln->ln_hold) {
+ /* XXX - QL
+ * Does this matter?
+ * rt->rt_flags &= ~RTF_REJECT;
+ */
+ ln->la_asked = 0;
+ if (ln->la_hold) {
struct mbuf *m_hold, *m_hold_next;
/*
- * reset the ln_hold in advance, to explicitly
- * prevent a ln_hold lookup in nd6_output()
+ * reset the la_hold in advance, to explicitly
+ * prevent a la_hold lookup in nd6_output()
* (wouldn't happen, though...)
*/
- for (m_hold = ln->ln_hold;
+ for (m_hold = ln->la_hold, ln->la_hold = NULL;
m_hold; m_hold = m_hold_next) {
m_hold_next = m_hold->m_nextpkt;
m_hold->m_nextpkt = NULL;
@@ -868,17 +874,25 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
* we assume ifp is not a loopback here, so just set
* the 2nd argument as the 1st one.
*/
- nd6_output(ifp, ifp, m_hold,
- (struct sockaddr_in6 *)rt_key(rt), rt);
+ nd6_output_lle(ifp, ifp, m_hold, L3_ADDR_SIN6(ln), NULL, ln, &chain);
}
- ln->ln_hold = NULL;
}
-
freeit:
+ if (ln != NULL) {
+ if (chain)
+ memcpy(&sin6, L3_ADDR_SIN6(ln), sizeof(sin6));
+ LLE_WUNLOCK(ln);
+
+ if (chain)
+ nd6_output_flush(ifp, ifp, chain, &sin6, NULL);
+ }
m_freem(m);
return;
bad:
+ if (ln != NULL)
+ LLE_WUNLOCK(ln);
+
V_icmp6stat.icp6s_badna++;
m_freem(m);
}
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index c9ed36d..7df364e 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
#include <net/vnet.h>
#include <netinet/in.h>
+#include <net/if_llatbl.h>
#include <netinet6/in6_var.h>
#include <netinet6/in6_ifattach.h>
#include <netinet/ip6.h>
@@ -471,10 +472,8 @@ defrouter_addreq(struct nd_defrouter *new)
(struct sockaddr *)&gate, (struct sockaddr *)&mask,
RTF_GATEWAY, &newrt);
if (newrt) {
- RT_LOCK(newrt);
nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
- RT_REMREF(newrt);
- RT_UNLOCK(newrt);
+ RTFREE(newrt);
}
if (error == 0)
new->installed = 1;
@@ -615,8 +614,7 @@ defrouter_select(void)
INIT_VNET_INET6(curvnet);
int s = splnet();
struct nd_defrouter *dr, *selected_dr = NULL, *installed_dr = NULL;
- struct rtentry *rt = NULL;
- struct llinfo_nd6 *ln = NULL;
+ struct llentry *ln = NULL;
/*
* This function should be called only when acting as an autoconfigured
@@ -648,12 +646,15 @@ defrouter_select(void)
*/
for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
dr = TAILQ_NEXT(dr, dr_entry)) {
+ IF_AFDATA_LOCK(dr->ifp);
if (selected_dr == NULL &&
- (rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) &&
- (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
+ (ln = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) &&
ND6_IS_LLINFO_PROBREACH(ln)) {
selected_dr = dr;
}
+ IF_AFDATA_UNLOCK(dr->ifp);
+ if (ln != NULL)
+ LLE_RUNLOCK(ln);
if (dr->installed && installed_dr == NULL)
installed_dr = dr;
@@ -676,12 +677,16 @@ defrouter_select(void)
selected_dr = TAILQ_FIRST(&V_nd_defrouter);
else
selected_dr = TAILQ_NEXT(installed_dr, dr_entry);
- } else if (installed_dr &&
- (rt = nd6_lookup(&installed_dr->rtaddr, 0, installed_dr->ifp)) &&
- (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
- ND6_IS_LLINFO_PROBREACH(ln) &&
- rtpref(selected_dr) <= rtpref(installed_dr)) {
- selected_dr = installed_dr;
+ } else if (installed_dr) {
+ IF_AFDATA_LOCK(installed_dr->ifp);
+ if ((ln = nd6_lookup(&installed_dr->rtaddr, 0, installed_dr->ifp)) &&
+ ND6_IS_LLINFO_PROBREACH(ln) &&
+ rtpref(selected_dr) <= rtpref(installed_dr)) {
+ selected_dr = installed_dr;
+ }
+ IF_AFDATA_UNLOCK(installed_dr->ifp);
+ if (ln != NULL)
+ LLE_RUNLOCK(ln);
}
/*
@@ -1323,18 +1328,21 @@ static struct nd_pfxrouter *
find_pfxlist_reachable_router(struct nd_prefix *pr)
{
struct nd_pfxrouter *pfxrtr;
- struct rtentry *rt;
- struct llinfo_nd6 *ln;
+ struct llentry *ln;
+ int canreach;
- for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr;
+ for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr != NULL;
pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
- if ((rt = nd6_lookup(&pfxrtr->router->rtaddr, 0,
- pfxrtr->router->ifp)) &&
- (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
- ND6_IS_LLINFO_PROBREACH(ln))
- break; /* found */
+ IF_AFDATA_LOCK(pfxrtr->router->ifp);
+ ln = nd6_lookup(&pfxrtr->router->rtaddr, 0, pfxrtr->router->ifp);
+ IF_AFDATA_UNLOCK(pfxrtr->router->ifp);
+ if (ln == NULL)
+ continue;
+ canreach = ND6_IS_LLINFO_PROBREACH(ln);
+ LLE_RUNLOCK(ln);
+ if (canreach)
+ break;
}
-
return (pfxrtr);
}
@@ -1541,8 +1549,10 @@ nd6_prefix_onlink(struct nd_prefix *pr)
struct nd_prefix *opr;
u_long rtflags;
int error = 0;
+ struct radix_node_head *rnh;
struct rtentry *rt = NULL;
char ip6buf[INET6_ADDRSTRLEN];
+ struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
/* sanity check */
if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
@@ -1609,21 +1619,24 @@ nd6_prefix_onlink(struct nd_prefix *pr)
bzero(&mask6, sizeof(mask6));
mask6.sin6_len = sizeof(mask6);
mask6.sin6_addr = pr->ndpr_mask;
- rtflags = ifa->ifa_flags | RTF_CLONING | RTF_UP;
- if (nd6_need_cache(ifp)) {
- /* explicitly set in case ifa_flags does not set the flag. */
- rtflags |= RTF_CLONING;
- } else {
- /*
- * explicitly clear the cloning bit in case ifa_flags sets it.
- */
- rtflags &= ~RTF_CLONING;
- }
+ rtflags = ifa->ifa_flags | RTF_UP;
error = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
ifa->ifa_addr, (struct sockaddr *)&mask6, rtflags, &rt);
if (error == 0) {
- if (rt != NULL) /* this should be non NULL, though */
+ if (rt != NULL) /* this should be non NULL, though */ {
+ rnh = V_rt_tables[rt->rt_fibnum][AF_INET6];
+ RADIX_NODE_HEAD_LOCK(rnh);
+ RT_LOCK(rt);
+ if (!rt_setgate(rt, rt_key(rt), (struct sockaddr *)&null_sdl)) {
+ ((struct sockaddr_dl *)rt->rt_gateway)->sdl_type =
+ rt->rt_ifp->if_type;
+ ((struct sockaddr_dl *)rt->rt_gateway)->sdl_index =
+ rt->rt_ifp->if_index;
+ }
+ RADIX_NODE_HEAD_UNLOCK(rnh);
nd6_rtmsg(RTM_ADD, rt);
+ RT_UNLOCK(rt);
+ }
pr->ndpr_stateflags |= NDPRF_ONLINK;
} else {
char ip6bufg[INET6_ADDRSTRLEN], ip6bufm[INET6_ADDRSTRLEN];
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index b132751..d342bc8 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -168,10 +168,10 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
INP_INFO_RLOCK(&V_ripcbinfo);
LIST_FOREACH(in6p, &V_ripcb, inp_list) {
/* XXX inp locking */
- if ((in6p->in6p_vflag & INP_IPV6) == 0)
+ if ((in6p->inp_vflag & INP_IPV6) == 0)
continue;
- if (in6p->in6p_ip6_nxt &&
- in6p->in6p_ip6_nxt != proto)
+ if (in6p->inp_ip_p &&
+ in6p->inp_ip_p != proto)
continue;
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
@@ -193,7 +193,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
continue;
}
}
- if (last) {
+ if (last != NULL) {
struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
#ifdef IPSEC
@@ -207,12 +207,12 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
} else
#endif /* IPSEC */
if (n) {
- if (last->in6p_flags & IN6P_CONTROLOPTS ||
- last->in6p_socket->so_options & SO_TIMESTAMP)
+ if (last->inp_flags & INP_CONTROLOPTS ||
+ last->inp_socket->so_options & SO_TIMESTAMP)
ip6_savecontrol(last, n, &opts);
/* strip intermediate headers */
m_adj(n, *offp);
- if (sbappendaddr(&last->in6p_socket->so_rcv,
+ if (sbappendaddr(&last->inp_socket->so_rcv,
(struct sockaddr *)&fromsa,
n, opts) == 0) {
m_freem(n);
@@ -220,7 +220,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
m_freem(opts);
V_rip6stat.rip6s_fullsock++;
} else
- sorwakeup(last->in6p_socket);
+ sorwakeup(last->inp_socket);
opts = NULL;
}
INP_RUNLOCK(last);
@@ -232,7 +232,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
/*
* Check AH/ESP integrity.
*/
- if (last && ipsec6_in_reject(m, last)) {
+ if ((last != NULL) && ipsec6_in_reject(m, last)) {
m_freem(m);
V_ipsec6stat.in_polvio++;
V_ip6stat.ip6s_delivered--;
@@ -240,20 +240,20 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
INP_RUNLOCK(last);
} else
#endif /* IPSEC */
- if (last) {
- if (last->in6p_flags & IN6P_CONTROLOPTS ||
- last->in6p_socket->so_options & SO_TIMESTAMP)
+ if (last != NULL) {
+ if (last->inp_flags & INP_CONTROLOPTS ||
+ last->inp_socket->so_options & SO_TIMESTAMP)
ip6_savecontrol(last, m, &opts);
/* Strip intermediate headers. */
m_adj(m, *offp);
- if (sbappendaddr(&last->in6p_socket->so_rcv,
+ if (sbappendaddr(&last->inp_socket->so_rcv,
(struct sockaddr *)&fromsa, m, opts) == 0) {
m_freem(m);
if (opts)
m_freem(opts);
V_rip6stat.rip6s_fullsock++;
} else
- sorwakeup(last->in6p_socket);
+ sorwakeup(last->inp_socket);
INP_RUNLOCK(last);
} else {
V_rip6stat.rip6s_nosock++;
@@ -353,11 +353,11 @@ rip6_output(m, va_alist)
control = va_arg(ap, struct mbuf *);
va_end(ap);
- in6p = sotoin6pcb(so);
+ in6p = sotoinpcb(so);
INP_WLOCK(in6p);
dst = &dstsock->sin6_addr;
- if (control) {
+ if (control != NULL) {
if ((error = ip6_setpktopts(control, &opt,
in6p->in6p_outputopts, so->so_cred,
so->so_proto->pr_protocol)) != 0) {
@@ -437,14 +437,14 @@ rip6_output(m, va_alist)
* Fill in the rest of the IPv6 header fields.
*/
ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
- (in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK);
+ (in6p->inp_flow & IPV6_FLOWINFO_MASK);
ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
(IPV6_VERSION & IPV6_VERSION_MASK);
/*
* ip6_plen will be filled in ip6_output, so not fill it here.
*/
- ip6->ip6_nxt = in6p->in6p_ip6_nxt;
+ ip6->ip6_nxt = in6p->inp_ip_p;
ip6->ip6_hlim = in6_selecthlim(in6p, oifp);
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 ||
@@ -491,7 +491,7 @@ rip6_output(m, va_alist)
m_freem(m);
freectl:
- if (control) {
+ if (control != NULL) {
ip6_clearpktopts(&opt, -1);
m_freem(control);
}
@@ -595,7 +595,7 @@ rip6_attach(struct socket *so, int proto, struct thread *td)
inp = (struct inpcb *)so->so_pcb;
INP_INFO_WUNLOCK(&V_ripcbinfo);
inp->inp_vflag |= INP_IPV6;
- inp->in6p_ip6_nxt = (long)proto;
+ inp->inp_ip_p = (long)proto;
inp->in6p_hops = -1; /* use kernel default */
inp->in6p_cksum = -1;
inp->in6p_icmp6filt = filter;
diff --git a/sys/netinet6/raw_ip6.h b/sys/netinet6/raw_ip6.h
index 9ebd823..a57253e 100644
--- a/sys/netinet6/raw_ip6.h
+++ b/sys/netinet6/raw_ip6.h
@@ -48,7 +48,9 @@ struct rip6stat {
};
#ifdef _KERNEL
+#ifdef VIMAGE_GLOBALS
extern struct rip6stat rip6stat;
#endif
+#endif
#endif
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index cfb0ad6..f1634cb 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -153,7 +153,7 @@ udp6_append(struct inpcb *inp, struct mbuf *n, int off,
}
#endif
opts = NULL;
- if (inp->in6p_flags & IN6P_CONTROLOPTS ||
+ if (inp->inp_flags & INP_CONTROLOPTS ||
inp->inp_socket->so_options & SO_TIMESTAMP)
ip6_savecontrol(inp, n, &opts);
m_adj(n, off + sizeof(struct udphdr));
@@ -259,7 +259,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
LIST_FOREACH(inp, &V_udb, inp_list) {
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
- if (inp->in6p_lport != uh->uh_dport)
+ if (inp->inp_lport != uh->uh_dport)
continue;
/*
* XXX: Do not check source port of incoming datagram
@@ -278,7 +278,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr,
&ip6->ip6_src) ||
- inp->in6p_fport != uh->uh_sport)
+ inp->inp_fport != uh->uh_sport)
continue;
}
@@ -562,7 +562,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
fport = sin6->sin6_port; /* allow 0 port */
if (IN6_IS_ADDR_V4MAPPED(faddr)) {
- if ((inp->in6p_flags & IN6P_IPV6_V6ONLY)) {
+ if ((inp->inp_flags & IN6P_IPV6_V6ONLY)) {
/*
* I believe we should explicitly discard the
* packet when mapped addresses are disabled,
@@ -606,7 +606,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
error = EADDRNOTAVAIL;
goto release;
}
- if (inp->in6p_lport == 0 &&
+ if (inp->inp_lport == 0 &&
(error = in6_pcbsetport(laddr, inp, td->td_ucred)) != 0)
goto release;
} else {
@@ -615,7 +615,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
goto release;
}
if (IN6_IS_ADDR_V4MAPPED(&inp->in6p_faddr)) {
- if ((inp->in6p_flags & IN6P_IPV6_V6ONLY)) {
+ if ((inp->inp_flags & IN6P_IPV6_V6ONLY)) {
/*
* XXX: this case would happen when the
* application sets the V6ONLY flag after
@@ -632,7 +632,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
}
laddr = &inp->in6p_laddr;
faddr = &inp->in6p_faddr;
- fport = inp->in6p_fport;
+ fport = inp->inp_fport;
}
if (af == AF_INET)
@@ -652,7 +652,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
* Stuff checksum and output datagram.
*/
udp6 = (struct udphdr *)(mtod(m, caddr_t) + hlen);
- udp6->uh_sport = inp->in6p_lport; /* lport is always set in the PCB */
+ udp6->uh_sport = inp->inp_lport; /* lport is always set in the PCB */
udp6->uh_dport = fport;
if (plen <= 0xffff)
udp6->uh_ulen = htons((u_short)plen);
@@ -663,7 +663,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
switch (af) {
case AF_INET6:
ip6 = mtod(m, struct ip6_hdr *);
- ip6->ip6_flow = inp->in6p_flowinfo & IPV6_FLOWINFO_MASK;
+ ip6->ip6_flow = inp->inp_flow & IPV6_FLOWINFO_MASK;
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
ip6->ip6_vfc |= IPV6_VERSION;
#if 0 /* ip6_plen will be filled in ip6_output. */
diff --git a/sys/netinet6/vinet6.h b/sys/netinet6/vinet6.h
index d6c3f33..e271d4f 100644
--- a/sys/netinet6/vinet6.h
+++ b/sys/netinet6/vinet6.h
@@ -78,7 +78,6 @@ struct vnet_inet6 {
int _nd6_inuse;
int _nd6_allocated;
int _nd6_onlink_ns_rfc4861;
- struct llinfo_nd6 _llinfo_nd6;
struct nd_drhead _nd_defrouter;
struct nd_prhead _nd_prefix;
struct ifnet * _nd6_defifp;
diff --git a/sys/netipsec/ipip_var.h b/sys/netipsec/ipip_var.h
index 7fbc643..3d4ee15 100644
--- a/sys/netipsec/ipip_var.h
+++ b/sys/netipsec/ipip_var.h
@@ -60,6 +60,8 @@ struct ipipstat
#ifdef _KERNEL
extern int ipip_allow;
+#ifdef VIMAGE_GLOBALS
extern struct ipipstat ipipstat;
+#endif
#endif /* _KERNEL */
#endif /* _NETINET_IPIP_H_ */
diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c
index 541e42e..108614f 100644
--- a/sys/netipsec/ipsec.c
+++ b/sys/netipsec/ipsec.c
@@ -230,7 +230,7 @@ SYSCTL_V_STRUCT(V_NET, vnet_ipsec, _net_inet6_ipsec6, IPSECCTL_STATS,
static int ipsec4_setspidx_inpcb __P((struct mbuf *, struct inpcb *pcb));
#ifdef INET6
-static int ipsec6_setspidx_in6pcb __P((struct mbuf *, struct in6pcb *pcb));
+static int ipsec6_setspidx_in6pcb __P((struct mbuf *, struct inpcb *pcb));
#endif
static int ipsec_setspidx __P((struct mbuf *, struct secpolicyindex *, int));
static void ipsec4_get_ulp __P((struct mbuf *m, struct secpolicyindex *, int));
@@ -376,7 +376,7 @@ ipsec_getpolicybysock(m, dir, inp, error)
if (inp->inp_vflag & INP_IPV6PROTO) {
#ifdef INET6
*error = ipsec6_setspidx_in6pcb(m, inp);
- pcbsp = inp->in6p_sp;
+ pcbsp = inp->inp_sp;
#else
*error = EINVAL; /* should not happen */
#endif
@@ -578,27 +578,27 @@ ipsec4_setspidx_inpcb(m, pcb)
static int
ipsec6_setspidx_in6pcb(m, pcb)
struct mbuf *m;
- struct in6pcb *pcb;
+ struct inpcb *pcb;
{
//INIT_VNET_IPSEC(curvnet);
struct secpolicyindex *spidx;
int error;
IPSEC_ASSERT(pcb != NULL, ("null pcb"));
- IPSEC_ASSERT(pcb->in6p_sp != NULL, ("null inp_sp"));
- IPSEC_ASSERT(pcb->in6p_sp->sp_out != NULL && pcb->in6p_sp->sp_in != NULL,
+ IPSEC_ASSERT(pcb->inp_sp != NULL, ("null inp_sp"));
+ IPSEC_ASSERT(pcb->inp_sp->sp_out != NULL && pcb->inp_sp->sp_in != NULL,
("null sp_in || sp_out"));
- bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx));
- bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));
+ bzero(&pcb->inp_sp->sp_in->spidx, sizeof(*spidx));
+ bzero(&pcb->inp_sp->sp_out->spidx, sizeof(*spidx));
- spidx = &pcb->in6p_sp->sp_in->spidx;
+ spidx = &pcb->inp_sp->sp_in->spidx;
error = ipsec_setspidx(m, spidx, 1);
if (error)
goto bad;
spidx->dir = IPSEC_DIR_INBOUND;
- spidx = &pcb->in6p_sp->sp_out->spidx;
+ spidx = &pcb->inp_sp->sp_out->spidx;
error = ipsec_setspidx(m, spidx, 1);
if (error)
goto bad;
@@ -607,8 +607,8 @@ ipsec6_setspidx_in6pcb(m, pcb)
return 0;
bad:
- bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx));
- bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));
+ bzero(&pcb->inp_sp->sp_in->spidx, sizeof(*spidx));
+ bzero(&pcb->inp_sp->sp_out->spidx, sizeof(*spidx));
return error;
}
#endif
@@ -1245,7 +1245,7 @@ ipsec_delete_pcbpolicy(inp)
#ifdef INET6
int
ipsec6_set_policy(in6p, optname, request, len, cred)
- struct in6pcb *in6p;
+ struct inpcb *in6p;
int optname;
caddr_t request;
size_t len;
@@ -1265,10 +1265,10 @@ ipsec6_set_policy(in6p, optname, request, len, cred)
/* select direction */
switch (xpl->sadb_x_policy_dir) {
case IPSEC_DIR_INBOUND:
- pcb_sp = &in6p->in6p_sp->sp_in;
+ pcb_sp = &in6p->inp_sp->sp_in;
break;
case IPSEC_DIR_OUTBOUND:
- pcb_sp = &in6p->in6p_sp->sp_out;
+ pcb_sp = &in6p->inp_sp->sp_out;
break;
default:
ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__,
@@ -1281,7 +1281,7 @@ ipsec6_set_policy(in6p, optname, request, len, cred)
int
ipsec6_get_policy(in6p, request, len, mp)
- struct in6pcb *in6p;
+ struct inpcb *in6p;
caddr_t request;
size_t len;
struct mbuf **mp;
@@ -1293,7 +1293,7 @@ ipsec6_get_policy(in6p, request, len, mp)
/* sanity check. */
if (in6p == NULL || request == NULL || mp == NULL)
return EINVAL;
- IPSEC_ASSERT(in6p->in6p_sp != NULL, ("null in6p_sp"));
+ IPSEC_ASSERT(in6p->inp_sp != NULL, ("null inp_sp"));
if (len < sizeof(*xpl))
return EINVAL;
xpl = (struct sadb_x_policy *)request;
@@ -1301,10 +1301,10 @@ ipsec6_get_policy(in6p, request, len, mp)
/* select direction */
switch (xpl->sadb_x_policy_dir) {
case IPSEC_DIR_INBOUND:
- pcb_sp = in6p->in6p_sp->sp_in;
+ pcb_sp = in6p->inp_sp->sp_in;
break;
case IPSEC_DIR_OUTBOUND:
- pcb_sp = in6p->in6p_sp->sp_out;
+ pcb_sp = in6p->inp_sp->sp_out;
break;
default:
ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__,
@@ -1684,7 +1684,7 @@ size_t
ipsec6_hdrsiz(m, dir, in6p)
struct mbuf *m;
u_int dir;
- struct in6pcb *in6p;
+ struct inpcb *in6p;
{
INIT_VNET_IPSEC(curvnet);
struct secpolicy *sp;
@@ -1692,7 +1692,7 @@ ipsec6_hdrsiz(m, dir, in6p)
size_t size;
IPSEC_ASSERT(m != NULL, ("null mbuf"));
- IPSEC_ASSERT(in6p == NULL || in6p->in6p_socket != NULL,
+ IPSEC_ASSERT(in6p == NULL || in6p->inp_socket != NULL,
("socket w/o inpcb"));
/* get SP for this packet */
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index f65d1f1..4906999 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -1160,42 +1160,24 @@ key_freeso(struct socket *so)
IPSEC_ASSERT(so != NULL, ("null so"));
switch (so->so_proto->pr_domain->dom_family) {
+#if defined(INET) || defined(INET6)
#ifdef INET
case PF_INET:
- {
- struct inpcb *pcb = sotoinpcb(so);
-
- /* Does it have a PCB ? */
- if (pcb == NULL)
- return;
- key_freesp_so(&pcb->inp_sp->sp_in);
- key_freesp_so(&pcb->inp_sp->sp_out);
- }
- break;
#endif
#ifdef INET6
case PF_INET6:
+#endif
{
-#ifdef HAVE_NRL_INPCB
- struct inpcb *pcb = sotoinpcb(so);
+ struct inpcb *pcb = sotoinpcb(so);
/* Does it have a PCB ? */
if (pcb == NULL)
return;
key_freesp_so(&pcb->inp_sp->sp_in);
key_freesp_so(&pcb->inp_sp->sp_out);
-#else
- struct in6pcb *pcb = sotoin6pcb(so);
-
- /* Does it have a PCB ? */
- if (pcb == NULL)
- return;
- key_freesp_so(&pcb->in6p_sp->sp_in);
- key_freesp_so(&pcb->in6p_sp->sp_out);
-#endif
}
break;
-#endif /* INET6 */
+#endif /* INET || INET6 */
default:
ipseclog((LOG_DEBUG, "%s: unknown address family=%d.\n",
__func__, so->so_proto->pr_domain->dom_family));
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c
index 3b860ac..ab09421 100644
--- a/sys/nfsserver/nfs_serv.c
+++ b/sys/nfsserver/nfs_serv.c
@@ -3615,9 +3615,12 @@ again:
* Probe one of the directory entries to see if the filesystem
* supports VGET.
*/
- if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE, &nvp) ==
- EOPNOTSUPP) {
- error = NFSERR_NOTSUPP;
+ error = VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE, &nvp);
+ if (error) {
+ if (error == EOPNOTSUPP)
+ error = NFSERR_NOTSUPP;
+ else
+ error = NFSERR_SERVERFAULT;
vrele(vp);
vp = NULL;
free((caddr_t)cookies, M_TEMP);
diff --git a/sys/pc98/conf/DEFAULTS b/sys/pc98/conf/DEFAULTS
index 962c099..c16a29b 100644
--- a/sys/pc98/conf/DEFAULTS
+++ b/sys/pc98/conf/DEFAULTS
@@ -22,5 +22,5 @@ device uart_ns8250
#device uart_i8251
# Default partitioning schemes
-options GEOM_BSD
-options GEOM_PC98
+options GEOM_PART_BSD
+options GEOM_PART_PC98
diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c
index 71866ce..d11d5d9 100644
--- a/sys/pci/if_rl.c
+++ b/sys/pci/if_rl.c
@@ -901,9 +901,15 @@ rl_attach(device_t dev)
}
if (sc->rl_type == 0) {
- device_printf(dev, "unknown device ID: %x\n", rl_did);
- error = ENXIO;
- goto fail;
+ device_printf(dev, "unknown device ID: %x assuming 8139\n",
+ rl_did);
+ sc->rl_type = RL_8139;
+ /*
+ * Read RL_IDR register to get ethernet address as accessing
+ * EEPROM may not extract correct address.
+ */
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ eaddr[i] = CSR_READ_1(sc, RL_IDR0 + i);
}
if ((error = rl_dma_alloc(sc)) != 0)
diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h
index d9df78c..b3569e8 100644
--- a/sys/pci/if_rlreg.h
+++ b/sys/pci/if_rlreg.h
@@ -131,6 +131,8 @@
#define RL_TBI_ANAR 0x0068
#define RL_TBI_LPAR 0x006A
#define RL_GMEDIASTAT 0x006C /* 8 bits */
+#define RL_MACDBG 0x006D /* 8 bits, 8168C SPIN2 only */
+#define RL_GPIO 0x006E /* 8 bits, 8168C SPIN2 only */
#define RL_MAXRXPKTLEN 0x00DA /* 16 bits, chip multiplies by 8 */
#define RL_GTXSTART 0x0038 /* 8 bits */
@@ -888,6 +890,8 @@ struct rl_softc {
#define RL_FLAG_PHY8169 0x0400
#define RL_FLAG_PHY8110S 0x0800
#define RL_FLAG_WOLRXENB 0x1000
+#define RL_FLAG_MACSLEEP 0x2000
+#define RL_FLAG_PCIE 0x4000
#define RL_FLAG_LINK 0x8000
};
diff --git a/sys/powerpc/aim/locore.S b/sys/powerpc/aim/locore.S
index cfe75d9..60e5e9d 100644
--- a/sys/powerpc/aim/locore.S
+++ b/sys/powerpc/aim/locore.S
@@ -129,14 +129,6 @@ kernel_text:
.text
.globl __start
__start:
-#ifdef FIRMWORKSBUGS
- mfmsr 0
- andi. 0,0,PSL_IR|PSL_DR
- beq 1f
-
- bl ofwr_init
-1:
-#endif
li 8,0
li 9,0x100
mtctr 9
@@ -154,7 +146,6 @@ __start:
lis 8,openfirmware_entry@ha
stw 5,openfirmware_entry@l(8) /* save client interface handler */
- mr 3,5
lis 1,(tmpstk+TMPSTKSZ-16)@ha
addi 1,1,(tmpstk+TMPSTKSZ-16)@l
@@ -172,7 +163,7 @@ __start:
mfsprg3 0
stw 0,16(9) /* ofmsr[4] = sprg3 */
- bl OF_init
+ bl OF_initial_setup
lis 4,end@ha
addi 4,4,end@l
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c
index 13fc2a7..2199cb1 100644
--- a/sys/powerpc/aim/machdep.c
+++ b/sys/powerpc/aim/machdep.c
@@ -291,9 +291,19 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
__asm __volatile("mtsprg 0, %0" :: "r"(pc));
+ /*
+ * Init mutexes, which we use heavily in PMAP
+ */
+
mutex_init();
/*
+ * Install the OF client interface
+ */
+
+ OF_bootstrap();
+
+ /*
* Initialize the console before printing anything.
*/
cninit();
@@ -307,8 +317,6 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
kdb_init();
- kobj_machdep_init();
-
/*
* XXX: Initialize the interrupt tables.
* Disable translation in case the vector area
diff --git a/sys/powerpc/aim/ofw_machdep.c b/sys/powerpc/aim/ofw_machdep.c
index 2755819..0d5f03b 100644
--- a/sys/powerpc/aim/ofw_machdep.c
+++ b/sys/powerpc/aim/ofw_machdep.c
@@ -65,6 +65,10 @@ static struct mem_region OFfree[OFMEM_REGIONS + 3];
extern register_t ofmsr[5];
extern struct pmap ofw_pmap;
static int (*ofwcall)(void *);
+static void *fdt;
+int ofw_real_mode;
+
+static int openfirmware(void *args);
/*
* Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback.
@@ -192,13 +196,45 @@ mem_regions(struct mem_region **memp, int *memsz,
}
void
-set_openfirm_callback(int (*openfirm)(void *))
+OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *))
{
+ if (ofmsr[0] & PSL_DR)
+ ofw_real_mode = 0;
+ else
+ ofw_real_mode = 1;
ofwcall = openfirm;
+ fdt = fdt_ptr;
}
-int
+boolean_t
+OF_bootstrap()
+{
+ boolean_t status = FALSE;
+
+ if (ofwcall != NULL) {
+ if (ofw_real_mode)
+ status = OF_install(OFW_STD_REAL, 0);
+ else
+ status = OF_install(OFW_STD_DIRECT, 0);
+
+ if (status != TRUE)
+ return status;
+
+ OF_init(openfirmware);
+ } else {
+ status = OF_install(OFW_FDT, 0);
+
+ if (status != TRUE)
+ return status;
+
+ OF_init(fdt);
+ }
+
+ return (status);
+}
+
+static int
openfirmware(void *args)
{
long oldmsr;
@@ -206,6 +242,9 @@ openfirmware(void *args)
u_int srsave[16];
u_int i;
+ if (pmap_bootstrapped && ofw_real_mode)
+ args = (void *)pmap_kextract((vm_offset_t)args);
+
__asm __volatile( "\t"
"sync\n\t"
"mfmsr %0\n\t"
@@ -217,7 +256,7 @@ openfirmware(void *args)
ofw_sprg_prepare();
- if (pmap_bootstrapped) {
+ if (pmap_bootstrapped && !ofw_real_mode) {
/*
* Swap the kernel's address space with Open Firmware's
*/
@@ -236,7 +275,7 @@ openfirmware(void *args)
result = ofwcall(args);
- if (pmap_bootstrapped) {
+ if (pmap_bootstrapped && !ofw_real_mode) {
/*
* Restore the kernel's addr space. The isync() doesn;t
* work outside the loop unless mtsrin() is open-coded
diff --git a/sys/powerpc/booke/interrupt.c b/sys/powerpc/booke/interrupt.c
index 1d20772..01ee3d9 100644
--- a/sys/powerpc/booke/interrupt.c
+++ b/sys/powerpc/booke/interrupt.c
@@ -93,7 +93,6 @@ dump_frame(struct trapframe *frame)
printf("\n");
}
-
void powerpc_crit_interrupt(struct trapframe *framep)
{
diff --git a/sys/powerpc/booke/locore.S b/sys/powerpc/booke/locore.S
index a6335e6..e4df6af 100644
--- a/sys/powerpc/booke/locore.S
+++ b/sys/powerpc/booke/locore.S
@@ -1,4 +1,5 @@
/*-
+ * Copyright (C) 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com>
* Copyright (C) 2006 Semihalf, Marian Balakowicz <m8@semihalf.com>
* All rights reserved.
*
@@ -10,8 +11,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -29,8 +28,8 @@
#include "assym.s"
-#include <machine/param.h>
#include <machine/asm.h>
+#include <machine/param.h>
#include <machine/spr.h>
#include <machine/psl.h>
#include <machine/pte.h>
@@ -60,207 +59,140 @@ kernel_text:
__start:
/*
- * Assumption on a boot loader:
+ * Assumptions on the boot loader:
* - system memory starts from physical address 0
- * - kernel is loaded at 16MB boundary
* - it's mapped by a single TBL1 entry
* - TLB1 mapping is 1:1 pa to va
+ * - kernel is loaded at 16MB boundary
* - all PID registers are set to the same value
+ * - CPU is running in AS=0
*
- * Loader register use:
+ * Registers contents provided by the loader(8):
* r1 : stack pointer
* r3 : metadata pointer
*
* We rearrange the TLB1 layout as follows:
- * - find AS and entry kernel started in
+ * - find TLB1 entry we started in
* - make sure it's protected, ivalidate other entries
- * - create temp entry in the second AS (make sure it's not TLB[15])
+ * - create temp entry in the second AS (make sure it's not TLB[1])
* - switch to temp mapping
- * - map 16MB of RAM in TLB1[15]
+ * - map 16MB of RAM in TLB1[1]
* - use AS=1, set EPN to KERNBASE and RPN to kernel load address
- * - switch to to TLB1[15] mapping
+ * - switch to to TLB1[1] mapping
* - invalidate temp mapping
*
- * locore register use:
+ * locore registers use:
* r1 : stack pointer
- * r2 : unused
- * r3 : kernel_text
- * r4 : _end
- * r5 : metadata pointer
- * r6-r9 : unused
- * r10 : entry we started in
- * r11 : temp entry
- * r12 : AS we started in
- * r13-r31 : auxiliary registers
+ * r2 : trace pointer (AP only, for early diagnostics)
+ * r3-r27 : scratch registers
+ * r28 : kernload
+ * r29 : temp TLB1 entry
+ * r30 : initial TLB1 entry we started in
+ * r31 : metadata pointer
*/
/*
- * Move metadata ptr to r5
+ * Keep metadata ptr in r31 for later use.
*/
- mr %r5, %r3
+ mr %r31, %r3
/*
* Initial cleanup
*/
- li %r16, 0x200 /* Keep debug exceptions for CodeWarrior. */
- mtmsr %r16
- isync
-#if 0
- mtspr SPR_HID0, %r16
- isync
- msync
- mtspr SPR_HID1, %r16
+ li %r3, PSL_DE /* Keep debug exceptions for CodeWarrior. */
+ mtmsr %r3
isync
-#endif
- /* Issue INV_ALL Invalidate on TLB0 */
- li %r16, 0x04
- tlbivax 0, %r16
- isync
- msync
+ /* Invalidate all entries in TLB0 */
+ li %r3, 0
+ bl tlb_inval_all
/*
- * Use tblsx to locate the TLB1 entry that maps kernel code
+ * Locate the TLB1 entry that maps this code
*/
- bl 1f /* Current address */
-1: mflr %r15
-
- /* Find entry that maps current address */
- mfspr %r17, SPR_PID0
- slwi %r17, %r17, MAS6_SPID0_SHIFT
- mtspr SPR_MAS6, %r17
- isync
- tlbsx 0, %r15
-
- /* Copy entry number to r10 */
- mfspr %r17, SPR_MAS0
- rlwinm %r10, %r17, 16, 28, 31
-
- /* Invalidate TLB1, skipping our entry. */
- mfspr %r17, SPR_TLB1CFG /* Get number of entries */
- andi. %r17, %r17, TLBCFG_NENTRY_MASK@l
- li %r16, 0 /* Start from Entry 0 */
-
-2: lis %r15, MAS0_TLBSEL1@h /* Select TLB1 */
- rlwimi %r15, %r16, 16, 12, 15
- mtspr SPR_MAS0, %r15
- isync
- tlbre
- mfspr %r15, SPR_MAS1
- cmpw %r16, %r10
- beq 3f
- /* Clear VALID and IPROT bits for other entries */
- rlwinm %r15, %r15, 0, 2, 31
- mtspr SPR_MAS1, %r15
- isync
- tlbwe
- isync
- msync
-3: addi %r16, %r16, 1
- cmpw %r16, %r17 /* Check if this is the last entry */
- bne 2b
+ bl 1f
+1: mflr %r3
+ bl tlb1_find_current /* the entry number found is returned in r30 */
+ bl tlb1_inval_all_but_current
/*
- * Create temporary mapping in the other Address Space
+ * Create temporary mapping in AS=1 and switch to it
*/
- lis %r17, MAS0_TLBSEL1@h /* Select TLB1 */
- rlwimi %r17, %r10, 16, 12, 15 /* Select our entry */
- mtspr SPR_MAS0, %r17
- isync
- tlbre /* Read it in */
-
- /* Prepare and write temp entry */
- lis %r17, MAS0_TLBSEL1@h /* Select TLB1 */
- addi %r11, %r10, 0x1 /* Use next entry. */
- rlwimi %r17, %r11, 16, 12, 15 /* Select temp entry */
- mtspr SPR_MAS0, %r17
- isync
-
- mfspr %r16, SPR_MAS1
- li %r15, 1 /* AS 1 */
- rlwimi %r16, %r15, 12, 19, 19
- mtspr SPR_MAS1, %r16
- li %r17, 0
- rlwimi %r16, %r17, 0, 8, 15 /* Global mapping, TID=0 */
- isync
-
- tlbwe
- isync
- msync
-
- mfmsr %r16
- ori %r16, %r16, 0x30 /* Switch to AS 1. */
-
- bl 4f /* Find current execution address */
-4: mflr %r15
- addi %r15, %r15, 20 /* Increment to instruction after rfi */
- mtspr SPR_SRR0, %r15
- mtspr SPR_SRR1, %r16
+ bl tlb1_temp_mapping_as1
+
+ mfmsr %r3
+ ori %r3, %r3, (PSL_IS | PSL_DS)
+ bl 2f
+2: mflr %r4
+ addi %r4, %r4, 20
+ mtspr SPR_SRR0, %r4
+ mtspr SPR_SRR1, %r3
rfi /* Switch context */
/*
* Invalidate initial entry
*/
- mr %r22, %r10
+ mr %r3, %r30
bl tlb1_inval_entry
/*
* Setup final mapping in TLB1[1] and switch to it
*/
/* Final kernel mapping, map in 16 MB of RAM */
- lis %r16, MAS0_TLBSEL1@h /* Select TLB1 */
- li %r17, 1 /* Entry 1 */
- rlwimi %r16, %r17, 16, 12, 15
- mtspr SPR_MAS0, %r16
+ lis %r3, MAS0_TLBSEL1@h /* Select TLB1 */
+ li %r4, 1 /* Entry 1 */
+ rlwimi %r3, %r4, 16, 12, 15
+ mtspr SPR_MAS0, %r3
isync
- li %r16, (TLB_SIZE_16M << MAS1_TSIZE_SHIFT)@l
- oris %r16, %r16, (MAS1_VALID | MAS1_IPROT)@h
- mtspr SPR_MAS1, %r16
+ li %r3, (TLB_SIZE_16M << MAS1_TSIZE_SHIFT)@l
+ oris %r3, %r3, (MAS1_VALID | MAS1_IPROT)@h
+ mtspr SPR_MAS1, %r3 /* note TS was not filled, so it's TS=0 */
isync
- lis %r19, KERNBASE@h
- ori %r19, %r19, KERNBASE@l
- mtspr SPR_MAS2, %r19 /* Set final EPN, clear WIMG */
+ lis %r3, KERNBASE@h
+ ori %r3, %r3, KERNBASE@l /* EPN = KERNBASE */
+ mtspr SPR_MAS2, %r3
isync
- bl 5f
-5: mflr %r16 /* Use current address */
- lis %r18, 0xff00 /* 16MB alignment mask */
- and %r16, %r16, %r18
- mr %r25, %r16 /* Copy kernel load address */
- ori %r16, %r16, (MAS3_SX | MAS3_SW | MAS3_SR)@l
- mtspr SPR_MAS3, %r16 /* Set RPN and protection */
+ /* Discover phys load address */
+ bl 3f
+3: mflr %r4 /* Use current address */
+ rlwinm %r4, %r4, 0, 0, 7 /* 16MB alignment mask */
+ mr %r28, %r4 /* Keep kernel load address */
+ ori %r4, %r4, (MAS3_SX | MAS3_SW | MAS3_SR)@l
+ mtspr SPR_MAS3, %r4 /* Set RPN and protection */
isync
tlbwe
isync
msync
/* Switch to the above TLB1[1] mapping */
- lis %r18, 0x00ff /* 16MB offset mask */
- ori %r18, %r18, 0xffff
- bl 6f
-6: mflr %r20 /* Use current address */
- and %r20, %r20, %r18 /* Offset from kernel load address */
- add %r20, %r20, %r19 /* Move to kernel virtual address */
- addi %r20, %r20, 32 /* Increment to instr. after rfi */
- li %r21, 0x200
- mtspr SPR_SRR0, %r20
- mtspr SPR_SRR1, %r21
+ bl 4f
+4: mflr %r4
+ rlwinm %r4, %r4, 0, 8, 31 /* Current offset from kernel load address */
+ rlwinm %r3, %r3, 0, 0, 19
+ add %r4, %r4, %r3 /* Convert to kernel virtual address */
+ addi %r4, %r4, 36
+ li %r3, PSL_DE /* Note AS=0 */
+ mtspr SPR_SRR0, %r4
+ mtspr SPR_SRR1, %r3
rfi
- /* Save kernel load address for later use */
- lis %r24, kernload@ha
- addi %r24, %r24, kernload@l
- stw %r25, 0(%r24)
-
/*
* Invalidate temp mapping
*/
- mr %r22, %r11
+ mr %r3, %r29
bl tlb1_inval_entry
/*
+ * Save kernel load address for later use.
+ */
+ lis %r3, kernload@ha
+ addi %r3, %r3, kernload@l
+ stw %r28, 0(%r3)
+
+/*
* Setup a temporary stack
*/
lis %r1, tmpstack@ha
@@ -268,119 +200,203 @@ __start:
addi %r1, %r1, (TMPSTACKSZ - 8)
/*
- * Intialise exception vector offsets
+ * Initialise exception vector offsets
*/
bl ivor_setup
/*
- * Jump to system initialization code
- *
- * Setup first two arguments for e500_init, metadata (r5) is already in place.
+ * Set up arguments and jump to system initialization code
*/
lis %r3, kernel_text@ha
addi %r3, %r3, kernel_text@l
lis %r4, _end@ha
addi %r4, %r4, _end@l
+ mr %r5, %r31 /* metadata ptr */
+ /* Prepare e500 core */
bl e500_init
- /* Switch to thread0.td_kstack */
+ /* Switch to thread0.td_kstack now */
mr %r1, %r3
li %r3, 0
stw %r3, 0(%r1)
- bl mi_startup /* Machine independet part, does not return */
+ /* Machine independet part, does not return */
+ bl mi_startup
+ /* NOT REACHED */
+5: b 5b
-/************************************************************************/
-/* locore subroutines */
-/************************************************************************/
+/*
+ * Invalidate all entries in the given TLB.
+ *
+ * r3 TLBSEL
+ */
+tlb_inval_all:
+ rlwinm %r3, %r3, 3, 0x18 /* TLBSEL */
+ ori %r3, %r3, 0x4 /* INVALL */
+ tlbivax 0, %r3
+ isync
+ msync
-tlb1_inval_entry:
- lis %r17, MAS0_TLBSEL1@h /* Select TLB1 */
- rlwimi %r17, %r22, 16, 12, 15 /* Select our entry */
- mtspr SPR_MAS0, %r17
+ tlbsync
+ msync
+ blr
+
+/*
+ * expects address to look up in r3, returns entry number in r30
+ *
+ * FIXME: the hidden assumption is we are now running in AS=0, but we should
+ * retrieve actual AS from MSR[IS|DS] and put it in MAS6[SAS]
+ */
+tlb1_find_current:
+ mfspr %r17, SPR_PID0
+ slwi %r17, %r17, MAS6_SPID0_SHIFT
+ mtspr SPR_MAS6, %r17
isync
- tlbre /* Read it in */
+ tlbsx 0, %r3
+ mfspr %r17, SPR_MAS0
+ rlwinm %r30, %r17, 16, 20, 31 /* MAS0[ESEL] -> r30 */
- li %r16, 0
- mtspr SPR_MAS1, %r16
+ /* Make sure we have IPROT set on the entry */
+ mfspr %r17, SPR_MAS1
+ oris %r17, %r17, MAS1_IPROT@h
+ mtspr SPR_MAS1, %r17
isync
tlbwe
isync
msync
blr
-ivor_setup:
- /* Set base address of interrupt handler routines */
- lis %r21, interrupt_vector_base@h
- mtspr SPR_IVPR, %r21
-
- /* Assign interrupt handler routines offsets */
- li %r21, int_critical_input@l
- mtspr SPR_IVOR0, %r21
- li %r21, int_machine_check@l
- mtspr SPR_IVOR1, %r21
- li %r21, int_data_storage@l
- mtspr SPR_IVOR2, %r21
- li %r21, int_instr_storage@l
- mtspr SPR_IVOR3, %r21
- li %r21, int_external_input@l
- mtspr SPR_IVOR4, %r21
- li %r21, int_alignment@l
- mtspr SPR_IVOR5, %r21
- li %r21, int_program@l
- mtspr SPR_IVOR6, %r21
- li %r21, int_syscall@l
- mtspr SPR_IVOR8, %r21
- li %r21, int_decrementer@l
- mtspr SPR_IVOR10, %r21
- li %r21, int_fixed_interval_timer@l
- mtspr SPR_IVOR11, %r21
- li %r21, int_watchdog@l
- mtspr SPR_IVOR12, %r21
- li %r21, int_data_tlb_error@l
- mtspr SPR_IVOR13, %r21
- li %r21, int_inst_tlb_error@l
- mtspr SPR_IVOR14, %r21
- li %r21, int_debug@l
- mtspr SPR_IVOR15, %r21
- blr
-
/*
- * void tlb1_inval_va(vm_offset_t va)
+ * Invalidates a single entry in TLB1.
*
- * r3 - va to invalidate
+ * r3 ESEL
+ * r4-r5 scratched
*/
-ENTRY(tlb1_inval_va)
- /* EA mask */
- lis %r6, 0xffff
- ori %r6, %r6, 0xf000
- and %r3, %r3, %r6
+tlb1_inval_entry:
+ lis %r4, MAS0_TLBSEL1@h /* Select TLB1 */
+ rlwimi %r4, %r3, 16, 12, 15 /* Select our entry */
+ mtspr SPR_MAS0, %r4
+ isync
+ tlbre
+ li %r5, 0 /* MAS1[V] = 0 */
+ mtspr SPR_MAS1, %r5
+ isync
+ tlbwe
+ isync
+ msync
+ blr
- /* Select TLB1 */
- ori %r3, %r3, 0x08
+/*
+ * r30 current entry number
+ * r29 returned temp entry
+ * r3-r5 scratched
+ */
+tlb1_temp_mapping_as1:
+ /* Read our current translation */
+ lis %r3, MAS0_TLBSEL1@h /* Select TLB1 */
+ rlwimi %r3, %r30, 16, 12, 15 /* Select our current entry */
+ mtspr SPR_MAS0, %r3
+ isync
+ tlbre
+ /*
+ * Prepare and write temp entry
+ *
+ * FIXME this is not robust against overflow i.e. when the current
+ * entry is the last in TLB1
+ */
+ lis %r3, MAS0_TLBSEL1@h /* Select TLB1 */
+ addi %r29, %r30, 1 /* Use next entry. */
+ li %r4, 1
+ cmpw %r4, %r29
+ bne 1f
+ addi %r29, %r29, 1
+1: rlwimi %r3, %r29, 16, 12, 15 /* Select temp entry */
+ mtspr SPR_MAS0, %r3
+ isync
+ mfspr %r5, SPR_MAS1
+ li %r4, 1 /* AS=1 */
+ rlwimi %r5, %r4, 12, 19, 19
+ li %r4, 0 /* Global mapping, TID=0 */
+ rlwimi %r5, %r4, 16, 8, 15
+ oris %r5, %r5, (MAS1_VALID | MAS1_IPROT)@h
+ mtspr SPR_MAS1, %r5
isync
- tlbivax 0, %r3
+ tlbwe
isync
msync
blr
/*
- * void tlb0_inval_va(vm_offset_t va)
+ * Loops over TLB1, invalidates all entries skipping the one which currently
+ * maps this code.
*
- * r3 - va to invalidate
+ * r30 current entry
+ * r3-r5 scratched
*/
-ENTRY(tlb0_inval_va)
- /* EA mask, this also clears TLBSEL, selecting TLB0 */
- lis %r6, 0xffff
- ori %r6, %r6, 0xf000
- and %r3, %r3, %r6
-
+tlb1_inval_all_but_current:
+ mr %r6, %r3
+ mfspr %r3, SPR_TLB1CFG /* Get number of entries */
+ andi. %r3, %r3, TLBCFG_NENTRY_MASK@l
+ li %r4, 0 /* Start from Entry 0 */
+1: lis %r5, MAS0_TLBSEL1@h
+ rlwimi %r5, %r4, 16, 12, 15
+ mtspr SPR_MAS0, %r5
isync
- tlbivax 0, %r3
+ tlbre
+ mfspr %r5, SPR_MAS1
+ cmpw %r4, %r30 /* our current entry? */
+ beq 2f
+ rlwinm %r5, %r5, 0, 2, 31 /* clear VALID and IPROT bits */
+ mtspr SPR_MAS1, %r5
+ isync
+ tlbwe
isync
msync
+2: addi %r4, %r4, 1
+ cmpw %r4, %r3 /* Check if this is the last entry */
+ bne 1b
+ blr
+
+/************************************************************************/
+/* locore subroutines */
+/************************************************************************/
+
+ivor_setup:
+ /* Set base address of interrupt handler routines */
+ lis %r3, interrupt_vector_base@h
+ mtspr SPR_IVPR, %r3
+
+ /* Assign interrupt handler routines offsets */
+ li %r3, int_critical_input@l
+ mtspr SPR_IVOR0, %r3
+ li %r3, int_machine_check@l
+ mtspr SPR_IVOR1, %r3
+ li %r3, int_data_storage@l
+ mtspr SPR_IVOR2, %r3
+ li %r3, int_instr_storage@l
+ mtspr SPR_IVOR3, %r3
+ li %r3, int_external_input@l
+ mtspr SPR_IVOR4, %r3
+ li %r3, int_alignment@l
+ mtspr SPR_IVOR5, %r3
+ li %r3, int_program@l
+ mtspr SPR_IVOR6, %r3
+ li %r3, int_syscall@l
+ mtspr SPR_IVOR8, %r3
+ li %r3, int_decrementer@l
+ mtspr SPR_IVOR10, %r3
+ li %r3, int_fixed_interval_timer@l
+ mtspr SPR_IVOR11, %r3
+ li %r3, int_watchdog@l
+ mtspr SPR_IVOR12, %r3
+ li %r3, int_data_tlb_error@l
+ mtspr SPR_IVOR13, %r3
+ li %r3, int_inst_tlb_error@l
+ mtspr SPR_IVOR14, %r3
+ li %r3, int_debug@l
+ mtspr SPR_IVOR15, %r3
blr
/*
@@ -395,6 +411,9 @@ ENTRY(dcache_inval)
isync
mtspr SPR_L1CSR0, %r3
isync
+1: mfspr %r3, SPR_L1CSR0
+ andi. %r3, %r3, L1CSR0_DCFI
+ bne 1b
blr
ENTRY(dcache_disable)
@@ -427,6 +446,9 @@ ENTRY(icache_inval)
isync
mtspr SPR_L1CSR1, %r3
isync
+1: mfspr %r3, SPR_L1CSR1
+ andi. %r3, %r3, L1CSR1_ICFI
+ bne 1b
blr
ENTRY(icache_disable)
@@ -495,7 +517,7 @@ tmpstack:
#define INTRCNT_COUNT 256 /* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
GLOBAL(kernload)
- .long
+ .long 0
GLOBAL(intrnames)
.space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
GLOBAL(eintrnames)
diff --git a/sys/powerpc/booke/machdep.c b/sys/powerpc/booke/machdep.c
index 218127d..a48ece1 100644
--- a/sys/powerpc/booke/machdep.c
+++ b/sys/powerpc/booke/machdep.c
@@ -10,8 +10,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -88,7 +86,6 @@ __FBSDID("$FreeBSD$");
#include <sys/cdefs.h>
#include <sys/types.h>
-
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/systm.h>
@@ -137,6 +134,9 @@ __FBSDID("$FreeBSD$");
#include <sys/linker.h>
#include <sys/reboot.h>
+#include <powerpc/mpc85xx/ocpbus.h>
+#include <powerpc/mpc85xx/mpc85xx.h>
+
#ifdef DEBUG
#define debugf(fmt, args...) printf(fmt, ##args)
#else
@@ -180,8 +180,8 @@ static void cpu_e500_startup(void *);
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_e500_startup, NULL);
void print_kernel_section_addr(void);
-void dump_bootinfo(void);
-void dump_kenv(void);
+void print_bootinfo(void);
+void print_kenv(void);
u_int e500_init(u_int32_t, u_int32_t, void *);
static void
@@ -204,16 +204,17 @@ cpu_e500_startup(void *dummy)
printf("Physical memory chunk(s):\n");
for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
size = phys_avail[indx + 1] - phys_avail[indx];
+
printf("0x%08x - 0x%08x, %d bytes (%d pages)\n",
- phys_avail[indx], phys_avail[indx + 1] - 1, size,
- size / PAGE_SIZE);
+ phys_avail[indx], phys_avail[indx + 1] - 1,
+ size, size / PAGE_SIZE);
}
}
vm_ksubmap_init(&kmi);
printf("avail memory = %ld (%ld MB)\n", ptoa(cnt.v_free_count),
- ptoa(cnt.v_free_count) / 1048576);
+ ptoa(cnt.v_free_count) / 1048576);
/* Set up buffers, so they can be used to read disk labels. */
bufinit();
@@ -235,7 +236,7 @@ kenv_next(char *cp)
}
void
-dump_kenv(void)
+print_kenv(void)
{
int len;
char *cp;
@@ -253,7 +254,7 @@ dump_kenv(void)
}
void
-dump_bootinfo(void)
+print_bootinfo(void)
{
struct bi_mem_region *mr;
struct bi_eth_addr *eth;
@@ -291,20 +292,20 @@ print_kernel_section_addr(void)
{
debugf("kernel image addresses:\n");
- debugf(" kernel_text = 0x%08x\n", (u_int32_t)kernel_text);
- debugf(" _etext (sdata) = 0x%08x\n", (u_int32_t)_etext);
- debugf(" _edata = 0x%08x\n", (u_int32_t)_edata);
- debugf(" __sbss_start = 0x%08x\n", (u_int32_t)__sbss_start);
- debugf(" __sbss_end = 0x%08x\n", (u_int32_t)__sbss_end);
- debugf(" __sbss_start = 0x%08x\n", (u_int32_t)__bss_start);
- debugf(" _end = 0x%08x\n", (u_int32_t)_end);
+ debugf(" kernel_text = 0x%08x\n", (uint32_t)kernel_text);
+ debugf(" _etext (sdata) = 0x%08x\n", (uint32_t)_etext);
+ debugf(" _edata = 0x%08x\n", (uint32_t)_edata);
+ debugf(" __sbss_start = 0x%08x\n", (uint32_t)__sbss_start);
+ debugf(" __sbss_end = 0x%08x\n", (uint32_t)__sbss_end);
+ debugf(" __sbss_start = 0x%08x\n", (uint32_t)__bss_start);
+ debugf(" _end = 0x%08x\n", (uint32_t)_end);
}
struct bi_mem_region *
bootinfo_mr(void)
{
- return((struct bi_mem_region *)bootinfo->bi_data);
+ return ((struct bi_mem_region *)bootinfo->bi_data);
}
struct bi_eth_addr *
@@ -346,7 +347,7 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
kmdp = preload_search_by_type("elf kernel");
if (kmdp != NULL) {
bootinfo = (struct bootinfo *)preload_search_info(kmdp,
- MODINFO_METADATA|MODINFOMD_BOOTINFO);
+ MODINFO_METADATA | MODINFOMD_BOOTINFO);
boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
@@ -384,7 +385,7 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
* Time Base and Decrementer are updated every 8 CCB bus clocks.
* HID0[SEL_TBCLK] = 0
*/
- decr_config(bootinfo->bi_bus_clk/8);
+ decr_config(bootinfo->bi_bus_clk / 8);
/* Init params/tunables that can be overridden by the loader. */
init_param1();
@@ -397,7 +398,6 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
pc = &__pcpu[0];
pcpu_init(pc, 0, sizeof(struct pcpu));
pc->pc_curthread = &thread0;
- pc->pc_cpuid = 0;
__asm __volatile("mtsprg 0, %0" :: "r"(pc));
/* Initialize system mutexes. */
@@ -410,14 +410,17 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
debugf("e500_init: console initialized\n");
debugf(" arg1 startkernel = 0x%08x\n", startkernel);
debugf(" arg2 endkernel = 0x%08x\n", endkernel);
- debugf(" arg3 midp = 0x%08x\n", (u_int32_t)mdp);
+ debugf(" arg3 mdp = 0x%08x\n", (u_int32_t)mdp);
debugf(" end = 0x%08x\n", (u_int32_t)end);
debugf(" boothowto = 0x%08x\n", boothowto);
debugf(" kernel ccsrbar = 0x%08x\n", CCSRBAR_VA);
debugf(" MSR = 0x%08x\n", mfmsr());
- dump_bootinfo();
+ debugf(" HID0 = 0x%08x\n", mfspr(SPR_HID0));
+ debugf(" HID1 = 0x%08x\n", mfspr(SPR_HID1));
+
+ print_bootinfo();
print_kernel_section_addr();
- dump_kenv();
+ print_kenv();
//tlb1_print_entries();
//tlb1_print_tlbentries();
@@ -427,7 +430,6 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
if (boothowto & RB_KDB)
kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
#endif
- kobj_machdep_init();
/* Initialise virtual memory. */
pmap_mmu_install(MMU_TYPE_BOOKE, 0);
@@ -459,6 +461,7 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
dcache_inval();
dcache_enable();
}
+
csr = mfspr(SPR_L1CSR0);
if ((boothowto & RB_VERBOSE) != 0 || (csr & L1CSR0_DCE) == 0)
printf("L1 D-cache %sabled\n",
@@ -470,6 +473,7 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
icache_inval();
icache_enable();
}
+
csr = mfspr(SPR_L1CSR1);
if ((boothowto & RB_VERBOSE) != 0 || (csr & L1CSR1_ICE) == 0)
printf("L1 I-cache %sabled\n",
diff --git a/sys/powerpc/include/elf.h b/sys/powerpc/include/elf.h
index d2b8e12..422a86a 100644
--- a/sys/powerpc/include/elf.h
+++ b/sys/powerpc/include/elf.h
@@ -80,9 +80,6 @@ __ElfType(Auxinfo);
#define AT_COUNT 13 /* Count of defined aux entry types. */
-/* Used in John Polstra's testbed stuff. */
-#define AT_DEBUG 14 /* Debugging level. */
-
/*
* Relocation types.
*/
diff --git a/sys/powerpc/include/ofw_machdep.h b/sys/powerpc/include/ofw_machdep.h
index a4b601e..1dd2027 100644
--- a/sys/powerpc/include/ofw_machdep.h
+++ b/sys/powerpc/include/ofw_machdep.h
@@ -28,9 +28,18 @@
#ifndef _MACHINE_OFW_MACHDEP_H_
#define _MACHINE_OFW_MACHDEP_H_
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/rman.h>
#include <sys/bus.h>
+#include <dev/ofw/openfirm.h>
+
+typedef uint32_t cell_t;
int OF_decode_addr(phandle_t, int, bus_space_tag_t *, bus_space_handle_t *);
void OF_getetheraddr(device_t dev, u_char *addr);
+void OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *));
+boolean_t OF_bootstrap(void);
+
#endif /* _MACHINE_OFW_MACHDEP_H_ */
diff --git a/sys/powerpc/include/param.h b/sys/powerpc/include/param.h
index 1b58db9..1a910ba 100644
--- a/sys/powerpc/include/param.h
+++ b/sys/powerpc/include/param.h
@@ -56,6 +56,9 @@
#ifndef _NO_NAMESPACE_POLLUTION
+/* Needed to display interrupts on OFW PCI */
+#define __PCI_REROUTE_INTERRUPT
+
#ifndef _MACHINE_PARAM_H_
#define _MACHINE_PARAM_H_
diff --git a/sys/powerpc/include/spr.h b/sys/powerpc/include/spr.h
index 1662add..70a0012 100644
--- a/sys/powerpc/include/spr.h
+++ b/sys/powerpc/include/spr.h
@@ -560,14 +560,15 @@
#define SPR_MCSRR1 0x23b /* ..8 571 Machine check SRR1 */
#define SPR_SVR 0x3ff /* ..8 1023 System Version Register */
-#define SVR_MPC8533 0x803c0010
-#define SVR_MPC8533E 0x80340010
-#define SVR_MPC8541 0x80720011
-#define SVR_MPC8541E 0x807a0011
-#define SVR_MPC8555 0x80710011
-#define SVR_MPC8555E 0x80790011
-#define SVR_MPC8572 0x80e00010
-#define SVR_MPC8572E 0x80e80010
+#define SVR_MPC8533 0x803c
+#define SVR_MPC8533E 0x8034
+#define SVR_MPC8541 0x8072
+#define SVR_MPC8541E 0x807a
+#define SVR_MPC8555 0x8071
+#define SVR_MPC8555E 0x8079
+#define SVR_MPC8572 0x80e0
+#define SVR_MPC8572E 0x80e8
+#define SVR_VER(svr) (((svr) >> 16) & 0xffff)
#define SPR_PID0 0x030 /* ..8 Process ID Register 0 */
#define SPR_PID1 0x279 /* ..8 Process ID Register 1 */
@@ -623,5 +624,4 @@
#endif /* #elif defined(E500) */
-
#endif /* !_POWERPC_SPR_H_ */
diff --git a/sys/powerpc/mpc85xx/lbc.c b/sys/powerpc/mpc85xx/lbc.c
index 4b168b8..2267245 100644
--- a/sys/powerpc/mpc85xx/lbc.c
+++ b/sys/powerpc/mpc85xx/lbc.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006-2008, Juniper Networks, Inc.
+ * Copyright (c) 2008 Semihalf, Rafal Czubak
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,6 +45,8 @@ __FBSDID("$FreeBSD$");
#include <vm/pmap.h>
#include <powerpc/mpc85xx/lbc.h>
+#include <powerpc/mpc85xx/mpc85xx.h>
+#include <powerpc/mpc85xx/ocpbus.h>
struct lbc_softc {
device_t sc_dev;
@@ -54,16 +57,41 @@ struct lbc_softc {
int sc_rid;
struct rman sc_rman;
- uintptr_t sc_kva;
+ vm_offset_t sc_kva[LBC_DEV_MAX];
};
struct lbc_devinfo {
int lbc_devtype;
- int lbc_memtype;
- /* Also the BAR number */
+ /* LBC child unit. It also represents resource table entry number */
int lbc_unit;
};
+/* Resources for MPC8555CDS system */
+const struct lbc_resource mpc85xx_lbc_resources[] = {
+ /* Boot flash bank */
+ {
+ LBC_DEVTYPE_CFI, 0, 0xff800000, 0x00800000, 16,
+ LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED,
+ LBCRES_ATOM_DISABLED, 0
+ },
+
+ /* Second flash bank */
+ {
+ LBC_DEVTYPE_CFI, 1, 0xff000000, 0x00800000, 16,
+ LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED,
+ LBCRES_ATOM_DISABLED, 0
+ },
+
+ /* DS1553 RTC/NVRAM */
+ {
+ LBC_DEVTYPE_RTC, 2, 0xf8000000, 0x8000, 8,
+ LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED,
+ LBCRES_ATOM_DISABLED, 0
+ },
+
+ {0}
+};
+
static int lbc_probe(device_t);
static int lbc_attach(device_t);
static int lbc_shutdown(device_t);
@@ -108,26 +136,170 @@ static driver_t lbc_driver = {
devclass_t lbc_devclass;
DRIVER_MODULE(lbc, ocpbus, lbc_driver, lbc_devclass, 0, 0);
+static __inline void
+lbc_write_reg(struct lbc_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val);
+}
+
+static __inline uint32_t
+lbc_read_reg(struct lbc_softc *sc, bus_size_t off)
+{
+
+ return (bus_space_read_4(sc->sc_bst, sc->sc_bsh, off));
+}
+
+/*
+ * Calculate address mask used by OR(n) registers. Use memory region size to
+ * determine mask value. The size must be a power of two and within the range
+ * of 32KB - 4GB. Otherwise error code is returned. Value representing
+ * 4GB size can be passed as 0xffffffff.
+ */
+static uint32_t
+lbc_address_mask(uint32_t size)
+{
+ int n = 15;
+
+ if (size == ~0UL)
+ return (0);
+
+ while (n < 32) {
+ if (size == (1UL << n))
+ break;
+ n++;
+ }
+
+ if (n == 32)
+ return (EINVAL);
+
+ return (0xffff8000 << (n - 15));
+}
+
static device_t
-lbc_mk_child(device_t dev, int type, int mtype, int unit)
+lbc_mk_child(device_t dev, const struct lbc_resource *lbcres)
{
struct lbc_devinfo *dinfo;
device_t child;
+ if (lbcres->lbr_unit > LBC_DEV_MAX - 1)
+ return (NULL);
+
child = device_add_child(dev, NULL, -1);
if (child == NULL) {
- device_printf(dev, "could not add child device\n");
+ device_printf(dev, "could not add LBC child device\n");
return (NULL);
}
dinfo = malloc(sizeof(struct lbc_devinfo), M_DEVBUF, M_WAITOK | M_ZERO);
- dinfo->lbc_devtype = type;
- dinfo->lbc_memtype = mtype;
- dinfo->lbc_unit = unit;
+ dinfo->lbc_devtype = lbcres->lbr_devtype;
+ dinfo->lbc_unit = lbcres->lbr_unit;
device_set_ivars(child, dinfo);
return (child);
}
static int
+lbc_init_child(device_t dev, device_t child)
+{
+ struct lbc_softc *sc;
+ struct lbc_devinfo *dinfo;
+ const struct lbc_resource *res;
+ u_long start, size;
+ uint32_t regbuff;
+ int error, unit;
+
+ sc = device_get_softc(dev);
+ dinfo = device_get_ivars(child);
+
+ res = mpc85xx_lbc_resources;
+
+ regbuff = 0;
+ unit = -1;
+ for (; res->lbr_devtype; res++) {
+ if (res->lbr_unit != dinfo->lbc_unit)
+ continue;
+
+ start = res->lbr_base_addr;
+ size = res->lbr_size;
+ unit = res->lbr_unit;
+
+ /*
+ * Configure LAW for this LBC device and map its physical
+ * memory region into KVA
+ */
+ error = law_enable(OCP85XX_TGTIF_LBC, start, size);
+ if (error)
+ return (error);
+
+ sc->sc_kva[unit] = (vm_offset_t)pmap_mapdev(start, size);
+ if (sc->sc_kva[unit] == 0) {
+ law_disable(OCP85XX_TGTIF_LBC, start, size);
+ return (ENOSPC);
+ }
+
+ /*
+ * Compute and program BR value
+ */
+ regbuff |= start;
+
+ switch (res->lbr_port_size) {
+ case 8:
+ regbuff |= (1 << 11);
+ break;
+ case 16:
+ regbuff |= (2 << 11);
+ break;
+ case 32:
+ regbuff |= (3 << 11);
+ break;
+ default:
+ error = EINVAL;
+ goto fail;
+ }
+ regbuff |= (res->lbr_decc << 9);
+ regbuff |= (res->lbr_wp << 8);
+ regbuff |= (res->lbr_msel << 5);
+ regbuff |= (res->lbr_atom << 2);
+ regbuff |= 1;
+
+ lbc_write_reg(sc, LBC85XX_BR(unit), regbuff);
+
+ /*
+ * Compute and program OR value
+ */
+ regbuff = 0;
+ regbuff |= lbc_address_mask(size);
+
+ switch (res->lbr_msel) {
+ case LBCRES_MSEL_GPCM:
+ /* TODO Add flag support for option registers */
+ regbuff |= 0x00000ff7;
+ break;
+ case LBCRES_MSEL_FCM:
+ printf("FCM mode not supported yet!");
+ error = ENOSYS;
+ goto fail;
+ case LBCRES_MSEL_UPMA:
+ case LBCRES_MSEL_UPMB:
+ case LBCRES_MSEL_UPMC:
+ printf("UPM mode not supported yet!");
+ error = ENOSYS;
+ goto fail;
+ }
+
+ lbc_write_reg(sc, LBC85XX_OR(unit), regbuff);
+
+ return (0);
+ }
+fail:
+ if (unit != -1) {
+ law_disable(OCP85XX_TGTIF_LBC, start, size);
+ pmap_unmapdev(sc->sc_kva[unit], size);
+ return (error);
+ } else
+ return (ENOENT);
+}
+
+static int
lbc_probe(device_t dev)
{
device_t parent;
@@ -150,7 +322,7 @@ lbc_attach(device_t dev)
{
struct lbc_softc *sc;
struct rman *rm;
- u_long start, size;
+ const struct lbc_resource *lbcres;
int error;
sc = device_get_softc(dev);
@@ -165,15 +337,11 @@ lbc_attach(device_t dev)
sc->sc_bst = rman_get_bustag(sc->sc_res);
sc->sc_bsh = rman_get_bushandle(sc->sc_res);
- error = bus_get_resource(dev, SYS_RES_MEMORY, 1, &start, &size);
- if (error)
- goto fail;
-
rm = &sc->sc_rman;
rm->rm_type = RMAN_ARRAY;
rm->rm_descr = "MPC85XX Local Bus Space";
- rm->rm_start = start;
- rm->rm_end = start + size - 1;
+ rm->rm_start = 0UL;
+ rm->rm_end = ~0UL;
error = rman_init(rm);
if (error)
goto fail;
@@ -184,13 +352,35 @@ lbc_attach(device_t dev)
goto fail;
}
- sc->sc_kva = (uintptr_t)pmap_mapdev(start, size);
-
- lbc_mk_child(dev, LBC_DEVTYPE_CFI, 0, 0);
+ /*
+ * Initialize configuration register:
+ * - enable Local Bus
+ * - set data buffer control signal function
+ * - disable parity byte select
+ * - set ECC parity type
+ * - set bus monitor timing and timer prescale
+ */
+ lbc_write_reg(sc, LBC85XX_LBCR, 0x00000000);
+
+ /*
+ * Initialize clock ratio register:
+ * - disable PLL bypass mode
+ * - configure LCLK delay cycles for the assertion of LALE
+ * - set system clock divider
+ */
+ lbc_write_reg(sc, LBC85XX_LCRR, 0x00030008);
+
+ lbcres = mpc85xx_lbc_resources;
+
+ for (; lbcres->lbr_devtype; lbcres++)
+ if (!lbc_mk_child(dev, lbcres)) {
+ error = ENXIO;
+ goto fail;
+ }
return (bus_generic_attach(dev));
- fail:
+fail:
bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res);
return (error);
}
@@ -208,11 +398,13 @@ lbc_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct lbc_softc *sc;
+ struct lbc_devinfo *dinfo;
struct resource *rv;
struct rman *rm;
int error;
sc = device_get_softc(dev);
+ dinfo = device_get_ivars(child);
if (type != SYS_RES_MEMORY && type != SYS_RES_IRQ)
return (NULL);
@@ -225,6 +417,12 @@ lbc_alloc_resource(device_t dev, device_t child, int type, int *rid,
return (bus_alloc_resource(dev, type, rid, start, end, count,
flags));
+ if (!sc->sc_kva[dinfo->lbc_unit]) {
+ error = lbc_init_child(dev, child);
+ if (error)
+ return (NULL);
+ }
+
error = lbc_get_resource(dev, child, type, *rid, &start, &count);
if (error)
return (NULL);
@@ -234,8 +432,7 @@ lbc_alloc_resource(device_t dev, device_t child, int type, int *rid,
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv != NULL) {
rman_set_bustag(rv, &bs_be_tag);
- rman_set_bushandle(rv, sc->sc_kva + rman_get_start(rv) -
- rm->rm_start);
+ rman_set_bushandle(rv, rman_get_start(rv));
}
return (rv);
}
@@ -279,12 +476,6 @@ lbc_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
case LBC_IVAR_DEVTYPE:
*result = dinfo->lbc_devtype;
return (0);
- case LBC_IVAR_CLOCK:
- *result = 1843200;
- return (0);
- case LBC_IVAR_REGSHIFT:
- *result = 0;
- return (0);
default:
break;
}
@@ -305,24 +496,35 @@ lbc_get_resource(device_t dev, device_t child, int type, int rid,
{
struct lbc_softc *sc;
struct lbc_devinfo *dinfo;
+ const struct lbc_resource *lbcres;
if (type != SYS_RES_MEMORY)
return (ENOENT);
- /* Currently all devices have a single RID per type. */
+ /* Currently all LBC devices have a single RID per type. */
if (rid != 0)
return (ENOENT);
sc = device_get_softc(dev);
dinfo = device_get_ivars(child);
+ if ((dinfo->lbc_unit < 0) || (dinfo->lbc_unit > (LBC_DEV_MAX - 1)))
+ return (EINVAL);
+
+ lbcres = mpc85xx_lbc_resources;
+
switch (dinfo->lbc_devtype) {
case LBC_DEVTYPE_CFI:
- *startp = sc->sc_rman.rm_start;
- *countp = sc->sc_rman.rm_end - sc->sc_rman.rm_start + 1;
- break;
+ case LBC_DEVTYPE_RTC:
+ for (; lbcres->lbr_devtype; lbcres++) {
+ if (dinfo->lbc_unit == lbcres->lbr_unit) {
+ *startp = sc->sc_kva[lbcres->lbr_unit];
+ *countp = lbcres->lbr_size;
+ return (0);
+ }
+ }
default:
- return(EDOOFUS);
+ return (EDOOFUS);
}
- return(0);
+ return (0);
}
diff --git a/sys/powerpc/mpc85xx/lbc.h b/sys/powerpc/mpc85xx/lbc.h
index 8bc7843..24e741a 100644
--- a/sys/powerpc/mpc85xx/lbc.h
+++ b/sys/powerpc/mpc85xx/lbc.h
@@ -30,11 +30,49 @@
#define _MACHINE_LBC_H_
#define LBC_IVAR_DEVTYPE 1
-#define LBC_IVAR_CLOCK 2
-#define LBC_IVAR_REGSHIFT 3
+
+/* Maximum number of devices on Local Bus */
+#define LBC_DEV_MAX 8
/* Device types. */
#define LBC_DEVTYPE_CFI 1
-#define LBC_DEVTYPE_UART 2
+#define LBC_DEVTYPE_RTC 2
+
+/* Local access registers */
+#define LBC85XX_BR(n) (OCP85XX_LBC_OFF + (8 * n))
+#define LBC85XX_OR(n) (OCP85XX_LBC_OFF + 4 + (8 * n))
+#define LBC85XX_LBCR (OCP85XX_LBC_OFF + 0xd0)
+#define LBC85XX_LCRR (OCP85XX_LBC_OFF + 0xd4)
+
+/* LBC machine select */
+#define LBCRES_MSEL_GPCM 0
+#define LBCRES_MSEL_FCM 1
+#define LBCRES_MSEL_UPMA 8
+#define LBCRES_MSEL_UPMB 9
+#define LBCRES_MSEL_UPMC 10
+
+/* LBC data error checking modes */
+#define LBCRES_DECC_DISABLED 0
+#define LBCRES_DECC_NORMAL 1
+#define LBCRES_DECC_RMW 2
+
+/* LBC atomic operation modes */
+#define LBCRES_ATOM_DISABLED 0
+#define LBCRES_ATOM_RAWA 1
+#define LBCRES_ATOM_WARA 2
+
+struct lbc_resource {
+ int lbr_devtype; /* LBC device type */
+ int lbr_unit; /* Resource table entry number */
+ vm_paddr_t lbr_base_addr; /* Device mem region base address */
+ size_t lbr_size; /* Device mem region size */
+ int lbr_port_size; /* Data bus width */
+ uint8_t lbr_msel; /* LBC machine select */
+ uint8_t lbr_decc; /* Data error checking mode */
+ uint8_t lbr_atom; /* Atomic operation mode */
+ uint8_t lbr_wp; /* Write protect */
+};
+
+extern const struct lbc_resource mpc85xx_lbc_resources[];
#endif /* _MACHINE_LBC_H_ */
diff --git a/sys/powerpc/mpc85xx/mpc85xx.c b/sys/powerpc/mpc85xx/mpc85xx.c
index 62a47a6..de9c771 100644
--- a/sys/powerpc/mpc85xx/mpc85xx.c
+++ b/sys/powerpc/mpc85xx/mpc85xx.c
@@ -10,9 +10,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the author nor the names of contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -38,33 +35,117 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/cpufunc.h>
-#include <machine/pio.h>
#include <machine/spr.h>
#include <powerpc/mpc85xx/ocpbus.h>
+#include <powerpc/mpc85xx/mpc85xx.h>
/*
* MPC85xx system specific routines
*/
+uint32_t
+ccsr_read4(uintptr_t addr)
+{
+ volatile uint32_t *ptr = (void *)addr;
+
+ return (*ptr);
+}
+
+void
+ccsr_write4(uintptr_t addr, uint32_t val)
+{
+ volatile uint32_t *ptr = (void *)addr;
+
+ *ptr = val;
+ __asm __volatile("eieio; sync");
+}
+
+static __inline int
+law_getmax(void)
+{
+ uint32_t ver;
+
+ ver = SVR_VER(mfspr(SPR_SVR));
+ if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
+ return (12);
+ else
+ return (8);
+}
+
+#define _LAW_SR(trgt,size) (0x80000000 | (trgt << 20) | (ffsl(size) - 2))
+#define _LAW_BAR(addr) (addr >> 12)
+
+int
+law_enable(int trgt, u_long addr, u_long size)
+{
+ uint32_t bar, sr;
+ int i, law_max;
+
+ law_max = law_getmax();
+ bar = _LAW_BAR(addr);
+ sr = _LAW_SR(trgt, size);
+
+ /* Bail if already programmed. */
+ for (i = 0; i < law_max; i++)
+ if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
+ bar == ccsr_read4(OCP85XX_LAWBAR(i)))
+ return (0);
+
+ /* Find an unused access window. */
+ for (i = 0; i < law_max; i++)
+ if ((ccsr_read4(OCP85XX_LAWSR(i)) & 0x80000000) == 0)
+ break;
+
+ if (i == law_max)
+ return (ENOSPC);
+
+ ccsr_write4(OCP85XX_LAWBAR(i), bar);
+ ccsr_write4(OCP85XX_LAWSR(i), sr);
+ return (0);
+}
+
+int
+law_disable(int trgt, u_long addr, u_long size)
+{
+ uint32_t bar, sr;
+ int i, law_max;
+
+ law_max = law_getmax();
+ bar = _LAW_BAR(addr);
+ sr = _LAW_SR(trgt, size);
+
+ /* Find and disable requested LAW. */
+ for (i = 0; i < law_max; i++)
+ if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
+ bar == ccsr_read4(OCP85XX_LAWBAR(i))) {
+ ccsr_write4(OCP85XX_LAWBAR(i), 0);
+ ccsr_write4(OCP85XX_LAWSR(i), 0);
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
void
-cpu_reset()
+cpu_reset(void)
{
- uint32_t svr = mfspr(SPR_SVR);
+ uint32_t ver = SVR_VER(mfspr(SPR_SVR));
- if (svr == SVR_MPC8572E || svr == SVR_MPC8572)
+ if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
/* Systems with dedicated reset register */
- out32(OCP85XX_RSTCR, 2);
+ ccsr_write4(OCP85XX_RSTCR, 2);
else {
/* Clear DBCR0, disables debug interrupts and events. */
mtspr(SPR_DBCR0, 0);
- __asm volatile("isync");
+ __asm __volatile("isync");
/* Enable Debug Interrupts in MSR. */
mtmsr(mfmsr() | PSL_DE);
/* Enable debug interrupts and issue reset. */
- mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) | DBCR0_IDM | DBCR0_RST_SYSTEM);
+ mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) | DBCR0_IDM |
+ DBCR0_RST_SYSTEM);
}
printf("Reset failed...\n");
diff --git a/sys/powerpc/mpc85xx/mpc85xx.h b/sys/powerpc/mpc85xx/mpc85xx.h
new file mode 100644
index 0000000..4d31b58
--- /dev/null
+++ b/sys/powerpc/mpc85xx/mpc85xx.h
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (C) 2008 Semihalf, Rafal Jaworowski
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL 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 _MPC85XX_H_
+#define _MPC85XX_H_
+
+uint32_t ccsr_read4(uintptr_t addr);
+void ccsr_write4(uintptr_t addr, uint32_t val);
+int law_enable(int trgt, u_long addr, u_long size);
+int law_disable(int trgt, u_long addr, u_long size);
+
+#endif /* _MPC85XX_H_ */
diff --git a/sys/powerpc/mpc85xx/nexus.c b/sys/powerpc/mpc85xx/nexus.c
index 01e0425..fa07247 100644
--- a/sys/powerpc/mpc85xx/nexus.c
+++ b/sys/powerpc/mpc85xx/nexus.c
@@ -70,13 +70,9 @@ __FBSDID("$FreeBSD$");
*/
static int nexus_probe(device_t);
static int nexus_activate_resource(device_t, device_t, int, int,
- struct resource *);
+ struct resource *);
static int nexus_deactivate_resource(device_t, device_t, int, int,
- struct resource *);
-
-/*
- * Local routines
- */
+ struct resource *);
static device_method_t nexus_methods[] = {
/* Device interface */
diff --git a/sys/powerpc/mpc85xx/ocpbus.c b/sys/powerpc/mpc85xx/ocpbus.c
index a741849..ae56fb0 100644
--- a/sys/powerpc/mpc85xx/ocpbus.c
+++ b/sys/powerpc/mpc85xx/ocpbus.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bootinfo.h>
#include <powerpc/mpc85xx/ocpbus.h>
+#include <powerpc/mpc85xx/mpc85xx.h>
#include "pic_if.h"
@@ -115,23 +116,6 @@ DRIVER_MODULE(ocpbus, nexus, ocpbus_driver, ocpbus_devclass, 0, 0);
static int law_max = 0;
-static __inline uint32_t
-ccsr_read4(uintptr_t addr)
-{
- volatile uint32_t *ptr = (void *)addr;
-
- return (*ptr);
-}
-
-static __inline void
-ccsr_write4(uintptr_t addr, uint32_t val)
-{
- volatile uint32_t *ptr = (void *)addr;
-
- *ptr = val;
- __asm __volatile("eieio; sync");
-}
-
static device_t
ocpbus_mk_child(device_t dev, int type, int unit)
{
@@ -154,8 +138,6 @@ static int
ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp)
{
u_long addr, size;
- int i;
- uint32_t bar, sr;
switch (type) {
case SYS_RES_MEMORY:
@@ -172,10 +154,6 @@ ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp)
addr = 0xA0000000;
size = 0x10000000;
break;
- case OCP85XX_TGTIF_LBC:
- addr = 0xff800000;
- size = 0x00800000;
- break;
default:
return (EINVAL);
}
@@ -205,40 +183,19 @@ ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp)
*startp = addr;
*countp = size;
- /* Program the LAWs for this memory range. */
- bar = addr >> 12;
- sr = 0x80000000 | (trgt << 20) | (ffsl(size) - 2);
-
- /* Check if already programmed. */
- for (i = 0; i < law_max; i++) {
- if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
- bar == ccsr_read4(OCP85XX_LAWBAR(i)))
- return (0);
- }
-
- /* Find an unused access window .*/
- for (i = 0; i < law_max; i++) {
- if ((ccsr_read4(OCP85XX_LAWSR(i)) & 0x80000000) == 0)
- break;
- }
- if (i == law_max)
- return (ENOSPC);
-
- ccsr_write4(OCP85XX_LAWBAR(i), bar);
- ccsr_write4(OCP85XX_LAWSR(i), sr);
- return (0);
+ return (law_enable(trgt, *startp, *countp));
}
static int
-ocpbus_probe (device_t dev)
+ocpbus_probe(device_t dev)
{
struct ocpbus_softc *sc;
- uint32_t svr;
+ uint32_t ver;
sc = device_get_softc(dev);
- svr = mfspr(SPR_SVR);
- if (svr == SVR_MPC8572E || svr == SVR_MPC8572)
+ ver = SVR_VER(mfspr(SPR_SVR));
+ if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
law_max = 12;
else
law_max = 8;
@@ -248,7 +205,7 @@ ocpbus_probe (device_t dev)
}
static int
-ocpbus_attach (device_t dev)
+ocpbus_attach(device_t dev)
{
struct ocpbus_softc *sc;
int error, i, tgt;
@@ -393,7 +350,6 @@ const struct ocp_resource mpc8555_resources[] = {
{OCPBUS_DEVTYPE_LBC, 0, SYS_RES_MEMORY, 0, OCP85XX_LBC_OFF,
OCP85XX_LBC_SIZE},
- {OCPBUS_DEVTYPE_LBC, 0, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_LBC},
{OCPBUS_DEVTYPE_I2C, 0, SYS_RES_MEMORY, 0, OCP85XX_I2C0_OFF,
OCP85XX_I2C_SIZE},
diff --git a/sys/powerpc/ofw/ofw_pcib_pci.c b/sys/powerpc/ofw/ofw_pcib_pci.c
index 5d6fba6..0b6e0ca 100644
--- a/sys/powerpc/ofw/ofw_pcib_pci.c
+++ b/sys/powerpc/ofw/ofw_pcib_pci.c
@@ -36,6 +36,7 @@
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -46,6 +47,8 @@
static int ofw_pcib_pci_probe(device_t bus);
static int ofw_pcib_pci_attach(device_t bus);
static phandle_t ofw_pcib_pci_get_node(device_t bus, device_t dev);
+static int ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev,
+ int intpin);
static device_method_t ofw_pcib_pci_methods[] = {
/* Device interface */
@@ -70,7 +73,7 @@ static device_method_t ofw_pcib_pci_methods[] = {
DEVMETHOD(pcib_maxslots, pcib_maxslots),
DEVMETHOD(pcib_read_config, pcib_read_config),
DEVMETHOD(pcib_write_config, pcib_write_config),
- DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt),
+ DEVMETHOD(pcib_route_interrupt, ofw_pcib_pci_route_interrupt),
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_node, ofw_pcib_pci_get_node),
@@ -80,8 +83,20 @@ static device_method_t ofw_pcib_pci_methods[] = {
static devclass_t pcib_devclass;
+struct ofw_pcib_softc {
+ /*
+ * This is here so that we can use pci bridge methods, too - the
+ * generic routines only need the dev, secbus and subbus members
+ * filled.
+ */
+ struct pcib_softc ops_pcib_sc;
+ phandle_t ops_node;
+ struct ofw_bus_iinfo ops_iinfo;
+};
+
+
DEFINE_CLASS_0(pcib, ofw_pcib_pci_driver, ofw_pcib_pci_methods,
- sizeof(struct pcib_softc));
+ sizeof(struct ofw_pcib_softc));
DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_pci_driver, pcib_devclass, 0, 0);
static int
@@ -103,6 +118,15 @@ ofw_pcib_pci_probe(device_t dev)
static int
ofw_pcib_pci_attach(device_t dev)
{
+ struct ofw_pcib_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->ops_pcib_sc.dev = dev;
+ sc->ops_node = ofw_bus_get_node(dev);
+
+ ofw_bus_setup_iinfo(sc->ops_node, &sc->ops_iinfo,
+ sizeof(cell_t));
+
pcib_attach_common(dev);
device_add_child(dev, "pci", -1);
@@ -110,7 +134,7 @@ ofw_pcib_pci_attach(device_t dev)
return (bus_generic_attach(dev));
}
-phandle_t
+static phandle_t
ofw_pcib_pci_get_node(device_t bridge, device_t dev)
{
/* We have only one child, the PCI bus, so pass it our node */
@@ -118,3 +142,37 @@ ofw_pcib_pci_get_node(device_t bridge, device_t dev)
return (ofw_bus_get_node(bridge));
}
+static int
+ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev, int intpin)
+{
+ struct ofw_pcib_softc *sc;
+ struct ofw_bus_iinfo *ii;
+ struct ofw_pci_register reg;
+ cell_t pintr, mintr;
+ uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
+
+ sc = device_get_softc(bridge);
+ ii = &sc->ops_iinfo;
+ if (ii->opi_imapsz > 0) {
+ pintr = intpin;
+ if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), ii, &reg,
+ sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
+ maskbuf)) {
+ /*
+ * If we've found a mapping, return it and don't map
+ * it again on higher levels - that causes problems
+ * in some cases, and never seems to be required.
+ */
+ return (mintr);
+ }
+ } else if (intpin >= 1 && intpin <= 4) {
+ /*
+ * When an interrupt map is missing, we need to do the
+ * standard PCI swizzle and continue mapping at the parent.
+ */
+ return (pcib_route_interrupt(bridge, dev, intpin));
+ }
+ return (PCIB_ROUTE_INTERRUPT(device_get_parent(device_get_parent(
+ bridge)), bridge, intpin));
+}
+
diff --git a/sys/powerpc/ofw/ofw_pcibus.c b/sys/powerpc/ofw/ofw_pcibus.c
index 916d98b..6ec2da6 100644
--- a/sys/powerpc/ofw/ofw_pcibus.c
+++ b/sys/powerpc/ofw/ofw_pcibus.c
@@ -1,6 +1,4 @@
/*-
- * Copyright (c) 1994 Charles M. Hannum. All rights reserved.
- * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
* Copyright (c) 1997, Stefan Esser <se@freebsd.org>
* Copyright (c) 2000, Michael Smith <msmith@freebsd.org>
* Copyright (c) 2000, BSDi
@@ -54,22 +52,27 @@ __FBSDID("$FreeBSD$");
#include "pcib_if.h"
#include "pci_if.h"
-/* Helper functions */
-static int find_node_intr(phandle_t, u_int32_t *, u_int32_t *);
-static int ofw_pci_find_intline(phandle_t node, uint32_t *irqs);
-static void ofw_pci_fixup_node(device_t dev, phandle_t node);
+typedef uint32_t ofw_pci_intr_t;
/* Methods */
static device_probe_t ofw_pcibus_probe;
static device_attach_t ofw_pcibus_attach;
static pci_assign_interrupt_t ofw_pcibus_assign_interrupt;
static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo;
+static int ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child,
+ char *buf, size_t buflen);
+
+static void ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno);
+static void ofw_pcibus_enum_bus(device_t dev, u_int domain, u_int busno);
static device_method_t ofw_pcibus_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ofw_pcibus_probe),
DEVMETHOD(device_attach, ofw_pcibus_attach),
+ /* Bus interface */
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_child_pnpinfo_str_method),
+
/* PCI interface */
DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt),
@@ -100,6 +103,7 @@ MODULE_DEPEND(ofw_pcibus, pci, 1, 1, 1);
static int
ofw_pcibus_probe(device_t dev)
{
+
if (ofw_bus_get_node(dev) == 0)
return (ENXIO);
device_set_desc(dev, "OFW PCI bus");
@@ -110,18 +114,43 @@ ofw_pcibus_probe(device_t dev)
static int
ofw_pcibus_attach(device_t dev)
{
- device_t pcib;
- struct ofw_pci_register pcir;
- struct ofw_pcibus_devinfo *dinfo;
- phandle_t node, child;
- u_int busno, domain, func, slot;
+ u_int busno, domain;
- pcib = device_get_parent(dev);
domain = pcib_get_domain(dev);
busno = pcib_get_bus(dev);
if (bootverbose)
device_printf(dev, "domain=%d, physical bus=%d\n",
domain, busno);
+
+ /*
+ * Attach those children represented in the device tree.
+ */
+
+ ofw_pcibus_enum_devtree(dev, domain, busno);
+
+ /*
+ * We now attach any laggard devices. FDT, for instance, allows
+ * the device tree to enumerate only some PCI devices. Apple's
+ * OF device tree on some Grackle-based hardware can also miss
+ * functions on multi-function cards.
+ */
+
+ ofw_pcibus_enum_bus(dev, domain, busno);
+
+ return (bus_generic_attach(dev));
+}
+
+static void
+ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno)
+{
+ device_t pcib;
+ struct ofw_pci_register pcir;
+ struct ofw_pcibus_devinfo *dinfo;
+ phandle_t node, child;
+ u_int func, slot;
+ int intline;
+
+ pcib = device_get_parent(dev);
node = ofw_bus_get_node(dev);
for (child = OF_child(node); child != 0; child = OF_peer(child)) {
@@ -134,226 +163,178 @@ ofw_pcibus_attach(device_t dev)
if (pci_find_dbsf(domain, busno, slot, func) != NULL)
continue;
- ofw_pci_fixup_node(pcib, child);
+ /*
+ * The preset in the intline register is usually bogus. Reset
+ * it such that the PCI code will reroute the interrupt if
+ * needed.
+ */
+
+ intline = PCI_INVALID_IRQ;
+ if (OF_getproplen(child, "interrupts") > 0)
+ intline = 0;
+ PCIB_WRITE_CONFIG(pcib, busno, slot, func, PCIR_INTLINE,
+ intline, 1);
+
+ /*
+ * Now set up the PCI and OFW bus layer devinfo and add it
+ * to the PCI bus.
+ */
dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib,
domain, busno, slot, func, sizeof(*dinfo));
-
if (dinfo == NULL)
continue;
-
- /* Set up OFW devinfo */
if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) !=
0) {
pci_freecfg((struct pci_devinfo *)dinfo);
continue;
}
-
pci_add_child(dev, (struct pci_devinfo *)dinfo);
/*
- * Some devices don't have an intpin set, but do have
- * interrupts. Add them to the appropriate resource list.
- */
- if (dinfo->opd_dinfo.cfg.intpin == 0) {
- uint32_t irqs[4];
-
- if (ofw_pci_find_intline(child, irqs) > 0)
- resource_list_add(&dinfo->opd_dinfo.resources,
- SYS_RES_IRQ, 0, irqs[0], irqs[0], 1);
- }
+ * Some devices don't have an intpin set, but do have
+ * interrupts. These are fully specified, and set in the
+ * interrupts property, so add that value to the device's
+ * resource list.
+ */
+ if (dinfo->opd_dinfo.cfg.intpin == 0) {
+ ofw_pci_intr_t intr;
+
+ if (OF_getprop(child, "interrupts", &intr,
+ sizeof(intr)) > 0) {
+ resource_list_add(&dinfo->opd_dinfo.resources,
+ SYS_RES_IRQ, 0, intr, intr, 1);
+ }
+ }
}
-
- return (bus_generic_attach(dev));
}
-static int
-ofw_pcibus_assign_interrupt(device_t dev, device_t child)
-{
- uint32_t irqs[4];
-
- device_printf(child,"Assigning interrupt\n");
-
- if (ofw_pci_find_intline(ofw_bus_get_node(child), irqs) < 0)
- return PCI_INVALID_IRQ;
-
- device_printf(child,"IRQ %d\n",irqs[0]);
-
- return irqs[0];
-
-// return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr));
-}
-
-static const struct ofw_bus_devinfo *
-ofw_pcibus_get_devinfo(device_t bus, device_t dev)
-{
- struct ofw_pcibus_devinfo *dinfo;
-
- dinfo = device_get_ivars(dev);
- return (&dinfo->opd_obdinfo);
-}
+/*
+ * The following is an almost exact clone of pci_add_children(), with the
+ * addition that it (a) will not add children that have already been added,
+ * and (b) will set up the OFW devinfo to point to invalid values. This is
+ * to handle non-enumerated PCI children as exist in FDT and on the second
+ * function of the Rage 128 in my Blue & White G3.
+ */
static void
-ofw_pci_fixup_node(device_t dev, phandle_t node)
+ofw_pcibus_enum_bus(device_t dev, u_int domain, u_int busno)
{
- uint32_t csr, intr, irqs[4];
- struct ofw_pci_register addr[8];
- int len, i;
+ device_t pcib;
+ struct ofw_pcibus_devinfo *dinfo;
+ int maxslots;
+ int s, f, pcifunchigh;
+ uint8_t hdrtype;
- len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr));
- if (len < (int)sizeof(struct ofw_pci_register)) {
- return;
- }
+ pcib = device_get_parent(dev);
- csr = PCIB_READ_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_COMMAND, 4);
- csr &= ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN);
-
- for (i = 0; i < len / sizeof(struct ofw_pci_register); i++) {
- switch (addr[i].phys_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
- case OFW_PCI_PHYS_HI_SPACE_IO:
- csr |= PCIM_CMD_PORTEN;
- break;
- case OFW_PCI_PHYS_HI_SPACE_MEM32:
- csr |= PCIM_CMD_MEMEN;
- break;
+ maxslots = PCIB_MAXSLOTS(pcib);
+ for (s = 0; s <= maxslots; s++) {
+ pcifunchigh = 0;
+ f = 0;
+ DELAY(1);
+ hdrtype = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_HDRTYPE, 1);
+ if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
+ continue;
+ if (hdrtype & PCIM_MFDEV)
+ pcifunchigh = PCI_FUNCMAX;
+ for (f = 0; f <= pcifunchigh; f++) {
+ /* Filter devices we have already added */
+ if (pci_find_dbsf(domain, busno, s, f) != NULL)
+ continue;
+
+ dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(
+ pcib, domain, busno, s, f, sizeof(*dinfo));
+ if (dinfo != NULL) {
+ dinfo->opd_obdinfo.obd_node = -1;
+
+ dinfo->opd_obdinfo.obd_name = NULL;
+ dinfo->opd_obdinfo.obd_compat = NULL;
+ dinfo->opd_obdinfo.obd_type = NULL;
+ dinfo->opd_obdinfo.obd_model = NULL;
+ pci_add_child(dev, (struct pci_devinfo *)dinfo);
+ }
}
}
-
- PCIB_WRITE_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_COMMAND, csr, 4);
-
- if (ofw_pci_find_intline(node, irqs) != -1) {
- intr = PCIB_READ_CONFIG(dev,
- OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_INTLINE, 2);
- intr &= ~(0xff);
- intr |= irqs[0] & 0xff;
- PCIB_WRITE_CONFIG(dev,
- OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_INTLINE,
- intr, 2);
- }
}
static int
-ofw_pci_find_intline(phandle_t node, uint32_t *irqs)
+ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf,
+ size_t buflen)
{
- uint32_t npintr, paddr[4];
- struct ofw_pci_register addr[8];
- int len;
+ pci_child_pnpinfo_str_method(cbdev, child, buf, buflen);
- len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr));
- if (len < (int)sizeof(struct ofw_pci_register))
- return -1;
- /*
- * Create PCI interrupt-map array element. pci-mid/pci-lo
- * aren't required, but the 'interrupts' property needs
- * to be appended
- */
- npintr = 0;
- OF_getprop(node, "interrupts", &npintr, 4);
- paddr[0] = addr[0].phys_hi;
- paddr[1] = 0;
- paddr[2] = 0;
- paddr[3] = npintr;
-
- return find_node_intr(node, paddr, irqs);
-}
+ if (ofw_bus_get_node(child) != -1) {
+ strlcat(buf, " ", buflen); /* Separate info */
+ ofw_bus_gen_child_pnpinfo_str(cbdev, child, buf, buflen);
+ }
+ return (0);
+}
+
static int
-find_node_intr(phandle_t node, u_int32_t *addr, u_int32_t *intr)
+ofw_pcibus_assign_interrupt(device_t dev, device_t child)
{
- phandle_t parent, iparent;
- int len, mlen, match, i;
- u_int32_t map[160], *mp, imask[8], maskedaddr[8], icells;
- char name[32];
-
- len = OF_getprop(node, "AAPL,interrupts", intr, 4);
- if (len == 4) {
- return (len);
- }
-
- parent = OF_parent(node);
- len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
- mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask));
+ ofw_pci_intr_t intr;
+ phandle_t node;
+ int isz;
- if (len == -1 || mlen == -1)
- goto nomap;
-
- memcpy(maskedaddr, addr, mlen);
- for (i = 0; i < mlen/4; i++)
- maskedaddr[i] &= imask[i];
-
- mp = map;
- while (len > mlen) {
- match = bcmp(maskedaddr, mp, mlen);
- mp += mlen / 4;
- len -= mlen;
+ node = ofw_bus_get_node(child);
+ if (node == -1) {
+ /* Non-firmware enumerated child, use standard routing */
+
/*
- * We must read "#interrupt-cells" for each time because
- * interrupt-parent may be different.
+ * XXX: Right now we don't have anything sensible to do here,
+ * since the ofw_imap stuff relies on nodes have a reg
+ * property. There exists ways around this, so the ePAPR
+ * spec will need to be studied.
*/
- iparent = *mp++;
- len -= 4;
- if (OF_getprop(iparent, "#interrupt-cells", &icells, 4) != 4)
- goto nomap;
-
- /* Found. */
- if (match == 0) {
- bcopy(mp, intr, icells * 4);
- return (icells * 4);
- }
- mp += icells;
- len -= icells * 4;
- }
+ return (0);
-nomap:
+#ifdef NOTYET
+ intr = pci_get_intpin(child);
+ return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child,
+ intr));
+#endif
+ }
+
/*
- * Check for local properties indicating interrupts
+ * Any AAPL,interrupts property gets priority and is
+ * fully specified (i.e. does not need routing)
*/
- len = OF_getprop(node, "interrupts", intr, 16);
- if (OF_getprop(node, "interrupt-parent", &iparent, sizeof(iparent)) ==
- sizeof(iparent)) {
- OF_getprop(iparent, "#interrupt-cells", &icells, sizeof(icells));
- for (i = 0; i < len/icells/4; i++)
- intr[i] = intr[i*icells];
+ isz = OF_getprop(node, "AAPL,interrupts", &intr, sizeof(intr));
+ if (isz == sizeof(intr)) {
+ return (intr);
+ }
- return (len);
+ isz = OF_getprop(node, "interrupts", &intr, sizeof(intr));
+ if (isz != sizeof(intr)) {
+ /* No property; our best guess is the intpin. */
+ intr = pci_get_intpin(child);
}
-
/*
- * If the node has no interrupt property and the parent is a PCI
- * bridge, use the parent's interrupt. This occurs on a PCI slot.
+ * If we got intr from a property, it may or may not be an intpin.
+ * For on-board devices, it frequently is not, and is completely out
+ * of the valid intpin range. For PCI slots, it hopefully is,
+ * otherwise we will have trouble interfacing with non-OFW buses
+ * such as cardbus.
+ * Since we cannot tell which it is without violating layering, we
+ * will always use the route_interrupt method, and treat exceptions
+ * on the level they become apparent.
*/
- bzero(name, sizeof(name));
- OF_getprop(parent, "name", name, sizeof(name));
- if (strcmp(name, "pci-bridge") == 0) {
- len = OF_getprop(parent, "AAPL,interrupts", intr, 4);
- if (len == 4) {
- return (len);
- }
+ return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr));
+}
- /*
- * XXX I don't know what is the correct local address.
- * XXX Use the first entry for now.
- */
- len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
- if (len >= 36) {
- addr = &map[5];
- /* XXX Use 0 for 'interrupts' for compat */
- return (find_node_intr(parent, addr, intr));
- }
- }
+static const struct ofw_bus_devinfo *
+ofw_pcibus_get_devinfo(device_t bus, device_t dev)
+{
+ struct ofw_pcibus_devinfo *dinfo;
- return (-1);
+ dinfo = device_get_ivars(dev);
+ return (&dinfo->opd_obdinfo);
}
diff --git a/sys/powerpc/ofw/ofw_syscons.c b/sys/powerpc/ofw/ofw_syscons.c
index 373ba11..1080dad 100644
--- a/sys/powerpc/ofw/ofw_syscons.c
+++ b/sys/powerpc/ofw/ofw_syscons.c
@@ -137,10 +137,12 @@ static video_switch_t ofwfbvidsw = {
*/
static vi_blank_display_t ofwfb_blank_display8;
static vi_putc_t ofwfb_putc8;
+static vi_putm_t ofwfb_putm8;
static vi_set_border_t ofwfb_set_border8;
static vi_blank_display_t ofwfb_blank_display32;
static vi_putc_t ofwfb_putc32;
+static vi_putm_t ofwfb_putm32;
static vi_set_border_t ofwfb_set_border32;
VIDEO_DRIVER(ofwfb, ofwfbvidsw, ofwfb_configure);
@@ -250,10 +252,12 @@ ofwfb_configure(int flags)
if (depth == 8) {
sc->sc_blank = ofwfb_blank_display8;
sc->sc_putc = ofwfb_putc8;
+ sc->sc_putm = ofwfb_putm8;
sc->sc_set_border = ofwfb_set_border8;
} else if (depth == 32) {
sc->sc_blank = ofwfb_blank_display32;
sc->sc_putc = ofwfb_putc32;
+ sc->sc_putm = ofwfb_putm32;
sc->sc_set_border = ofwfb_set_border32;
} else
return (0);
@@ -304,36 +308,14 @@ ofwfb_init(int unit, video_adapter_t *adp, int flags)
{
struct ofwfb_softc *sc;
video_info_t *vi;
- char name[64];
- ihandle_t ih;
- int i;
int cborder;
int font_height;
- int retval;
sc = (struct ofwfb_softc *)adp;
vi = &adp->va_info;
vid_init_struct(adp, "ofwfb", -1, unit);
- if (sc->sc_depth == 8) {
- /*
- * Install the ISO6429 colormap - older OFW systems
- * don't do this by default
- */
- memset(name, 0, sizeof(name));
- OF_package_to_path(sc->sc_node, name, sizeof(name));
- ih = OF_open(name);
- for (i = 0; i < 16; i++) {
- OF_call_method("color!", ih, 4, 1,
- ofwfb_cmap[i].red,
- ofwfb_cmap[i].green,
- ofwfb_cmap[i].blue,
- i,
- &retval);
- }
- }
-
/* The default font size can be overridden by loader */
font_height = 16;
TUNABLE_INT_FETCH("hw.syscons.fsize", &font_height);
@@ -375,10 +357,13 @@ ofwfb_init(int unit, video_adapter_t *adp, int flags)
*/
adp->va_window = (vm_offset_t) ofwfb_static_window;
- /* Enable future font-loading and flag color support */
- adp->va_flags |= V_ADP_FONT | V_ADP_COLOR;
-
- ofwfb_blank_display(&sc->sc_va, V_DISPLAY_ON);
+ /*
+ * Enable future font-loading and flag color support, as well as
+ * adding V_ADP_MODECHANGE so that we ofwfb_set_mode() gets called
+ * when the X server shuts down. This enables us to get the console
+ * back when X disappears.
+ */
+ adp->va_flags |= V_ADP_FONT | V_ADP_COLOR | V_ADP_MODECHANGE;
ofwfb_set_mode(&sc->sc_va, 0);
@@ -404,6 +389,37 @@ ofwfb_query_mode(video_adapter_t *adp, video_info_t *info)
static int
ofwfb_set_mode(video_adapter_t *adp, int mode)
{
+ struct ofwfb_softc *sc;
+ char name[64];
+ ihandle_t ih;
+ int i, retval;
+
+ sc = (struct ofwfb_softc *)adp;
+
+ /*
+ * Open the display device, which will initialize it.
+ */
+
+ memset(name, 0, sizeof(name));
+ OF_package_to_path(sc->sc_node, name, sizeof(name));
+ ih = OF_open(name);
+
+ if (sc->sc_depth == 8) {
+ /*
+ * Install the ISO6429 colormap - older OFW systems
+ * don't do this by default
+ */
+ for (i = 0; i < 16; i++) {
+ OF_call_method("color!", ih, 4, 1,
+ ofwfb_cmap[i].red,
+ ofwfb_cmap[i].green,
+ ofwfb_cmap[i].blue,
+ i,
+ &retval);
+ }
+ }
+
+ ofwfb_blank_display(&sc->sc_va, V_DISPLAY_ON);
return (0);
}
@@ -823,7 +839,86 @@ ofwfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
sc = (struct ofwfb_softc *)adp;
- /* put mouse */
+ return ((*sc->sc_putm)(adp, x, y, pixel_image, pixel_mask, size,
+ width));
+}
+
+static int
+ofwfb_putm8(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
+ uint32_t pixel_mask, int size, int width)
+{
+ struct ofwfb_softc *sc;
+ int i, j, k;
+ uint32_t *addr;
+ u_char fg, bg;
+ union {
+ uint32_t l[2];
+ uint8_t c[8];
+ } ch;
+
+
+ sc = (struct ofwfb_softc *)adp;
+ addr = (u_int32_t *)((int)sc->sc_addr
+ + (y + sc->sc_ymargin)*sc->sc_stride
+ + x + sc->sc_xmargin);
+
+ fg = ofwfb_foreground(SC_NORM_ATTR);
+ bg = ofwfb_background(SC_NORM_ATTR);
+
+ for (i = 0; i < size && i+y < sc->sc_height - 2*sc->sc_ymargin; i++) {
+ /*
+ * Use the current values for the line
+ */
+ ch.l[0] = addr[0];
+ ch.l[1] = addr[1];
+
+ /*
+ * Calculate 2 x 4-chars at a time, and then
+ * write these out.
+ */
+ for (j = 0, k = width; j < 8; j++, k--) {
+ if (x + j >= sc->sc_width - 2*sc->sc_xmargin)
+ continue;
+
+ if (pixel_image[i] & (1 << k))
+ ch.c[j] = (ch.c[j] == fg) ? bg : fg;
+ }
+
+ addr[0] = ch.l[0];
+ addr[1] = ch.l[1];
+ addr += (sc->sc_stride / sizeof(u_int32_t));
+ }
+
+ return (0);
+}
+
+static int
+ofwfb_putm32(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
+ uint32_t pixel_mask, int size, int width)
+{
+ struct ofwfb_softc *sc;
+ int i, j, k;
+ uint32_t fg, bg;
+ uint32_t *addr;
+
+ sc = (struct ofwfb_softc *)adp;
+ addr = (uint32_t *)sc->sc_addr
+ + (y + sc->sc_ymargin)*(sc->sc_stride/4)
+ + x + sc->sc_xmargin;
+
+ fg = ofwfb_pix32(ofwfb_foreground(SC_NORM_ATTR));
+ bg = ofwfb_pix32(ofwfb_background(SC_NORM_ATTR));
+
+ for (i = 0; i < size && i+y < sc->sc_height - 2*sc->sc_ymargin; i++) {
+ for (j = 0, k = width; j < 8; j++, k--) {
+ if (x + j >= sc->sc_width - 2*sc->sc_xmargin)
+ continue;
+
+ if (pixel_image[i] & (1 << k))
+ *(addr + j) = (*(addr + j) == fg) ? bg : fg;
+ }
+ addr += (sc->sc_stride/4);
+ }
return (0);
}
diff --git a/sys/powerpc/ofw/ofw_syscons.h b/sys/powerpc/ofw/ofw_syscons.h
index af33c52..01b9727 100644
--- a/sys/powerpc/ofw/ofw_syscons.h
+++ b/sys/powerpc/ofw/ofw_syscons.h
@@ -51,6 +51,7 @@ struct ofwfb_softc {
vi_blank_display_t *sc_blank;
vi_putc_t *sc_putc;
+ vi_putm_t *sc_putm;
vi_set_border_t *sc_set_border;
#define OFWSC_MAXADDR 8
diff --git a/sys/powerpc/powermac/cuda.c b/sys/powerpc/powermac/cuda.c
index 274bb98..e6c010c 100644
--- a/sys/powerpc/powermac/cuda.c
+++ b/sys/powerpc/powermac/cuda.c
@@ -104,8 +104,6 @@ static devclass_t cuda_devclass;
DRIVER_MODULE(cuda, macio, cuda_driver, cuda_devclass, 0, 0);
DRIVER_MODULE(adb, cuda, adb_driver, adb_devclass, 0, 0);
-MALLOC_DEFINE(M_CUDA, "cuda", "CUDA packet queue");
-
static void cuda_intr(void *arg);
static uint8_t cuda_read_reg(struct cuda_softc *sc, u_int offset);
static void cuda_write_reg(struct cuda_softc *sc, u_int offset, uint8_t value);
@@ -178,6 +176,10 @@ cuda_attach(device_t dev)
STAILQ_INIT(&sc->sc_inq);
STAILQ_INIT(&sc->sc_outq);
+ STAILQ_INIT(&sc->sc_freeq);
+
+ for (i = 0; i < CUDA_MAXPACKETS; i++)
+ STAILQ_INSERT_TAIL(&sc->sc_freeq, &sc->sc_pkts[i], pkt_q);
/* Init CUDA */
@@ -348,11 +350,17 @@ cuda_send(void *cookie, int poll, int length, uint8_t *msg)
mtx_lock(&sc->sc_mutex);
- pkt = malloc(sizeof(struct cuda_packet), M_CUDA, M_WAITOK);
+ pkt = STAILQ_FIRST(&sc->sc_freeq);
+ if (pkt == NULL) {
+ mtx_unlock(&sc->sc_mutex);
+ return (-1);
+ }
+
pkt->len = length - 1;
pkt->type = msg[0];
memcpy(pkt->data, &msg[1], pkt->len);
+ STAILQ_REMOVE_HEAD(&sc->sc_freeq, pkt_q);
STAILQ_INSERT_TAIL(&sc->sc_outq, pkt, pkt_q);
/*
@@ -389,8 +397,8 @@ cuda_send_outbound(struct cuda_softc *sc)
memcpy(sc->sc_out, &pkt->type, pkt->len + 1);
sc->sc_sent = 0;
- free(pkt, M_CUDA);
STAILQ_REMOVE_HEAD(&sc->sc_outq, pkt_q);
+ STAILQ_INSERT_TAIL(&sc->sc_freeq, pkt, pkt_q);
sc->sc_waiting = 1;
@@ -455,9 +463,9 @@ cuda_send_inbound(struct cuda_softc *sc)
break;
}
- free(pkt,M_CUDA);
-
mtx_lock(&sc->sc_mutex);
+
+ STAILQ_INSERT_TAIL(&sc->sc_freeq, pkt, pkt_q);
}
mtx_unlock(&sc->sc_mutex);
@@ -559,18 +567,22 @@ switch_start:
cuda_idle(sc);
/* Queue up the packet */
- pkt = malloc(sizeof(struct cuda_packet), M_CUDA,
- M_WAITOK);
+ pkt = STAILQ_FIRST(&sc->sc_freeq);
+ if (pkt != NULL) {
+ /* If we have a free packet, process it */
- pkt->len = sc->sc_received - 2;
- pkt->type = sc->sc_in[1];
- memcpy(pkt->data, &sc->sc_in[2], pkt->len);
+ pkt->len = sc->sc_received - 2;
+ pkt->type = sc->sc_in[1];
+ memcpy(pkt->data, &sc->sc_in[2], pkt->len);
- STAILQ_INSERT_TAIL(&sc->sc_inq, pkt, pkt_q);
+ STAILQ_REMOVE_HEAD(&sc->sc_freeq, pkt_q);
+ STAILQ_INSERT_TAIL(&sc->sc_inq, pkt, pkt_q);
+
+ process_inbound = 1;
+ }
sc->sc_state = CUDA_IDLE;
sc->sc_received = 0;
- process_inbound = 1;
/*
* If there is something waiting to be sent out,
diff --git a/sys/powerpc/powermac/cudavar.h b/sys/powerpc/powermac/cudavar.h
index b6f25fe..02791cb 100644
--- a/sys/powerpc/powermac/cudavar.h
+++ b/sys/powerpc/powermac/cudavar.h
@@ -35,6 +35,7 @@
#define _POWERPC_CUDAVAR_H_
#define CUDA_DEVSTR "Apple CUDA I/O Controller"
+#define CUDA_MAXPACKETS 10
/* Cuda addresses */
#define CUDA_ADB 0
@@ -99,8 +100,10 @@ struct cuda_softc {
int sc_out_length;
int sc_received;
+ struct cuda_packet sc_pkts[CUDA_MAXPACKETS];
struct cuda_pktq sc_inq;
struct cuda_pktq sc_outq;
+ struct cuda_pktq sc_freeq;
};
#endif /* _POWERPC_CUDAVAR_H_ */
diff --git a/sys/powerpc/powermac/grackle.c b/sys/powerpc/powermac/grackle.c
index 08e14ac..9dd796d 100644
--- a/sys/powerpc/powermac/grackle.c
+++ b/sys/powerpc/powermac/grackle.c
@@ -37,6 +37,7 @@
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -164,7 +165,7 @@ static int
grackle_attach(device_t dev)
{
struct grackle_softc *sc;
- phandle_t node;
+ phandle_t node, iparent;
u_int32_t busrange[2];
struct grackle_range *rp, *io, *mem[2];
int nmem, i, error;
@@ -251,6 +252,16 @@ grackle_attach(device_t dev)
}
}
+ ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
+
+ /* We need the number of interrupt cells to read the imap */
+ if (OF_getprop(node, "interrupt-parent", &iparent,sizeof(iparent)) <= 0)
+ iparent = node;
+
+ if (OF_getprop(iparent,"#interrupt-cells",&sc->sc_icells,
+ sizeof(sc->sc_icells)) <= 0)
+ sc->sc_icells = 1;
+
device_add_child(dev, "pci", device_get_unit(dev));
return (bus_generic_attach(dev));
}
@@ -335,8 +346,25 @@ grackle_write_config(device_t dev, u_int bus, u_int slot, u_int func,
static int
grackle_route_interrupt(device_t bus, device_t dev, int pin)
{
+ struct grackle_softc *sc;
+ struct ofw_pci_register reg;
+ uint32_t pintr, mintr[2];
+ uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
- return (0);
+ sc = device_get_softc(bus);
+ pintr = pin;
+ if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
+ sizeof(reg), &pintr, sizeof(pintr), &mintr,
+ sizeof(mintr[0])*sc->sc_icells, maskbuf))
+ return (mintr[0]);
+
+ /* Maybe it's a real interrupt, not an intpin */
+ if (pin > 4)
+ return (pin);
+
+ device_printf(bus, "could not route pin %d for device %d.%d\n",
+ pin, pci_get_slot(dev), pci_get_function(dev));
+ return (PCI_INVALID_IRQ);
}
static int
diff --git a/sys/powerpc/powermac/gracklevar.h b/sys/powerpc/powermac/gracklevar.h
index bb5b150..78461d8 100644
--- a/sys/powerpc/powermac/gracklevar.h
+++ b/sys/powerpc/powermac/gracklevar.h
@@ -52,6 +52,9 @@ struct grackle_softc {
struct rman sc_mem_rman;
bus_space_tag_t sc_memt;
bus_dma_tag_t sc_dmat;
+ int sc_icells;
+
+ struct ofw_bus_iinfo sc_pci_iinfo;
};
/*
diff --git a/sys/powerpc/powermac/macio.c b/sys/powerpc/powermac/macio.c
index 9a4b3ac..71be113 100644
--- a/sys/powerpc/powermac/macio.c
+++ b/sys/powerpc/powermac/macio.c
@@ -107,6 +107,8 @@ static device_method_t macio_methods[] = {
DEVMETHOD(bus_deactivate_resource, macio_deactivate_resource),
DEVMETHOD(bus_get_resource_list, macio_get_resource_list),
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
+
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_devinfo, macio_get_devinfo),
DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
diff --git a/sys/powerpc/powermac/uninorth.c b/sys/powerpc/powermac/uninorth.c
index 097532c..b0b55a4 100644
--- a/sys/powerpc/powermac/uninorth.c
+++ b/sys/powerpc/powermac/uninorth.c
@@ -35,6 +35,7 @@
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -163,8 +164,7 @@ uninorth_attach(device_t dev)
{
struct uninorth_softc *sc;
const char *compatible;
- phandle_t node;
- phandle_t child;
+ phandle_t node, child, iparent;
u_int32_t reg[2], busrange[2];
struct uninorth_range *rp, *io, *mem[2];
int nmem, i, error;
@@ -294,6 +294,14 @@ uninorth_attach(device_t dev)
}
}
+ ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
+
+ /* We need the number of interrupt cells to read the imap */
+ sc->sc_icells = 2;
+ if (OF_getprop(node, "interrupt-parent", &iparent,sizeof(iparent)) > 0)
+ OF_getprop(iparent,"#interrupt-cells",&sc->sc_icells,
+ sizeof(sc->sc_icells));
+
device_add_child(dev, "pci", device_get_unit(dev));
return (bus_generic_attach(dev));
}
@@ -360,8 +368,25 @@ uninorth_write_config(device_t dev, u_int bus, u_int slot, u_int func,
static int
uninorth_route_interrupt(device_t bus, device_t dev, int pin)
{
+ struct uninorth_softc *sc;
+ struct ofw_pci_register reg;
+ uint32_t pintr, mintr[2];
+ uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
- return (0);
+ sc = device_get_softc(bus);
+ pintr = pin;
+ if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
+ sizeof(reg), &pintr, sizeof(pintr), mintr,
+ sizeof(mintr[0])*sc->sc_icells, maskbuf))
+ return (mintr[0]);
+
+ /* Maybe it's a real interrupt, not an intpin */
+ if (pin > 4)
+ return (pin);
+
+ device_printf(bus, "could not route pin %d for device %d.%d\n",
+ pin, pci_get_slot(dev), pci_get_function(dev));
+ return (PCI_INVALID_IRQ);
}
static int
diff --git a/sys/powerpc/powermac/uninorthvar.h b/sys/powerpc/powermac/uninorthvar.h
index ff789ac..6bb4024 100644
--- a/sys/powerpc/powermac/uninorthvar.h
+++ b/sys/powerpc/powermac/uninorthvar.h
@@ -61,8 +61,10 @@ struct uninorth_softc {
bus_space_tag_t sc_iot;
bus_space_tag_t sc_memt;
bus_dma_tag_t sc_dmat;
+ struct ofw_bus_iinfo sc_pci_iinfo;
int sc_u3;
+ int sc_icells;
};
struct unin_chip_softc {
diff --git a/sys/powerpc/powerpc/pmap_dispatch.c b/sys/powerpc/powerpc/pmap_dispatch.c
index 55112bb..33e94d1 100644
--- a/sys/powerpc/powerpc/pmap_dispatch.c
+++ b/sys/powerpc/powerpc/pmap_dispatch.c
@@ -37,9 +37,8 @@ __FBSDID("$FreeBSD$");
* the highest priority call will be installed as the default
* MMU handler when pmap_bootstrap() is called.
*
- * It is required that kobj_machdep_init() be called before
- * pmap_bootstrap() to allow the kobj subsystem to initialise. This
- * in turn requires that mutex_init() has been called.
+ * It is required that mutex_init() be called before pmap_bootstrap(),
+ * as the PMAP layer makes extensive use of mutexes.
*/
#include <sys/param.h>
diff --git a/sys/sparc64/conf/DEFAULTS b/sys/sparc64/conf/DEFAULTS
index 910e61e..38b2408 100644
--- a/sys/sparc64/conf/DEFAULTS
+++ b/sys/sparc64/conf/DEFAULTS
@@ -14,8 +14,8 @@ device uart_sab82532
device uart_z8530
# Default partitioning schemes
-options GEOM_BSD
-options GEOM_SUNLABEL
+options GEOM_PART_BSD
+options GEOM_PART_VTOC8
# Let sunkbd emulate an AT keyboard by default.
options SUNKBD_EMULATE_ATKBD
diff --git a/sys/sparc64/ebus/ebus.c b/sys/sparc64/ebus/ebus.c
index bcc92a2..9baa7a8 100644
--- a/sys/sparc64/ebus/ebus.c
+++ b/sys/sparc64/ebus/ebus.c
@@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/openfirm.h>
-#include <machine/ofw_bus.h>
#include <machine/resource.h>
#include <dev/pci/pcireg.h>
@@ -118,6 +117,7 @@ static device_method_t ebus_methods[] = {
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_release_resource, ebus_release_resource),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_devinfo, ebus_get_devinfo),
diff --git a/sys/sparc64/include/elf.h b/sys/sparc64/include/elf.h
index 76e3a76..108ade1 100644
--- a/sys/sparc64/include/elf.h
+++ b/sys/sparc64/include/elf.h
@@ -78,18 +78,6 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-
-/*
- * The following non-standard values are used for passing information
- * from John Polstra's testbed program to the dynamic linker. These
- * are expected to go away soon.
- *
- * Unfortunately, these overlap the Linux non-standard values, so they
- * must not be used in the same context.
- */
-#define T_BRK 10 /* Starting point for sbrk and brk. */
-#define AT_DEBUG 11 /* Debugging level. */
-
/*
* The following non-standard values are used in Linux ELF binaries.
*/
diff --git a/sys/sparc64/include/ofw_bus.h b/sys/sparc64/include/ofw_bus.h
deleted file mode 100644
index 1e9004e..0000000
--- a/sys/sparc64/include/ofw_bus.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*-
- * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 _MACHINE_OFW_BUS_H_
-#define _MACHINE_OFW_BUS_H_
-
-#define ORIP_NOINT -1
-#define ORIR_NOTFOUND 0xffffffff
-
-/*
- * Other than in Open Firmware calls, the size of a bus cell seems to be
- * always the same.
- */
-typedef u_int32_t pcell_t;
-
-struct ofw_bus_iinfo {
- u_int8_t *opi_imap;
- u_int8_t *opi_imapmsk;
- int opi_imapsz;
- pcell_t opi_addrc;
-};
-
-void ofw_bus_setup_iinfo(phandle_t, struct ofw_bus_iinfo *, int);
-int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int,
- void *, int, void *, int, void *);
-int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *,
- void *, void *, int);
-
-#endif /* !_MACHINE_OFW_BUS_H_ */
diff --git a/sys/sparc64/include/ofw_machdep.h b/sys/sparc64/include/ofw_machdep.h
index ac1fcc1..625b131 100644
--- a/sys/sparc64/include/ofw_machdep.h
+++ b/sys/sparc64/include/ofw_machdep.h
@@ -29,10 +29,15 @@
#define _MACHINE_OFW_MACHDEP_H_
#include <sys/bus.h>
+#include <machine/bus.h>
+#include <dev/ofw/openfirm.h>
+
+typedef uint64_t cell_t;
int OF_decode_addr(phandle_t, int, int *, bus_addr_t *);
void OF_getetheraddr(device_t, u_char *);
void cpu_shutdown(void *);
-void openfirmware_exit(void *);
+int ofw_entry(void *);
+void ofw_exit(void *);
#endif /* _MACHINE_OFW_MACHDEP_H_ */
diff --git a/sys/sparc64/isa/ofw_isa.c b/sys/sparc64/isa/ofw_isa.c
index e1d7537..de90869 100644
--- a/sys/sparc64/isa/ofw_isa.c
+++ b/sys/sparc64/isa/ofw_isa.c
@@ -41,10 +41,10 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <machine/bus.h>
#include <machine/resource.h>
-#include <machine/ofw_bus.h>
#include <sparc64/pci/ofw_pci.h>
#include <sparc64/isa/ofw_isa.h>
diff --git a/sys/sparc64/pci/apb.c b/sys/sparc64/pci/apb.c
index d908c17..ba0698c 100644
--- a/sys/sparc64/pci/apb.c
+++ b/sys/sparc64/pci/apb.c
@@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
-#include <machine/ofw_bus.h>
#include <machine/resource.h>
#include <dev/pci/pcireg.h>
diff --git a/sys/sparc64/pci/ofw_pci.h b/sys/sparc64/pci/ofw_pci.h
index 252f474..19c2fbe 100644
--- a/sys/sparc64/pci/ofw_pci.h
+++ b/sys/sparc64/pci/ofw_pci.h
@@ -34,7 +34,7 @@
#ifndef _SPARC64_PCI_OFW_PCI_H_
#define _SPARC64_PCI_OFW_PCI_H_
-#include <machine/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
typedef uint32_t ofw_pci_intr_t;
diff --git a/sys/sparc64/pci/ofw_pcib.c b/sys/sparc64/pci/ofw_pcib.c
index 966d77f..8a5b991 100644
--- a/sys/sparc64/pci/ofw_pcib.c
+++ b/sys/sparc64/pci/ofw_pcib.c
@@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
-#include <machine/ofw_bus.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
diff --git a/sys/sparc64/pci/ofw_pcib_subr.c b/sys/sparc64/pci/ofw_pcib_subr.c
index 9996b7e..6dd0990 100644
--- a/sys/sparc64/pci/ofw_pcib_subr.c
+++ b/sys/sparc64/pci/ofw_pcib_subr.c
@@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
-#include <machine/ofw_bus.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
diff --git a/sys/sparc64/pci/ofw_pcibus.c b/sys/sparc64/pci/ofw_pcibus.c
index 7918370..65a498a 100644
--- a/sys/sparc64/pci/ofw_pcibus.c
+++ b/sys/sparc64/pci/ofw_pcibus.c
@@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$");
#include <sys/pciio.h>
#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/openfirm.h>
@@ -69,6 +68,8 @@ static device_probe_t ofw_pcibus_probe;
static device_attach_t ofw_pcibus_attach;
static pci_assign_interrupt_t ofw_pcibus_assign_interrupt;
static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo;
+static int ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child,
+ char *buf, size_t buflen);
static device_method_t ofw_pcibus_methods[] = {
/* Device interface */
@@ -76,6 +77,7 @@ static device_method_t ofw_pcibus_methods[] = {
DEVMETHOD(device_attach, ofw_pcibus_attach),
/* Bus interface */
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_child_pnpinfo_str_method),
/* PCI interface */
DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt),
@@ -302,3 +304,18 @@ ofw_pcibus_get_devinfo(device_t bus, device_t dev)
dinfo = device_get_ivars(dev);
return (&dinfo->opd_obdinfo);
}
+
+static int
+ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf,
+ size_t buflen)
+{
+ pci_child_pnpinfo_str_method(cbdev, child, buf, buflen);
+
+ if (ofw_bus_get_node(child) != -1) {
+ strlcat(buf, " ", buflen); /* Separate info */
+ ofw_bus_gen_child_pnpinfo_str(cbdev, child, buf, buflen);
+ }
+
+ return (0);
+}
+
diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c
index d961191..505eec4 100644
--- a/sys/sparc64/pci/psycho.c
+++ b/sys/sparc64/pci/psycho.c
@@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus_private.h>
#include <machine/iommureg.h>
#include <machine/iommuvar.h>
-#include <machine/ofw_bus.h>
#include <machine/resource.h>
#include <machine/ver.h>
diff --git a/sys/sparc64/pci/schizo.c b/sys/sparc64/pci/schizo.c
index 8f01f9c..2425294 100644
--- a/sys/sparc64/pci/schizo.c
+++ b/sys/sparc64/pci/schizo.c
@@ -65,7 +65,6 @@ __FBSDID("$FreeBSD$");
#include <machine/fsr.h>
#include <machine/iommureg.h>
#include <machine/iommuvar.h>
-#include <machine/ofw_bus.h>
#include <machine/resource.h>
#include <dev/pci/pcireg.h>
@@ -395,9 +394,10 @@ schizo_attach(device_t dev)
/*
* Hunt through all the interrupt mapping regs and register
- * the interrupt controller for our interrupt vectors. This
- * is complicated by the fact that a pair of Schizo PBMs
- * share one IGN.
+ * the interrupt controller for our interrupt vectors. We do
+ * this early in order to be able to catch stray interrupts.
+ * This is complicated by the fact that a pair of Schizo PBMs
+ * shares one IGN.
*/
n = OF_getprop(node, "ino-bitmap", (void *)prop_array,
sizeof(prop_array));
@@ -412,8 +412,8 @@ schizo_attach(device_t dev)
continue;
i = schizo_intr_register(sc, n);
if (i != 0)
- panic("%s: could not register interrupt controller "
- "for INO %d (%d)", __func__, n, i);
+ device_printf(dev, "could not register interrupt "
+ "controller for INO %d (%d)\n", n, i);
}
/*
@@ -1128,16 +1128,40 @@ schizo_setup_intr(device_t dev, device_t child, struct resource *ires,
sc = device_get_softc(dev);
/*
- * Make sure the vector is fully specified and we registered
- * our interrupt controller for it.
+ * Make sure the vector is fully specified.
*/
vec = rman_get_start(ires);
- if (INTIGN(vec) != sc->sc_ign ||
- intr_vectors[vec].iv_ic != &schizo_ic) {
+ if (INTIGN(vec) != sc->sc_ign) {
device_printf(dev, "invalid interrupt vector 0x%lx\n", vec);
return (EINVAL);
}
+ if (intr_vectors[vec].iv_ic == &schizo_ic) {
+ /*
+ * Ensure we use the right softc in case the interrupt
+ * is routed to our companion PBM for some odd reason.
+ */
+ sc = ((struct schizo_icarg *)intr_vectors[vec].iv_icarg)->
+ sica_sc;
+ } else if (intr_vectors[vec].iv_ic == NULL) {
+ /*
+ * Work around broken firmware which misses entries in
+ * the ino-bitmap.
+ */
+ error = schizo_intr_register(sc, INTINO(vec));
+ if (error != 0) {
+ device_printf(dev, "could not register interrupt "
+ "controller for vector 0x%lx (%d)\n", vec, error);
+ return (error);
+ }
+ device_printf(dev, "belatedly registered as interrupt "
+ "controller for vector 0x%lx\n", vec);
+ } else {
+ device_printf(dev,
+ "invalid interrupt controller for vector 0x%lx\n", vec);
+ return (EINVAL);
+ }
+
/*
* Install a a wrapper for CDMA flushing/syncing for devices
* behind PCI-PCI bridges if possible.
@@ -1206,7 +1230,7 @@ schizo_setup_intr(device_t dev, device_t child, struct resource *ires,
return (error);
} else if (found != 0)
device_printf(dev, "WARNING: using devices behind PCI-PCI "
- "bridges may cause data corruption");
+ "bridges may cause data corruption\n");
return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr,
arg, cookiep));
}
diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c
index a97fd10..d6b8393 100644
--- a/sys/sparc64/sbus/sbus.c
+++ b/sys/sparc64/sbus/sbus.c
@@ -226,6 +226,7 @@ static device_method_t sbus_methods[] = {
DEVMETHOD(bus_get_resource_list, sbus_get_resource_list),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_get_dma_tag, sbus_get_dma_tag),
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_devinfo, sbus_get_devinfo),
diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c
index 0be9af9..4e1e300 100644
--- a/sys/sparc64/sparc64/machdep.c
+++ b/sys/sparc64/sparc64/machdep.c
@@ -276,9 +276,10 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
tick_stop();
/*
- * Initialize Open Firmware (needed for console).
+ * Set up Open Firmware entry points
*/
- OF_init(vec);
+ ofw_tba = rdpr(tba);
+ ofw_vec = (u_long)vec;
/*
* Parse metadata if present and fetch parameters. Must be before the
@@ -301,6 +302,12 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
init_param1();
/*
+ * Initialize Open Firmware (needed for console).
+ */
+ OF_install(OFW_STD_DIRECT, 0);
+ OF_init(ofw_entry);
+
+ /*
* Prime our per-CPU data page for use. Note, we are using it for
* our stack, so don't pass the real size (PAGE_SIZE) to pcpu_init
* or it'll zero it out from under us.
@@ -481,14 +488,6 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
}
void
-set_openfirm_callback(ofw_vec_t *vec)
-{
-
- ofw_tba = rdpr(tba);
- ofw_vec = (u_long)vec;
-}
-
-void
sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct trapframe *tf;
@@ -725,7 +724,7 @@ cpu_shutdown(void *args)
#ifdef SMP
cpu_mp_shutdown();
#endif
- openfirmware_exit(args);
+ ofw_exit(args);
}
/* Get current clock frequency for the given CPU ID. */
diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c
index 5cace48..bf79adf 100644
--- a/sys/sparc64/sparc64/mp_machdep.c
+++ b/sys/sparc64/sparc64/mp_machdep.c
@@ -221,7 +221,7 @@ sun4u_startcpu(phandle_t cpu, void *func, u_long arg)
args.cpu = cpu;
args.func = (cell_t)func;
args.arg = (cell_t)arg;
- openfirmware(&args);
+ ofw_entry(&args);
}
/*
@@ -238,7 +238,7 @@ sun4u_stopself(void)
(cell_t)SUNW_STOPSELF,
};
- openfirmware_exit(&args);
+ ofw_exit(&args);
panic("%s: failed.", __func__);
}
diff --git a/sys/sparc64/sparc64/ofw_bus.c b/sys/sparc64/sparc64/ofw_bus.c
deleted file mode 100644
index f7458dc..0000000
--- a/sys/sparc64/sparc64/ofw_bus.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*-
- * Copyright (C) 1996 Wolfgang Solfrank.
- * Copyright (C) 1996 TooLs GmbH.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by TooLs GmbH.
- * 4. The name of TooLs GmbH may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
- */
-/*-
- * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- *
- * from: $NetBSD: ofw_machdep.c,v 1.16 2001/07/20 00:07:14 eeh Exp $
- *
- * $FreeBSD$
- */
-
-/*
- * Open Firmware bus support code that is (hopefully) independent from the
- * used hardware.
- * Maybe this should go into dev/ofw/; there may however be sparc specific
- * bits left.
- */
-
-#include <sys/param.h>
-#include <sys/malloc.h>
-#include <sys/systm.h>
-
-#include <dev/ofw/openfirm.h>
-
-#include <machine/ofw_bus.h>
-
-static int
-ofw_bus_searchprop(phandle_t node, char *propname, void *buf, int buflen)
-{
- int rv;
-
- for (; node != 0; node = OF_parent(node)) {
- if ((rv = OF_getprop(node, propname, buf, buflen)) != -1)
- return (rv);
- }
- return (-1);
-}
-
-void
-ofw_bus_setup_iinfo(phandle_t node, struct ofw_bus_iinfo *ii, int intrsz)
-{
- pcell_t addrc;
- int msksz;
-
- if (OF_getprop(node, "#address-cells", &addrc, sizeof(addrc)) == -1)
- addrc = 2;
- ii->opi_addrc = addrc * sizeof(pcell_t);
-
- ii->opi_imapsz = OF_getprop_alloc(node, "interrupt-map", 1,
- (void **)&ii->opi_imap);
- if (ii->opi_imapsz > 0) {
- msksz = OF_getprop_alloc(node, "interrupt-map-mask", 1,
- (void **)&ii->opi_imapmsk);
- /*
- * Failure to get the mask is ignored; a full mask is used then.
- * Barf on bad mask sizes, however.
- */
- if (msksz != -1 && msksz != ii->opi_addrc + intrsz) {
- panic("ofw_bus_setup_iinfo: bad interrupt-map-mask "
- "property!");
- }
- }
-
-}
-
-int
-ofw_bus_lookup_imap(phandle_t node, struct ofw_bus_iinfo *ii, void *reg,
- int regsz, void *pintr, int pintrsz, void *mintr, int mintrsz,
- void *maskbuf)
-{
- int rv;
-
- if (ii->opi_imapsz <= 0)
- return (0);
- KASSERT(regsz >= ii->opi_addrc,
- ("ofw_bus_lookup_imap: register size too small: %d < %d",
- regsz, ii->opi_addrc));
- rv = OF_getprop(node, "reg", reg, regsz);
- if (rv < regsz)
- panic("ofw_bus_lookup_imap: could not get reg property");
- return (ofw_bus_search_intrmap(pintr, pintrsz, reg, ii->opi_addrc,
- ii->opi_imap, ii->opi_imapsz, ii->opi_imapmsk, maskbuf, mintr,
- mintrsz));
-}
-
-/*
- * Map an interrupt using the firmware reg, interrupt-map and
- * interrupt-map-mask properties.
- * The interrupt property to be mapped must be of size intrsz, and pointed to
- * by intr. The regs property of the node for which the mapping is done must
- * be passed as regs. This property is an array of register specifications;
- * the size of the address part of such a specification must be passed as
- * physsz. Only the first element of the property is used.
- * imap and imapsz hold the interrupt mask and it's size.
- * imapmsk is a pointer to the interrupt-map-mask property, which must have
- * a size of physsz + intrsz; it may be NULL, in which case a full mask is
- * assumed.
- * maskbuf must point to a buffer of length physsz + intrsz.
- * The interrupt is returned in result, which must point to a buffer of length
- * rintrsz (which gives the expected size of the mapped interrupt).
- * Returns 1 if a mapping was found, 0 otherwise.
- */
-int
-ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz,
- void *imap, int imapsz, void *imapmsk, void *maskbuf, void *result,
- int rintrsz)
-{
- phandle_t parent;
- u_int8_t *ref = maskbuf;
- u_int8_t *uiintr = intr;
- u_int8_t *uiregs = regs;
- u_int8_t *uiimapmsk = imapmsk;
- u_int8_t *mptr;
- pcell_t pintrsz;
- int i, rsz, tsz;
-
- rsz = -1;
- if (imapmsk != NULL) {
- for (i = 0; i < physsz; i++)
- ref[i] = uiregs[i] & uiimapmsk[i];
- for (i = 0; i < intrsz; i++)
- ref[physsz + i] = uiintr[i] & uiimapmsk[physsz + i];
- } else {
- bcopy(regs, ref, physsz);
- bcopy(intr, ref + physsz, intrsz);
- }
-
- mptr = imap;
- i = imapsz;
- tsz = physsz + intrsz + sizeof(phandle_t) + rintrsz;
- while (i > 0) {
- KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map"));
- bcopy(mptr + physsz + intrsz, &parent, sizeof(parent));
- if (ofw_bus_searchprop(parent, "#interrupt-cells",
- &pintrsz, sizeof(pintrsz)) == -1)
- pintrsz = 1; /* default */
- pintrsz *= sizeof(pcell_t);
- if (pintrsz != rintrsz)
- panic("ofw_bus_search_intrmap: expected interrupt cell "
- "size incorrect: %d != %d", rintrsz, pintrsz);
- if (bcmp(ref, mptr, physsz + intrsz) == 0) {
- bcopy(mptr + physsz + intrsz + sizeof(parent),
- result, rintrsz);
- return (1);
- }
- mptr += tsz;
- i -= tsz;
- }
- return (0);
-}
diff --git a/sys/sparc64/sparc64/ofw_machdep.c b/sys/sparc64/sparc64/ofw_machdep.c
index 7efc807..bcacea7 100644
--- a/sys/sparc64/sparc64/ofw_machdep.c
+++ b/sys/sparc64/sparc64/ofw_machdep.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/idprom.h>
-#include <machine/ofw_bus.h>
#include <machine/ofw_machdep.h>
void
diff --git a/sys/sparc64/sparc64/support.S b/sys/sparc64/sparc64/support.S
index a3f6501..821e694 100644
--- a/sys/sparc64/sparc64/support.S
+++ b/sys/sparc64/sparc64/support.S
@@ -745,9 +745,9 @@ ENTRY(setjmp)
END(setjmp)
/*
- * void openfirmware(cell_t args[])
+ * void ofw_entry(cell_t args[])
*/
-ENTRY(openfirmware)
+ENTRY(ofw_entry)
save %sp, -CCFSZ, %sp
SET(ofw_vec, %l7, %l6)
ldx [%l6], %l6
@@ -758,12 +758,12 @@ ENTRY(openfirmware)
wrpr %l7, 0, %pil
ret
restore %o0, %g0, %o0
-END(openfirmware)
+END(ofw_entry)
/*
- * void openfirmware_exit(cell_t args[])
+ * void ofw_exit(cell_t args[])
*/
-ENTRY(openfirmware_exit)
+ENTRY(ofw_exit)
save %sp, -CCFSZ, %sp
flushw
wrpr %g0, PIL_TICK, %pil
@@ -783,7 +783,7 @@ ENTRY(openfirmware_exit)
call %l6
mov %i0, %o0
! never to return
-END(openfirmware_exit)
+END(ofw_exit)
#ifdef GPROF
diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c
index 9de8e26..c10dbc4 100644
--- a/sys/sparc64/sparc64/trap.c
+++ b/sys/sparc64/sparc64/trap.c
@@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$");
#include <security/audit/audit.h>
#include <dev/ofw/openfirm.h>
+#include <machine/ofw_machdep.h>
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -248,7 +249,7 @@ sun4u_set_traptable(void *tba_addr)
};
args.tba_addr = (cell_t)tba_addr;
- openfirmware(&args);
+ ofw_entry(&args);
}
void
diff --git a/sys/sparc64/sparc64/vm_machdep.c b/sys/sparc64/sparc64/vm_machdep.c
index c163fd8..b769753 100644
--- a/sys/sparc64/sparc64/vm_machdep.c
+++ b/sys/sparc64/sparc64/vm_machdep.c
@@ -334,7 +334,7 @@ cpu_reset(void)
bspec[sizeof(bspec) - 1] = '\0';
}
- openfirmware_exit(&args);
+ ofw_exit(&args);
}
/*
diff --git a/sys/sun4v/conf/DEFAULTS b/sys/sun4v/conf/DEFAULTS
index ba7c539..610d653 100644
--- a/sys/sun4v/conf/DEFAULTS
+++ b/sys/sun4v/conf/DEFAULTS
@@ -9,5 +9,5 @@ machine sun4v
device mem # Memory and kernel memory devices
# Default partitioning schemes
-options GEOM_BSD
-options GEOM_SUNLABEL
+options GEOM_PART_BSD
+options GEOM_PART_VTOC8
diff --git a/sys/sun4v/include/elf.h b/sys/sun4v/include/elf.h
index 76e3a76..108ade1 100644
--- a/sys/sun4v/include/elf.h
+++ b/sys/sun4v/include/elf.h
@@ -78,18 +78,6 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-
-/*
- * The following non-standard values are used for passing information
- * from John Polstra's testbed program to the dynamic linker. These
- * are expected to go away soon.
- *
- * Unfortunately, these overlap the Linux non-standard values, so they
- * must not be used in the same context.
- */
-#define T_BRK 10 /* Starting point for sbrk and brk. */
-#define AT_DEBUG 11 /* Debugging level. */
-
/*
* The following non-standard values are used in Linux ELF binaries.
*/
diff --git a/sys/sun4v/include/ofw_bus.h b/sys/sun4v/include/ofw_bus.h
deleted file mode 100644
index 1e9004e..0000000
--- a/sys/sun4v/include/ofw_bus.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*-
- * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 _MACHINE_OFW_BUS_H_
-#define _MACHINE_OFW_BUS_H_
-
-#define ORIP_NOINT -1
-#define ORIR_NOTFOUND 0xffffffff
-
-/*
- * Other than in Open Firmware calls, the size of a bus cell seems to be
- * always the same.
- */
-typedef u_int32_t pcell_t;
-
-struct ofw_bus_iinfo {
- u_int8_t *opi_imap;
- u_int8_t *opi_imapmsk;
- int opi_imapsz;
- pcell_t opi_addrc;
-};
-
-void ofw_bus_setup_iinfo(phandle_t, struct ofw_bus_iinfo *, int);
-int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int,
- void *, int, void *, int, void *);
-int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *,
- void *, void *, int);
-
-#endif /* !_MACHINE_OFW_BUS_H_ */
diff --git a/sys/sun4v/sun4v/machdep.c b/sys/sun4v/sun4v/machdep.c
index 6281f00..b7c0869 100644
--- a/sys/sun4v/sun4v/machdep.c
+++ b/sys/sun4v/sun4v/machdep.c
@@ -310,18 +310,18 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
end = 0;
kmdp = NULL;
- /*
- * Initialize Open Firmware (needed for console).
- */
- OF_init(vec);
-
-
/*
* XXX
*/
bootverbose = 1;
/*
+ * Set up Open Firmware entry points
+ */
+ ofw_tba = rdpr(tba);
+ ofw_vec = (u_long)vec;
+
+ /*
* Parse metadata if present and fetch parameters. Must be before the
* console is inited so cninit gets the right value of boothowto.
*/
@@ -344,6 +344,12 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
init_param1();
+ /*
+ * Initialize Open Firmware (needed for console).
+ */
+ OF_install(OFW_STD_DIRECT, 0);
+ OF_init(ofw_entry);
+
root = OF_peer(0);
for (child = OF_child(root); child != 0; child = OF_peer(child)) {
OF_getprop(child, "device_type", type, sizeof(type));
@@ -516,13 +522,6 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
}
void
-set_openfirm_callback(ofw_vec_t *vec)
-{
- ofw_tba = rdpr(tba);
- ofw_vec = (u_long)vec;
-}
-
-void
sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct trapframe *tf;
diff --git a/sys/sun4v/sun4v/mp_machdep.c b/sys/sun4v/sun4v/mp_machdep.c
index 8bd4ba6..5f4f632 100644
--- a/sys/sun4v/sun4v/mp_machdep.c
+++ b/sys/sun4v/sun4v/mp_machdep.c
@@ -272,7 +272,7 @@ start_ap_bycpuid(int cpuid, void *func, u_long arg)
args.cpuid = cpuid;
args.func = (cell_t)func;
args.arg = (cell_t)arg;
- openfirmware(&args);
+ ofw_entry(&args);
return (int)args.result;
}
diff --git a/sys/sun4v/sun4v/support.S b/sys/sun4v/sun4v/support.S
index e6bac5d..699a40f 100644
--- a/sys/sun4v/sun4v/support.S
+++ b/sys/sun4v/sun4v/support.S
@@ -622,9 +622,9 @@ ENTRY(setjmp)
END(setjmp)
/*
- * void openfirmware(cell_t args[])
+ * void ofw_entry(cell_t args[])
*/
-ENTRY(openfirmware)
+ENTRY(ofw_entry)
save %sp, -CCFSZ, %sp
SET(ofw_vec, %l7, %l6)
ldx [%l6], %l6
@@ -635,14 +635,14 @@ ENTRY(openfirmware)
wrpr %l7, 0, %pil
ret
restore %o0, %g0, %o0
-END(openfirmware)
+END(ofw_entry)
#ifdef notyet
/* SUN4V_FIXME - uses a now illegal ASI */
/*
* void ofw_exit(cell_t args[])
*/
-ENTRY(openfirmware_exit)
+ENTRY(ofw_exit)
save %sp, -CCFSZ, %sp
flushw
wrpr %g0, PIL_TICK, %pil
@@ -661,7 +661,7 @@ ENTRY(openfirmware_exit)
call %l6
mov %i0, %o0
! never to return
-END(openfirmware_exit)
+END(ofw_exit)
#endif
ENTRY(set_mmfsa_scratchpad)
diff --git a/sys/sun4v/sun4v/trap.c b/sys/sun4v/sun4v/trap.c
index f04c424..bac4f55 100644
--- a/sys/sun4v/sun4v/trap.c
+++ b/sys/sun4v/sun4v/trap.c
@@ -261,7 +261,7 @@ set_mmfsa_traptable(void *tba_addr, uint64_t mmfsa_ra)
args.tba_addr = (cell_t)tba_addr;
args.mmfsa_ra = mmfsa_ra;
- openfirmware(&args);
+ ofw_entry(&args);
}
void
diff --git a/sys/sys/buf_ring.h b/sys/sys/buf_ring.h
index 6d0cb7d..efea85a 100644
--- a/sys/sys/buf_ring.h
+++ b/sys/sys/buf_ring.h
@@ -48,10 +48,11 @@ struct buf_ring {
volatile uint32_t br_prod_tail;
int br_prod_size;
int br_prod_mask;
+ uint64_t br_drops;
/*
* Pad out to next L2 cache line
*/
- uint64_t _pad0[14];
+ uint64_t _pad0[13];
volatile uint32_t br_cons_head;
volatile uint32_t br_cons_tail;
diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h
index 95f3352..688fab2 100644
--- a/sys/sys/elf_common.h
+++ b/sys/sys/elf_common.h
@@ -101,6 +101,7 @@ typedef struct {
#define ELFOSABI_OPENBSD 12 /* OpenBSD */
#define ELFOSABI_OPENVMS 13 /* Open VMS */
#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */
+#define ELFOSABI_AROS 15 /* Amiga Research OS */
#define ELFOSABI_ARM 97 /* ARM */
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
@@ -169,6 +170,61 @@ typedef struct {
#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */
#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */
#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */
+#define EM_PDSP 63 /* Sony DSP Processor. */
+#define EM_FX66 66 /* Siemens FX66 microcontroller. */
+#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16
+ microcontroller. */
+#define EM_ST7 68 /* STmicroelectronics ST7 8-bit
+ microcontroller. */
+#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller. */
+#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller. */
+#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller. */
+#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller. */
+#define EM_SVX 73 /* Silicon Graphics SVx. */
+#define EM_ST19 74 /* STMicroelectronics ST19 8-bit mc. */
+#define EM_VAX 75 /* Digital VAX. */
+#define EM_CRIS 76 /* Axis Communications 32-bit embedded
+ processor. */
+#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded
+ processor. */
+#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor. */
+#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor. */
+#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc. */
+#define EM_HUANY 81 /* Harvard University machine-independent
+ object files. */
+#define EM_PRISM 82 /* SiTera Prism. */
+#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller. */
+#define EM_FR30 84 /* Fujitsu FR30. */
+#define EM_D10V 85 /* Mitsubishi D10V. */
+#define EM_D30V 86 /* Mitsubishi D30V. */
+#define EM_V850 87 /* NEC v850. */
+#define EM_M32R 88 /* Mitsubishi M32R. */
+#define EM_MN10300 89 /* Matsushita MN10300. */
+#define EM_MN10200 90 /* Matsushita MN10200. */
+#define EM_PJ 91 /* picoJava. */
+#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor. */
+#define EM_ARC_A5 93 /* ARC Cores Tangent-A5. */
+#define EM_XTENSA 94 /* Tensilica Xtensa Architecture. */
+#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor. */
+#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose
+ Processor. */
+#define EM_NS32K 97 /* National Semiconductor 32000 series. */
+#define EM_TPC 98 /* Tenor Network TPC processor. */
+#define EM_SNP1K 99 /* Trebia SNP 1000 processor. */
+#define EM_ST200 100 /* STMicroelectronics ST200 microcontroller. */
+#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family. */
+#define EM_MAX 102 /* MAX Processor. */
+#define EM_CR 103 /* National Semiconductor CompactRISC
+ microprocessor. */
+#define EM_F2MC16 104 /* Fujitsu F2MC16. */
+#define EM_MSP430 105 /* Texas Instruments embedded microcontroller
+ msp430. */
+#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor. */
+#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors. */
+#define EM_SEP 108 /* Sharp embedded microprocessor. */
+#define EM_ARCA 109 /* Arca RISC Microprocessor. */
+#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd.
+ and MPRC of Peking University */
/* Non-standard or deprecated. */
#define EM_486 6 /* Intel i486. */
@@ -195,12 +251,12 @@ typedef struct {
#define SHT_STRTAB 3 /* string table section */
#define SHT_RELA 4 /* relocation section with addends */
#define SHT_HASH 5 /* symbol hash table section */
-#define SHT_DYNAMIC 6 /* dynamic section */
+#define SHT_DYNAMIC 6 /* dynamic section */
#define SHT_NOTE 7 /* note section */
#define SHT_NOBITS 8 /* no space section */
#define SHT_REL 9 /* relocation section - no addends */
#define SHT_SHLIB 10 /* reserved - purpose unknown */
-#define SHT_DYNSYM 11 /* dynamic symbol table section */
+#define SHT_DYNSYM 11 /* dynamic symbol table section */
#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */
#define SHT_FINI_ARRAY 15 /* Termination function pointers. */
#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */
diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h
index 663a090..ec1d638 100644
--- a/sys/sys/imgact_elf.h
+++ b/sys/sys/imgact_elf.h
@@ -52,7 +52,6 @@ typedef struct {
Elf_Size base;
Elf_Size flags;
Elf_Size entry;
- Elf_Size trace;
} __ElfN(Auxargs);
typedef struct {
diff --git a/sys/sys/kobj.h b/sys/sys/kobj.h
index b744db8..64a666a 100644
--- a/sys/sys/kobj.h
+++ b/sys/sys/kobj.h
@@ -246,9 +246,4 @@ kobj_method_t* kobj_lookup_method(kobj_class_t cls,
*/
int kobj_error_method(void);
-/*
- * Machine-dependent initialisation call for boot-time kobj clients
- */
-void kobj_machdep_init(void);
-
#endif /* !_SYS_KOBJ_H_ */
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 51cff5d..60086c6 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -316,6 +316,7 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
#define MNTK_SOFTDEP 0x00000004 /* async disabled by softdep */
#define MNTK_NOINSMNTQ 0x00000008 /* insmntque is not allowed */
#define MNTK_DRAINING 0x00000010 /* lock draining is happening */
+#define MNTK_REFEXPIRE 0x00000020 /* refcount expiring is happening */
#define MNTK_UNMOUNT 0x01000000 /* unmount in progress */
#define MNTK_MWAIT 0x02000000 /* waiting for unmount to finish */
#define MNTK_SUSPEND 0x08000000 /* request write suspension */
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 497b362..fad4d51 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -57,7 +57,7 @@
* is created, otherwise 1.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 800058 /* Master, propagated to newvers */
+#define __FreeBSD_version 800060 /* Master, propagated to newvers */
#ifndef LOCORE
#include <sys/types.h>
diff --git a/sys/sys/ttyhook.h b/sys/sys/ttyhook.h
index 7a0a0bc..2a6d088 100644
--- a/sys/sys/ttyhook.h
+++ b/sys/sys/ttyhook.h
@@ -66,7 +66,7 @@ struct ttyhook {
th_close_t *th_close;
};
-int ttyhook_register(struct tty **, struct thread *, int,
+int ttyhook_register(struct tty **, struct proc *, int,
struct ttyhook *, void *);
void ttyhook_unregister(struct tty *);
#define ttyhook_softc(tp) ((tp)->t_hooksoftc)
diff --git a/sys/sys/vtoc.h b/sys/sys/vtoc.h
index 83b8547..231da00 100644
--- a/sys/sys/vtoc.h
+++ b/sys/sys/vtoc.h
@@ -72,7 +72,7 @@ struct vtoc8 {
struct {
uint16_t tag;
uint16_t flag;
- } part[VTOC8_NPARTS];
+ } part[VTOC8_NPARTS] __packed;
uint16_t __alignment;
uint32_t bootinfo[3];
uint32_t sanity;
diff --git a/sys/ufs/ufs/ufs_vfsops.c b/sys/ufs/ufs/ufs_vfsops.c
index 14ce4c6..ac1fbcf 100644
--- a/sys/ufs/ufs/ufs_vfsops.c
+++ b/sys/ufs/ufs/ufs_vfsops.c
@@ -118,9 +118,6 @@ ufs_quotactl(mp, cmds, id, arg, td)
if ((u_int)type >= MAXQUOTAS)
return (EINVAL);
- if (vfs_busy(mp, MBF_NOWAIT))
- return (0);
-
switch (cmd) {
case Q_QUOTAON:
error = quotaon(td, mp, type, arg);
@@ -150,7 +147,6 @@ ufs_quotactl(mp, cmds, id, arg, td)
error = EINVAL;
break;
}
- vfs_unbusy(mp);
return (error);
#endif
}
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index e5047e9..7b639e8 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -2013,7 +2013,7 @@ ufs_strategy(ap)
bp->b_error = error;
bp->b_ioflags |= BIO_ERROR;
bufdone(bp);
- return (error);
+ return (0);
}
if ((long)bp->b_blkno == -1)
vfs_bio_clrbuf(bp);
OpenPOWER on IntegriCloud